Skip to content

Conversation

@bhousel
Copy link
Collaborator

@bhousel bhousel commented Oct 22, 2025

This introduces breaking changes to the Viewport (projection), Transform, and Tiler code to support "world coordinates".
(see Google Maps world coordinates)

I've been using it with my private fork of Rapid for several months and it's proven useful! We can now cache geometry in Mercator - this speeds up rendering and spatial testing for things like bounding boxes and conflation.

  • Now the projection code is split up so that the expensive trig functions only need to happen once, this geometry data can be cached, then rendering to screen can just be translate/scale.
  • This introduces new methods in Viewport to do these conversions:
    • wgs84ToWorld(lonlat) : xy
    • worldToWgs84(xy): lonlat
    • worldToScreen(xy): xy
    • screenToWorld(xy): xy
  • We retain the legacy methods which do the same thing they did before:
    • project(lonlat): xy = worldToScreen(wgs84ToWorld(lonlat))
    • unproject(xy): lonlat = worldToWgs84(screenToWorld(xy))
  • This also changes the Transform code to replace the old k scale with a straightforward z parameter.
    • It's a bit less work and math now, as we don't need to convert between scale (which had Math.PI baked into it) and zoom (which is just an integer).
    • The legacy geoZoomToScale and geoScaleToZoom functions are still there.
  • All the tests are updated. We were even able to increase the float the precision on many of them.

This also fixes #296 along the way, reversing the winding of Extent.polygon() to be counterclockwise, as GeoJSON expects.

This will allows us to store coordinate data in an unscaled mercator
(like Google Maps world coordinates)

This will have several benefits:
- it breaks the projection code up so that the expensive trig functions only
  need to happen once, and each projection can just be a translate/scale
- we can store world coordinates for indexing, it should ease things like
  label placement, conflation
This has some benefits, but the main one is that it makes
the transform from world -> screen easier
(reprojections/pans/zooms should speed up with less division)

It means we will need to change how Transform works, I'll do that next.
This makes things much simpler. Project/unproject can go through
world coordinates and we can avoid doing math with extra Math.PI
and division associated with the D3-like `scale`/`k` property.
This replaces "pxExtent" which was in a different kind of world coordinates
with "tileExtent" which will be in the world coordinates used everywhere.

The tiler behavior has changed slightly around non-256px tile sizes.
Before we would calculate the tiles in these sizes, now we just adjust the zoom.
I will test to see if this works as expected.
(re: #296)

This also adds "@esbuild/darwin-arm64" optional dependency
@bhousel bhousel merged commit 5526200 into main Oct 22, 2025
3 checks passed
@bhousel bhousel deleted the world_coordinates branch October 22, 2025 13:14
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

Successfully merging this pull request may close these issues.

Extent polygon should return coordinates wound counterclockwise

2 participants