Citygml can now generate the envelop out of the buildings
This commit is contained in:
parent
88eb9006ea
commit
920d95eef2
|
@ -115,7 +115,7 @@ class Idf:
|
||||||
lower_z = lower_corner[2]
|
lower_z = lower_corner[2]
|
||||||
points_list = []
|
points_list = []
|
||||||
for point in points:
|
for point in points:
|
||||||
point_tuple = (point[0]-lower_x, point[1]-lower_y, point[2]-lower_z)
|
point_tuple = (point[0] - lower_x, point[1] - lower_y, point[2] - lower_z)
|
||||||
points_list.append(point_tuple)
|
points_list.append(point_tuple)
|
||||||
return points_list
|
return points_list
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ class Idf:
|
||||||
def _add_window_construction_and_material(self, thermal_opening):
|
def _add_window_construction_and_material(self, thermal_opening):
|
||||||
for window_material in self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]:
|
for window_material in self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]:
|
||||||
if window_material['UFactor'] == thermal_opening.overall_u_value and \
|
if window_material['UFactor'] == thermal_opening.overall_u_value and \
|
||||||
window_material['Solar_Heat_Gain_Coefficient'] == thermal_opening.g_value:
|
window_material['Solar_Heat_Gain_Coefficient'] == thermal_opening.g_value:
|
||||||
return
|
return
|
||||||
|
|
||||||
order = str(len(self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]) + 1)
|
order = str(len(self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]) + 1)
|
||||||
|
@ -407,7 +407,11 @@ class Idf:
|
||||||
Reporting_Frequency="Hourly",
|
Reporting_Frequency="Hourly",
|
||||||
)
|
)
|
||||||
self._idf.match()
|
self._idf.match()
|
||||||
self._idf.intersect_match()
|
try:
|
||||||
|
self._idf.intersect_match()
|
||||||
|
except IndexError:
|
||||||
|
# seems to be a bug from geomeppy when surfaces cannot be intersected
|
||||||
|
pass
|
||||||
self._idf.saveas(str(self._output_file))
|
self._idf.saveas(str(self._output_file))
|
||||||
return self._idf
|
return self._idf
|
||||||
|
|
||||||
|
@ -482,7 +486,7 @@ class Idf:
|
||||||
for material in self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]:
|
for material in self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]:
|
||||||
if material['Name'] == glazing:
|
if material['Name'] == glazing:
|
||||||
if material['UFactor'] == opening.overall_u_value and \
|
if material['UFactor'] == opening.overall_u_value and \
|
||||||
material['Solar_Heat_Gain_Coefficient'] == opening.g_value:
|
material['Solar_Heat_Gain_Coefficient'] == opening.g_value:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import xmltodict
|
import xmltodict
|
||||||
from city_model_structure.city import City
|
from city_model_structure.city import City
|
||||||
|
@ -22,6 +25,8 @@ class CityGml:
|
||||||
self._city = None
|
self._city = None
|
||||||
self._lod1_tags = ['lod1Solid', 'lod1MultiSurface']
|
self._lod1_tags = ['lod1Solid', 'lod1MultiSurface']
|
||||||
self._lod2_tags = ['lod2Solid', 'lod2MultiSurface', 'lod2MultiCurve']
|
self._lod2_tags = ['lod2Solid', 'lod2MultiSurface', 'lod2MultiCurve']
|
||||||
|
self._lower_corner = None
|
||||||
|
self._upper_corner = None
|
||||||
with open(path) as gml:
|
with open(path) as gml:
|
||||||
# Clean the namespaces is an important task to prevent wrong ns:field due poor citygml_classes implementations
|
# Clean the namespaces is an important task to prevent wrong ns:field due poor citygml_classes implementations
|
||||||
force_list = ('cityObjectMember', 'curveMember', 'boundedBy', 'surfaceMember', 'consistsOfBuildingPart')
|
force_list = ('cityObjectMember', 'curveMember', 'boundedBy', 'surfaceMember', 'consistsOfBuildingPart')
|
||||||
|
@ -48,17 +53,45 @@ class CityGml:
|
||||||
|
|
||||||
self._city_objects = None
|
self._city_objects = None
|
||||||
self._geometry = GeometryHelper()
|
self._geometry = GeometryHelper()
|
||||||
|
if 'boundedBy' in self._gml['CityModel']:
|
||||||
for bound in self._gml['CityModel']['boundedBy']:
|
for bound in self._gml['CityModel']['boundedBy']:
|
||||||
envelope = bound['Envelope']
|
envelope = bound['Envelope']
|
||||||
if '#text' in envelope['lowerCorner']:
|
if '#text' in envelope['lowerCorner']:
|
||||||
self._lower_corner = np.fromstring(envelope['lowerCorner']['#text'], dtype=float, sep=' ')
|
self._lower_corner = np.fromstring(envelope['lowerCorner']['#text'], dtype=float, sep=' ')
|
||||||
self._upper_corner = np.fromstring(envelope['upperCorner']['#text'], dtype=float, sep=' ')
|
self._upper_corner = np.fromstring(envelope['upperCorner']['#text'], dtype=float, sep=' ')
|
||||||
else:
|
else:
|
||||||
self._lower_corner = np.fromstring(envelope['lowerCorner'], dtype=float, sep=' ')
|
self._lower_corner = np.fromstring(envelope['lowerCorner'], dtype=float, sep=' ')
|
||||||
self._upper_corner = np.fromstring(envelope['upperCorner'], dtype=float, sep=' ')
|
self._upper_corner = np.fromstring(envelope['upperCorner'], dtype=float, sep=' ')
|
||||||
if '@srsName' in envelope:
|
if '@srsName' in envelope:
|
||||||
self._srs_name = envelope['@srsName']
|
self._srs_name = envelope['@srsName']
|
||||||
|
else:
|
||||||
|
# get the boundary from the city objects instead
|
||||||
|
for city_object_member in self._gml['CityModel']['cityObjectMember']:
|
||||||
|
city_object = city_object_member['Building']
|
||||||
|
if 'boundedBy' in city_object:
|
||||||
|
for bound in city_object['boundedBy']:
|
||||||
|
if 'Envelope' not in bound:
|
||||||
|
continue
|
||||||
|
envelope = bound['Envelope']
|
||||||
|
self._srs_name = envelope['@srsName']
|
||||||
|
lower_corner = None
|
||||||
|
upper_corner = None
|
||||||
|
if '#text' in envelope['lowerCorner']:
|
||||||
|
lower_corner = np.fromstring(envelope['lowerCorner']['#text'], dtype=float, sep=' ')
|
||||||
|
upper_corner = np.fromstring(envelope['upperCorner']['#text'], dtype=float, sep=' ')
|
||||||
|
else:
|
||||||
|
lower_corner = np.fromstring(envelope['lowerCorner'], dtype=float, sep=' ')
|
||||||
|
upper_corner = np.fromstring(envelope['upperCorner'], dtype=float, sep=' ')
|
||||||
|
if self._lower_corner is None:
|
||||||
|
self._lower_corner = lower_corner
|
||||||
|
self._upper_corner = upper_corner
|
||||||
|
else:
|
||||||
|
self._lower_corner[0] = min(self._lower_corner[0], lower_corner[0])
|
||||||
|
self._lower_corner[1] = min(self._lower_corner[1], lower_corner[1])
|
||||||
|
self._lower_corner[2] = min(self._lower_corner[2], lower_corner[2])
|
||||||
|
self._upper_corner[0] = max(self._upper_corner[0], upper_corner[0])
|
||||||
|
self._upper_corner[1] = max(self._upper_corner[1], upper_corner[1])
|
||||||
|
self._upper_corner[2] = max(self._upper_corner[2], upper_corner[2])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def content(self):
|
def content(self):
|
||||||
|
|
|
@ -48,19 +48,26 @@ class CityGmlLod2(CityGmlBase):
|
||||||
try:
|
try:
|
||||||
surface_encoding, surface_subtype = cls._surface_encoding(bounded[surface_type])
|
surface_encoding, surface_subtype = cls._surface_encoding(bounded[surface_type])
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
|
|
||||||
continue
|
continue
|
||||||
for member in bounded[surface_type][surface_encoding][surface_subtype]['surfaceMember']:
|
for member in bounded[surface_type][surface_encoding][surface_subtype]['surfaceMember']:
|
||||||
if '@srsDimension' in member['Polygon']['exterior']['LinearRing']['posList']:
|
if 'CompositeSurface' in member:
|
||||||
gml_points = member['Polygon']['exterior']['LinearRing']['posList']["#text"]
|
for composite_members in member['CompositeSurface']['surfaceMember']:
|
||||||
|
for composite_member in composite_members['CompositeSurface']['surfaceMember']:
|
||||||
|
surfaces.append(cls._add_member_surface(composite_member, surface_type))
|
||||||
else:
|
else:
|
||||||
gml_points = member['Polygon']['exterior']['LinearRing']['posList']
|
surfaces.append(cls._add_member_surface(member, surface_type))
|
||||||
solid_points = cls._solid_points(cls._remove_last_point(gml_points))
|
|
||||||
polygon = Polygon(solid_points)
|
|
||||||
surface = Surface(polygon, polygon, surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
|
|
||||||
surfaces.append(surface)
|
|
||||||
return surfaces
|
return surfaces
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _add_member_surface(cls, member, surface_type):
|
||||||
|
if '@srsDimension' in member['Polygon']['exterior']['LinearRing']['posList']:
|
||||||
|
gml_points = member['Polygon']['exterior']['LinearRing']['posList']["#text"]
|
||||||
|
else:
|
||||||
|
gml_points = member['Polygon']['exterior']['LinearRing']['posList']
|
||||||
|
solid_points = cls._solid_points(cls._remove_last_point(gml_points))
|
||||||
|
polygon = Polygon(solid_points)
|
||||||
|
return Surface(polygon, polygon, surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _multi_curve(cls, city_object_member):
|
def _multi_curve(cls, city_object_member):
|
||||||
raise NotImplementedError('multi curve')
|
raise NotImplementedError('multi curve')
|
||||||
|
|
|
@ -66,4 +66,4 @@ class GeometryFactory:
|
||||||
Enrich the city given to the class using the class given handler
|
Enrich the city given to the class using the class given handler
|
||||||
:return: City
|
:return: City
|
||||||
"""
|
"""
|
||||||
return Rhino(self._path).city
|
return CityGml(self._path).city
|
||||||
|
|
|
@ -41,7 +41,7 @@ class TestGeometryFactory(TestCase):
|
||||||
|
|
||||||
def _get_rhino(self, file):
|
def _get_rhino(self, file):
|
||||||
file_path = (self._example_path / file).resolve()
|
file_path = (self._example_path / file).resolve()
|
||||||
self._city = GeometryFactory('rhino', file_path).city_debug
|
self._city = GeometryFactory('rhino', file_path).city
|
||||||
self.assertIsNotNone(self._city, 'city is none')
|
self.assertIsNotNone(self._city, 'city is none')
|
||||||
return self._city
|
return self._city
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,4 @@ class TestConstructionCatalog(TestCase):
|
||||||
catalog = UsageCatalogFactory('comnet').catalog
|
catalog = UsageCatalogFactory('comnet').catalog
|
||||||
self.assertIsNotNone(catalog, 'catalog is none')
|
self.assertIsNotNone(catalog, 'catalog is none')
|
||||||
content = catalog.entries()
|
content = catalog.entries()
|
||||||
self.assertEqual(len(content.usages), 33, 'Wrong number of usages')
|
self.assertEqual(len(content.usages), 32, 'Wrong number of usages')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user