To create a new CityJSON model from scratch using the cjio Python API, follow a hierarchical pattern:
- Initialize a
CityJSON model: Create an empty container using cityjson.CityJSON(). - Create
CityObject instances: Instantiate CityObject(id='...'). An id is required. You can assign attributes via the .attributes dictionary. - Define
Geometry: Instantiate Geometry(type='...', lod=...). Note that for CityJSON 1.0.0, lod must be a numeric value, not a string. - Build Boundaries: Define the geometric shape by appending boundary lists to
geom.boundaries. - Define Semantic Surfaces: Map boundary indices to surface types (e.g.,
WallSurface, GroundSurface, RoofSurface) using the geom.surfaces dictionary. - Assemble: Append the
Geometry to the CityObject, and add the CityObject to the CityJSON model using cm.cityobjects[co.id] = co. - Finalize and Save: Before saving, you must index the geometry and update the model using
cm.reference_geometry() and cm.add_to_j(). Finally, use cityjson.save(cm, outfile) to write the file.
from cjio import cityjson
from cjio.models import CityObject, Geometry
# 1. Create empty model
cm = cityjson.CityJSON()
# 2. Create CityObject
co = CityObject(id='1')
co.attributes = {'some_attribute': 42}
co.type = 'Building'
# 3. Create Geometry
geom = Geometry(type='Solid', lod=2)
# 4. Add boundaries (example: a simple list of polygons)
bdry = [[[(0.0, 0.0, 0.0), (10.0, 0.0, 0.0), (10.0, 0.0, 10.0), (0.0, 0.0, 10.0)]]]
geom.boundaries.append(bdry)
# 5. Define Semantic Surfaces
# surface_idx format for Solid: [Shell index, Surface index]
geom.surfaces[0] = {'surface_idx': [[0, 0]], 'type': 'WallSurface'}
# 6. Assemble
co.geometry.append(geom)
cm.cityobjects[co.id] = co
# 7. Finalize and Save
cityobjects, vertex_lookup = cm.reference_geometry()
cm.add_to_j(cityobjects, vertex_lookup)
cm.update_bbox()
cityjson.save(cm, 'output.json')