""" Geojson module parses geojson files and import the geometry into the city model structure SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project Coder Guillermo Gutierrez Guillermo.GutierrezMorote@concordia.ca """ import json import trimesh.creation from pyproj import Transformer from shapely.geometry import Polygon as ShapelyPolygon import helpers.constants as cte from city_model_structure.city import City from city_model_structure.attributes.polygon import Polygon from city_model_structure.building_demand.surface import Surface from city_model_structure.building import Building class Geojson: """ Geojson class """ def __init__(self, path, extrusion_height=None, year_of_construction=None, function=None): self._transformer = Transformer.from_crs('epsg:4326', 'epsg:26911') self._min_x = cte.MAX_FLOAT self._min_y = cte.MAX_FLOAT self._max_x = cte.MIN_FLOAT self._max_y = cte.MIN_FLOAT self._city = None self._extrusion_height = 0 if self._extrusion_height is not None: self._extrusion_height = extrusion_height self._year_of_construction = year_of_construction self._function = function with open(path) as json_file: self._geojson = json.loads(json_file.read()) def _save_bounds(self, x, y): print(x, y) if x > self._max_x: self._max_x = x if x < self._min_x: self._min_x = x if y > self._max_y: self._max_y = y if y < self._min_y: self._min_y = y @staticmethod def _create_building_lod0(name, year_of_construction, function, surfaces_coordinates): surfaces = [] for surface_coordinates in surfaces_coordinates: polygon = Polygon(surface_coordinates) surfaces.append(Surface(polygon, polygon)) Building(name, 0, surfaces, year_of_construction, function) @staticmethod def _create_building_lod1(name, year_of_construction, function, height, surfaces_coordinates): surfaces = [] for surface_coordinates in surfaces_coordinates: shapely_coordinates = [surface_coordinates[n:n + 3] for n in range(0, len(surface_coordinates), 3)] shapely_polygon = ShapelyPolygon(shapely_coordinates) mesh = trimesh.creation.extrude_polygon(shapely_polygon,height) for face in mesh.faces: points = [] for vertex_index in face: points.append(mesh.vertices[vertex_index]) polygon = Polygon(points) surface = Surface(polygon, polygon) surfaces.append(surface) Building(name, 1, surfaces, year_of_construction, function) @property def city(self) -> City: """ Get city out of a Geojson file """ if self._city is None: buildings = [] for feature in self._geojson['features']: extrusion_height = float(feature['properties'][self._extrusion_height]) year_of_construction = int(feature['properties'][self._year_of_construction]) function = feature['properties'][self._function] geometry = feature['geometry'] building_name = feature['id'] surfaces_coordinates = [] for coordinates_set in geometry['coordinates']: surface_coordinates = [] for coordinates in coordinates_set: print(coordinates) if type(coordinates[0]) != float: print(feature) coordinates[0], coordinates[1] = self._transformer.transform(coordinates[0], coordinates[1]) self._save_bounds(coordinates[0], coordinates[1]) surface_coordinates = surface_coordinates + coordinates + [0.0] surfaces_coordinates.append(surface_coordinates) # todo: create building if extrusion_height == 0: buildings.append(Geojson._create_building_lod0(building_name, year_of_construction, function, surfaces_coordinates)) else: buildings.append(Geojson._create_building_lod1(building_name, year_of_construction, function, extrusion_height, surfaces_coordinates)) return self._city