forked from s_ranjbar/city_retrofit
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
|
||||
import numpy as np
|
||||
import uuid
|
||||
from helpers.geometry_helper import GeometryHelper as gh
|
||||
from city_model_structure.attributes.polygon import Polygon
|
||||
|
||||
|
||||
|
@ -16,15 +15,13 @@ class Surface:
|
|||
"""
|
||||
Surface class
|
||||
"""
|
||||
def __init__(self, coordinates, holes_coordinates=None, surface_type=None, name=None, swr=None):
|
||||
self._coordinates = coordinates
|
||||
self._holes_coordinates = holes_coordinates
|
||||
def __init__(self, solid_polygon, perimeter_polygon, holes_polygons=None, surface_type=None, name=None,
|
||||
swr=None, id_number=None):
|
||||
self._type = surface_type
|
||||
self._name = name
|
||||
self._id = id_number
|
||||
self._swr = swr
|
||||
self._points = None
|
||||
self._holes_points = None
|
||||
self._perimeter_points = None
|
||||
|
||||
self._azimuth = None
|
||||
self._inclination = None
|
||||
self._area_above_ground = None
|
||||
|
@ -34,9 +31,9 @@ class Surface:
|
|||
self._envelope_upper_corner = None
|
||||
self._shared_surfaces = []
|
||||
self._global_irradiance = dict()
|
||||
self._perimeter_polygon = None
|
||||
self._holes_polygons = None
|
||||
self._solid_polygons = None
|
||||
self._perimeter_polygon = perimeter_polygon
|
||||
self._holes_polygons = holes_polygons
|
||||
self._solid_polygons = solid_polygon
|
||||
|
||||
def parent(self, parent, surface_id):
|
||||
"""
|
||||
|
@ -58,6 +55,14 @@ class Surface:
|
|||
self._name = uuid.uuid4()
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
Surface id
|
||||
:return: str
|
||||
"""
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def swr(self):
|
||||
"""
|
||||
|
@ -75,62 +80,6 @@ class Surface:
|
|||
"""
|
||||
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):
|
||||
if axis == 'x':
|
||||
axis = 0
|
||||
|
@ -139,7 +88,7 @@ class Surface:
|
|||
else:
|
||||
axis = 2
|
||||
max_coordinate = ''
|
||||
for point in self.points:
|
||||
for point in self.perimeter_polygon.points:
|
||||
if max_coordinate == '':
|
||||
max_coordinate = point[axis]
|
||||
elif max_coordinate < point[axis]:
|
||||
|
@ -154,7 +103,7 @@ class Surface:
|
|||
else:
|
||||
axis = 2
|
||||
min_coordinate = ''
|
||||
for point in self.points:
|
||||
for point in self.perimeter_polygon.points:
|
||||
if min_coordinate == '':
|
||||
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
|
||||
:return: Polygon
|
||||
"""
|
||||
if self._perimeter_polygon is None:
|
||||
self._perimeter_polygon = Polygon(self.perimeter_points)
|
||||
return self._perimeter_polygon
|
||||
|
||||
@property
|
||||
|
@ -282,8 +229,6 @@ class Surface:
|
|||
solid surface
|
||||
:return: Polygon
|
||||
"""
|
||||
if self._solid_polygons is None:
|
||||
self._solid_polygons = Polygon(self.points)
|
||||
return self._solid_polygons
|
||||
|
||||
@property
|
||||
|
@ -295,11 +240,4 @@ class Surface:
|
|||
[] -> no 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
|
||||
|
|
|
@ -24,7 +24,8 @@ class Building(CityObject):
|
|||
"""
|
||||
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)
|
||||
self._basement_heated = None
|
||||
self._attic_heated = None
|
||||
|
@ -44,11 +45,14 @@ class Building(CityObject):
|
|||
self._grounds = []
|
||||
self._roofs = []
|
||||
self._walls = []
|
||||
# ToDo: Check this for LOD4
|
||||
self._internal_walls = []
|
||||
|
||||
self._thermal_zones = []
|
||||
if self.lod < 4:
|
||||
# for lod under 4 is just one thermal zone
|
||||
self._thermal_zones.append(ThermalZone(self.surfaces))
|
||||
for zone_surfaces_ids in zones_surfaces_ids:
|
||||
zone_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:
|
||||
t_zones.bounded = [ThermalBoundary(s, [t_zones]) for s in t_zones.surfaces]
|
||||
|
@ -60,8 +64,10 @@ class Building(CityObject):
|
|||
self._grounds.append(surface)
|
||||
elif surface.type == 'Wall':
|
||||
self._walls.append(surface)
|
||||
else:
|
||||
elif surface.type == 'Roof':
|
||||
self._roofs.append(surface)
|
||||
else:
|
||||
self._internal_walls.append(surface)
|
||||
|
||||
@property
|
||||
def grounds(self) -> [Surface]:
|
||||
|
@ -287,7 +293,7 @@ class Building(CityObject):
|
|||
if self._eave_height is None:
|
||||
self._eave_height = 0
|
||||
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
|
||||
|
||||
@property
|
||||
|
|
|
@ -5,12 +5,13 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
|
|||
"""
|
||||
import numpy as np
|
||||
import xmltodict
|
||||
import time
|
||||
|
||||
from city_model_structure.city import City
|
||||
from city_model_structure.building import Building
|
||||
from city_model_structure.attributes.surface import Surface
|
||||
from helpers.geometry_helper import GeometryHelper
|
||||
import time
|
||||
from city_model_structure.attributes.polygon import Polygon
|
||||
|
||||
|
||||
class CityGml:
|
||||
|
@ -182,3 +183,79 @@ class CityGml:
|
|||
array = points.split(' ')
|
||||
res = " "
|
||||
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