[PROJ] DerivedProjectedCRS — database support gap and proposed PR
Ben Griffin
ben at redsnapper.net
Fri Mar 27 04:13:02 PDT 2026
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
More information about the PROJ
mailing list