Skip to content

fix: use proj4 +over flag to prevent antimeridian longitude wrapping#353

Closed
yharby wants to merge 1 commit intodevelopmentseed:mainfrom
yharby:fix/proj4-over-antimeridian
Closed

fix: use proj4 +over flag to prevent antimeridian longitude wrapping#353
yharby wants to merge 1 commit intodevelopmentseed:mainfrom
yharby:fix/proj4-over-antimeridian

Conversation

@yharby
Copy link

@yharby yharby commented Mar 18, 2026

Summary

  • Use proj4's +over flag on target projection definitions (EPSG:4326 and EPSG:3857) to disable adjust_lon longitude normalization
  • Fixes 360° round-trip errors at the antimeridian that make Delatin mesh refinement unconvergeable for global COGs spanning ±180°

Problem

proj4's adjust_lon normalizes longitude to (-π, π], causing:

  • forward(-180.001°, lat) → positive easting (wrong sign)
  • inverse(-WM_HALF, northing) → +180° instead of -180°

For tiles touching the antimeridian on global EPSG:4326 COGs (e.g. 1.4M×600K pixel DEM), the round-trip error equals the full image width (5625 pixels), producing visibly distorted tile meshes at low zoom levels.

Fix

Add +over to the target projection definitions:

proj4.defs("__WGS84_OVER", "+proj=longlat +datum=WGS84 +over");
proj4.defs("__MERC_OVER", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +over");

The +over flag is safe for longlat and Mercator projections where the 180° meridian is a straight line. Supported since proj4js v2.20.0 (proj4js#530).

Test plan

  • Load a global EPSG:4326 COG spanning ±180° longitude (e.g. GEDTM30 at 1440010×600010 pixels)
  • Verify z=0 tiles at the antimeridian (x=0, x=2) converge without 5625-pixel error
  • Verify regional COGs (EPSG:2193, EPSG:32610) render correctly
  • Verify no regressions with non-geographic source CRS

Fixes #352

proj4's `adjust_lon` normalizes longitude to (-π, π], which causes 360°
round-trip errors for coordinates at the antimeridian (±180°):

- `forward(-180.001°, lat)` wraps to positive easting (wrong sign)
- `inverse(-WM_HALF, northing)` returns +180° instead of -180°

These errors make the Delatin mesh refinement unconvergeable for tiles
touching the antimeridian on global EPSG:4326 COGs (e.g. a 1.4M×600K
pixel DEM spanning ±180° longitude). The round-trip error equals the
full image width, producing visibly distorted tile meshes at low zoom.

Fix: Add `+over` to the target projection definitions for both the 4326
and 3857 converters. The `+over` flag disables `adjust_lon`, allowing
coordinates to pass through unwrapped. This is safe for longlat and
Mercator projections where the 180° meridian is a straight line.

The `+over` flag is supported since proj4js v2.20.0 (PR proj4js#530).

Fixes developmentseed#352
@github-actions github-actions bot added the fix label Mar 18, 2026
@kylebarron
Copy link
Member

This looks very hacky.

I think we need a deeper consideration of how to handle images spanning the antimeridian.

@yharby
Copy link
Author

yharby commented Mar 18, 2026

Thanks, I’ve just discovered #171 and #269 .. will close this !

@yharby yharby closed this Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PR #349: Antimeridian longitude wrap + NaN from oversized tile matrices on global COGs

2 participants