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-42is a root, so itsfeature_idis its ownid, and the part inherits it.- The attributes stay on the
Buildingrow.yearOfConstructionis inferredBIGINT;+heatCapacitybecomesenergy_heatCapacity, inferredDOUBLE, and the header’sextensionsmember becomescity.extensionskeyed byenergy(see the extensions example). - The
boundariesare resolved againstverticesand thetransforminto world-coordinate WKB, so the source quantisation is not kept. The solid’s two faces become a two-facePolyhedralSurfaceZ. - The per-shell
semantics.values[[0, 1]]becomes the per-faceface_semantics[0, 1], and the shell partition moves toshells: [[2]]. The LoD2.2lives 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 amaterials.parquetid. - The
Buildinghas no geometry of its own, so itsbboxis its part’s.