forked from s_ranjbar/city_retrofit
112 lines
4.3 KiB
Python
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
|
|
|