Skip to content

cj_loader

Scripts to load CityJSON files.

Classes:

Name Description
CityjsonLoader

Utility CityJSON loader that extracts all data from a CityJSON file and transforms the integer coordinates to their real coordinates.

Functions:

Name Description
cj_object_to_mesh

Build the Trimesh representation of the geometry, based on a full CityJSON object.

CityjsonLoader

Utility CityJSON loader that extracts all data from a CityJSON file and transforms the integer coordinates to their real coordinates.

Source code in python/src/data_pipeline/cj_loading/cj_loader.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
class CityjsonLoader:
    """
    Utility CityJSON loader that extracts all data from a CityJSON file and transforms the integer coordinates to their real coordinates.
    """

    def __init__(self, cj_path: Path) -> None:
        self.path = cj_path

        self.data = self._cj_load()
        self.vertices = self._cj_extract_vertices()

    def _cj_load(self) -> dict[str, Any]:
        """
        Load the whole file.

        Returns
        -------
        dict[str, Any]
            The CityJSON file directly as a dictionary.
        """
        with open(self.path) as cj_file:
            cj_data = json.load(cj_file)

        return cj_data

    def _cj_extract_vertices(self) -> NDArray[np.float64]:
        """
        Extract and transforms the vertices to their real coordinates.

        Returns
        -------
        NDArray[np.float64]
            The array (N, 3) of vertices coordinates.
        """
        normalised_vertices = np.array(self.data["vertices"], dtype=np.float64)
        translate = np.array(self.data["transform"]["translate"], dtype=np.float64)
        scale = np.array(self.data["transform"]["scale"], dtype=np.float64)
        vertices = scale * normalised_vertices + translate
        return vertices

cj_object_to_mesh(obj_dict, vertices)

Build the Trimesh representation of the geometry, based on a full CityJSON object. All the LoDs are created and returned.

Parameters:

Name Type Description Default
obj_dict dict[str, typing.Any]

The full CityJSON object as stored in the file. In particular, the geometry with potentally multiple LoDs is expected to be stored in "geometry".

required
vertices numpy.typing.NDArray[numpy.float64]

The array (N,3) of the vertices coordinates, that the geometry refers to.

required

Returns:

Type Description
dict[str, trimesh.Trimesh] | None

A dictionary mapping the LoD to its Trimesh representation.

Raises:

Type Description
NotImplementedError

If the geometry is not one of the supported geometry types.

Source code in python/src/data_pipeline/cj_loading/cj_loader.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
def cj_object_to_mesh(
    obj_dict: dict[str, Any], vertices: NDArray[np.float64]
) -> dict[str, trimesh.Trimesh] | None:
    """
    Build the Trimesh representation of the geometry, based on a full CityJSON object.
    All the LoDs are created and returned.

    Parameters
    ----------
    obj_dict : dict[str, Any]
        The full CityJSON object as stored in the file.
        In particular, the geometry with potentally multiple LoDs is expected to be stored in "geometry".
    vertices : NDArray[np.float64]
        The array (N,3) of the vertices coordinates, that the geometry refers to.

    Returns
    -------
    dict[str, trimesh.Trimesh] | None
        A dictionary mapping the LoD to its Trimesh representation.

    Raises
    ------
    NotImplementedError
        If the geometry is not one of the supported geometry types.
    """

    # Return None if there is no geometry
    if "geometry" not in obj_dict or len(obj_dict["geometry"]) == 0:
        return None

    # CityObjects may contain several geometry entries (different LoDs)
    meshes_lods = {}
    for geom in obj_dict["geometry"]:
        lod = geom["lod"]
        geom_type = geom["type"]
        boundaries = geom["boundaries"]
        if geom_type == "MultiSurface":
            mesh = _cj_multisurface_to_mesh(
                boundaries=boundaries,
                vertices=vertices,
            )
        elif geom_type == "Solid":
            mesh = _cj_solid_to_mesh(
                boundaries=boundaries,
                vertices=vertices,
            )
        else:
            raise NotImplementedError(f"Unexpected geometry type: '{geom_type}'")
        meshes_lods[lod] = mesh

    return meshes_lods