Skip to content

Use CRS area-of-use bounds for coordinate clamping instead of proj4 string detection #186

@frewsxcv

Description

@frewsxcv

Context

When reprojecting raster extents to a target CRS, source coordinates may fall outside the target CRS's valid area of use. For example, EPSG:3857 (Web Mercator) is only defined for latitudes ±85.06° — near-polar vertices produce extreme Y values that stretch the projected extent.

Current workaround

We detect Mercator by checking if the target CRS's PROJ4 string contains +proj=merc, and clamp source latitudes to ±85.06° when it does:

let target_is_mercator = crs_definitions::from_code(self.target_crs.epsg_code)
    .map(|def| def.proj4.contains("+proj=merc"))
    .unwrap_or(false);
if target_is_mercator {
    const MERCATOR_LAT_LIMIT: f64 = 85.06;
    min.y = min.y.max(-MERCATOR_LAT_LIMIT);
    max.y = max.y.min(MERCATOR_LAT_LIMIT);
}

This only handles Mercator. Other projections with limited areas of use (e.g., UTM zones, Lambert conformal conic) are not clamped.

Ideal solution

Use a proper CRS area-of-use database to clamp coordinates for any target CRS, similar to PROJ's proj_get_area_of_use(). This would:

  • Handle all projections with limited areas of use, not just Mercator
  • Use the official EPSG-defined bounds rather than hardcoded constants
  • Remove the fragile PROJ4 string parsing

Blockers

The crs-definitions crate we use only exposes code, proj4, and wkt — it does not include area-of-use/bounds information. Options:

  1. Contribute area-of-use bounds to crs-definitions upstream
  2. Use a different crate that includes bounds data
  3. Build a lookup table from the EPSG database

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions