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

expose the projection to make it reusable #1191

Open
Fil opened this issue Dec 16, 2022 · 7 comments · May be fixed by #2038
Open

expose the projection to make it reusable #1191

Fil opened this issue Dec 16, 2022 · 7 comments · May be fixed by #2038
Labels
enhancement New feature or request geo Maps and projections question Further information is needed

Comments

@Fil
Copy link
Contributor

Fil commented Dec 16, 2022

maybe just as plot.scale("projection")? If the goal is to make it reusable, it doesn't matter if it's an opaque {stream}, and the code is ultra-simple. If we extend the scope and want to get the name back, it's much more difficult.

@Fil Fil added enhancement New feature or request question Further information is needed geo Maps and projections labels Dec 16, 2022
@jheer
Copy link

jheer commented Mar 21, 2024

Exposing projection information would be very useful to Mosaic vgplot. We could then support brushing/filtering over explicitly projected data, at least initially for planar projections and those with separable lon -> x, lat -> y mappings (like unrotated mercator or equirectangular).

I have a working prototype of this locally, which extends Plot's projection.js like so:

return {
  width: dx,
  height: dy,
  offset: [marginLeft + insetLeft, marginTop + insetTop],
  translate: [tx, ty],
  scale: k,
  invert: projection.invert, // may be undefined
  stream: (s) => projection.stream(transform.stream(clip(s)))
};

One also needs to first define let k = 1 in the outer scope. I'm exporting dimension information (width, height, offset) to infer the equivalent of scale ranges and to aid setting the boundaries of the brushable region. I use the (translate, scale) data to create my own invert methods (including optimized 1D variants for planar projections). Alternatively, an end-to-end invert method that takes any affine transform into account would work fine.

The only other change is to modify plot.js to expose the projection:

figure.projection = () => context.projection;

I assume you would want to run this through an exposeProjection method that makes a defensive copy.

Not sure how well something like the above would fit in with your plans and sensibilities, but I can make a PR if it does.

@Fil
Copy link
Contributor Author

Fil commented Mar 21, 2024

Not to say that we should absolutely support every funky projection out there, but I'm weary of an approach that by design wouldn't allow to work, for example, with polar projections, or maps rotated to include the antimeridian?

Have you thought of going in the opposite direction? If mosaic had only access to the stream — or maybe a convenience method projection(lon, lat) => [x, y] returned by Plot, could it initialize its brushing component by computing all the screen positions (once); these derived dimensions would be added to the datacube, and brushing would work normally. This would make no assumption on what the projection returns.

The drawback of this approach —and I guess that's what you're trying to avoid?— is that you have to compute projected values [x,y] for the whole dataset. But since brushing does not require an extreme precision (that is, a precision of 1 pixel or 0.5 pixel is enough), there might be ways to optimize this even when you have a bazillion data points, by binning or sampling?

Happy to explore this with you in any case—the more maps we can make, the 👍

@jheer
Copy link

jheer commented Mar 21, 2024

Yes, there are plenty of non-invertible projections that would be nice to support. As you note, we can compute the projection as a pre-processing step, then rely on the projected (x, y) values. We do this in-database for examples like the Gaia star map and NYC taxis. In the Mosaic context, we need these projected coordinates to reside in-database for scalable and interoperable filtering.

However, all that resides outside of Plot. So for cases where we want to use Plot projections (and their nice defaults, scaling, etc) we currently have a bit of a chicken-and-egg problem. So I've been exploring cases where we can create meaningful selections over lon/lat via projection inversion. If ultimately this proves to be a dead-end, so be it!

In any case it would be nice to be able to access the projection - even if just the stream!

@Fil Fil linked a pull request Mar 26, 2024 that will close this issue
4 tasks
@jaanli

This comment was marked as off-topic.

@Fil

This comment was marked as off-topic.

@jaanli

This comment was marked as off-topic.

@jaanli
Copy link

jaanli commented Apr 10, 2024

Would also want to use this to enable filtering for data like this: https://jaanli.github.io/new-york-real-estate between Mosaic, Plot, and Protomaps / Maplibre GL types of visualizations like this...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request geo Maps and projections question Further information is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants