changes for new definition of surfaces (by polygons) and buildings (by polyhedrons)
This commit is contained in:
parent
bf0cda131e
commit
ba735fb53d
|
@ -8,7 +8,6 @@ contributors Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import uuid
|
import uuid
|
||||||
from helpers.geometry_helper import GeometryHelper as gh
|
|
||||||
from city_model_structure.attributes.polygon import Polygon
|
from city_model_structure.attributes.polygon import Polygon
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,15 +15,13 @@ class Surface:
|
||||||
"""
|
"""
|
||||||
Surface class
|
Surface class
|
||||||
"""
|
"""
|
||||||
def __init__(self, coordinates, holes_coordinates=None, surface_type=None, name=None, swr=None):
|
def __init__(self, solid_polygon, perimeter_polygon, holes_polygons=None, surface_type=None, name=None,
|
||||||
self._coordinates = coordinates
|
swr=None, id_number=None):
|
||||||
self._holes_coordinates = holes_coordinates
|
|
||||||
self._type = surface_type
|
self._type = surface_type
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._id = id_number
|
||||||
self._swr = swr
|
self._swr = swr
|
||||||
self._points = None
|
|
||||||
self._holes_points = None
|
|
||||||
self._perimeter_points = None
|
|
||||||
self._azimuth = None
|
self._azimuth = None
|
||||||
self._inclination = None
|
self._inclination = None
|
||||||
self._area_above_ground = None
|
self._area_above_ground = None
|
||||||
|
@ -34,9 +31,9 @@ class Surface:
|
||||||
self._envelope_upper_corner = None
|
self._envelope_upper_corner = None
|
||||||
self._shared_surfaces = []
|
self._shared_surfaces = []
|
||||||
self._global_irradiance = dict()
|
self._global_irradiance = dict()
|
||||||
self._perimeter_polygon = None
|
self._perimeter_polygon = perimeter_polygon
|
||||||
self._holes_polygons = None
|
self._holes_polygons = holes_polygons
|
||||||
self._solid_polygons = None
|
self._solid_polygons = solid_polygon
|
||||||
|
|
||||||
def parent(self, parent, surface_id):
|
def parent(self, parent, surface_id):
|
||||||
"""
|
"""
|
||||||
|
@ -58,6 +55,14 @@ class Surface:
|
||||||
self._name = uuid.uuid4()
|
self._name = uuid.uuid4()
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
"""
|
||||||
|
Surface id
|
||||||
|
:return: str
|
||||||
|
"""
|
||||||
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def swr(self):
|
def swr(self):
|
||||||
"""
|
"""
|
||||||
|
@ -75,62 +80,6 @@ class Surface:
|
||||||
"""
|
"""
|
||||||
self._swr = value
|
self._swr = value
|
||||||
|
|
||||||
@property
|
|
||||||
def points(self) -> np.ndarray:
|
|
||||||
"""
|
|
||||||
Solid surface point matrix [[x, y, z],[x, y, z],...]
|
|
||||||
:return: np.ndarray
|
|
||||||
"""
|
|
||||||
if self._points is None:
|
|
||||||
self._points = np.fromstring(self._coordinates, dtype=float, sep=' ')
|
|
||||||
self._points = gh.to_points_matrix(self._points)
|
|
||||||
return self._points
|
|
||||||
|
|
||||||
@property
|
|
||||||
def holes_points(self) -> [np.ndarray]:
|
|
||||||
"""
|
|
||||||
Holes surfaces point matrices [[[x, y, z],[x, y, z],...]]
|
|
||||||
:return: np.ndarray
|
|
||||||
"""
|
|
||||||
if self._holes_coordinates is not None:
|
|
||||||
self._holes_points = []
|
|
||||||
for hole_coordinates in self._holes_coordinates:
|
|
||||||
hole_points = np.fromstring(hole_coordinates, dtype=float, sep=' ')
|
|
||||||
hole_points = gh.to_points_matrix(hole_points)
|
|
||||||
self._holes_points.append(hole_points)
|
|
||||||
return self._holes_points
|
|
||||||
|
|
||||||
@property
|
|
||||||
def perimeter_points(self) -> np.ndarray:
|
|
||||||
"""
|
|
||||||
Matrix of points of the perimeter in the same order as in coordinates [[x, y, z],[x, y, z],...]
|
|
||||||
:return: np.ndarray
|
|
||||||
"""
|
|
||||||
if self._perimeter_points is None:
|
|
||||||
if self.holes_points is None:
|
|
||||||
self._perimeter_points = self.points
|
|
||||||
else:
|
|
||||||
_perimeter_coordinates = self._coordinates
|
|
||||||
for hole_points in self.holes_points:
|
|
||||||
_hole = np.append(hole_points, hole_points[0])
|
|
||||||
_closed_hole = ' '.join(str(e) for e in [*_hole[:]])
|
|
||||||
# add a mark 'M' to ensure that the recombination of points does not provoke errors in finding holes
|
|
||||||
_perimeter_coordinates = _perimeter_coordinates.replace(_closed_hole, 'M')
|
|
||||||
_perimeter_coordinates = _perimeter_coordinates.replace('M', '')
|
|
||||||
self._perimeter_points = np.fromstring(_perimeter_coordinates, dtype=float, sep=' ')
|
|
||||||
self._perimeter_points = gh.to_points_matrix(self._perimeter_points)
|
|
||||||
# remove duplicated points
|
|
||||||
pv = np.array([self._perimeter_points[0]])
|
|
||||||
for point in self._perimeter_points:
|
|
||||||
duplicated_point = False
|
|
||||||
for p in pv:
|
|
||||||
if gh().almost_equal(0.0, p, point):
|
|
||||||
duplicated_point = True
|
|
||||||
if not duplicated_point:
|
|
||||||
pv = np.append(pv, [point], axis=0)
|
|
||||||
self._perimeter_points = pv
|
|
||||||
return self._perimeter_points
|
|
||||||
|
|
||||||
def _max_coord(self, axis):
|
def _max_coord(self, axis):
|
||||||
if axis == 'x':
|
if axis == 'x':
|
||||||
axis = 0
|
axis = 0
|
||||||
|
@ -139,7 +88,7 @@ class Surface:
|
||||||
else:
|
else:
|
||||||
axis = 2
|
axis = 2
|
||||||
max_coordinate = ''
|
max_coordinate = ''
|
||||||
for point in self.points:
|
for point in self.perimeter_polygon.points:
|
||||||
if max_coordinate == '':
|
if max_coordinate == '':
|
||||||
max_coordinate = point[axis]
|
max_coordinate = point[axis]
|
||||||
elif max_coordinate < point[axis]:
|
elif max_coordinate < point[axis]:
|
||||||
|
@ -154,7 +103,7 @@ class Surface:
|
||||||
else:
|
else:
|
||||||
axis = 2
|
axis = 2
|
||||||
min_coordinate = ''
|
min_coordinate = ''
|
||||||
for point in self.points:
|
for point in self.perimeter_polygon.points:
|
||||||
if min_coordinate == '':
|
if min_coordinate == '':
|
||||||
min_coordinate = point[axis]
|
min_coordinate = point[axis]
|
||||||
elif min_coordinate > point[axis]:
|
elif min_coordinate > point[axis]:
|
||||||
|
@ -272,8 +221,6 @@ class Surface:
|
||||||
total surface defined by the perimeter, merging solid and holes
|
total surface defined by the perimeter, merging solid and holes
|
||||||
:return: Polygon
|
:return: Polygon
|
||||||
"""
|
"""
|
||||||
if self._perimeter_polygon is None:
|
|
||||||
self._perimeter_polygon = Polygon(self.perimeter_points)
|
|
||||||
return self._perimeter_polygon
|
return self._perimeter_polygon
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -282,8 +229,6 @@ class Surface:
|
||||||
solid surface
|
solid surface
|
||||||
:return: Polygon
|
:return: Polygon
|
||||||
"""
|
"""
|
||||||
if self._solid_polygons is None:
|
|
||||||
self._solid_polygons = Polygon(self.points)
|
|
||||||
return self._solid_polygons
|
return self._solid_polygons
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -295,11 +240,4 @@ class Surface:
|
||||||
[] -> no holes in the surface
|
[] -> no holes in the surface
|
||||||
[Polygon] -> one or more holes in the surface
|
[Polygon] -> one or more holes in the surface
|
||||||
"""
|
"""
|
||||||
if self._holes_polygons is None:
|
|
||||||
if self.holes_points is None:
|
|
||||||
self._holes_polygons = None
|
|
||||||
else:
|
|
||||||
self._holes_polygons = []
|
|
||||||
for hole_points in self.holes_points:
|
|
||||||
self._holes_polygons.append(Polygon(hole_points))
|
|
||||||
return self._holes_polygons
|
return self._holes_polygons
|
||||||
|
|
|
@ -24,7 +24,8 @@ class Building(CityObject):
|
||||||
"""
|
"""
|
||||||
Building(CityObject) class
|
Building(CityObject) class
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, lod, surfaces, terrains, year_of_construction, function, city_lower_corner):
|
def __init__(self, name, lod, surfaces, zones_surfaces_ids, terrains, year_of_construction, function,
|
||||||
|
city_lower_corner):
|
||||||
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
|
||||||
|
@ -44,11 +45,14 @@ class Building(CityObject):
|
||||||
self._grounds = []
|
self._grounds = []
|
||||||
self._roofs = []
|
self._roofs = []
|
||||||
self._walls = []
|
self._walls = []
|
||||||
# ToDo: Check this for LOD4
|
self._internal_walls = []
|
||||||
|
|
||||||
self._thermal_zones = []
|
self._thermal_zones = []
|
||||||
if self.lod < 4:
|
for zone_surfaces_ids in zones_surfaces_ids:
|
||||||
# for lod under 4 is just one thermal zone
|
zone_surfaces = []
|
||||||
self._thermal_zones.append(ThermalZone(self.surfaces))
|
for surface_id in zone_surfaces_ids:
|
||||||
|
zone_surfaces.append(self.surface(surface_id))
|
||||||
|
self._thermal_zones.append(ThermalZone(zone_surfaces))
|
||||||
|
|
||||||
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]
|
||||||
|
@ -60,8 +64,10 @@ class Building(CityObject):
|
||||||
self._grounds.append(surface)
|
self._grounds.append(surface)
|
||||||
elif surface.type == 'Wall':
|
elif surface.type == 'Wall':
|
||||||
self._walls.append(surface)
|
self._walls.append(surface)
|
||||||
else:
|
elif surface.type == 'Roof':
|
||||||
self._roofs.append(surface)
|
self._roofs.append(surface)
|
||||||
|
else:
|
||||||
|
self._internal_walls.append(surface)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def grounds(self) -> [Surface]:
|
def grounds(self) -> [Surface]:
|
||||||
|
@ -287,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.max_z)
|
self._eave_height = max(self._eave_height, wall.envelope_upper_corner[2])
|
||||||
return self._eave_height
|
return self._eave_height
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -5,12 +5,13 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
|
||||||
"""
|
"""
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
import time
|
||||||
|
|
||||||
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 helpers.geometry_helper import GeometryHelper
|
||||||
import time
|
from city_model_structure.attributes.polygon import Polygon
|
||||||
|
|
||||||
|
|
||||||
class CityGml:
|
class CityGml:
|
||||||
|
@ -182,3 +183,79 @@ class CityGml:
|
||||||
array = points.split(' ')
|
array = points.split(' ')
|
||||||
res = " "
|
res = " "
|
||||||
return res.join(array[0:len(array) - 3])
|
return res.join(array[0:len(array) - 3])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _solid_points(coordinates) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Solid surface point matrix [[x, y, z],[x, y, z],...]
|
||||||
|
:parameter coordinates: string from file
|
||||||
|
:return: np.ndarray
|
||||||
|
"""
|
||||||
|
solid_points = np.fromstring(coordinates, dtype=float, sep=' ')
|
||||||
|
solid_points = GeometryHelper.to_points_matrix(solid_points)
|
||||||
|
return solid_points
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _holes_points(holes_coordinates) -> [np.ndarray]:
|
||||||
|
"""
|
||||||
|
Holes surfaces point matrices [[[x, y, z],[x, y, z],...]]
|
||||||
|
:parameter holes_coordinates: strings from file
|
||||||
|
:return: [np.ndarray]
|
||||||
|
"""
|
||||||
|
holes_points = []
|
||||||
|
for hole_coordinates in holes_coordinates:
|
||||||
|
hole_points = np.fromstring(hole_coordinates, dtype=float, sep=' ')
|
||||||
|
hole_points = GeometryHelper.to_points_matrix(hole_points)
|
||||||
|
holes_points.append(hole_points)
|
||||||
|
return holes_points
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _perimeter_points(coordinates, solid_points, holes_points) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Matrix of points of the perimeter in the same order as in coordinates [[x, y, z],[x, y, z],...]
|
||||||
|
:parameter coordinates: string from file
|
||||||
|
:parameter solid_points: np.ndarray points that define the solid part of a surface
|
||||||
|
:parameter holes_points: [np.ndarray] points that define each the holes in a surface
|
||||||
|
:return: np.ndarray
|
||||||
|
"""
|
||||||
|
if holes_points is None:
|
||||||
|
perimeter_points = solid_points
|
||||||
|
else:
|
||||||
|
_perimeter_coordinates = coordinates
|
||||||
|
for hole_points in holes_points:
|
||||||
|
_hole = np.append(hole_points, hole_points[0])
|
||||||
|
_closed_hole = ' '.join(str(e) for e in [*_hole[:]])
|
||||||
|
# add a mark 'M' to ensure that the recombination of points does not provoke errors in finding holes
|
||||||
|
_perimeter_coordinates = _perimeter_coordinates.replace(_closed_hole, 'M')
|
||||||
|
_perimeter_coordinates = _perimeter_coordinates.replace('M', '')
|
||||||
|
perimeter_points = np.fromstring(_perimeter_coordinates, dtype=float, sep=' ')
|
||||||
|
perimeter_points = GeometryHelper.to_points_matrix(perimeter_points)
|
||||||
|
# remove duplicated points
|
||||||
|
pv = np.array([perimeter_points[0]])
|
||||||
|
for point in perimeter_points:
|
||||||
|
duplicated_point = False
|
||||||
|
for p in pv:
|
||||||
|
if GeometryHelper().almost_equal(0.0, p, point):
|
||||||
|
duplicated_point = True
|
||||||
|
if not duplicated_point:
|
||||||
|
pv = np.append(pv, [point], axis=0)
|
||||||
|
perimeter_points = pv
|
||||||
|
return perimeter_points
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _holes_polygons(holes_points) -> [Polygon]:
|
||||||
|
"""
|
||||||
|
hole surfaces, a list of hole polygons found in a surface
|
||||||
|
:parameter holes_points: [np.ndarray] that define each of the holes
|
||||||
|
:return: None, [] or [Polygon]
|
||||||
|
None -> not known whether holes exist in reality or not due to low level of detail of input data
|
||||||
|
[] -> no holes in the surface
|
||||||
|
[Polygon] -> one or more holes in the surface
|
||||||
|
"""
|
||||||
|
if holes_points is None:
|
||||||
|
holes_polygons = None
|
||||||
|
else:
|
||||||
|
holes_polygons = []
|
||||||
|
for hole_points in holes_points:
|
||||||
|
holes_polygons.append(Polygon(hole_points))
|
||||||
|
return holes_polygons
|
||||||
|
|
Loading…
Reference in New Issue
Block a user