partial geojson implementation

This commit is contained in:
Guille Gutierrez 2022-11-17 15:56:49 -05:00
parent c090fd8025
commit 13fa69b438
3 changed files with 123 additions and 0 deletions

View File

@ -64,6 +64,9 @@ class CityGml:
self._upper_corner = np.fromstring(envelope['upperCorner'], dtype=float, sep=' ')
if '@srsName' in envelope:
self._srs_name = envelope['@srsName']
else:
# If not coordinate system given assuming hub standard
self._srs_name = "EPSG:4326"
else:
# get the boundary from the city objects instead
for city_object_member in self._gml['CityModel']['cityObjectMember']:

110
imports/geometry/geojson.py Normal file
View File

@ -0,0 +1,110 @@
"""
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 trimesh
import trimesh.exchange.load
import trimesh.geometry
import trimesh.creation
import trimesh.repair
from shapely.geometry import Point
from shapely.geometry import Polygon as ShapelyPoly
from trimesh import Scene
from city_model_structure.attributes.polygon import Polygon
from city_model_structure.building import Building
from city_model_structure.building_demand.surface import Surface
from city_model_structure.city import City
import helpers.constants as cte
class Geojson:
"""
GeoPandas class
"""
def __init__(self, path):
"""
"""
self._srs_name = srs_name
self._city = None
self._scene = dataframe
self._scene = self._scene.to_crs(self._srs_name)
min_x, min_y, max_x, max_y = self._scene.total_bounds
self._lower_corner = [min_x, min_y, 0]
self._upper_corner = [max_x, max_y, 0]
@property
def scene(self) -> Scene:
"""
Get GeoPandas scene
"""
return self._scene
@property
def city(self) -> City:
"""
Get city out of a GeoPandas Table
"""
if self._city is None:
self._city = City(self._lower_corner, self._upper_corner, self._srs_name)
for scene_index, bldg in self._scene.iterrows():
geom = bldg.geom
polygon = ShapelyPoly(geom['coordinates'][0])
height = float(bldg['height_mean'])
building_mesh = trimesh.creation.extrude_polygon(polygon, height)
trimesh.repair.fill_holes(building_mesh)
trimesh.repair.fix_winding(building_mesh)
year_of_construction = int(bldg['year_built'])
name = str(scene_index)
lod = 1
if year_of_construction > 2000:
function = cte.RESIDENTIAL
else:
function = cte.INDUSTRY
surfaces = []
for face_index, face in enumerate(building_mesh.faces):
points = []
for vertex_index in face:
points.append(building_mesh.vertices[vertex_index])
solid_polygon = Polygon(points)
perimeter_polygon = solid_polygon
surface = Surface(solid_polygon, perimeter_polygon)
surfaces.append(surface)
building = Building(name, lod, surfaces, year_of_construction, function, self._lower_corner, terrains=None)
self._city.add_city_object(building)
return self._city
@staticmethod
def resize_polygon(poly, factor=0.10, expand=False) -> ShapelyPoly:
"""
returns the shapely polygon which is smaller or bigger by passed factor.
Arguments:
poly {shapely.geometry.Polygon} -- an input geometry in shapely polygon format
Keyword Arguments:
factor {float} -- factor of expansion (default: {0.10})
expand {bool} -- If expand = True , then it returns bigger polygon, else smaller (default: {False})
Returns:
{shapely.geometry.Polygon} -- output geometry in shapely polygon format
"""
xs = list(poly.exterior.coords.xy[0])
ys = list(poly.exterior.coords.xy[1])
x_center = 0.5 * min(xs) + 0.5 * max(xs)
y_center = 0.5 * min(ys) + 0.5 * max(ys)
min_corner = Point(min(xs), min(ys))
center = Point(x_center, y_center)
shrink_distance = center.distance(min_corner) * factor
if expand:
poly_resized = poly.buffer(shrink_distance) # expand
else:
poly_resized = poly.buffer(-shrink_distance) # shrink
return poly_resized

View File

@ -48,6 +48,16 @@ class GeometryFactory:
self._data_frame = geopandas.read_file(self._path)
return GPandas(self._data_frame).city
@property
def _geojson(self) -> City:
"""
Enrich the city by using Geojson information as data source
:return: City
"""
if self._data_frame is None:
self._data_frame = geopandas.read_file(self._path)
return Geojson(self._data_frame).city
@property
def _osm_subway(self) -> City:
"""