created import obj and tested
This commit is contained in:
parent
634bbc286f
commit
e19a22920b
|
@ -24,8 +24,8 @@ class Surface:
|
||||||
self._area_above_ground = None
|
self._area_above_ground = None
|
||||||
self._area_below_ground = None
|
self._area_below_ground = None
|
||||||
self._parent = None
|
self._parent = None
|
||||||
self._envelope_lower_corner = None
|
self._bounds_lower_corner = None
|
||||||
self._envelope_upper_corner = None
|
self._bounds_upper_corner = None
|
||||||
self._shared_surfaces = []
|
self._shared_surfaces = []
|
||||||
self._global_irradiance = dict()
|
self._global_irradiance = dict()
|
||||||
self._perimeter_polygon = perimeter_polygon
|
self._perimeter_polygon = perimeter_polygon
|
||||||
|
@ -91,16 +91,16 @@ class Surface:
|
||||||
return min_coordinate
|
return min_coordinate
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def envelope_lower_corner(self):
|
def bounds_lower_corner(self):
|
||||||
if self._envelope_lower_corner is None:
|
if self._bounds_lower_corner is None:
|
||||||
self._envelope_lower_corner = [self._min_coord('x'), self._min_coord('y'), self._min_coord('z')]
|
self._bounds_lower_corner = [self._min_coord('x'), self._min_coord('y'), self._min_coord('z')]
|
||||||
return self._envelope_lower_corner
|
return self._bounds_lower_corner
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def envelope_upper_corner(self):
|
def bounds_upper_corner(self):
|
||||||
if self._envelope_upper_corner is None:
|
if self._bounds_upper_corner is None:
|
||||||
self._envelope_upper_corner = [self._max_coord('x'), self._max_coord('y'), self._max_coord('z')]
|
self._bounds_upper_corner = [self._max_coord('x'), self._max_coord('y'), self._max_coord('z')]
|
||||||
return self._envelope_upper_corner
|
return self._bounds_upper_corner
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def area_above_ground(self):
|
def area_above_ground(self):
|
||||||
|
|
|
@ -24,8 +24,8 @@ class Building(CityObject):
|
||||||
"""
|
"""
|
||||||
Building(CityObject) class
|
Building(CityObject) class
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, lod, surfaces, terrains, year_of_construction, function,
|
def __init__(self, name, lod, surfaces, year_of_construction, function,
|
||||||
city_lower_corner, zones_surfaces_ids=[]):
|
city_lower_corner, terrains=None, zones_surfaces_ids=[]):
|
||||||
super().__init__(lod, surfaces, name, city_lower_corner)
|
super().__init__(lod, surfaces, name, city_lower_corner)
|
||||||
self._basement_heated = None
|
self._basement_heated = None
|
||||||
self._attic_heated = None
|
self._attic_heated = None
|
||||||
|
@ -57,9 +57,9 @@ class Building(CityObject):
|
||||||
for t_zones in self._thermal_zones:
|
for t_zones in self._thermal_zones:
|
||||||
t_zones.bounded = [ThermalBoundary(s, [t_zones]) for s in t_zones.surfaces]
|
t_zones.bounded = [ThermalBoundary(s, [t_zones]) for s in t_zones.surfaces]
|
||||||
for surface in self.surfaces:
|
for surface in self.surfaces:
|
||||||
self._min_x = min(self._min_x, surface.envelope_lower_corner[0])
|
self._min_x = min(self._min_x, surface.bounds_lower_corner[0])
|
||||||
self._min_y = min(self._min_y, surface.envelope_lower_corner[1])
|
self._min_y = min(self._min_y, surface.bounds_lower_corner[1])
|
||||||
self._min_z = min(self._min_z, surface.envelope_lower_corner[2])
|
self._min_z = min(self._min_z, surface.bounds_lower_corner[2])
|
||||||
if surface.type == 'Ground':
|
if surface.type == 'Ground':
|
||||||
self._grounds.append(surface)
|
self._grounds.append(surface)
|
||||||
elif surface.type == 'Wall':
|
elif surface.type == 'Wall':
|
||||||
|
@ -293,7 +293,7 @@ class Building(CityObject):
|
||||||
if self._eave_height is None:
|
if self._eave_height is None:
|
||||||
self._eave_height = 0
|
self._eave_height = 0
|
||||||
for wall in self.walls:
|
for wall in self.walls:
|
||||||
self._eave_height = max(self._eave_height, wall.envelope_upper_corner[2])
|
self._eave_height = max(self._eave_height, wall.bounds_upper_corner[2])
|
||||||
return self._eave_height
|
return self._eave_height
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -211,10 +211,10 @@ class EnergyAde:
|
||||||
'gml:boundedBy': {
|
'gml:boundedBy': {
|
||||||
'gml:Envelope': {
|
'gml:Envelope': {
|
||||||
'@srsName': city.srs_name,
|
'@srsName': city.srs_name,
|
||||||
'gml:lowerCorner': f'{surface.envelope_lower_corner[0]} {surface.envelope_lower_corner[1]}'
|
'gml:lowerCorner': f'{surface.bounds_lower_corner[0]} {surface.bounds_lower_corner[1]}'
|
||||||
f' {surface.envelope_lower_corner[2]}',
|
f' {surface.bounds_lower_corner[2]}',
|
||||||
'gml:upperCorner': f'{surface.envelope_upper_corner[0]} {surface.envelope_upper_corner[1]}'
|
'gml:upperCorner': f'{surface.bounds_upper_corner[0]} {surface.bounds_upper_corner[1]}'
|
||||||
f' {surface.envelope_upper_corner[2]}'
|
f' {surface.bounds_upper_corner[2]}'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'bldg:lod2MultiSurface': {
|
'bldg:lod2MultiSurface': {
|
||||||
|
|
|
@ -15,7 +15,6 @@ class Triangular:
|
||||||
self._write_mode = write_mode
|
self._write_mode = write_mode
|
||||||
self._export()
|
self._export()
|
||||||
|
|
||||||
|
|
||||||
def _export(self):
|
def _export(self):
|
||||||
if self._city.name is None:
|
if self._city.name is None:
|
||||||
self._city.name = 'unknown_city'
|
self._city.name = 'unknown_city'
|
||||||
|
|
|
@ -66,7 +66,7 @@ class GeometryFactory:
|
||||||
"""
|
"""
|
||||||
just for debug. More information is provided without the lambda parameter
|
just for debug. More information is provided without the lambda parameter
|
||||||
"""
|
"""
|
||||||
return CityGml(self._path).city
|
return Obj(self._path).city
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _osm_subway(self):
|
def _osm_subway(self):
|
||||||
|
|
|
@ -108,8 +108,8 @@ class CityGml:
|
||||||
year_of_construction = o['Building']['yearOfConstruction']
|
year_of_construction = o['Building']['yearOfConstruction']
|
||||||
if 'function' in o['Building']:
|
if 'function' in o['Building']:
|
||||||
function = o['Building']['function']
|
function = o['Building']['function']
|
||||||
self._city.add_city_object(Building(name, lod, surfaces, terrains, year_of_construction, function,
|
self._city.add_city_object(Building(name, lod, surfaces, year_of_construction, function,
|
||||||
self._lower_corner))
|
self._lower_corner, terrains))
|
||||||
return self._city
|
return self._city
|
||||||
|
|
||||||
def _terrains(self, city_object, lod_terrain_str):
|
def _terrains(self, city_object, lod_terrain_str):
|
||||||
|
|
|
@ -3,11 +3,12 @@ Obj module parses obj files and import the geometry into the city model structur
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
"""
|
"""
|
||||||
import trimesh.exchange.obj
|
import trimesh.exchange.load
|
||||||
|
from trimesh import Scene
|
||||||
|
import trimesh.geometry
|
||||||
from city_model_structure.city import City
|
from city_model_structure.city import City
|
||||||
from city_model_structure.building import Building
|
from city_model_structure.building import Building
|
||||||
from city_model_structure.attributes.surface import Surface
|
from city_model_structure.attributes.surface import Surface
|
||||||
from helpers.geometry_helper import GeometryHelper
|
|
||||||
from city_model_structure.attributes.polygon import Polygon
|
from city_model_structure.attributes.polygon import Polygon
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,17 +19,57 @@ class Obj:
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self._city = None
|
self._city = None
|
||||||
with open(path, 'r') as file:
|
with open(path, 'r') as file:
|
||||||
self._scene = trimesh.exchange.obj.load_obj(file)
|
self._scene = trimesh.exchange.load.load(file, file_type='obj', force='scene')
|
||||||
# todo: review class trimesh.exchange.load that returns Trimesh or Trimesh.scene
|
self._corners = self._scene.bounds_corners
|
||||||
|
_bound_corner_min = None
|
||||||
|
_bound_corner_max = None
|
||||||
|
for corner in self._corners:
|
||||||
|
if _bound_corner_min is None:
|
||||||
|
_bound_corner_min = corner
|
||||||
|
elif _bound_corner_max is None:
|
||||||
|
_bound_corner_max = corner
|
||||||
|
else:
|
||||||
|
_bound_corner_min[0] = min(_bound_corner_min[0], corner[0])
|
||||||
|
_bound_corner_min[1] = min(_bound_corner_min[1], corner[1])
|
||||||
|
_bound_corner_min[2] = min(_bound_corner_min[2], corner[2])
|
||||||
|
_bound_corner_max[0] = max(_bound_corner_max[0], corner[0])
|
||||||
|
_bound_corner_max[1] = max(_bound_corner_max[1], corner[1])
|
||||||
|
_bound_corner_max[2] = max(_bound_corner_max[2], corner[2])
|
||||||
|
self._lower_corner = _bound_corner_min
|
||||||
|
self._upper_corner = _bound_corner_max
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def scene(self) -> dict:
|
def scene(self) -> Scene:
|
||||||
return self._scene
|
return self._scene
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def city(self) -> dict:
|
def city(self) -> City:
|
||||||
if self._city is None:
|
if self._city is None:
|
||||||
# todo: refactor this method to clearly choose the gml type
|
# todo: refactor this method to clearly choose the obj type
|
||||||
self._city = City(self._lower_corner, self._upper_corner, self._srs_name)
|
# todo: where do we get this information from?
|
||||||
|
srs_name = 'EPSG:26911'
|
||||||
|
|
||||||
|
self._city = City(self._lower_corner, self._upper_corner, srs_name)
|
||||||
|
scene = self.scene.geometry
|
||||||
|
keys = scene.keys()
|
||||||
|
for key in keys:
|
||||||
|
name = key
|
||||||
|
# todo: where do we get this information from?
|
||||||
|
lod = 1
|
||||||
|
year_of_construction = 0
|
||||||
|
function = ''
|
||||||
|
|
||||||
|
obj = scene[key]
|
||||||
|
surfaces = []
|
||||||
|
for face in obj.faces:
|
||||||
|
# todo: review for obj with windows
|
||||||
|
points = []
|
||||||
|
for vertex_index in face:
|
||||||
|
points.append(obj.vertices[vertex_index])
|
||||||
|
solid_polygon = Polygon(points)
|
||||||
|
perimeter_polygon = solid_polygon
|
||||||
|
surface = Surface(solid_polygon, perimeter_polygon)
|
||||||
|
surfaces.append(surface)
|
||||||
|
self._city.add_city_object(Building(name, lod, surfaces, year_of_construction, function,
|
||||||
|
self._lower_corner))
|
||||||
return self._city
|
return self._city
|
||||||
|
|
|
@ -4,7 +4,6 @@ and enriches the city with archetypes and materials
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
|
Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
from imports.physics_feeders.data_classes.nrel_building_achetype import NrelBuildingArchetype as nba
|
from imports.physics_feeders.data_classes.nrel_building_achetype import NrelBuildingArchetype as nba
|
||||||
|
|
|
@ -32,7 +32,11 @@ class TestExports(TestCase):
|
||||||
if self._city_gml is None:
|
if self._city_gml is None:
|
||||||
file_path = (self._example_path / 'one_building_in_kelowna.gml').resolve()
|
file_path = (self._example_path / 'one_building_in_kelowna.gml').resolve()
|
||||||
self._city_gml = GeometryFactory('citygml', file_path).city
|
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()
|
PhysicsFactory('ca', self._city_gml).enrich()
|
||||||
|
for building in self._city_gml.buildings:
|
||||||
|
print(building.thermal_zones)
|
||||||
UsageFactory('ca', self._city_gml).enrich()
|
UsageFactory('ca', self._city_gml).enrich()
|
||||||
SchedulesFactory('comnet', self._city_gml).enrich()
|
SchedulesFactory('comnet', self._city_gml).enrich()
|
||||||
for building in self._city_gml.buildings:
|
for building in self._city_gml.buildings:
|
||||||
|
|
|
@ -113,8 +113,8 @@ class TestGeometryFactory(TestCase):
|
||||||
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
|
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
|
||||||
self.assertIsNotNone(surface.global_irradiance, 'monthly irradiance is none')
|
self.assertIsNotNone(surface.global_irradiance, 'monthly irradiance is none')
|
||||||
self.assertIsNone(surface.swr, 'surface swr is not none')
|
self.assertIsNone(surface.swr, 'surface swr is not none')
|
||||||
self.assertIsNotNone(surface.envelope_lower_corner, 'surface envelope_lower_corner is none')
|
self.assertIsNotNone(surface.bounds_lower_corner, 'surface envelope_lower_corner is none')
|
||||||
self.assertIsNotNone(surface.envelope_upper_corner, 'surface envelope_upper_corner is none')
|
self.assertIsNotNone(surface.bounds_upper_corner, 'surface envelope_upper_corner is none')
|
||||||
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
|
self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none')
|
||||||
self.assertIsNotNone(surface.perimeter_polygon, 'surface perimeter_polygon is none')
|
self.assertIsNotNone(surface.perimeter_polygon, 'surface perimeter_polygon is none')
|
||||||
self.assertIsNone(surface.holes_polygons, 'surface hole_polygons is not none')
|
self.assertIsNone(surface.holes_polygons, 'surface hole_polygons is not none')
|
||||||
|
|
|
@ -10,8 +10,6 @@ from imports.geometry_factory import GeometryFactory
|
||||||
|
|
||||||
|
|
||||||
class MyTestCase(TestCase):
|
class MyTestCase(TestCase):
|
||||||
def test_something(self):
|
|
||||||
self.assertEqual(True, False)
|
|
||||||
"""
|
"""
|
||||||
TestImports
|
TestImports
|
||||||
"""
|
"""
|
||||||
|
@ -20,14 +18,18 @@ class MyTestCase(TestCase):
|
||||||
Test setup
|
Test setup
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
self._city_gml = None
|
self._city_obj = None
|
||||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||||
|
|
||||||
def _get_city(self):
|
def _get_city(self):
|
||||||
if self._city_gml is None:
|
if self._city_obj is None:
|
||||||
file_path = (self._example_path / 'kelowna.obj').resolve()
|
file_path = (self._example_path / 'kelowna.obj').resolve()
|
||||||
scene = GeometryFactory('obj', file_path)._scene_debug
|
self._city_obj = GeometryFactory('obj', file_path)._city_debug
|
||||||
self._city_gml = scene.city
|
return self._city_obj
|
||||||
return self._city_gml
|
|
||||||
|
|
||||||
|
def test_import_obj(self):
|
||||||
|
city = self._get_city()
|
||||||
|
self.assertIsNotNone(city, 'city is none')
|
||||||
|
for building in city.buildings:
|
||||||
|
self.assertIsNotNone(building, 'building is none')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user