Custom extrusion and volume calculation for Geojson
This commit is contained in:
parent
f0a07d9c0e
commit
20b88fbccb
|
@ -34,6 +34,7 @@ class CityObject:
|
||||||
self._max_y = ConfigurationHelper().min_coordinate
|
self._max_y = ConfigurationHelper().min_coordinate
|
||||||
self._max_z = ConfigurationHelper().min_coordinate
|
self._max_z = ConfigurationHelper().min_coordinate
|
||||||
self._centroid = None
|
self._centroid = None
|
||||||
|
self._volume = None
|
||||||
self._external_temperature = dict()
|
self._external_temperature = dict()
|
||||||
self._global_horizontal = dict()
|
self._global_horizontal = dict()
|
||||||
self._diffuse = dict()
|
self._diffuse = dict()
|
||||||
|
@ -63,7 +64,13 @@ class CityObject:
|
||||||
Get city object volume in cubic meters
|
Get city object volume in cubic meters
|
||||||
:return: float
|
:return: float
|
||||||
"""
|
"""
|
||||||
return self.simplified_polyhedron.volume
|
if self._volume is None:
|
||||||
|
self._volume = self.simplified_polyhedron.volume
|
||||||
|
return self._volume
|
||||||
|
|
||||||
|
@volume.setter
|
||||||
|
def volume(self, value):
|
||||||
|
self._volume = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def detailed_polyhedron(self) -> Polyhedron:
|
def detailed_polyhedron(self) -> Polyhedron:
|
||||||
|
|
|
@ -6,6 +6,7 @@ Project Coder Guillermo Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
import trimesh.creation
|
import trimesh.creation
|
||||||
|
|
||||||
from pyproj import Transformer
|
from pyproj import Transformer
|
||||||
|
@ -64,8 +65,10 @@ class Geojson:
|
||||||
buildings = []
|
buildings = []
|
||||||
for zone, surface_coordinates in enumerate(surfaces_coordinates):
|
for zone, surface_coordinates in enumerate(surfaces_coordinates):
|
||||||
points = igh.points_from_string(igh.remove_last_point_from_string(surface_coordinates))
|
points = igh.points_from_string(igh.remove_last_point_from_string(surface_coordinates))
|
||||||
|
# geojson provides the roofs, need to be transform into grounds
|
||||||
|
points = igh.invert_points(points)
|
||||||
polygon = Polygon(points)
|
polygon = Polygon(points)
|
||||||
surfaces.append(Surface(polygon, polygon, surface_type=cte.GROUND))
|
surfaces.append(Surface(polygon, polygon))
|
||||||
buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function))
|
buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function))
|
||||||
return buildings
|
return buildings
|
||||||
|
|
||||||
|
@ -74,22 +77,41 @@ class Geojson:
|
||||||
lod0_buildings = Geojson._create_buildings_lod0(name, year_of_construction, function, surface_coordinates)
|
lod0_buildings = Geojson._create_buildings_lod0(name, year_of_construction, function, surface_coordinates)
|
||||||
surfaces = []
|
surfaces = []
|
||||||
buildings = []
|
buildings = []
|
||||||
|
|
||||||
for zone, lod0_building in enumerate(lod0_buildings):
|
for zone, lod0_building in enumerate(lod0_buildings):
|
||||||
for surface in lod0_building.surfaces:
|
for surface in lod0_building.grounds:
|
||||||
shapely_polygon = ShapelyPolygon(surface.solid_polygon.coordinates)
|
volume = surface.solid_polygon.area * height
|
||||||
if not shapely_polygon.is_valid:
|
|
||||||
print(surface.solid_polygon.area)
|
|
||||||
print('error?', name, surface_coordinates)
|
|
||||||
continue
|
|
||||||
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)
|
surfaces.append(surface)
|
||||||
buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function))
|
roof_coordinates = []
|
||||||
|
# adding a roof means invert the polygon coordinates and change the Z value
|
||||||
|
for coordinate in surface.solid_polygon.coordinates:
|
||||||
|
roof_coordinate = np.array([coordinate[0], coordinate[1], height])
|
||||||
|
# insert the roof rotated already
|
||||||
|
roof_coordinates.insert(0, roof_coordinate)
|
||||||
|
polygon = Polygon(roof_coordinates)
|
||||||
|
roof = Surface(polygon, polygon)
|
||||||
|
surfaces.append(roof)
|
||||||
|
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
|
||||||
|
coordinates_length = len(roof.solid_polygon.coordinates)
|
||||||
|
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
|
||||||
|
j = i + 1
|
||||||
|
if j == coordinates_length:
|
||||||
|
j = 0
|
||||||
|
next_coordinate = roof.solid_polygon.coordinates[j]
|
||||||
|
wall_coordinates = [
|
||||||
|
np.array([coordinate[0], coordinate[1], 0.0]),
|
||||||
|
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
|
||||||
|
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
|
||||||
|
np.array([coordinate[0], coordinate[1], coordinate[2]])
|
||||||
|
]
|
||||||
|
polygon = Polygon(wall_coordinates)
|
||||||
|
wall = Surface(polygon, polygon)
|
||||||
|
surfaces.append(wall)
|
||||||
|
|
||||||
|
building = Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function)
|
||||||
|
building.volume = volume
|
||||||
|
buildings.append(building)
|
||||||
|
|
||||||
return buildings
|
return buildings
|
||||||
|
|
||||||
def _get_polygons(self, polygons, coordinates):
|
def _get_polygons(self, polygons, coordinates):
|
||||||
|
@ -119,6 +141,8 @@ class Geojson:
|
||||||
|
|
||||||
def _store_shared_percentage_to_walls(self, city, city_mapped):
|
def _store_shared_percentage_to_walls(self, city, city_mapped):
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
|
if building.name not in city_mapped.keys():
|
||||||
|
continue
|
||||||
building_mapped = city_mapped[building.name]
|
building_mapped = city_mapped[building.name]
|
||||||
for wall in building.walls:
|
for wall in building.walls:
|
||||||
percentage = 0
|
percentage = 0
|
||||||
|
@ -207,7 +231,7 @@ class Geojson:
|
||||||
self._city.add_city_object(building)
|
self._city.add_city_object(building)
|
||||||
self._city.level_of_detail.geometry = lod
|
self._city.level_of_detail.geometry = lod
|
||||||
if lod == 1:
|
if lod == 1:
|
||||||
lines_information = GeometryHelper.city_mapping(self._city)
|
lines_information = GeometryHelper.city_mapping(self._city, plot=True)
|
||||||
self._store_shared_percentage_to_walls(self._city, lines_information)
|
self._store_shared_percentage_to_walls(self._city, lines_information)
|
||||||
if len(missing_functions) > 0:
|
if len(missing_functions) > 0:
|
||||||
print(f'There are unknown functions {missing_functions}')
|
print(f'There are unknown functions {missing_functions}')
|
||||||
|
|
|
@ -45,3 +45,10 @@ class GeometryHelper:
|
||||||
array = points.split(' ')
|
array = points.split(' ')
|
||||||
res = " "
|
res = " "
|
||||||
return res.join(array[0:len(array) - 3])
|
return res.join(array[0:len(array) - 3])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def invert_points(points):
|
||||||
|
res = []
|
||||||
|
for point in points:
|
||||||
|
res.insert(0,point)
|
||||||
|
return res
|
||||||
|
|
|
@ -132,13 +132,14 @@ class TestGeometryFactory(TestCase):
|
||||||
"""
|
"""
|
||||||
Test geojson import
|
Test geojson import
|
||||||
"""
|
"""
|
||||||
file = 'neighbours.geojson'
|
file = 'concordia.geojson'
|
||||||
city = self._get_city(file, 'geojson',
|
city = self._get_city(file, 'geojson',
|
||||||
height_field='citygml_me',
|
height_field='citygml_me',
|
||||||
year_of_construction_field='ANNEE_CONS',
|
year_of_construction_field='ANNEE_CONS',
|
||||||
function_field='CODE_UTILI')
|
function_field='CODE_UTILI')
|
||||||
|
|
||||||
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
|
for building in city.buildings:
|
||||||
|
print(building.volume)
|
||||||
self.assertEqual(207, len(city.buildings), 'wrong number of buildings')
|
self.assertEqual(207, len(city.buildings), 'wrong number of buildings')
|
||||||
self._check_buildings(city)
|
self._check_buildings(city)
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
|
@ -150,13 +151,21 @@ class TestGeometryFactory(TestCase):
|
||||||
Test neighbours map creation
|
Test neighbours map creation
|
||||||
"""
|
"""
|
||||||
file = 'neighbours.geojson'
|
file = 'neighbours.geojson'
|
||||||
|
city = self._get_city(file, 'geojson',
|
||||||
|
year_of_construction_field='ANNEE_CONS',
|
||||||
|
function_field='LIBELLE_UT')
|
||||||
|
info_lod0 = GeometryHelper.city_mapping(city, plot=False)
|
||||||
|
|
||||||
city = self._get_city(file, 'geojson',
|
city = self._get_city(file, 'geojson',
|
||||||
height_field='citygml_me',
|
height_field='citygml_me',
|
||||||
year_of_construction_field='ANNEE_CONS',
|
year_of_construction_field='ANNEE_CONS',
|
||||||
function_field='LIBELLE_UT')
|
function_field='LIBELLE_UT')
|
||||||
print(GeometryHelper.city_mapping(city, plot=True))
|
info_lod1 = GeometryHelper.city_mapping(city, plot=False)
|
||||||
|
|
||||||
|
self.assertEqual(info_lod0, info_lod1)
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
self.assertEqual(2, len(building.neighbours))
|
self.assertEqual(2, len(building.neighbours))
|
||||||
|
print(building.volume)
|
||||||
|
|
||||||
self.assertEqual('2_part_0_zone_0',city.city_object('1_part_0_zone_0').neighbours[0].name)
|
self.assertEqual('2_part_0_zone_0',city.city_object('1_part_0_zone_0').neighbours[0].name)
|
||||||
self.assertEqual('3_part_0_zone_0',city.city_object('1_part_0_zone_0').neighbours[1].name)
|
self.assertEqual('3_part_0_zone_0',city.city_object('1_part_0_zone_0').neighbours[1].name)
|
||||||
|
|
|
@ -12,18 +12,18 @@
|
||||||
-73.580414175680588,
|
-73.580414175680588,
|
||||||
45.497641136608358
|
45.497641136608358
|
||||||
],
|
],
|
||||||
[
|
|
||||||
-73.581414175680588,
|
|
||||||
45.497641136608358
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-73.581414175680588,
|
|
||||||
45.498641136608358
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
-73.580414175680588,
|
-73.580414175680588,
|
||||||
45.498641136608358
|
45.498641136608358
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
-73.581414175680588,
|
||||||
|
45.498641136608358
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-73.581414175680588,
|
||||||
|
45.497641136608358
|
||||||
|
],
|
||||||
[
|
[
|
||||||
-73.580414175680588,
|
-73.580414175680588,
|
||||||
45.497641136608358
|
45.497641136608358
|
||||||
|
@ -204,19 +204,20 @@
|
||||||
[
|
[
|
||||||
-73.581414175680588,
|
-73.581414175680588,
|
||||||
45.497641136608358
|
45.497641136608358
|
||||||
|
]
|
||||||
|
,
|
||||||
|
[
|
||||||
|
-73.581414175680588,
|
||||||
|
45.498441136608358
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-73.582214175680588,
|
||||||
|
45.498441136608358
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
-73.582214175680588,
|
-73.582214175680588,
|
||||||
45.497641136608358
|
45.497641136608358
|
||||||
],
|
],
|
||||||
[
|
|
||||||
-73.582214175680588,
|
|
||||||
45.498441136608358
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-73.581414175680588,
|
|
||||||
45.498441136608358
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
-73.581414175680588,
|
-73.581414175680588,
|
||||||
45.497641136608358
|
45.497641136608358
|
||||||
|
@ -399,31 +400,30 @@
|
||||||
-73.581914175680588,
|
-73.581914175680588,
|
||||||
45.498441136608358
|
45.498441136608358
|
||||||
],
|
],
|
||||||
[
|
|
||||||
-73.581914175680588,
|
|
||||||
45.499641136608358
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-73.580914175680588,
|
|
||||||
45.499641136608358
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-73.580914175680588,
|
|
||||||
45.498641136608358
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-73.581414175680588,
|
|
||||||
45.498641136608358
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
-73.581414175680588,
|
-73.581414175680588,
|
||||||
45.498441136608358
|
45.498441136608358
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
-73.581414175680588,
|
||||||
|
45.498641136608358
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-73.580914175680588,
|
||||||
|
45.498641136608358
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-73.580914175680588,
|
||||||
|
45.499641136608358
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-73.581914175680588,
|
||||||
|
45.499641136608358
|
||||||
|
],
|
||||||
[
|
[
|
||||||
-73.581914175680588,
|
-73.581914175680588,
|
||||||
45.498441136608358
|
45.498441136608358
|
||||||
]
|
]
|
||||||
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user