Skip to content

Projection API polish: extent validation, UTM accessors and benchmarks - #245

Closed
trasch wants to merge 1 commit into
utm-wkt-identificationfrom
projection-api-polish
Closed

trasch wants to merge 1 commit into
utm-wkt-identificationfrom
projection-api-polish

Conversation

@trasch

@trasch trasch commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Three follow-ups to the projection work chain (#237–#244). Stacks on #244.

Validation API

  • Coordinate3D.isValid / BoundingBox.isValid — report whether the coordinate/box lies within the valid extent of its projection, resolved through the ProjectionRegistry. Always true for unbounded projections (EPSG:4978, noSRID)
  • Complements the existing clamped() / normalized(): report first, fix second

UTM convenience API

  • UtmHemisphere is now public (it appears in the public API)
  • Projection.utmZone: Int? / Projection.utmHemisphere: UtmHemisphere?
  • Projection(utmZone:hemisphere:) — Projection(utmZone: 19, hemisphere: .north) == .epsg32619; validates zone 1 ... 60

Benchmarks (ProjectionBenchmarks, skipped in CI like the other benchmark suites)

Baseline = the pre-registry inline formulas (verbatim copies of the old math), with correctness cross-checks. Release-build findings per coordinate:

Path Cost
direct math (baseline) ~5 ns
registry lookup alone ~30 ns
projection via fixed definition ~9 ns
full projected(to:) ~125 ns

Reacted to the first numbers: added an EPSG:4326 pivot short-circuit in Coordinate3D.projected(to:) — skips the registry lookup + identity coordinate copy when projecting from or to the pivot (the two most common directions). Behavior-identical (guarded by the round-trip correctness assertions). ~1.79 → ~1.68 ms/10k.

Documented verdict (in the suite docs): the remaining ~125 ns/op is bounded by dictionary reads + existential dispatch; closing the gap fully requires a non-existential registry redesign. Not worth it now — algorithm hot paths reproject per geometry feature, not per point cloud. Revisit only if bulk reprojection of large point clouds becomes a use case (batch API / restructure, noted as options). Decomposition tests (lookupAlone, fixedDefinitionForward) isolate the components so future profiling has a starting point.

Testing (+15)

  • ValidityTests: extent boundaries for 4326/3857/UTM sectors, unbounded projections always valid, invalid-then-clamp round trip
  • UtmDefinitionTests.utmConvenienceApi: zone sweep across zones 1/19/33/60 × hemispheres, invalid zone numbers, non-UTM accessors return nil
  • Benchmarks CI-skipped, print to verbose test output

Full suite: 2482 tests in 179 suites, zero warnings.

Three follow-ups to the projection-genericity effort:

Validation API:
- Coordinate3D.isValid and BoundingBox.isValid report whether the
  coordinate/box lies within the valid extent of its projection,
  resolved through the projection registry. Always true for
  unbounded projections (EPSG:4978, noSRID).

UTM convenience API:
- UtmHemisphere is now public (it appears in the public API below)
- Projection.utmZone / Projection.utmHemisphere accessors return
  the zone number or hemisphere of a UTM zone projection, nil for
  non-UTM projections
- Projection(utmZone:hemisphere:) creates a zone projection from a
  zone number (1...60) and hemisphere

Benchmarks:
- ProjectionBenchmarks suite (skipped in CI like the other suites):
  compares the pre-registry inline formulas as a baseline against
  the registry path, with correctness cross-checks. An EPSG:4326
  pivot short-circuit in Coordinate3D.projected(to:) skips the
  registry lookup and identity copy in the two most common
  directions (behavior-identical).
- Decomposition tests isolate lookup, fixed-definition projection
  and full-path costs (release: ~5 ns baseline, ~30 ns lookup,
  ~125 ns full path per coordinate). The overhead only matters for
  bulk reprojection; algorithm hot paths reproject per feature,
  and the analysis is documented in the suite docs along with the
  options if a batch reprojection use case appears.

Tests: ValidityTests (extent boundaries for 4326/3857/UTM sectors,
unbounded projections, invalid-then-clamp) and
UtmDefinitionTests.utmConvenienceApi (zone sweep, invalid zones,
non-UTM accessors).
@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