Skip to content

Route projections through a ProjectionDefinition registry - #238

Closed
trasch wants to merge 2 commits into
generic-projection-kindsfrom
generic-projection-registry
Closed

trasch wants to merge 2 commits into
generic-projection-kindsfrom
generic-projection-registry

Conversation

@trasch

@trasch trasch commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 2 of making the projection system generic. Stacks on #237 (phase 1: ProjectionKind + capability flags) — review/merge that one first.

Extracts the inline transform math into a ProjectionDefinition strategy protocol and routes all conversions through a registry, keeping EPSG:4326 as the pivot.

Changes

  • ProjectionDefinition protocol (new file): forward/inverse conversions relative to the EPSG:4326 pivot, plus validExtent and worldBoundingBox metadata
  • ProjectionRegistry: maps each Projection to its definition
  • Definitions: Epsg4326Definition (identity), Epsg3857Definition (Web Mercator), Epsg4978Definition (ECEF — geodetic/ECEF helpers moved here from Coordinate3D), NoSridDefinition (null math)
  • Coordinate3D.projected(to:): the 4×4 nested switch matrix replaced by inverse → 4326 pivot → forward through the registry
  • Coordinate3D.clamped(): uses the definition's validExtent
  • latitudeProjected / longitudeProjected: derive from the full projection (noSRID special case preserved)
  • BoundingBox.expanded(byDistance:) and Random's world box: use registry metadata instead of per-CRS switches

noSRID semantics (pinned by tests)

The historical convention is preserved and now documented:

  • Projecting to .noSRID copies values verbatim
  • Projecting from .noSRID into EPSG:4326 or EPSG:3857 copies values verbatim (the library treats noSRID values as planar meters — intersection/unaryUnion rely on this)
  • Projecting from .noSRID into EPSG:4978 interprets the values as EPSG:4326

Testing

  • New tests: round trips across all projection pairs, pivot routing, noSRID semantics, per-axis helper consistency, altitude/m preservation, clamped() extents
  • Full suite passes: 2430 tests in 172 suites, zero warnings

Phase 2 of making the projection system generic: extract the inline
transform math into a ProjectionDefinition strategy protocol and route
all conversions through a registry, keeping EPSG:4326 as the pivot.

- ProjectionDefinition protocol: forward/inverse relative to the
  EPSG:4326 pivot, plus validExtent and worldBoundingBox metadata
- Definitions for EPSG:4326 (identity), EPSG:3857 (Web Mercator),
  EPSG:4978 (ECEF, with the geodetic/ECEF helpers moved here) and
  noSRID (null math)
- ProjectionRegistry maps a Projection to its definition
- Coordinate3D.projected(to:) now dispatches through the registry;
  clamped() uses the definition's validExtent; latitudeProjected/
  longitudeProjected derive from the full projection
- BoundingBox.expanded(byDistance:) and Random's world box use the
  registry metadata instead of per-CRS switches

noSRID keeps its historical semantics, now documented and pinned by
tests: verbatim copy to .noSRID, verbatim relabel to EPSG:4326 and
EPSG:3857 (planar-meter convention), interpreted as EPSG:4326 into
EPSG:4978.

New tests: round trips across all projection pairs, pivot routing,
noSRID semantics, per-axis helper consistency, altitude/m preservation
and clamped() extents.
@trasch
trasch marked this pull request as draft September 14, 2026 14:20
@trasch trasch self-assigned this Sep 14, 2026
@trasch trasch added the enhancement New feature or request label Sep 14, 2026
@trasch

trasch commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #250, which consolidates the full projection-genericity chain into a single reviewable PR. All commits are unchanged in #250.

@trasch trasch closed this Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant