[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