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

Feature Properties Transform #4198

Open
wipfli opened this issue May 29, 2024 · 4 comments
Open

Feature Properties Transform #4198

wipfli opened this issue May 29, 2024 · 4 comments

Comments

@wipfli
Copy link
Contributor

wipfli commented May 29, 2024

The things that a user can do with MapLibre style expressions based on feature properties is limited to the implemented styling language. While the style language has support for basic math, logic, and rudimentary string operations, many things cannot be done easily.

For example, it is hard to format a number to the locale India with 3 significant digits, e.g.: turn 1434389.043 to 14,30,000.

Another example: it is not possible to extract a value from a JSON encoded dictionary.

Both of these tasks are trivial to achieve in JavaScript or any other programming language and we usually motivate users to do such transformation at tile generation time.

In the past, we rejected a proposal to reference user-defined javascript functions from the style.json.

What I would like to introduce instead is a user-defined Feature Properties Transform, a callback which gets executed during vector tile parsing.

The Feature Properties Transform gets executed on every feature and has access to the following data:

  • source name
  • source layer name
  • tileID z/x/y
  • feature properties

With this information, one can easily filter based on source and source-layer, like people do usually in style.json documents and since the transform has access to all feature properties, it can do arbitrary logic and execute javascript on the properties dictionary. This is very powerful and opens the way to an alternative way of styling maps, namely more styling in JavaScript and less in the styling language.

Proof-of-concept implementation: #4199

@HarelM
Copy link
Collaborator

HarelM commented May 29, 2024

I think this is a very good idea for a hook.
We need to remember that allowing things to be only in javascript will cause issues with parity between native and web.
This is true for add protocol as well, but addProtocol forces you to put something "Wrong" in the style as opposed to this feature which you might just get an empty label and this can "fail" siliently.

In any case, these hooks are important and people using them should know that they create issues with parity.

One thing to keep in mind looking at the PR is that the transform is done in the worker thread while the map API is available in the main thread, and passing a method to the worker is very hard (you can probably pass very basic method, without the context of the main thread).
So there needs to be a way to pass a method to the worker, which is only using importScript, which needs a javascript file or a string converted to dataURI.

In any case, I think adding that hook, since it is in the worker can be done differently maybe, using some "noop" method you override in the worker tile class - i.e something like

class WorkerTile {
...
    transfromFeature(feature) = return feature // this is a new noop method

}

and call this code in the worker context:

WorkerTile.prototype.transfromFeature = (f) => {//do something else with f and return it }

IDK, worth prototyping to see what's the easiest approach.

@wipfli
Copy link
Contributor Author

wipfli commented May 29, 2024

Thanks for the feedback.

Here is an example how to use the proof-of-concept: https://github.com/wipfli/maplibre-feature-properties-transform-example

And you are right @HarelM the setFeaturePropertiesTransform function should not be available in the main thread, only in the worker...

@HarelM
Copy link
Collaborator

HarelM commented May 30, 2024

This looks elegant. Nice work!

@neodescis
Copy link
Collaborator

neodescis commented Jun 1, 2024

This would be great! I just went to a lot of work to implement color hashing of features based on some feature value. Without this, I had to get a list of unique values up-front from another endpoint, hash those, and put them all into a (sometimes giant) case expression. With this addition, it would be just a few lines of code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants