You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Public API for third-party / custom projections #242
The projection-genericity effort (#239, #240, #241) made projections pluggable internally: ProjectionDefinition (strategy) + ProjectionRegistry map each Projection enum case to its transform math, all below the public API surface. During that work we decided explicitly not to expose the protocol publicly ("Keep internal" decision, made after reviewing the trade-offs).
What this issue would add
An option for users of the library to register custom projections (e.g. a local grid CRS or a projection the library hasn't shipped) without forking:
A public protocol (or struct-based descriptor — probably preferable; public protocols are sticky API commitments, see Swift API design guidelines) exposing:
forward/inverse relative to the EPSG:4326 pivot
validExtent / worldBoundingBox metadata (would need a proper struct, not the current tuple in the internal protocol)
kind: ProjectionKind capability classification
A registration API (dictionary-backed lookup replacing/customizing the current eager dictionary in ProjectionRegistry)
Likely also a way for custom SRIDs to appear as Projection values — which conflicts with the current closed enum: Int design (would need a raw-value-backed case or a restructure)
Considerations / prior decisions
The current internal-first design was deliberate: nothing in shipping projections requires a public API, and pre-registry phases pinned semantics (noSRID verbatim copy, pivot routing) that a public seam would have to preserve
.swiftformat/style conventions and strict concurrency apply to any public surface
If pursued, design the descriptor now while the internal protocol is still small; retrofitting is more expensive
Implemented in PR #247 (stacked on #245), per the agreed revised scope:
Projection becomes a struct with SRID identity (emoji-breaking for pattern matching; constant names unchanged so dot-shorthand survives). Codable keeps the SRID wire format.
Custom registration API: Projection.register(CustomProjection) — value-type descriptor with @Sendable forward/inverse closures relative to the EPSG:4326 (WGS84) pivot (documented as the datum-transformation seam for Support CRSs on other datums (NAD27, OSGB, CH1903+, ...) #243), public struct ProjectionExtent replacing the internal tuple.
Add-only by design (per review): no unregister/deactivate; built-ins permanently registered and always enabled. Family toggles / opt-in enablement were explicitly dropped — performance-neutral and correctness-degrading; compile-time trimming (SwiftPM traits) noted as the alternative if binary size ever matters.
Performance motivation discovered en route (release benchmarks + parallel test run): per-access registry reads contended catastrophically under Swift Testing's parallelism; the definition-capture design takes the full projected(to:) path to ~1.7× the direct-math baseline, with registry access confined to cold lookups.
Activity
trasch commentedon Sep 15, 2026
Implemented in PR #247 (stacked on #245), per the agreed revised scope:
Projectionbecomes a struct with SRID identity (emoji-breaking for pattern matching; constant names unchanged so dot-shorthand survives).Codablekeeps the SRID wire format.Projection.register(CustomProjection)— value-type descriptor with@Sendableforward/inverse closures relative to the EPSG:4326 (WGS84) pivot (documented as the datum-transformation seam for Support CRSs on other datums (NAD27, OSGB, CH1903+, ...) #243),public struct ProjectionExtentreplacing the internal tuple.projected(to:)path to ~1.7× the direct-math baseline, with registry access confined to cold lookups.Closes #242 once #247 merges.
trasch commentedon Sep 15, 2026
Implemented in #250 (consolidation of the reviewed chain; closes #242 on merge).