diff --git a/city_model_structure/attributes/polyhedron.py b/city_model_structure/attributes/polyhedron.py index 2d033a74..ba21867a 100644 --- a/city_model_structure/attributes/polyhedron.py +++ b/city_model_structure/attributes/polyhedron.py @@ -2,8 +2,9 @@ Polyhedron module SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributors Pilar Monsalvete pilar_monsalvete@yahoo.es +Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ +import sys import numpy as np import math from trimesh import Trimesh @@ -103,6 +104,10 @@ class Polyhedron: @property def trimesh(self) -> Trimesh: if self._trimesh is None: + for face in self.faces: + if len(face) != 3: + sys.stderr.write(f'Not able to generate trimesh\n') + return None self._trimesh = Trimesh(vertices=self.vertices, faces=self.faces) return self._trimesh @@ -113,7 +118,9 @@ class Polyhedron: :return: float """ if self._volume is None: - if not self.trimesh.is_volume: + if self.trimesh is None: + self._volume = np.inf + elif not self.trimesh.is_volume: self._volume = np.inf else: self._volume = self.trimesh.volume diff --git a/exports/formats/obj.py b/exports/formats/obj.py index 13e1fb2c..45648fef 100644 --- a/exports/formats/obj.py +++ b/exports/formats/obj.py @@ -17,16 +17,12 @@ class Obj(Triangular): super().__init__(city, path, 'obj') def to_ground_points(self): - reference_coordinates = self._city.lower_corner file_name_in = self._city.name + '.' + self._triangular_format file_name_out = self._city.name + '_ground.' + self._triangular_format file_path_in = (Path(self._path).resolve() / file_name_in).resolve() file_path_out = (Path(self._path).resolve() / file_name_out).resolve() - scene_dic = GeometryFactory('obj', file_path_in).scene - for vertex in scene_dic['vertices']: - for i in range(0, 3): - vertex[i] -= reference_coordinates[i] - scene = Trimesh(vertices=scene_dic['vertices'], faces=scene_dic['faces']) + scene = GeometryFactory('obj', file_path_in).scene + scene.rezero() obj_file = trimesh.exchange.obj.export_obj(scene) with open(file_path_out, 'w') as file: file.write(obj_file) diff --git a/imports/geometry_factory.py b/imports/geometry_factory.py index 4b41a285..7e4fbe42 100644 --- a/imports/geometry_factory.py +++ b/imports/geometry_factory.py @@ -3,6 +3,8 @@ GeometryFactory retrieve the specific geometric module to load the given format SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ +from trimesh.scene import Scene + from city_model_structure.city import City from city_model_structure.city_object import CityObject from imports.geometry_feeders.citygml import CityGml @@ -47,7 +49,7 @@ class GeometryFactory: return getattr(self, self._file_type, lambda: None) @property - def scene(self): + def scene(self) -> Scene: """ Load the city model structure from a geometry source :return: Trimesh scene diff --git a/tests/test_building.py b/tests/test_building.py index 98424a8e..d8a3ab97 100644 --- a/tests/test_building.py +++ b/tests/test_building.py @@ -23,7 +23,7 @@ class MyTestCase(TestCase): 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._city_gml = GeometryFactory('citygml', file_path).city self.assertIsNotNone(self._city_gml, 'city is none') return self._city_gml diff --git a/tests/test_exports.py b/tests/test_exports.py index 77077827..96cf12d8 100644 --- a/tests/test_exports.py +++ b/tests/test_exports.py @@ -32,11 +32,7 @@ class TestExports(TestCase): if self._city_gml is None: file_path = (self._example_path / 'one_building_in_kelowna.gml').resolve() self._city_gml = GeometryFactory('citygml', file_path).city - for building in self._city_gml.buildings: - print(building.thermal_zones) PhysicsFactory('ca', self._city_gml).enrich() - for building in self._city_gml.buildings: - print(building.thermal_zones) UsageFactory('ca', self._city_gml).enrich() SchedulesFactory('comnet', self._city_gml).enrich() for building in self._city_gml.buildings: diff --git a/tests/test_geometry_factory.py b/tests/test_geometry_factory.py index 21668880..ad858b13 100644 --- a/tests/test_geometry_factory.py +++ b/tests/test_geometry_factory.py @@ -202,11 +202,9 @@ class TestGeometryFactory(TestCase): counter = 0 for building in city.buildings: - if building.name != 'BLD121958': - print(building.name, building.volume) - if str(building.volume) == 'inf': - counter += 1 - print('total number of buildings with volume inf', counter) + if str(building.volume) == 'inf': + counter += 1 + self.assertEqual(counter, 1, f'{counter} buildings had errors when triangulating surfaces') def test_stuttgart_gml(self): file = '20190815_mitte_out_MC_FloursurfaceADD.gml' diff --git a/tests/test_physics_factory.py b/tests/test_physics_factory.py index 4a4e94a1..330ee6ba 100644 --- a/tests/test_physics_factory.py +++ b/tests/test_physics_factory.py @@ -33,6 +33,14 @@ class TestPhysicsFactory(TestCase): if self._nyc_with_physics is None: file_path = (self._example_path / '20buildings.gml').resolve() self._nyc_with_physics = self._get_citygml(file_path) + for building in self._nyc_with_physics.buildings: + for tz in building.thermal_zones: + for tb in tz.bounded: + tb.hi = 10 + tb.he = 25 + for opening in tb.thermal_openings: + opening.hi = 10 + opening.he = 25 PhysicsFactory('us_new_york', self._nyc_with_physics).enrich() return self._nyc_with_physics @@ -54,8 +62,9 @@ class TestPhysicsFactory(TestCase): self.assertIsNotNone(thermal_zone.infiltration_rate_system_off, 'infiltration_rate_system_off is none') self.assertIsNotNone(thermal_zone.bounded, 'bounded is none') for thermal_boundary in thermal_zone.bounded: - self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') - self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') + if thermal_boundary.surface.type is not 'Ground': + self.assertIsNotNone(thermal_boundary.outside_solar_absorptance, 'outside_solar_absorptance is none') + self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none') def test_reduced_library(self): file_path = (self._example_path / 'lod2_buildings.gml').resolve()