Skip to content

Positions in reference systems beside the native CRS#577

Open
cportele wants to merge 4 commits into
masterfrom
tmp2
Open

Positions in reference systems beside the native CRS#577
cportele wants to merge 4 commits into
masterfrom
tmp2

Conversation

@cportele

Copy link
Copy Markdown
Contributor

Part of addressing ldproxy/ldproxy#1692

Adds support for feature types that store geometries in one of several CRSs.

  • FeatureSchema: a variants declaration on the primary geometry property groups the sibling properties that store a position as recorded; new roles ORIGINAL_GEOMETRY, ORIGINAL_HEIGHT and ORIGINAL_CRS_IDENTIFIER identify the group members and make them internal (readable, but not part of any public schema or regular encoding). Variant properties declare the identifiers of their reference systems (originalCrsIdentifiers), the CRS they are stored in (nativeCrs), the CRS of the recorded positions (originalCrs) and, where needed, a falseEastingDifference.
  • GML decoder: positions are routed by their verbatim srsName to the matching variant property (1D positions as scalars, the identifier stored verbatim); the read pipeline restores originalCrs so encodings receive the recorded positions.
  • Write path: geometries are transformed to the per-property storage CRS.
  • EpsgCrs: new auxiliary alternativeUri for community URIs of a CRS.
  • Collection extents are computed from the primary geometry only.

Also extends the GML decoder for ISO 19139 metadata structures on the wire (value-wrapper chains with attributes and empty elements, xsi:type on wrapper elements), so documents shaped like the encoder's output can be ingested losslessly.

cportele added 4 commits July 14, 2026 17:42
The wire form of an ISO 19139 quantitative result types the anyType
value element via xsi:type (<gco:Record xsi:type="gml:doubleList">) and
carries an empty valueUnit sibling. The decoder rejected any xsi:type;
inside a value-wrap chain the attribute types the content of a value
element rather than substituting a schema type, so it is now tolerated
and dropped there. xsi:type on schema-mapped elements (feature, object
and property elements) remains rejected.

- FeatureTokenDecoderGml: exempt value-wrap chain elements from
  rejectXsiType via the new isValueWrapChainElement, which also
  replaces the equivalent inline condition for pushing VALUE_WRAPPER
  frames
- FeatureTokenDecoderGmlSpec: cover the full genauigkeitswert
  structure including xsi:type and the empty valueUnit element
Some application schemas (e.g. AX_PunktortAU in the German
AFIS-ALKIS-ATKIS NAS schema) carry exactly one position per feature,
but in one of several CRSs - including realizations that map to the
same EPSG code, 1D vertical reference systems, and coordinate forms
whose false easting differs from the CRS definition (Gauss-Krueger
without the zone prefix). Each variant is stored in its own geometry
property with its own storage CRS; the verbatim srsName is stored
alongside so encoders can reproduce it.

- SchemaBase/FeatureSchema: new `crs` option - the storage CRS of a
  geometry property, overriding the provider's nativeCrs
- features-sql: the storage CRS travels as the WKT/WKB operation
  parameters (code, axis-order force); geometry writes route by
  property path, transform from the geometry's CRS to the column's
  storage CRS and emit the column's SRID (inserts and native updates)
- FeatureTokenTransformerCoordinates: geometries with their own
  storage CRS pass through the request-CRS transformation untouched
- geometries: EastingShift coordinates transformation - adds a
  constant to the easting, rounded to micrometres; converts between
  coordinate forms that differ only in the false easting
- gml decoder: GmlGeometryVariants routing on the input profile - a
  position is routed by its verbatim srsName to a variant property
  (with a configured false-easting difference applied) or, for 1D
  vertical reference systems, captured as a scalar value at a FLOAT
  property; the verbatim srsName is emitted at a companion property;
  GeometryDecoderGml exposes the verbatim srsName and consumes 1D
  positions without building a Geometry
The mutation stats collector fed every geometry token into the spatial
extent of the change events, interpreting position variants stored in
a different CRS as native coordinates. Only the primary geometry now
contributes, mirroring the read side, which computes the extent over
the filter/primary geometry column. Also accumulate min/max across
geometries instead of keeping only the last one.
- FeatureSchema: a 'variants' declaration on the primary geometry
  property groups the sibling properties that store the position as
  recorded (crsProperty, verticalProperty, geometryProperties); the new
  roles ORIGINAL_GEOMETRY, ORIGINAL_HEIGHT and ORIGINAL_CRS_IDENTIFIER
  identify the group members (implied when not declared) and make them
  internal: read from the data source, but excluded from queryables,
  sortables, public schemas and regular property encoding
- variant properties declare the identifiers of their reference systems
  (originalCrsIdentifiers), the CRS they are stored in (nativeCrs), the
  CRS of the recorded positions (originalCrs, e.g. the authority axis
  order of a geographic CRS whose stored coordinates follow the GIS
  axis order) and a falseEastingDifference for identifiers whose
  coordinates use a different false easting than the CRS
- VariantsResolver validates the declarations and sets the implied
  roles at provider start
- GML decoder: a position is routed by its verbatim srsName to the
  variant property that lists the identifier, interpreted in
  originalCrs and shifted to conform to nativeCrs; a 1D vertical
  position is captured as a scalar at the vertical property; the
  srsName is stored verbatim at the crsProperty; the routing metadata
  moved from the decoder input profile into the schema
- the read pipeline restores originalCrs so downstream encodings
  receive the positions as recorded
- EpsgCrs: new auxiliary attribute alternativeUri declares an
  identifier under which a CRS is known in a community, used when
  rendering and decoding CRS identifiers on the wire
- new WithoutInternal visitor for deriving public schemas
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant