Citygml can now generate the envelop out of the buildings

This commit is contained in:
Guille Gutierrez 2022-06-07 13:31:35 -04:00
parent 88eb9006ea
commit 920d95eef2
6 changed files with 70 additions and 26 deletions

View File

@ -115,7 +115,7 @@ class Idf:
lower_z = lower_corner[2]
points_list = []
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)
return points_list
@ -407,7 +407,11 @@ class Idf:
Reporting_Frequency="Hourly",
)
self._idf.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))
return self._idf

View File

@ -4,6 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import math
import sys
import numpy as np
import xmltodict
from city_model_structure.city import City
@ -22,6 +25,8 @@ class CityGml:
self._city = None
self._lod1_tags = ['lod1Solid', 'lod1MultiSurface']
self._lod2_tags = ['lod2Solid', 'lod2MultiSurface', 'lod2MultiCurve']
self._lower_corner = None
self._upper_corner = None
with open(path) as gml:
# Clean the namespaces is an important task to prevent wrong ns:field due poor citygml_classes implementations
force_list = ('cityObjectMember', 'curveMember', 'boundedBy', 'surfaceMember', 'consistsOfBuildingPart')
@ -48,7 +53,7 @@ class CityGml:
self._city_objects = None
self._geometry = GeometryHelper()
if 'boundedBy' in self._gml['CityModel']:
for bound in self._gml['CityModel']['boundedBy']:
envelope = bound['Envelope']
if '#text' in envelope['lowerCorner']:
@ -59,6 +64,34 @@ class CityGml:
self._upper_corner = np.fromstring(envelope['upperCorner'], dtype=float, sep=' ')
if '@srsName' in envelope:
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
def content(self):

View File

@ -48,18 +48,25 @@ class CityGmlLod2(CityGmlBase):
try:
surface_encoding, surface_subtype = cls._surface_encoding(bounded[surface_type])
except NotImplementedError:
continue
for member in bounded[surface_type][surface_encoding][surface_subtype]['surfaceMember']:
if 'CompositeSurface' in member:
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:
surfaces.append(cls._add_member_surface(member, surface_type))
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)
surface = Surface(polygon, polygon, surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
surfaces.append(surface)
return surfaces
return Surface(polygon, polygon, surface_type=GeometryHelper.gml_surface_to_libs(surface_type))
@classmethod
def _multi_curve(cls, city_object_member):

View File

@ -66,4 +66,4 @@ class GeometryFactory:
Enrich the city given to the class using the class given handler
:return: City
"""
return Rhino(self._path).city
return CityGml(self._path).city

View File

@ -41,7 +41,7 @@ class TestGeometryFactory(TestCase):
def _get_rhino(self, file):
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')
return self._city

View File

@ -14,4 +14,4 @@ class TestConstructionCatalog(TestCase):
catalog = UsageCatalogFactory('comnet').catalog
self.assertIsNotNone(catalog, 'catalog is none')
content = catalog.entries()
self.assertEqual(len(content.usages), 33, 'Wrong number of usages')
self.assertEqual(len(content.usages), 32, 'Wrong number of usages')