city_retrofit/hub/city_model_structure/city_object.py
2023-08-07 12:32:33 -04:00

301 lines
7.8 KiB
Python

"""
CityObject module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from __future__ import annotations
from typing import List, Union
from hub.city_model_structure.level_of_detail import LevelOfDetail
from hub.city_model_structure.iot.sensor import Sensor
from hub.city_model_structure.building_demand.surface import Surface
from hub.city_model_structure.attributes.polyhedron import Polyhedron
from hub.helpers.configuration_helper import ConfigurationHelper
class CityObject:
"""
class CityObject
"""
def __init__(self, name, surfaces):
self._name = name
self._level_of_detail = LevelOfDetail()
self._surfaces = surfaces
self._type = None
self._city_object_lower_corner = None
self._city_object_upper_corner = None
self._detailed_polyhedron = None
self._simplified_polyhedron = None
self._min_x = ConfigurationHelper().max_coordinate
self._min_y = ConfigurationHelper().max_coordinate
self._min_z = ConfigurationHelper().max_coordinate
self._max_x = ConfigurationHelper().min_coordinate
self._max_y = ConfigurationHelper().min_coordinate
self._max_z = ConfigurationHelper().min_coordinate
self._centroid = None
self._volume = None
self._external_temperature = {}
self._ground_temperature = {}
self._global_horizontal = {}
self._diffuse = {}
self._beam = {}
self._sensors = []
self._neighbours = None
@property
def level_of_detail(self) -> LevelOfDetail:
"""
Get level of detail of different aspects of the city: geometry, construction and usage
:return: LevelOfDetail
"""
return self._level_of_detail
@property
def name(self):
"""
Get city object name
:return: str
"""
return self._name
@property
def type(self) -> str:
"""
Get city object type
:return: str
"""
return self._type
@property
def volume(self) -> float:
"""
Get city object volume in cubic meters
:return: float
"""
if self._volume is None:
self._volume = self.simplified_polyhedron.volume
return self._volume
@volume.setter
def volume(self, value):
self._volume = value
@property
def detailed_polyhedron(self) -> Polyhedron:
"""
Get city object polyhedron including details such as holes
:return: Polyhedron
"""
if self._detailed_polyhedron is None:
polygons = []
for surface in self.surfaces:
polygons.append(surface.solid_polygon)
if surface.holes_polygons is not None:
for hole_polygon in surface.holes_polygons:
polygons.append(hole_polygon)
self._detailed_polyhedron = Polyhedron(polygons)
return self._detailed_polyhedron
@property
def simplified_polyhedron(self) -> Polyhedron:
"""
Get city object polyhedron, just the simple lod2 representation
:return: Polyhedron
"""
if self._simplified_polyhedron is None:
polygons = []
for surface in self.surfaces:
polygons.append(surface.perimeter_polygon)
self._simplified_polyhedron = Polyhedron(polygons)
return self._simplified_polyhedron
@property
def surfaces(self) -> List[Surface]:
"""
Get city object surfaces
:return: [Surface]
"""
return self._surfaces
@surfaces.setter
def surfaces(self, value):
"""
Set city object surfaces
:return: [Surface]
"""
self._surfaces = value
def surface(self, name) -> Union[Surface, None]:
"""
Get the city object surface with a given name
:param name: str
:return: None or Surface
"""
for s in self.surfaces:
if s.name == name:
return s
return None
def surface_by_id(self, identification_number) -> Union[Surface, None]:
"""
Get the city object surface with a given name
:param identification_number: str
:return: None or Surface
"""
for s in self.surfaces:
if str(s.id) == str(identification_number):
return s
return None
@property
def centroid(self) -> List[float]:
"""
Get city object centroid
:return: [x,y,z]
"""
if self._centroid is None:
self._centroid = self.simplified_polyhedron.centroid
return self._centroid
@property
def max_height(self) -> float:
"""
Get city object maximal height in meters
:return: float
"""
return self.simplified_polyhedron.max_z
@property
def external_temperature(self) -> {float}:
"""
Get external temperature surrounding the city object in Celsius
:return: dict{dict{[float]}}
"""
return self._external_temperature
@external_temperature.setter
def external_temperature(self, value):
"""
Set external temperature surrounding the city object in Celsius
:param value: dict{dict{[float]}}
"""
self._external_temperature = value
@property
def ground_temperature(self) -> dict:
"""
Get ground temperature under the city object in Celsius at different depths in meters for different time steps
example of use: {month: {0.5: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]}}
:return: dict{dict{[float]}}
"""
return self._ground_temperature
@ground_temperature.setter
def ground_temperature(self, value):
"""
Set ground temperature under the city object in Celsius at different depths
:param value: dict{dict{[float]}}
"""
self._ground_temperature = value
@property
def global_horizontal(self) -> dict:
"""
Get global horizontal radiation surrounding the city object in W/m2
:return: dict{dict{[float]}}
"""
return self._global_horizontal
@global_horizontal.setter
def global_horizontal(self, value):
"""
Set global horizontal radiation surrounding the city object in W/m2
:param value: dict{dict{[float]}}
"""
self._global_horizontal = value
@property
def diffuse(self) -> dict:
"""
Get diffuse radiation surrounding the city object in W/m2
:return: dict{dict{[float]}}
"""
return self._diffuse
@diffuse.setter
def diffuse(self, value):
"""
Set diffuse radiation surrounding the city object in W/m2
:param value: dict{dict{[float]}}
"""
self._diffuse = value
@property
def beam(self) -> dict:
"""
Get beam radiation surrounding the city object in W/m2
:return: dict{dict{[float]}}
"""
return self._beam
@beam.setter
def beam(self, value):
"""
Set beam radiation surrounding the city object in W/m2
:param value: dict{dict{[float]}}
"""
self._beam = value
@property
def lower_corner(self):
"""
Get city object lower corner coordinates [x, y, z]
:return: [x,y,z]
"""
if self._city_object_lower_corner is None:
self._city_object_lower_corner = [self._min_x, self._min_y, self._min_z]
return self._city_object_lower_corner
@property
def upper_corner(self):
"""
Get city object upper corner coordinates [x, y, z]
:return: [x,y,z]
"""
if self._city_object_upper_corner is None:
self._city_object_upper_corner = [self._max_x, self._max_y, self._max_z]
return self._city_object_upper_corner
@property
def sensors(self) -> List[Sensor]:
"""
Get sensors belonging to the city object
:return: [Sensor]
"""
return self._sensors
@sensors.setter
def sensors(self, value):
"""
Set sensors belonging to the city object
:param value: [Sensor]
"""
self._sensors = value
@property
def neighbours(self) -> Union[None, List[CityObject]]:
"""
Get the list of neighbour_objects and their properties associated to the current city_object
"""
return self._neighbours
@neighbours.setter
def neighbours(self, value):
"""
Set the list of neighbour_objects and their properties associated to the current city_object
"""
self._neighbours = value