testing building separation in storeys with the new configuration of geometry using polygons and polyhedrons (NOT working yet).

This commit is contained in:
Pilar 2021-03-25 09:11:42 -04:00
parent dbbe3d56fc
commit 9a40cfa54b
8 changed files with 109 additions and 39 deletions

View File

@ -376,8 +376,7 @@ class Polyhedron:
self._max_z = ConfigurationHelper().min_coordinate
for polygon in self._polygons:
for point in polygon.points:
if self._max_z < point[2]:
self._max_z = point[2]
self._max_z = max(self._max_z, point[2])
return self._max_z
@property
@ -450,15 +449,14 @@ class Polyhedron:
return self._min_x
@property
def center(self):
def centroid(self):
"""
Polyhedron centroid
:return: [x,y,z]
"""
x = (self.max_x + self.min_x) / 2
y = (self.max_y + self.min_y) / 2
z = (self.max_z + self.min_z) / 2
return [x, y, z]
if self._centroid is None:
self._centroid = self.trimesh.centroid
return self._centroid
def stl_export(self, full_path):
"""

View File

@ -14,6 +14,9 @@ from city_model_structure.attributes.thermal_zone import ThermalZone
from city_model_structure.attributes.usage_zone import UsageZone
from city_model_structure.city_object import CityObject
from helpers.geometry_helper import GeometryHelper as gh
from helpers.configuration_helper import ConfigurationHelper
import math
from pathlib import Path
class Building(CityObject):
@ -21,15 +24,14 @@ class Building(CityObject):
Building(CityObject) class
"""
def __init__(self, name, lod, surfaces, terrains, year_of_construction, function, city_lower_corner):
# todo: take the default values out of the classes!!
super().__init__(lod, surfaces, name)
self._basement_heated = None
self._attic_heated = None
self._terrains = terrains
self._year_of_construction = year_of_construction
self._function = function
#todo: change lower_corner to building lower_corner instead city lower corner
self._lower_corner = city_lower_corner
self._city_lower_corner = city_lower_corner
self._building_lower_corner = None
self._heated = None
self._cooled = None
self._average_storey_height = None
@ -43,6 +45,10 @@ class Building(CityObject):
self._global_horizontal = dict()
self._diffuse = dict()
self._beam = dict()
self._min_x = ConfigurationHelper().max_coordinate
self._min_y = ConfigurationHelper().max_coordinate
self._min_z = ConfigurationHelper().max_coordinate
self._centroid = None
# ToDo: Check this for LOD4
self._thermal_zones = []
@ -54,8 +60,10 @@ class Building(CityObject):
t_zones.bounded = [ThermalBoundary(s, [t_zones]) for s in t_zones.surfaces]
surface_id = 0
for surface in self.surfaces:
surface.lower_corner = self._lower_corner
surface.parent(self, surface_id)
self._min_x = min(self._min_x, surface.min_x)
self._min_y = min(self._min_y, surface.min_y)
self._min_z = min(self._min_z, surface.min_z)
surface_id += 1
@property
@ -303,24 +311,47 @@ class Building(CityObject):
"""
self._beam = value
@property
def building_lower_corner(self):
if self._building_lower_corner is None:
self._building_lower_corner = [self._min_x, self._min_y, self._min_z]
return self._building_lower_corner
@property
def storeys(self):
storeys = []
# todo: these values are not read yet from the files
# number_of_storeys = self.storeys_above_ground
# height = self.average_storey_height
number_of_storeys = 4
height = 1.5
height = self.average_storey_height
if self.storeys_above_ground is not None:
number_of_storeys = self.storeys_above_ground
else:
number_of_storeys = math.floor(float(self.max_height) / height) + 1
print('number_of_storeys', number_of_storeys)
last_storey_height = float(self.max_height) - height*(number_of_storeys-1)
print('last_storey_height', last_storey_height)
if last_storey_height < height/2:
number_of_storeys -= 1
print('number storeys', number_of_storeys)
trimesh = self.simplified_polyhedron.trimesh
normal_plane = [0, 0, -1]
rest_trimesh = trimesh
for n in range(0, number_of_storeys - 1):
# todo: I need the lower corner of the building!!
# point_plane = [self._lower_corner[0], self._lower_corner[1], self._lower_corner[2] + height]
point_plane = [self._lower_corner[0] + 0.5, self._lower_corner[1] + 0.5, self._lower_corner[2] + height * (n + 1)]
print(n)
point_plane = [self.building_lower_corner[0], self.building_lower_corner[1],
self.building_lower_corner[2] + height*(n+1)]
print('point plane', point_plane)
print('rest trimesh', rest_trimesh.volume)
trimeshes = gh.divide_mesh_by_plane(rest_trimesh, normal_plane, point_plane)
print('number meshes', len(trimeshes))
storey = trimeshes[0]
file_name = 'storey_' + str(n) + '.obj'
path_name = (Path(__file__).parent.parent / 'tests' / 'tests_outputs' / file_name).resolve()
with open(path_name, 'w') as file:
file.write(storey.export(file_type='obj'))
rest_trimesh = trimeshes[1]
file_name = 'rest_trimesh_' + str(n) + '.obj'
path_name = (Path(__file__).parent.parent / 'tests' / 'tests_outputs' / file_name).resolve()
with open(path_name, 'w') as file:
file.write(rest_trimesh.export(file_type='obj'))
storeys.append(storey)
storeys.append(rest_trimesh)
return storeys
@ -338,7 +369,8 @@ class Building(CityObject):
self._floor_area += surface.perimeter_polygon.area
return self._floor_area
# todo: erase this function, only for rabeehs case
@floor_area.setter
def floor_area(self, value):
self._floor_area = value
@property
def centroid(self):
if self._centroid is None:
self._centroid = self.simplified_polyhedron.centroid
return self._centroid

View File

@ -15,7 +15,6 @@ from city_model_structure.building import Building
from city_model_structure.city_object import CityObject
from helpers.geometry_helper import GeometryHelper
import math
import time
class City:
@ -191,7 +190,7 @@ class City:
selected_region_upper_corner = [center[0] + radius, center[1] + radius, center[2] + radius]
selected_region_city = City(selected_region_lower_corner, selected_region_upper_corner, srs_name=self.srs_name)
for city_object in self.city_objects:
location = city_object.location
location = city_object.centroid
distance = math.sqrt(math.pow(location[0]-center[0], 2) + math.pow(location[1]-center[1], 2)
+ math.pow(location[2]-center[2], 2))
if distance < radius:

View File

@ -88,12 +88,12 @@ class CityObject:
return None
@property
def location(self):
def centroid(self):
"""
City object location
:return: [x,y,z]
"""
return self.simplified_polyhedron.center
return self.simplified_polyhedron.centroid
@property
def max_height(self):

View File

@ -2,3 +2,4 @@
[buildings]
max_location_distance_for_shared_walls = 5.0
min_coordinate = -1.7976931348623157e+308
max_coordinate = 1.7976931348623157e+308

View File

@ -31,3 +31,11 @@ class ConfigurationHelper:
:return: float
"""
return self._config.getfloat('buildings', 'min_coordinate')
@property
def max_coordinate(self) -> float:
"""
Configured maximal coordinate value
:return: float
"""
return self._config.getfloat('buildings', 'max_coordinate')

42
tests/test_building.py Normal file
View File

@ -0,0 +1,42 @@
"""
Building test
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from pathlib import Path
from unittest import TestCase
from imports.geometry_factory import GeometryFactory
class MyTestCase(TestCase):
"""
TestBuilding TestCase 1
"""
def setUp(self) -> None:
"""
Test setup
:return: None
"""
self._city_gml = None
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
def _get_citygml(self, file):
if self._city_gml is None:
file_path = (self._example_path / file).resolve()
self._city_gml = GeometryFactory('citygml', file_path)._city_debug
self.assertIsNotNone(self._city_gml, 'city is none')
return self._city_gml
def test_storeys_division(self):
file = 'kelowna.gml'
city = self._get_citygml(file)
for building in city.buildings:
if building.name == 'BLD126221':
building.average_storey_height = 1.5
print(building.name)
print(building.volume)
print(building.floor_area)
print(building.max_height)
print(building.centroid)
print(len(building.storeys))

View File

@ -2,6 +2,7 @@
TestGeometryFactory test and validate the city model structure geometric parameters
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
Contributors Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import os
from pathlib import Path
@ -79,7 +80,7 @@ class TestGeometryFactory(TestCase):
for building in city.buildings:
self.assertIsNotNone(building.name, 'building name is none')
self.assertIsNotNone(building.lod, 'building lod is none')
self.assertIsNotNone(building.location, 'building location is none')
self.assertIsNotNone(building.centroid, 'building centroid is none')
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
self.assertIsNotNone(building.function, 'building function is none')
self.assertIsNotNone(building.volume, 'building volume is none')
@ -223,17 +224,6 @@ class TestGeometryFactory(TestCase):
for building in city.buildings:
self.assertIsNotNone(building.volume, 'building volume is none')
def test_divide_mesh_by_plane(self):
file = 'FZK-Haus-LoD-all-KIT-IAI-KHH-B36-V1.gml'
# todo @Guille: this file has 5 lods (0, 1, 2, 3 and 4), all as one single city_object.
# Only lod1 is read and saved
city = self._get_citygml(file)
for building in city.buildings:
print(building.name)
print(building.volume)
print(building.thermal_zones[0].floor_area)
print(len(building.storeys))
def test_surface(self):
coordinates = '0.0 0.0 0.0 0.0 4.0 0.0 4.0 4.0 0.0 4.0 0.0 0.0 0.0 0.0 0.0 ' \
'1.0 1.0 0.0 2.0 1.0 0.0 2.0 2.0 0.0 1.0 2.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 ' \