system_assignation/imports/geometry/geojson.py

112 lines
4.3 KiB
Python

"""
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