diff --git a/city_model_structure/attributes/layer.py b/city_model_structure/attributes/layer.py index 54bc532d..9998cdd9 100644 --- a/city_model_structure/attributes/layer.py +++ b/city_model_structure/attributes/layer.py @@ -3,6 +3,7 @@ Layers module SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ +import uuid from city_model_structure.attributes.material import Material @@ -13,6 +14,13 @@ class Layer: def __init__(self): self._material = None self._thickness = None + self._id = None + + @property + def id(self): + if self._id is None: + self._id = uuid.uuid4() + return self._id @property def material(self) -> Material: diff --git a/exports/formats/energy_ade.py b/exports/formats/energy_ade.py index a0477aab..af10a07f 100644 --- a/exports/formats/energy_ade.py +++ b/exports/formats/energy_ade.py @@ -13,8 +13,10 @@ class EnergyAde: def __init__(self, city, path): self._city = city self._path = path + self._surface_members = None self._export() + def _export(self): energy_ade = { 'core:CityModel': { @@ -62,7 +64,7 @@ class EnergyAde: } } building_dic = EnergyAde._measures(building, building_dic) - building_dic = EnergyAde._building_geometry(building, building_dic, self._city) + building_dic = self._building_geometry(building, building_dic, self._city) building_dic['bldg:Building']['energy:volume'] = { 'energy:VolumeType': { 'energy:type':'grossVolume', @@ -79,10 +81,11 @@ class EnergyAde: 'gml:Pos': f'{" ".join(map(str,building.centroid))}' } } - building_dic['bldg:Building']['energy:thermalZone'] = EnergyAde._thermal_zones(building,self._city) + building_dic['bldg:Building']['energy:thermalZone'] = self._thermal_zones(building,self._city) buildings.append(building_dic) energy_ade['core:CityModel']['core:cityObjectMember'] = buildings + print(energy_ade) file_name = self._city.name + '_ade.gml' file_path = Path(self._path / file_name).resolve() with open(file_path, 'w' ) as file: @@ -157,8 +160,8 @@ class EnergyAde: } return demand - @staticmethod - def _building_geometry(building, building_dic, city): + + def _building_geometry(self, building, building_dic, city): building_dic['bldg:Building']['bldg:function'] = building.function building_dic['bldg:Building']['bldg:usage'] = ', '.join([u.usage for u in building.usage_zones]) @@ -170,19 +173,19 @@ class EnergyAde: } building_dic['bldg:Building']['bldg:storeysAboveGround'] = building.storeys_above_ground if building.lod == 1: - building_dic = EnergyAde._lod1(building, building_dic, city) + building_dic = self._lod1(building, building_dic, city) elif building.lod == 2: - building_dic = EnergyAde._lod2(building, building_dic, city) + building_dic = self._lod2(building, building_dic, city) else: raise NotImplementedError('Only lod 1 and 2 can be exported') return building_dic - @staticmethod - def _lod1(building, building_dic, city): + + def _lod1(self, building, building_dic, city): raise NotImplementedError('Only lod 1 and 2 can be exported') - @staticmethod - def _lod2(building, building_dic, city): - surface_members = [] + + def _lod2(self, building, building_dic, city): + self._surface_members = [] boundaries = [{ 'gml:Envelope': { '@srsName': city.srs_name, @@ -192,7 +195,7 @@ class EnergyAde: }}] for surface in building.surfaces: surface_member = { '@xlink:href': f'#PolyId{surface.name}'} - surface_members.append(surface_member) + self._surface_members.append(surface_member) if surface.type == 'Wall': surface_type = 'bldg:WallSurface' elif surface.type == 'Ground': @@ -243,7 +246,7 @@ class EnergyAde: 'gml:CompositeSurface': { '@srsName': city.srs_name, '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:surfaceMember': surface_members + 'gml:surfaceMember': self._surface_members } } } @@ -252,8 +255,7 @@ class EnergyAde: building_dic['bldg:Building']['gml:boundedBy'] = boundaries return building_dic - @staticmethod - def _thermal_zones(building, city): + def _thermal_zones(self, building, city): thermal_zones = [] for index, thermal_zone in enumerate(building.thermal_zones): usage_zones = [] @@ -286,10 +288,67 @@ class EnergyAde: }, 'energy:isCooled': f'{thermal_zone.is_cooled}', 'energy:isHeated': f'{thermal_zone.is_heated}', - + 'energy:volumeGeometry': { + 'gml:Solid': { + '@gml:id': f'GML_{uuid.uuid4()}', + 'gml:exterior': { + 'gml:CompositeSurface': { + '@srsName': f'{city.srs_name}', + '@gml:id': f'GML_{uuid.uuid4()}', + 'gml:surfaceMember': self._surface_members + } + } + } + }, + 'energy:boundedBy': self._thermal_boundaries(city, thermal_zone) } } thermal_zone_dic['energy:ThermalZone']['energy:contains'] = usage_zones thermal_zones.append(thermal_zone_dic) - print(thermal_zones) - return thermal_zones \ No newline at end of file + return thermal_zones + + def _thermal_boundaries(self, city, thermal_zone): + thermal_boundaries = [] + for thermal_boundary in thermal_zone.bounded: + thermal_boundary_dic = { + '@gml:id': f'GML_{uuid.uuid4()}', + 'gml:name': f'{thermal_boundary.construction_name}', + 'energy:thermalBoundaryType': thermal_boundary.type, + 'energy:azumuth': { + '@uom': 'rad', + '#text': f'{thermal_boundary.azimuth}' + }, + 'energy:inclination': { + '@uom': 'rad', + '#text': f'{thermal_boundary.inclination}' + }, + 'energy:area': { + '@uom': 'm2', + '#text': f'{thermal_boundary.area}' + }, + 'energy:surfaceGeometry': { + 'gml:MultiSurface': { + '@srsName': city.srs_name, + '@gml:id': f'GML_{uuid.uuid4()}', + 'gml:surfaceMember': { + 'gml:Polygon': { + '@srsName': city.srs_name, + '@gml:id': f'GML_{uuid.uuid4()}', + 'gml:exterior': { + 'gml:LinearRing': { + '@gml:id': f'GML_{uuid.uuid4()}', + 'gml:posList': { + '@srsDimension': '3', + '@count': len(thermal_boundary.surface.points) + 1, + '#text': f'{" ".join(map(str, thermal_boundary.surface.points_list))} ' + f'{" ".join(map(str, thermal_boundary.surface.points[0]))}' + } + } + } + } + } + } + } + } + thermal_boundaries.append(thermal_boundary_dic) + return thermal_boundaries \ No newline at end of file