Skip to content
CityParquet is v0.1.0-draft — the specification is still changing.
Esc
↑↓navigate↵open⌘Jpreview
On this page

Mapping from CityGML / CityJSON

The reference mapping from CityGML and CityJSON / CityJSONSeq into CityParquet.

This page is the converter reference: how a source model’s fields land in the CityParquet object table, sidecars, and metadata. It is informative — the normative rules live in the specification body — but every row here points at the section that governs it.

CityGML

CityGML features map to CityParquet object rows directly, since CityParquet encodes the CityGML conceptual model:

CityGML CityParquet
feature id id
feature class object_type — the CityGML class name verbatim; an ADE class carries its extension namespace as a prefix
feature hierarchy parents / children / feature_id
feature attributes inferred typed attribute columns
geometry, per LoD WKB geometry_lod*
boundary surfaces and their attributes geometry_properties_lod* (surfaces + face_semantics)
appearance (surface data) material_lod* / texture_lod* + sidecars
implicit geometry (ImplicitGeometry) implicit_geometry struct (reference point, transformation matrix) + the relative geometry in implicit_geometries.parquet
address the address column
CityObjectGroup + its members the group is a row (in generics.parquet); membership is carried by children / children_roles / parents, a member referenced by xlink:href staying a feature of its own — no dedicated file
ADE feature types / attributes extension rules

3DCityDB’s normalised relational schema is not reproduced: its property, appearance, surface-data and implicit-geometry tables become nullable object-table columns plus sidecar files (rationale: the schema-strategy decisions). The one place CityParquet borrows 3DCityDB’s shape deliberately is the address struct, whose fields follow its ADDRESS table.

CityJSON / CityJSONSeq

CityJSON field CityParquet mapping
CityObjects.{id} id
CityObjects.{id}.type object_type — mapped to the CityGML class name (TransportSquare→Square, GenericCityObject→GenericOccupiedSpace, BuildingStorey→Storey, TunnelHollowSpace→HollowSpace; others unchanged); an extension type carries its namespace prefix in place of the + (+ThermalZone→energy_ThermalZone)
attributes inferred typed attribute columns; an extension attribute carries its namespace prefix in place of the + (+heatCapacity→energy_heatCapacity)
children / parents / children_roles same-named columns
address the address column; address[].location becomes a WKB MultiPointZ
geometry[].boundaries encoded into WKB geometry_lod*
geometry[].lod the column’s LoD suffix (lod2_2); exact source spelling not separately retained
geometry[].semantics geometry_properties_lod* — surfaces verbatim except that an extension surface type carries its namespace prefix (+PartyWallSurface→energy_PartyWallSurface), values flattened to face_semantics
geometry[] shell nesting geometry_properties_lod*.shells
geometry[].material material_lod* for the geometry’s LoD — one map entry per theme, values flattened to one sidecar id per WKB face, a whole-geometry value expanded per face
geometry[].texture texture_lod* for the geometry’s LoD — one map entry per theme, values flattened per WKB face, each ring’s texture index and UV indices resolved to {id, uv}
geometry[].template implicit_geometry.id
geometry[].transformationMatrix implicit_geometry.transformationMatrix
geometry instance reference point implicit_geometry.point as WKB PointZ
CityObjects.{id}.geographicalExtent bbox (unioned with the extent computed from the object’s subtree geometry; reconstructed from bbox on export)
appearance.materials materials.parquet
appearance.textures textures.parquet
appearance.vertices-texture resolved into the uv pairs of texture_lod*; no UV pool is stored
geometry-templates.templates implicit_geometries.parquet, one row per template (the relative geometry)
geometry-templates.vertices-templates encoded into the relative geometry’s WKB in implicit_geometries.parquet
metadata city.other and/or the STAC Item’s city3d:* fields
transform applied to the geometry at encode; not a structural key — MAY be carried informationally in city.other
extensions the city.extensions metadata key, keyed by the namespace derived from each member key ("Energy"→energy), with its url and version; the member key becomes name
other object members the object-table other column, restored into attributes on export (JSON; null when the object has none)

Example: one feature, end to end

Constructed. A Building with one BuildingPart. The part has an LoD 2.2 Solid of two faces, a roof and a wall, both of material 3. The building carries a core attribute and an attribute of the Energy ADE, the one extension the source declares. Coordinates are elided, and the solid is cut to two faces to keep the rows short.

{ "type": "CityJSON", "version": "2.0", "transform": { /* … */ },
  "extensions": { "Energy": { "url": "https://…/energy.ext.json", "version": "3.0" } },
  "CityObjects": {}, "vertices": [] }

{ "type": "CityJSONFeature", "id": "b-42",
  "CityObjects": {
    "b-42":   { "type": "Building", "children": ["b-42-0"],
                "attributes": { "yearOfConstruction": 1998, "+heatCapacity": 120000.0 } },
    "b-42-0": { "type": "BuildingPart", "parents": ["b-42"],
                "geometry": [ { "type": "Solid", "lod": "2.2",
                  "boundaries": [ [ [[0,1,2,3]], [[4,5,6,7]] ] ],
                  "semantics": { "surfaces": [ {"type":"RoofSurface"}, {"type":"WallSurface"} ],
                                 "values": [ [0, 1] ] },
                  "material": { "": { "values": [ [3, 3] ] } } } ] } },
  "vertices": [ /* … */ ] }

The two objects become two rows of building.parquet:

id feature_id object_type parents children geometry_lod2_2 geometry_properties_lod2_2 material_lod2_2 energy_heatCapacity yearOfConstruction
b-42 b-42 Building — [b-42-0] null null null 120000.0 1998
b-42-0 b-42 BuildingPart [b-42] — WKB PolyhedralSurfaceZ (2 faces) {type:"Solid", surfaces:[…], face_semantics:[0,1], shells:[[2]]} {"": [3, 3]} null null

What the mapping did, row by row of the tables above:

  • b-42 is a root, so its feature_id is its own id, and the part inherits it.
  • The attributes stay on the Building row. yearOfConstruction is inferred BIGINT; +heatCapacity becomes energy_heatCapacity, inferred DOUBLE, and the header’s extensions member becomes city.extensions keyed by energy (see the extensions example).
  • The boundaries are resolved against vertices and the transform into world-coordinate WKB, so the source quantisation is not kept. The solid’s two faces become a two-face PolyhedralSurfaceZ.
  • The per-shell semantics.values [[0, 1]] becomes the per-face face_semantics [0, 1], and the shell partition moves to shells: [[2]]. The LoD 2.2 lives only in the column suffix.
  • The per-shell material.values [[3, 3]] becomes the per-face [3, 3] under the unnamed theme "", and the feature-local index becomes a materials.parquet id.
  • The Building has no geometry of its own, so its bbox is its part’s.

Last updated on October 14, 2026

Was this page helpful?