From fdef2152d9466963cddd90791e6262974287302e Mon Sep 17 00:00:00 2001 From: guille Date: Thu, 16 Mar 2023 10:51:41 -0400 Subject: [PATCH] export to obj partial implementation --- hub/exports/exports_factory.py | 2 +- hub/exports/formats/obj.py | 63 +++++++++++++++++++------- hub/imports/geometry/geojson.py | 2 +- hub/unittests/test_geometry_factory.py | 7 ++- 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/hub/exports/exports_factory.py b/hub/exports/exports_factory.py index 678b5a06..ae99dd0d 100644 --- a/hub/exports/exports_factory.py +++ b/hub/exports/exports_factory.py @@ -71,7 +71,7 @@ class ExportsFactory: Export the city geometry to obj with grounded coordinates :return: None """ - return Obj(self._city, self._path).to_ground_points() + return Obj(self._city, self._path) @property def _sra(self): diff --git a/hub/exports/formats/obj.py b/hub/exports/formats/obj.py index ccdb07d4..7e51655e 100644 --- a/hub/exports/formats/obj.py +++ b/hub/exports/formats/obj.py @@ -11,24 +11,55 @@ from hub.exports.formats.triangular import Triangular from hub.imports.geometry_factory import GeometryFactory -class Obj(Triangular): +class Obj: """ Export to obj format """ def __init__(self, city, path): - super().__init__(city, path, 'obj') + self._city = city + self._path = path + self._export() + + def _to_vertex(self, coordinate): + x = coordinate[0] - self._city.lower_corner[0] + y = coordinate[1] - self._city.lower_corner[1] + z = coordinate[2] - self._city.lower_corner[2] + return f'v {x} {y} {z}\n' + + def _export(self): + if self._city.name is None: + self._city.name = 'unknown_city' + file_name = self._city.name + '.obj' + file_path = (Path(self._path).resolve() / file_name).resolve() + vertices = {} + with open(file_path, 'w') as obj: + obj.write("# cerc-hub export\n") + vertex_index = 0 + faces = [] + for building in self._city.buildings: + obj.write(f'# building {building.name}\n') + for surface in building.surfaces: + obj.write(f'# surface {surface.name}\n') + face = 'f ' + len_ = len(surface.perimeter_polygon.coordinates) + if len_ > 40: + print(len_, building.name) + for coordinate in surface.perimeter_polygon.coordinates: + + vertex = self._to_vertex(coordinate) + if vertex not in vertices.keys(): + vertex_index += 1 + vertices[vertex] = vertex_index + current = vertex_index + obj.write(vertex) + else: + current = vertices[vertex] + + face = f'{face} {current}' + + faces.append(f'{face} {face.split(" ")[1]}\n') + obj.writelines(faces) + faces = [] + + - def to_ground_points(self): - """ - Move closer to the origin - """ - 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() - obj = GeometryFactory('obj', path=file_path_in) - scene = obj.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/hub/imports/geometry/geojson.py b/hub/imports/geometry/geojson.py index f526bebd..095de21e 100644 --- a/hub/imports/geometry/geojson.py +++ b/hub/imports/geometry/geojson.py @@ -231,7 +231,7 @@ class Geojson: self._city.add_city_object(building) self._city.level_of_detail.geometry = lod if lod == 1: - lines_information = GeometryHelper.city_mapping(self._city, plot=True) + lines_information = GeometryHelper.city_mapping(self._city) self._store_shared_percentage_to_walls(self._city, lines_information) if len(missing_functions) > 0: print(f'There are unknown functions {missing_functions}') diff --git a/hub/unittests/test_geometry_factory.py b/hub/unittests/test_geometry_factory.py index 69860803..29647af4 100644 --- a/hub/unittests/test_geometry_factory.py +++ b/hub/unittests/test_geometry_factory.py @@ -138,9 +138,8 @@ class TestGeometryFactory(TestCase): year_of_construction_field='ANNEE_CONS', function_field='CODE_UTILI') - for building in city.buildings: - print(building.volume) - self.assertEqual(207, len(city.buildings), 'wrong number of buildings') + hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export() + self.assertEqual(195, len(city.buildings), 'wrong number of buildings') self._check_buildings(city) for building in city.buildings: for wall in building.walls: @@ -161,7 +160,7 @@ class TestGeometryFactory(TestCase): year_of_construction_field='ANNEE_CONS', function_field='LIBELLE_UT') info_lod1 = GeometryHelper.city_mapping(city, plot=False) - + hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export() self.assertEqual(info_lod0, info_lod1) for building in city.buildings: self.assertEqual(2, len(building.neighbours))