[PROJ] DerivedProjectedCRS — database support gap and proposed PR
Even Rouault
even.rouault at spatialys.com
Fri Mar 27 06:50:46 PDT 2026
Ben,
the general plan if we wanted to introduce support for
DerivedProjectedCRS in the database is sound, but I still don't think
that using that concept for polyhedral projections with a face
identifier is ISO-19111 compliant. AFAICS, there is no Coordinate System
subclass that allows mixing linear axis (X,Y) and an ordinal one (face
number). In particular a Cartesian CS is "a coordinate system in
Euclidean space which gives the position of points relative to n
mutually perpendicular straight axes all having the same unit of measure".
Even
Le 27/03/2026 à 12:13, Ben Griffin via PROJ a écrit :
> Hi all,
>
> Following the earlier thread on face/octant coordinates and the UTM zone analogy, I've been investigating whether DERIVEDPROJCRS could be used to formally express planar net projections as derived from intermediate octahedral ProjectedCRS.
>
> In doing so I found that the C++ side is already largely in place — the object model, WKT parser, and operation factory all handle DerivedProjectedCRS correctly.
> The operation factory catches via the DerivedCRS* cast and routes through createOperationsDerivedTo, so WGS84 → ProjectedCRS → derivedProjectedCRS chains already work when the CRS is constructed programmatically or from inline WKT.
>
> The gap, as I understand it, is purely in the database layer:
>
> 1. There is no derived_projected_crs table in proj.db / user.db
> 2. crs_view has no entry for this type, so authority-code lookup fails
> 3. createCoordinateReferenceSystem() has no dispatch for the type
> 4. createProjectedCRSEnd() throws a generic error if text_definition contains a DERIVEDPROJCRS WKT
>
> I my thought is to offer a fix that is additive and non-breaking:
> A new derived_projected_crs table (FK to projected_crs as base, consistent with ISO 19111's restriction that the base must be a ProjectedCRS);
> A new type “derived projected” in crs_view;
> A new createDerivedProjectedCRS() factory method;
> And a clearer error message, with the existing text_definition path pointing users to the new derived_projected_crs table.
>
> Use Cases (there may be others)
> * Polyhedral projections, where a face index is a necessary part of the coordinate — analogous to a UTM zone number.
> The intermediate ProjectedCRS could carry the ellipsoid relationship and the face identifier; the DerivedProjectedCRS consumes both and produces a globally unambiguous planar coordinate. PROJ already includes several polyhedral projections (ISEA, HEALPix) where this two-layer architecture might be the correct formal expression. Any future polyhedral work (such as my own project!) would benefit from the same foundation.
>
> * Datum-agnostic net/tile projections — a butterfly net derived from an octahedral CRS that is itself derived from ED50 rather than WGS84 is just a different base ProjectedCRS. The net definition doesn't change. Currently we are expected to register a separate CRS for each datum combination.
>
> * Rotated or recentred projections — a Transverse Mercator variant recentred on a local origin, expressed as derived from a standard TM ProjectedCRS, rather than as a fresh projection from the ellipsoid. The datum relationship is inherited, not repeated.
>
> In brief, and as I understand it, the ISO 19111:2019 defines DerivedProjectedCRS as a first-class CRS type, and PROJ's C++ object model reflects this faithfully. However without database registration support, the type cannot be used in the authority-code workflows that most users depend on — making it effectively unavailable in practice.
>
> I have started to compose a PR against master in order to close this gap, but I felt it wise to check in: is there anything architecturally that would make this unwelcome, or any prior discussion I should be aware of, or does the plan sound reasonable?
>
> === Affected files ===
> ** SQL (data/sql)
> proj_db_table_defs.sql : derived_projected_crs table; extend crs_view.
> consistency_checks_triggers.sql : Duplicate preventions (2) on crs_view, insert rejections (coordinate_system not found, base_crs not found)
>
> ** src/iso19111/factory.cpp
> Add #define DERIVED_PROJECTED "derived projected”
> Add functions to support DerivedProjectedCRS
> Modify createCoordinateReferenceSystem, createObject, createProjectedCRSEnd to support DerivedProjectedCRS
>
> ** Public API
> include/proj/io.hpp
> public `createDerivedProjectedCRS(const std::string &code)` on `AuthorityFactory`
>
> ** C API
> src/iso19111/c_api.cpp
> Wire authority-code lookup in `proj_create_derived_projected_crs()` to use `createDerivedProjectedCRS()`
>
> ** Tests
> test/unit/test_factory.cpp createDerivedProjectedCRS, createCoordinateReferenceSystem,
> `text_definition` : `projected_crs` containing `DERIVEDPROJCRS` WKT gives directed error
> `text_definition` in `derived_projected_crs` round-trips correctly
> `cs2cs`-equivalent pipeline resolves end-to-end for a registered `DerivedProjectedCRS`
>
> ** No change
> No need to modify the wkt2 grammar/parser, iso19111 io, operations, crs, or their test frameworks.
>
> Best regards
> -Ben
>
>
> _______________________________________________
> PROJ mailing list
> PROJ at lists.osgeo.org
> https://lists.osgeo.org/mailman/listinfo/proj
--
http://www.spatialys.com
My software is free, but my time generally not.
More information about the PROJ
mailing list