Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow arbitrary expressions in functions and filters #4077

Closed
lucaswoj opened this issue Feb 1, 2017 · 19 comments
Closed

Allow arbitrary expressions in functions and filters #4077

lucaswoj opened this issue Feb 1, 2017 · 19 comments
Labels
cross-platform 📺 Requires coordination with Mapbox GL Native (style specification, rendering tests, etc.) feature 🍏 needs discussion 💬

Comments

@lucaswoj
Copy link
Contributor

lucaswoj commented Feb 1, 2017

From @nickidlugash on June 16, 2014 20:1

Will it be possible to support +, -, *, and /?

Copied from original issue: mapbox/mapbox-gl-style-spec#47

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @tmcw on June 16, 2014 20:21

Could you go into a little more detail about how these would be represented? Like "{{a}} + {{b}}"?

Fwiw, expressions like this are probably super useful, but I'd be interested in whether the approach we've taken for filters could be applied rather than doing infix like Carto or string like Mapnik - like we would have something like

{
  "+": ["{{a}}", 2]
}

Instead of

"{{a}} + 2"

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @jfirebaugh on January 22, 2015 1:10

Can we enumerate some uses cases for this feature? I'm particularly interested in how much it overlaps with #226 (Stop functions based on arbitrary properties).

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @nickidlugash on January 22, 2015 22:40

hrm. In theory, there are some use cases for this not covered by stop functions based on arbitrary properties. I might not be fully understanding the stop functions, but they seem to mainly be for assigning different values of the same style property for different values of the same field in a data layer. With math operators, you could manipulate values across different properties and different GL layers.

A use case that I think would overlap with a use case for mapbox/mapbox-gl-style-spec#226 is using math operators in conjunction with tokens, e.g. for building heights.

The two main non-overlapping use cases I had in mind for this were for creating systems of line widths and font sizes across different GL layers. These could potentially be really useful for creating template styles that are fast to customize. However, these use cases require the ability to use constant values in functions, which you currently can't do in the editor.

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @danpat on February 18, 2016 19:1

I have a specific use case. I'm generating vector tiles from OSRM that contain speed values on roads, in km/h. It would be nice to show localized values (mph vs km/h) by doing some simple math in the style.

I'm ambivalent about the syntax, but I've found this capability in Mapnik hugely useful.

Other basic math functions, like round() would also be helpful in my case.

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @timrobertson100 on March 12, 2016 15:49

A use case:

Given vector tiles containing polygons which represent sales regions. Each polygon is accompanied with data giving sales totals for a range of months in an attribute list (e.g. Month1:€10000, Month2:€23000 etc). You want to do a visualisation with a double handled time slider, where the user selects the period (e.g. month23-month45) and the polygons are then coloured based on total sales in the month ranges - this lets the user explore which regions are hot over different time ranges. You need to do math across feature attributes to total them up, and they can't be predetermined, as the slider control on the page is not known in advance.

As far as I can tell from my (very limited) use, this is not possible using filters.

(If this is possible, can you please point me at how - I am trying to find ways around this at the moment)

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @stackTom on June 18, 2016 18:7

@timrobertson100 have you found a solution to this problem?

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @timrobertson100 on June 18, 2016 19:42

@stackTom - I ended up doing server side processing on UI changes as I couldn't find a way in filters.

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @jfirebaugh on August 26, 2016 20:36

See mapbox/DEPRECATED-mapbox-gl#15 for additional syntax proposals.

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

Let's continue the conversation from mapbox/mapbox-gl-function#28 here 😄

To summarize so far:

  • Arbitrary expression functions will make our filters, functions, and cluster aggregators more powerful & flexible
  • Implementing arbitrary expressions will be challenging because they may need to run on the GPU
  • We are leaning towards a lispy syntax comprised of nested arrays
  • Devising a workable GUI for arbitrary expressions may be a challenge.

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

@1ec5 Agreed, creating a point & click GUI for this will be a little tricky. I'm not sure that users demand a point and click GUI for this, however. Most computer users are familiar with the notion of editing formulas, in Excel or Numbers for example.

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

From @1ec5 on December 21, 2016 19:36

Most computer users are familiar with the notion of editing formulas, in Excel or Numbers for example.

I have no qualms about an inline, text-based GUI for arithmetic or statistical expressions. But as soon as you introduce the notion of conditionals, you get a mini string language – an outcome that we took #104 on a tangent to avoid.

@lucaswoj
Copy link
Contributor Author

lucaswoj commented Feb 1, 2017

Important use cases:

  • unit conversion
  • number formatting
  • token defaults
  • customizable interpolation
  • arithmetic on feature properties within functions

@stevage
Copy link
Contributor

stevage commented Mar 29, 2017

I came here from #4049. Not sure if it's totally covered in this discussion, so just wanted to spell out my use case:

We have a visualisation of buildings colored by category. We want to be able to highlight the building that the mouse is currently over. The only way to avoid the highlighted building jumping to the front of the others (or being behind them all) is to ensure that it is part of the same layer (as opposed to creating a separate layer for the highlight). And the only way to do that (that I can think of, anyway) is to have a data-driven expression that is derived from two properties: the building category, and the building ID.

The only workaround I can think of would be something fairly laborious, like generating a new attribute which moves IDs into distinct numeric ranges so it can use them for both the category and the ID. Quite a lot of extra messing around in this case.

For this particular use case, we certainly don't need arbitrary expressions. Either of two much more limited solutions would work:

@1ec5
Copy link
Contributor

1ec5 commented Mar 30, 2017

token-replacement strings

This sounds like #4079, which has a proof of concept but no consensus about the preferred syntax.

Incidentally @stevage, have you tried using three layers – say, under_highlight, highlight, and above_highlight – and moving features back and forth among those three layers as needed to keep the z-order correct? (I realize that could have a performance penalty compared to the approach you’re proposing.)

@stevage
Copy link
Contributor

stevage commented Mar 30, 2017

Hmm, interesting idea! I'm not sure how I'd compute that z-order though - the issue here is the 3D angle, so the "z-order" is really the front-to-back ordering from the camera.

@brandonbloom
Copy link
Contributor

I'm not sure if this is covered by the use cases above, but I'd also like to see some notion of global properties. This was I could, for example, compute a weighted average in a property function and control the weights uniformly across all features. Absent such a notion, the workaround would seem to be using setPaintProperty and bake the weights in to the custom expression as constants. That may be fast enough, but may it would be better to not have to re-analyze expressions when interactively manipulating global properties.

@GLosch
Copy link

GLosch commented Jul 25, 2017

Is there an ETA on this feature? If I've correctly followed all the threads between supercluster and mapbox-gl, it seems like this is the ticket tracking the ability to pass an argument dictating how custom property aggregation gets calculated. I have a use case for that currently:

I'm rendering a map of geographical regions, each representing a number of buildings (e.g. a dot for New York representing ~50 buildings, another dot for San Francisco representing ~10 buildings). The GeoJSON payload has values for each region, but not for the underlying buildings (this is on purpose); instead, it has a building_count property. In order to render the number of buildings in each region, I'm passing the layer a property for the building_count:

id: 'clusters',
type: 'circle',
source: 'clusters',
paint: {
            'circle-radius': {
              'property': 'building_count',
              'type': 'interval'
          }

but I need a way to tell the clusters to sum the aggregated clusters by building_count, which I don't believe is currently possible in mapbox-gl. As it stands, when two region clusters combine, they simply lose their value.

@anandthakker
Copy link
Contributor

Work on this feature is in progress at #4777

@anandthakker anandthakker changed the title Allow arbitrary expressions in functions, filters, and cluster aggregators Allow arbitrary expressions in functions and filters Aug 31, 2017
@jfirebaugh
Copy link
Contributor

Filter support landed in #5434.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cross-platform 📺 Requires coordination with Mapbox GL Native (style specification, rendering tests, etc.) feature 🍏 needs discussion 💬
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants