Merge remote-tracking branch 'origin/master'

# Conflicts:
#	city_model_structure/attributes/surface.py
#	city_model_structure/city.py
This commit is contained in:
Pilar 2021-04-13 15:11:39 -04:00
commit a0613201e3
7 changed files with 150 additions and 9 deletions

View File

@ -42,6 +42,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 str(self.name)[:8]
@property @property
def swr(self): def swr(self):
""" """

View File

@ -14,6 +14,7 @@ from pyproj import Transformer
from city_model_structure.building import Building from city_model_structure.building import Building
from city_model_structure.city_object import CityObject from city_model_structure.city_object import CityObject
from helpers.geometry_helper import GeometryHelper from helpers.geometry_helper import GeometryHelper
from helpers.location import Location
import math import math
@ -32,12 +33,13 @@ class City:
# todo: right now extracted at city level, in the future should be extracted also at building level if exist # todo: right now extracted at city level, in the future should be extracted also at building level if exist
self._location = None self._location = None
self._country_code = None self._country_code = None
self._climate_reference_city = None
self._climate_file = None
self._latitude = None self._latitude = None
self._longitude = None self._longitude = None
self._time_zone = None self._time_zone = None
@property def _get_location(self) -> Location:
def _get_location(self):
if self._location is None: if self._location is None:
gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth
try: try:
@ -57,7 +59,7 @@ class City:
City country code City country code
:return: str :return: str
""" """
return self._get_location[0] return self._get_location().country
@property @property
def name(self): def name(self):
@ -65,7 +67,23 @@ class City:
City name City name
:return: str :return: str
""" """
return self._get_location[1] return self._get_location().city
@property
def climate_reference_city(self):
return self._climate_reference_city
@climate_reference_city.setter
def climate_reference_city(self, value):
self._climate_reference_city = value
@property
def climate_file(self):
return self._climate_file
@climate_file.setter
def climate_file(self, value):
self._climate_file = value
@property @property
def city_objects(self) -> Union[List[CityObject], None]: def city_objects(self) -> Union[List[CityObject], None]:

View File

@ -7,6 +7,7 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
from exports.formats.stl import Stl from exports.formats.stl import Stl
from exports.formats.obj import Obj from exports.formats.obj import Obj
from exports.formats.energy_ade import EnergyAde from exports.formats.energy_ade import EnergyAde
from exports.formats.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
class ExportsFactory: class ExportsFactory:
@ -44,6 +45,14 @@ class ExportsFactory:
@property @property
def _obj(self): def _obj(self):
"""
Export the city geometry to obj
:return: None
"""
return Obj(self._city, self._path)
@property
def _grounded_obj(self):
""" """
Export the city geometry to obj Export the city geometry to obj
:return: None :return: None
@ -58,6 +67,10 @@ class ExportsFactory:
""" """
raise NotImplementedError() raise NotImplementedError()
@property
def _sra(self):
return SimplifiedRadiosityAlgorithm(self._city, (self._path/ f'{self._city.name}_sra.xml'))
def export(self): def export(self):
""" """
Export the city model structure to the given export type Export the city model structure to the given export type

View File

@ -0,0 +1,83 @@
"""
Simplified Radiosity Algorithm
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guillermo.GutierrezMorote@concordia.ca
"""
from pathlib import Path
import xmltodict
class SimplifiedRadiosityAlgorithm:
def __init__(self, city, file_name, begin_month=1, begin_day=1, end_month=12, end_day=31):
self._file_name = file_name
self._begin_month = begin_month
self._begin_day = begin_day
self._end_month = end_month
self._end_day = end_day
self._city = city
self._export()
def _correct_point(self, point):
# correct the x, y, z values into the reference frame set by city lower_corner
x = point[0] - self._city.lower_corner[0]
y = point[1] - self._city.lower_corner[1]
z = point[2] - self._city.lower_corner[2]
return [x, y, z]
def _export(self):
print('export')
buildings = []
for building_index, building in enumerate(self._city.buildings):
building_dict = {
'@Name': f'{building.name}',
'@id': f'{building_index}',
'@key': f'{building.name}',
'@Simulate': 'True'
}
walls, roofs, floors = [], [], []
for surface in building.surfaces:
surface_dict = {
'@id': f'{surface.id}',
'@ShortWaveReflectance': f'{surface.swr}'
}
for point_index, point in enumerate(surface.perimeter_polygon.points):
# todo: check corrected points
point = self._correct_point(point)
surface_dict[f'V{point_index}'] = {
'@x': f'{point[0]}',
'@y': f'{point[1]}',
'@z': f'{point[2]}'
}
if surface.type == 'Wall':
walls.append(surface_dict)
elif surface.type == 'Roof':
roofs.append(surface_dict)
else:
floors.append(surface_dict)
building_dict['Wall'] = walls
building_dict['Roof'] = roofs
building_dict['Floor'] = floors
buildings.append(building_dict)
sra = {
'CitySim': {
'@name': f'{self._file_name.name}',
'Simulation': {
'@beginMonth': f'{self._begin_month}',
'@beginDay': f'{self._begin_day}',
'@endMonth': f'{self._end_month}',
'@endDay': f'{self._end_day}',
},
'Climate': {
'@location': f'{self._city.climate_file}',
'@city': f'{self._city.climate_reference_city}'
},
'District': {
'FarFieldObstructions': None,
'Building': buildings
}
}
}
with open(self._file_name, "w") as file:
file.write(xmltodict.unparse(sra, pretty=True, short_empty_elements=True))
return

View File

@ -12,6 +12,7 @@ from trimesh import intersections
from helpers.configuration_helper import ConfigurationHelper from helpers.configuration_helper import ConfigurationHelper
from city_model_structure.attributes.polygon import Polygon from city_model_structure.attributes.polygon import Polygon
from city_model_structure.attributes.polyhedron import Polyhedron from city_model_structure.attributes.polyhedron import Polyhedron
from helpers.location import Location
class GeometryHelper: class GeometryHelper:
@ -192,12 +193,12 @@ class GeometryHelper:
@staticmethod @staticmethod
def get_location(latitude, longitude): def get_location(latitude, longitude):
url = 'https://nominatim.openstreetmap.org/reverse?lat={latitude}&lon={longitude}&format=json' url = 'https://nominatim.openstreetmap.org/reverse?lat={latitude}&lon={longitude}&format=json'
resp = requests.get(url.format(latitude=latitude, longitude=longitude)) response = requests.get(url.format(latitude=latitude, longitude=longitude))
if resp.status_code != 200: if response.status_code != 200:
# This means something went wrong. # This means something went wrong.
raise Exception('GET /tasks/ {}'.format(resp.status_code)) raise Exception('GET /tasks/ {}'.format(response.status_code))
else: else:
response = resp.json() response = response.json()
# todo: this is wrong, remove in the future # todo: this is wrong, remove in the future
city = 'new_york_city' city = 'new_york_city'
country = 'us' country = 'us'
@ -205,7 +206,7 @@ class GeometryHelper:
city = response['address']['city'] city = response['address']['city']
if 'country_code' in response['address']: if 'country_code' in response['address']:
country = response['address']['country_code'] country = response['address']['country_code']
return [country, city] return Location(country, city)
@staticmethod @staticmethod
def distance_between_points(vertex1, vertex2): def distance_between_points(vertex1, vertex2):

12
helpers/location.py Normal file
View File

@ -0,0 +1,12 @@
class Location:
def __init__(self, country, city):
self._country = country
self._city = city
@property
def city(self):
return self._city
@property
def country(self):
return self._country

View File

@ -35,6 +35,9 @@ class TestExports(TestCase):
PhysicsFactory('ca', self._city_gml).enrich() PhysicsFactory('ca', self._city_gml).enrich()
UsageFactory('ca', self._city_gml).enrich() UsageFactory('ca', self._city_gml).enrich()
SchedulesFactory('comnet', self._city_gml).enrich() SchedulesFactory('comnet', self._city_gml).enrich()
cli = 'C:\\Users\\Pilar\\PycharmProjects\\monthlyenergybalance\\tests_data\\weather\\inseldb_Summerland.cli'
self._city_gml.climate_file = Path(cli)
self._city_gml.climate_reference_city = 'Summerland'
for building in self._city_gml.buildings: for building in self._city_gml.buildings:
building.heating['month'] = pd.DataFrame({'INSEL': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}) building.heating['month'] = pd.DataFrame({'INSEL': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]})
building.cooling['month'] = pd.DataFrame({'INSEL': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}) building.cooling['month'] = pd.DataFrame({'INSEL': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]})
@ -54,3 +57,6 @@ class TestExports(TestCase):
def test_energy_ade_export(self): def test_energy_ade_export(self):
self._export('energy_ade') self._export('energy_ade')
def test_sra_export(self):
self._export('sra')