Added all tests to verify that any of them are creating the Montreal.cli file
This commit is contained in:
parent
c9cc46f943
commit
d432a0bacf
108
tests/test_city_merge.py
Normal file
108
tests/test_city_merge.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
"""
|
||||
TestCityMerge test and validate the merge of several cities into one
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
import copy
|
||||
import distutils.spawn
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
from hub.city_model_structure.city import City
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class TestCityMerge(TestCase):
|
||||
"""
|
||||
Functional TestCityMerge
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
self._executable = 'sra'
|
||||
|
||||
def test_merge(self):
|
||||
file_path = Path(self._example_path / 'test.geojson').resolve()
|
||||
full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city
|
||||
self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings')
|
||||
odd_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name)
|
||||
even_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name)
|
||||
for building in full_city.buildings:
|
||||
if int(building.name) % 2 == 0:
|
||||
even_city.add_city_object(copy.deepcopy(building))
|
||||
else:
|
||||
odd_city.add_city_object(copy.deepcopy(building))
|
||||
self.assertEqual(8, len(odd_city.buildings), 'Wrong number of odd buildings')
|
||||
self.assertEqual(9, len(even_city.buildings), 'Wrong number of par buildings')
|
||||
merged_city = odd_city.merge(even_city)
|
||||
self.assertEqual(17, len(merged_city.buildings), 'Wrong number of buildings in merged city')
|
||||
merged_city = even_city.merge(odd_city)
|
||||
self.assertEqual(17, len(merged_city.buildings), 'Wrong number of buildings in merged city')
|
||||
merged_city = full_city.merge(odd_city).merge(even_city)
|
||||
self.assertEqual(17, len(merged_city.buildings), 'Wrong number of buildings in merged city')
|
||||
|
||||
def test_merge_with_radiation(self):
|
||||
sra = distutils.spawn.find_executable('sra')
|
||||
file_path = Path(self._example_path / 'test.geojson').resolve()
|
||||
|
||||
full_city = GeometryFactory('geojson', file_path, height_field='citygml_me').city
|
||||
even_city = City(full_city.lower_corner, full_city.upper_corner, full_city.srs_name)
|
||||
for building in full_city.buildings:
|
||||
if int(building.name) % 2 == 0:
|
||||
even_city.add_city_object(copy.deepcopy(building))
|
||||
ExportsFactory('sra', full_city, self._output_path).export()
|
||||
sra_file = str((self._output_path / f'{full_city.name}_sra.xml').resolve())
|
||||
subprocess.run([sra, sra_file], stdout=subprocess.DEVNULL)
|
||||
ResultFactory('sra', full_city, self._output_path).enrich()
|
||||
self.assertEqual(17, len(full_city.buildings), 'Wrong number of buildings')
|
||||
merged_city = full_city.merge(even_city)
|
||||
|
||||
full_city_building_total_radiation = 0
|
||||
for building in merged_city.buildings:
|
||||
for surface in building.surfaces:
|
||||
if surface.global_irradiance:
|
||||
full_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
|
||||
|
||||
merged_city_building_total_radiation = 0
|
||||
for building in merged_city.buildings:
|
||||
for surface in building.surfaces:
|
||||
if surface.global_irradiance:
|
||||
merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
|
||||
self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation)
|
||||
|
||||
merged_city = even_city.merge(full_city)
|
||||
merged_city_building_total_radiation = 0
|
||||
for building in merged_city.buildings:
|
||||
for surface in building.surfaces:
|
||||
if surface.global_irradiance:
|
||||
merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
|
||||
self.assertEqual(full_city_building_total_radiation, merged_city_building_total_radiation)
|
||||
|
||||
for building in even_city.buildings:
|
||||
for surface in building.surfaces:
|
||||
surface.global_irradiance[cte.YEAR] = [3]
|
||||
|
||||
merged_city = full_city.merge(even_city)
|
||||
first_merged_city_building_total_radiation = 0
|
||||
for building in merged_city.buildings:
|
||||
for surface in building.surfaces:
|
||||
if surface.global_irradiance:
|
||||
first_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
|
||||
merged_city = even_city.merge(full_city)
|
||||
second_merged_city_building_total_radiation = 0
|
||||
for building in merged_city.buildings:
|
||||
for surface in building.surfaces:
|
||||
if surface.global_irradiance:
|
||||
second_merged_city_building_total_radiation += surface.global_irradiance[cte.YEAR][0]
|
||||
self.assertAlmostEqual(first_merged_city_building_total_radiation, second_merged_city_building_total_radiation, 8)
|
||||
|
73
tests/test_construction_catalog.py
Normal file
73
tests/test_construction_catalog.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
"""
|
||||
TestConstructionCatalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
||||
|
||||
|
||||
class TestConstructionCatalog(TestCase):
|
||||
|
||||
def test_nrel_catalog(self):
|
||||
catalog = ConstructionCatalogFactory('nrel').catalog
|
||||
catalog_categories = catalog.names()
|
||||
constructions = catalog.names('constructions')
|
||||
windows = catalog.names('windows')
|
||||
materials = catalog.names('materials')
|
||||
self.assertEqual(33, len(constructions['constructions']))
|
||||
self.assertEqual(5, len(windows['windows']))
|
||||
self.assertEqual(33, len(materials['materials']))
|
||||
with self.assertRaises(ValueError):
|
||||
catalog.names('unknown')
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
for value in catalog_categories[category]:
|
||||
catalog.get_entry(value)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
||||
|
||||
def test_nrcan_catalog(self):
|
||||
catalog = ConstructionCatalogFactory('nrcan').catalog
|
||||
catalog_categories = catalog.names()
|
||||
constructions = catalog.names('constructions')
|
||||
windows = catalog.names('windows')
|
||||
materials = catalog.names('materials')
|
||||
self.assertEqual(540, len(constructions['constructions']))
|
||||
self.assertEqual(96, len(windows['windows']))
|
||||
self.assertEqual(552, len(materials['materials']))
|
||||
with self.assertRaises(ValueError):
|
||||
catalog.names('unknown')
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
for value in catalog_categories[category]:
|
||||
catalog.get_entry(value)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
||||
|
||||
def test_eilat_catalog(self):
|
||||
catalog = ConstructionCatalogFactory('eilat').catalog
|
||||
catalog_categories = catalog.names()
|
||||
constructions = catalog.names('constructions')
|
||||
windows = catalog.names('windows')
|
||||
materials = catalog.names('materials')
|
||||
self.assertEqual(9, len(constructions['constructions']))
|
||||
self.assertEqual(3, len(windows['windows']))
|
||||
self.assertEqual(553, len(materials['materials']))
|
||||
with self.assertRaises(ValueError):
|
||||
catalog.names('unknown')
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
for value in catalog_categories[category]:
|
||||
catalog.get_entry(value)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
308
tests/test_construction_factory.py
Normal file
308
tests/test_construction_factory.py
Normal file
|
@ -0,0 +1,308 @@
|
|||
"""
|
||||
TestConstructionFactory test and validate the city model structure construction parameters
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
|
||||
|
||||
class TestConstructionFactory(TestCase):
|
||||
"""
|
||||
TestConstructionFactory TestCase
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Configure test environment
|
||||
:return:
|
||||
"""
|
||||
self._city = None
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
|
||||
def _get_citygml(self, file):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('citygml', path=file_path).city
|
||||
self.assertIsNotNone(self._city, 'city is none')
|
||||
self.assertIsNotNone(self._city.level_of_detail.geometry, 'wrong construction level of detail')
|
||||
return self._city
|
||||
|
||||
@staticmethod
|
||||
def _internal_function(function_format, original_function):
|
||||
if function_format == 'hft':
|
||||
new_function = Dictionaries().hft_function_to_hub_function[original_function]
|
||||
elif function_format == 'pluto':
|
||||
new_function = Dictionaries().pluto_function_to_hub_function[original_function]
|
||||
else:
|
||||
raise Exception('Function key not recognized. Implemented only "hft" and "pluto"')
|
||||
return new_function
|
||||
|
||||
def test_citygml_function(self):
|
||||
"""
|
||||
Test city objects' functions in the city
|
||||
"""
|
||||
# case 1: hft
|
||||
file = 'one_building_in_kelowna.gml'
|
||||
function_format = 'hft'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.function = self._internal_function(function_format, building.function)
|
||||
self.assertEqual('residential', building.function, 'format hft')
|
||||
|
||||
# case 2: Pluto
|
||||
file = 'pluto_building.gml'
|
||||
function_format = 'pluto'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.function = self._internal_function(function_format, building.function)
|
||||
self.assertEqual('education', building.function, 'format pluto')
|
||||
|
||||
# case 3: Alkis
|
||||
file = 'one_building_in_kelowna_alkis.gml'
|
||||
function_format = 'alkis'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
self.assertRaises(Exception, lambda: self._internal_function(function_format, building.function))
|
||||
|
||||
def _check_buildings(self, city):
|
||||
for building in city.buildings:
|
||||
self.assertIsNotNone(building.name, 'building name is none')
|
||||
self.assertIsNotNone(building.type, 'building type is none')
|
||||
self.assertIsNotNone(building.volume, 'building volume is none')
|
||||
self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
|
||||
self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
|
||||
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
|
||||
self.assertIsNotNone(building.centroid, 'building centroid is none')
|
||||
self.assertIsNotNone(building.max_height, 'building max_height is none')
|
||||
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
|
||||
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
|
||||
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
|
||||
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
|
||||
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
|
||||
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
|
||||
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
|
||||
self.assertIsNotNone(building.grounds, 'building grounds is none')
|
||||
self.assertIsNotNone(building.walls, 'building walls is none')
|
||||
self.assertIsNotNone(building.roofs, 'building roofs is none')
|
||||
self.assertIsNotNone(building.internal_walls, 'building internal walls is none')
|
||||
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
||||
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
||||
self.assertIsNone(building.terrains, 'building terrains is not none')
|
||||
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
|
||||
self.assertIsNotNone(building.function, 'building function is none')
|
||||
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
|
||||
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none')
|
||||
self.assertEqual(len(building.heating_demand), 0, 'building heating is not none')
|
||||
self.assertEqual(len(building.cooling_demand), 0, 'building cooling is not none')
|
||||
self.assertIsNotNone(building.eave_height, 'building eave height is none')
|
||||
self.assertIsNotNone(building.roof_type, 'building roof type is none')
|
||||
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
|
||||
self.assertIsNone(building.households, 'building households is not none')
|
||||
self.assertFalse(building.is_conditioned, 'building is conditioned')
|
||||
self.assertIsNotNone(building.shell, 'building shell is none')
|
||||
|
||||
def _check_thermal_zones(self, internal_zone):
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
|
||||
self.assertIsNotNone(thermal_zone.footprint_area, 'thermal_zone floor area is none')
|
||||
self.assertTrue(len(thermal_zone.thermal_boundaries) > 0, 'thermal_zone thermal_boundaries not defined')
|
||||
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, 'additional_thermal_bridge_u_value is none')
|
||||
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, 'thermal_zone effective_thermal_capacity is none')
|
||||
self.assertIsNotNone(thermal_zone.infiltration_rate_system_off,
|
||||
'thermal_zone infiltration_rate_system_off is none')
|
||||
self.assertIsNotNone(thermal_zone.infiltration_rate_system_on, 'thermal_zone infiltration_rate_system_on is none')
|
||||
self.assertIsNotNone(thermal_zone.volume, 'thermal_zone volume is none')
|
||||
self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not none')
|
||||
self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none')
|
||||
self.assertIsNotNone(thermal_zone.total_floor_area, 'thermal zone total_floor_area is none')
|
||||
self.assertIsNone(thermal_zone.usage_name, 'thermal_zone usage is not none')
|
||||
self.assertIsNone(thermal_zone.hours_day, 'thermal_zone hours a day is not none')
|
||||
self.assertIsNone(thermal_zone.days_year, 'thermal_zone days a year is not none')
|
||||
self.assertIsNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is not none')
|
||||
self.assertIsNone(thermal_zone.occupancy, 'thermal_zone occupancy is not none')
|
||||
self.assertIsNone(thermal_zone.lighting, 'thermal_zone lighting is not none')
|
||||
self.assertIsNone(thermal_zone.appliances, 'thermal_zone appliances is not none')
|
||||
self.assertIsNone(thermal_zone.thermal_control, 'thermal_zone thermal control is not none')
|
||||
self.assertIsNone(thermal_zone.internal_gains, 'thermal_zone internal gains not returns none')
|
||||
|
||||
def _check_thermal_boundaries(self, thermal_zone):
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.id, 'thermal_boundary id is none')
|
||||
self.assertIsNotNone(thermal_boundary.parent_surface, 'thermal_boundary surface is none')
|
||||
self.assertIsNotNone(thermal_boundary.thermal_zones, 'thermal_boundary delimits no thermal zone')
|
||||
self.assertIsNotNone(thermal_boundary.opaque_area, 'thermal_boundary area is none')
|
||||
self.assertIsNotNone(thermal_boundary.thickness, 'thermal_boundary thickness is none')
|
||||
self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none')
|
||||
self.assertIsNotNone(thermal_boundary.thermal_openings, 'thermal_openings is none')
|
||||
self.assertIsNotNone(thermal_boundary.window_ratio, 'window_ratio is none')
|
||||
self.assertIsNone(thermal_boundary.windows_areas, 'windows_areas is not none')
|
||||
self.assertIsNotNone(thermal_boundary.u_value, 'u_value is none')
|
||||
self.assertIsNotNone(thermal_boundary.hi, 'hi is none')
|
||||
self.assertIsNotNone(thermal_boundary.he, 'he is none')
|
||||
self.assertIsNotNone(thermal_boundary.internal_surface, 'virtual_internal_surface is none')
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is not none')
|
||||
|
||||
def _check_thermal_openings(self, thermal_boundary):
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
self.assertIsNotNone(thermal_opening.id, 'thermal opening id is not none')
|
||||
self.assertIsNotNone(thermal_opening.area, 'thermal opening area is not none')
|
||||
self.assertIsNotNone(thermal_opening.frame_ratio, 'thermal opening frame_ratio is none')
|
||||
self.assertIsNotNone(thermal_opening.g_value, 'thermal opening g_value is none')
|
||||
self.assertIsNotNone(thermal_opening.overall_u_value, 'thermal opening overall_u_value is none')
|
||||
self.assertIsNotNone(thermal_opening.hi, 'thermal opening hi is none')
|
||||
self.assertIsNotNone(thermal_opening.he, 'thermal opening he is none')
|
||||
|
||||
def _check_surfaces(self, thermal_boundary):
|
||||
external_surface = thermal_boundary.external_surface
|
||||
internal_surface = thermal_boundary.internal_surface
|
||||
self.assertIsNotNone(external_surface.short_wave_reflectance,
|
||||
'external surface short_wave_reflectance id is not none')
|
||||
self.assertIsNotNone(external_surface.long_wave_emittance, 'external surface long_wave_emittance id is not none')
|
||||
self.assertIsNotNone(internal_surface.short_wave_reflectance,
|
||||
'external surface short_wave_reflectance id is not none')
|
||||
self.assertIsNotNone(internal_surface.long_wave_emittance, 'external surface long_wave_emittance id is not none')
|
||||
|
||||
def test_city_with_construction_extended_library(self):
|
||||
"""
|
||||
Enrich the city with the construction information and verify it
|
||||
"""
|
||||
file = 'one_building_in_kelowna.gml'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 1980
|
||||
building.function = self._internal_function('hft', building.function)
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._check_thermal_zones(internal_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_boundaries(thermal_zone)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||
self._check_thermal_openings(thermal_boundary)
|
||||
self._check_surfaces(thermal_boundary)
|
||||
|
||||
file = 'pluto_building.gml'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 1980
|
||||
building.function = self._internal_function('pluto', building.function)
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._check_thermal_zones(internal_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_boundaries(thermal_zone)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||
self._check_thermal_openings(thermal_boundary)
|
||||
self._check_surfaces(thermal_boundary)
|
||||
|
||||
file = 'pluto_building.gml'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
building.function = self._internal_function('pluto', building.function)
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._check_thermal_zones(internal_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_boundaries(thermal_zone)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||
self._check_thermal_openings(thermal_boundary)
|
||||
self._check_surfaces(thermal_boundary)
|
||||
|
||||
file = 'one_building_in_kelowna.gml'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 1980
|
||||
building.function = self._internal_function('hft', building.function)
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._check_thermal_zones(internal_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_boundaries(thermal_zone)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||
self._check_thermal_openings(thermal_boundary)
|
||||
self._check_surfaces(thermal_boundary)
|
||||
|
||||
file_path = (self._example_path / 'test.geojson').resolve()
|
||||
self._city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._check_thermal_zones(internal_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_boundaries(thermal_zone)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||
self._check_thermal_openings(thermal_boundary)
|
||||
self._check_surfaces(thermal_boundary)
|
||||
|
||||
def test_nrcan_construction_factory(self):
|
||||
file = 'test.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._check_thermal_zones(internal_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_boundaries(thermal_zone)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||
self._check_thermal_openings(thermal_boundary)
|
||||
self._check_surfaces(thermal_boundary)
|
||||
|
||||
def test_eilat_construction_factory(self):
|
||||
file = 'eilat.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='heightmax',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().eilat_function_to_hub_function).city
|
||||
ConstructionFactory('eilat', city).enrich()
|
||||
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._check_thermal_zones(internal_zone)
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_boundaries(thermal_zone)
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.layers, 'layers is none')
|
||||
self._check_thermal_openings(thermal_boundary)
|
||||
self._check_surfaces(thermal_boundary)
|
28
tests/test_costs_catalog.py
Normal file
28
tests/test_costs_catalog.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""
|
||||
TestMontrealCustomCatalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Atiya atiya.atiya@mail.concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
from hub.catalog_factories.costs_catalog_factory import CostsCatalogFactory
|
||||
|
||||
|
||||
class TestCostsCatalog(TestCase):
|
||||
|
||||
def test_costs_catalog(self):
|
||||
catalog = CostsCatalogFactory('montreal_custom').catalog
|
||||
catalog_categories = catalog.names()
|
||||
self.assertIsNotNone(catalog, 'catalog is none')
|
||||
content = catalog.entries()
|
||||
self.assertTrue(len(content.archetypes) == 2)
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
for value in catalog_categories[category]:
|
||||
catalog.get_entry(value)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
138
tests/test_custom_insel_block.py
Normal file
138
tests/test_custom_insel_block.py
Normal file
|
@ -0,0 +1,138 @@
|
|||
"""
|
||||
TestInselExports test
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
import pandas as pd
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
|
||||
|
||||
class TestExports(TestCase):
|
||||
"""
|
||||
TestExports class contains the unittest for export functionality
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._city = None
|
||||
self._complete_city = None
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
|
||||
def _get_citygml(self, file):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('citygml', path=file_path).city
|
||||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _set_irradiance_surfaces(self, city):
|
||||
"""
|
||||
saves in building surfaces the correspondent irradiance at different time-scales depending on the mode
|
||||
if building is None, it saves all buildings' surfaces in file, if building is specified, it saves only that
|
||||
specific building values
|
||||
:parameter city: city
|
||||
:return: none
|
||||
"""
|
||||
city.level_of_detail.surface_radiation = 2
|
||||
path = (self._example_path / "one_building_in_kelowna_sra_SW.out").resolve()
|
||||
self._results = pd.read_csv(path, sep='\s+', header=0).to_dict(orient='list')
|
||||
_irradiance = {}
|
||||
for key in self._results:
|
||||
header_name = key.split(':')
|
||||
result = [x / cte.WATTS_HOUR_TO_JULES for x in self._results[key]]
|
||||
city_object_name = header_name[1]
|
||||
building = self._city.city_object(city_object_name)
|
||||
surface_id = header_name[2]
|
||||
surface = building.surface_by_id(surface_id)
|
||||
monthly_result = MonthlyValues.get_total_month(result)
|
||||
yearly_result = [sum(result)]
|
||||
_irradiance[cte.YEAR] = yearly_result
|
||||
_irradiance[cte.MONTH] = monthly_result
|
||||
_irradiance[cte.HOUR] = result
|
||||
surface.global_irradiance = _irradiance
|
||||
|
||||
def test_insel_monthly_energy_balance_export(self):
|
||||
"""
|
||||
export to Insel MonthlyEnergyBalance
|
||||
"""
|
||||
city = self._get_citygml('one_building_in_kelowna.gml')
|
||||
WeatherFactory('epw', city).enrich()
|
||||
for building in city.buildings:
|
||||
building.external_temperature[cte.MONTH] = MonthlyValues().\
|
||||
get_mean_values(building.external_temperature[cte.HOUR])
|
||||
self._set_irradiance_surfaces(city)
|
||||
|
||||
for building in city.buildings:
|
||||
self.assertIsNotNone(building.external_temperature[cte.MONTH], f'building {building.name} '
|
||||
f'external_temperature is none')
|
||||
for surface in building.surfaces:
|
||||
if surface.type != 'Ground':
|
||||
self.assertIsNotNone(surface.global_irradiance[cte.MONTH], f'surface in building {building.name} '
|
||||
f'global_irradiance is none')
|
||||
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
if building.function is None:
|
||||
building.function = 'large office'
|
||||
building.attic_heated = 0
|
||||
building.basement_heated = 0
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
|
||||
# parameters written:
|
||||
for building in city.buildings:
|
||||
self.assertIsNotNone(building.volume, f'building {building.name} volume is none')
|
||||
self.assertIsNotNone(building.average_storey_height, f'building {building.name} average_storey_height is none')
|
||||
self.assertIsNotNone(building.storeys_above_ground, f'building {building.name} storeys_above_ground is none')
|
||||
self.assertIsNotNone(building.attic_heated, f'building {building.name} attic_heated is none')
|
||||
self.assertIsNotNone(building.basement_heated, f'building {building.name} basement_heated is none')
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNotNone(internal_zone.area, f'internal zone {internal_zone.id} area is none')
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self.assertIsNotNone(thermal_zone.indirectly_heated_area_ratio, f'thermal zone {thermal_zone.id} '
|
||||
f'indirectly_heated_area_ratio is none')
|
||||
self.assertIsNotNone(thermal_zone.effective_thermal_capacity, f'thermal zone {thermal_zone.id} '
|
||||
f'effective_thermal_capacity is none')
|
||||
self.assertIsNotNone(thermal_zone.additional_thermal_bridge_u_value, f'thermal zone {thermal_zone.id} '
|
||||
f'additional_thermal_bridge_u_value '
|
||||
f'is none')
|
||||
self.assertIsNotNone(thermal_zone.total_floor_area, f'thermal zone {thermal_zone.id} '
|
||||
f'total_floor_area is none')
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self.assertIsNotNone(thermal_boundary.type)
|
||||
self.assertIsNotNone(thermal_boundary.opaque_area)
|
||||
if thermal_boundary.type in (cte.WALL, cte.ROOF):
|
||||
self.assertIsNotNone(thermal_boundary.window_ratio)
|
||||
self.assertIsNotNone(thermal_boundary.u_value)
|
||||
self.assertIsNotNone(thermal_boundary.thermal_openings)
|
||||
if thermal_boundary.type is not cte.GROUND:
|
||||
self.assertIsNotNone(thermal_boundary.external_surface.short_wave_reflectance)
|
||||
|
||||
for usage in internal_zone.usages:
|
||||
self.assertIsNotNone(usage.percentage, f'usage zone {usage.name} percentage is none')
|
||||
self.assertIsNotNone(usage.internal_gains, f'usage zone {usage.name} internal_gains is none')
|
||||
self.assertIsNotNone(usage.thermal_control, f'usage zone {usage.name} thermal_control is none')
|
||||
self.assertIsNotNone(usage.hours_day, f'usage zone {usage.name} hours_day is none')
|
||||
self.assertIsNotNone(usage.days_year, f'usage zone {usage.name} days_year is none')
|
||||
self.assertIsNotNone(
|
||||
usage.mechanical_air_change,
|
||||
f'usage zone {usage.name} mechanical_air_change is none'
|
||||
)
|
||||
# export files
|
||||
try:
|
||||
EnergyBuildingsExportsFactory('insel_monthly_energy_balance', city, self._output_path, 'MEB_Montreal').export()
|
||||
except Exception as err:
|
||||
logging.exception(err)
|
||||
self.fail("Insel MonthlyEnergyBalance ExportsFactory raised ExceptionType unexpectedly!")
|
161
tests/test_enrichement.py
Normal file
161
tests/test_enrichement.py
Normal file
|
@ -0,0 +1,161 @@
|
|||
"""
|
||||
TestGeometryFactory test and validate the city model structure geometric parameters
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
|
||||
|
||||
class TestGeometryFactory(TestCase):
|
||||
"""
|
||||
Non-functional TestGeometryFactory
|
||||
Load testing
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._city = None
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
|
||||
def _get_citygml(self, file):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('citygml', path=file_path).city
|
||||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _check_result(self, city):
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usages), 0, 'no building usages defined')
|
||||
for usage in internal_zone.usages:
|
||||
self.assertIsNotNone(usage.id, 'usage id is none')
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_thermal_zone(thermal_zone)
|
||||
|
||||
def _check_buildings(self, city):
|
||||
for building in city.buildings:
|
||||
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNotNone(internal_zone.usages, 'usage zones are not defined')
|
||||
self.assertIsNotNone(internal_zone.thermal_zones_from_internal_zones, 'thermal zones are not defined')
|
||||
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
||||
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
||||
self.assertIsNotNone(building.average_storey_height, 'building average_storey_height is none')
|
||||
self.assertIsNotNone(building.storeys_above_ground, 'building storeys_above_ground is none')
|
||||
self.assertTrue(building.is_conditioned, 'building is_conditioned is not conditioned')
|
||||
|
||||
def _check_thermal_zone(self, thermal_zone):
|
||||
self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none')
|
||||
self.assertIsNotNone(thermal_zone.usage_name, 'thermal_zone usage is not none')
|
||||
self.assertIsNotNone(thermal_zone.hours_day, 'thermal_zone hours a day is none')
|
||||
self.assertIsNotNone(thermal_zone.days_year, 'thermal_zone days a year is none')
|
||||
self.assertIsNotNone(thermal_zone.occupancy, 'thermal_zone occupancy is none')
|
||||
self.assertIsNotNone(thermal_zone.thermal_control, 'thermal_zone thermal control is none')
|
||||
self.assertIsNotNone(thermal_zone.internal_gains, 'thermal_zone internal gains returns none')
|
||||
|
||||
def _check_extra_thermal_zone(self, thermal_zone):
|
||||
self.assertIsNotNone(thermal_zone.lighting, 'thermal_zone lighting is none')
|
||||
self.assertIsNotNone(thermal_zone.appliances, 'thermal_zone appliances is none')
|
||||
self.assertIsNotNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is none')
|
||||
|
||||
@staticmethod
|
||||
def _prepare_case_usage_first(city, input_key, construction_key, usage_key):
|
||||
if input_key == 'pluto':
|
||||
for building in city.buildings:
|
||||
building.function = Dictionaries().pluto_function_to_hub_function[building.function]
|
||||
elif input_key == 'hft':
|
||||
for building in city.buildings:
|
||||
building.function = Dictionaries().hft_function_to_hub_function[building.function]
|
||||
UsageFactory(usage_key, city).enrich()
|
||||
ConstructionFactory(construction_key, city).enrich()
|
||||
|
||||
@staticmethod
|
||||
def _prepare_case_construction_first(city, input_key, construction_key, usage_key):
|
||||
if input_key == 'pluto':
|
||||
for building in city.buildings:
|
||||
building.function = Dictionaries().pluto_function_to_hub_function[building.function]
|
||||
elif input_key == 'hft':
|
||||
for building in city.buildings:
|
||||
building.function = Dictionaries().hft_function_to_hub_function[building.function]
|
||||
ConstructionFactory(construction_key, city).enrich()
|
||||
UsageFactory(usage_key, city).enrich()
|
||||
|
||||
def _test_hft(self, file):
|
||||
_construction_keys = ['nrel']
|
||||
_usage_keys = ['comnet']
|
||||
for construction_key in _construction_keys:
|
||||
for usage_key in _usage_keys:
|
||||
print(construction_key, usage_key)
|
||||
# construction factory called first
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_construction_first(city, 'hft', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
# usage factory called first
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_usage_first(city, 'hft', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
|
||||
def _test_pluto(self, file):
|
||||
_construction_keys = ['nrel']
|
||||
_usage_keys = ['comnet', 'nrcan']
|
||||
for construction_key in _construction_keys:
|
||||
for usage_key in _usage_keys:
|
||||
# construction factory called first
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_construction_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
# usage factory called first
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
self.assertTrue(len(city.buildings) > 0)
|
||||
self._prepare_case_usage_first(city, 'pluto', construction_key, usage_key)
|
||||
self._check_result(city)
|
||||
if usage_key == 'comnet':
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
|
||||
self._check_extra_thermal_zone(thermal_zone)
|
||||
|
||||
def test_enrichment(self):
|
||||
"""
|
||||
Test enrichment of the city with different orders
|
||||
:return: None
|
||||
"""
|
||||
file_1 = 'one_building_in_kelowna.gml'
|
||||
self._test_hft(file_1)
|
||||
file_2 = 'C40_Final.gml'
|
||||
self._test_hft(file_2)
|
150
tests/test_exports.py
Normal file
150
tests/test_exports.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
"""
|
||||
TestExports test and validate the city export formats
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
from hub.city_model_structure.city import City
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
|
||||
|
||||
class TestExports(TestCase):
|
||||
"""
|
||||
TestExports class contains the unittest for export functionality
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._city = None
|
||||
self._complete_city = None
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
|
||||
def _get_citygml(self, file):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('citygml', path=file_path).city
|
||||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _get_complete_city(self, from_pickle):
|
||||
if self._complete_city is None:
|
||||
if from_pickle:
|
||||
file_path = (self._example_path / 'ConcordiaSWGcampus.pickle').resolve()
|
||||
self._complete_city = City.load(file_path)
|
||||
else:
|
||||
file_path = (self._example_path / 'one_building_in_kelowna.gml').resolve()
|
||||
self._complete_city = self._get_citygml(file_path)
|
||||
for building in self._complete_city.buildings:
|
||||
building.function = Dictionaries().hft_function_to_hub_function[building.function]
|
||||
building.year_of_construction = 2006
|
||||
ConstructionFactory('nrel', self._complete_city).enrich()
|
||||
UsageFactory('nrcan', self._complete_city).enrich()
|
||||
cli = (self._example_path / 'weather' / 'inseldb_Summerland.cli').resolve()
|
||||
self._complete_city.climate_file = Path(cli)
|
||||
self._complete_city.climate_reference_city = 'Summerland'
|
||||
dummy_measures = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||||
for building in self._complete_city.buildings:
|
||||
building.heating_demand[cte.MONTH] = dummy_measures
|
||||
building.cooling_demand[cte.MONTH] = dummy_measures
|
||||
building.heating_demand[cte.YEAR] = [0.0]
|
||||
building.cooling_demand[cte.YEAR] = [0.0]
|
||||
return self._complete_city
|
||||
|
||||
def _export(self, export_type, from_pickle=False):
|
||||
self._complete_city = self._get_complete_city(from_pickle)
|
||||
ExportsFactory(export_type, self._complete_city, self._output_path, base_uri='../glb').export()
|
||||
|
||||
def _export_building_energy(self, export_type, from_pickle=False):
|
||||
self._complete_city = self._get_complete_city(from_pickle)
|
||||
EnergyBuildingsExportsFactory(export_type, self._complete_city, self._output_path).export()
|
||||
|
||||
def test_obj_export(self):
|
||||
"""
|
||||
export to obj
|
||||
"""
|
||||
self._export('obj', False)
|
||||
|
||||
def test_cesiumjs_tileset_export(self):
|
||||
"""
|
||||
export to cesiumjs tileset
|
||||
"""
|
||||
self._export('cesiumjs_tileset', False)
|
||||
tileset = Path(self._output_path / f'{self._city.name}.json')
|
||||
self.assertTrue(tileset.exists())
|
||||
with open(tileset, 'r') as f:
|
||||
json_tileset = json.load(f)
|
||||
self.assertEqual(1, len(json_tileset['root']['children']), "Wrong number of children")
|
||||
|
||||
def test_glb_export(self):
|
||||
"""
|
||||
export to glb format
|
||||
"""
|
||||
self._export('glb', False)
|
||||
for building in self._city.buildings:
|
||||
glb_file = Path(self._output_path / f'{building.name}.glb')
|
||||
self.assertTrue(glb_file.exists(), f'{building.name} Building glb wasn\'t correctly generated')
|
||||
|
||||
def test_geojson_export(self):
|
||||
self._export('geojson', False)
|
||||
geojson_file = Path(self._output_path / f'{self._city.name}.geojson')
|
||||
self.assertTrue(geojson_file.exists(), f'{geojson_file} doesn\'t exists')
|
||||
with open(geojson_file, 'r') as f:
|
||||
geojson = json.load(f)
|
||||
self.assertEqual(1, len(geojson['features']), 'Wrong number of buildings')
|
||||
geometry = geojson['features'][0]['geometry']
|
||||
self.assertEqual('Polygon', geometry['type'], 'Wrong geometry type')
|
||||
self.assertEqual(1, len(geometry['coordinates']), 'Wrong polygon structure')
|
||||
self.assertEqual(11, len(geometry['coordinates'][0]), 'Wrong number of vertices')
|
||||
os.unlink(geojson_file) # todo: this test need to cover a multipolygon example too
|
||||
|
||||
def test_energy_ade_export(self):
|
||||
"""
|
||||
export to energy ADE
|
||||
"""
|
||||
self._export_building_energy('energy_ade')
|
||||
|
||||
def test_sra_export(self):
|
||||
"""
|
||||
export to SRA
|
||||
"""
|
||||
self._export('sra')
|
||||
|
||||
def test_idf_export(self):
|
||||
"""
|
||||
export to IDF
|
||||
"""
|
||||
file = 'test.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
self.assertIsNotNone(city, 'city is none')
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
print(self._output_path)
|
||||
try:
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
except Exception:
|
||||
self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")
|
186
tests/test_geometry_factory.py
Normal file
186
tests/test_geometry_factory.py
Normal file
|
@ -0,0 +1,186 @@
|
|||
"""
|
||||
TestGeometryFactory test and validate the city model structure geometric parameters
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
import hub.exports.exports_factory
|
||||
from hub.helpers.dictionaries import MontrealFunctionToHubFunction
|
||||
from hub.helpers.geometry_helper import GeometryHelper
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
|
||||
|
||||
class TestGeometryFactory(TestCase):
|
||||
"""
|
||||
Non-functional TestGeometryFactory
|
||||
Load testing
|
||||
"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._city = None
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
|
||||
def _get_city(self, file, file_type, height_field=None, year_of_construction_field=None, function_field=None):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory(file_type,
|
||||
path=file_path,
|
||||
height_field=height_field,
|
||||
year_of_construction_field=year_of_construction_field,
|
||||
function_field=function_field,
|
||||
).city
|
||||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _check_buildings(self, city):
|
||||
for building in city.buildings:
|
||||
self.assertIsNotNone(building.name, 'building name is none')
|
||||
self.assertIsNotNone(building.type, 'building type is none')
|
||||
self.assertIsNotNone(building.volume, 'building volume is none')
|
||||
self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
|
||||
self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
|
||||
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
|
||||
self.assertIsNotNone(building.max_height, 'building max_height is none')
|
||||
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
|
||||
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
|
||||
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
|
||||
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
|
||||
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
|
||||
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
|
||||
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
|
||||
self.assertIsNotNone(building.grounds, 'building grounds is none')
|
||||
self.assertIsNotNone(building.walls, 'building walls is none')
|
||||
self.assertIsNotNone(building.roofs, 'building roofs is none')
|
||||
self.assertIsNotNone(building.internal_zones, 'building internal zones is none')
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNone(internal_zone.usages, 'usage zones are defined')
|
||||
self.assertIsNone(internal_zone.thermal_archetype, 'thermal archetype is defined')
|
||||
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
||||
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
||||
self.assertIsNone(building.terrains, 'building terrains is not none')
|
||||
self.assertIsNone(building.average_storey_height, 'building average_storey_height is not none')
|
||||
self.assertIsNone(building.storeys_above_ground, 'building storeys_above_ground is not none')
|
||||
self.assertEqual(len(building.heating_demand), 0, 'building heating is not none')
|
||||
self.assertEqual(len(building.cooling_demand), 0, 'building cooling is not none')
|
||||
self.assertIsNotNone(building.eave_height, 'building eave height is none')
|
||||
self.assertIsNotNone(building.roof_type, 'building roof type is none')
|
||||
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
|
||||
self.assertIsNone(building.households, 'building households is not none')
|
||||
self.assertFalse(building.is_conditioned, 'building is_conditioned is conditioned')
|
||||
|
||||
def _check_surfaces(self, building):
|
||||
for surface in building.surfaces:
|
||||
self.assertIsNotNone(surface.name, 'surface name is none')
|
||||
self.assertIsNotNone(surface.id, 'surface id is none')
|
||||
self.assertIsNotNone(surface.lower_corner, 'surface envelope_lower_corner is none')
|
||||
self.assertIsNotNone(surface.upper_corner, 'surface envelope_upper_corner is none')
|
||||
self.assertIsNotNone(surface.perimeter_area, 'surface area_above_ground is none')
|
||||
self.assertIsNotNone(surface.azimuth, 'surface azimuth is none')
|
||||
self.assertIsNotNone(surface.inclination, 'surface inclination is none')
|
||||
self.assertIsNotNone(surface.type, 'surface type is none')
|
||||
self.assertEqual(len(surface.global_irradiance), 0, 'global irradiance is calculated')
|
||||
self.assertIsNotNone(surface.perimeter_polygon, 'surface perimeter_polygon is none')
|
||||
self.assertIsNone(surface.holes_polygons, 'surface hole_polygons is not none')
|
||||
self.assertIsNotNone(surface.solid_polygon, 'surface solid_polygon is none')
|
||||
self.assertIsNone(surface.short_wave_reflectance, 'surface short_wave_reflectance is not none')
|
||||
self.assertIsNone(surface.long_wave_emittance, 'surface long_wave_emittance is not none')
|
||||
self.assertIsNotNone(surface.inverse, 'surface inverse is none')
|
||||
self.assertEqual(len(surface.associated_thermal_boundaries), 0, 'associated_thermal_boundaries are assigned')
|
||||
self.assertIsNone(surface.vegetation, 'surface vegetation is not none')
|
||||
|
||||
# citygml_classes
|
||||
def test_import_citygml(self):
|
||||
"""
|
||||
Test city objects in the city
|
||||
:return: None
|
||||
"""
|
||||
file = 'FZK_Haus_LoD_2.gml'
|
||||
city = self._get_city(file, 'citygml')
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
self._check_surfaces(building)
|
||||
city = ConstructionFactory('nrel', city).enrich()
|
||||
|
||||
def test_import_obj(self):
|
||||
"""
|
||||
Test obj import
|
||||
"""
|
||||
file = 'kelowna.obj'
|
||||
city = self._get_city(file, 'obj')
|
||||
self.assertTrue(len(city.buildings) == 1)
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
self._check_surfaces(building)
|
||||
|
||||
def test_import_geojson(self):
|
||||
"""
|
||||
Test geojson import
|
||||
"""
|
||||
file = Path(self._example_path / 'test.geojson').resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=file,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
aliases_field=['ID_UEV', 'CIVIQUE_DE', 'NOM_RUE'],
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=MontrealFunctionToHubFunction().dictionary).city
|
||||
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
|
||||
for building in city.building_alias('01002777'):
|
||||
self.assertEqual('1', building.name, 'Wrong building name when looking for alias')
|
||||
self.assertEqual(8, len(city.building_alias('rue Sherbrooke Ouest (MTL+MTO+WMT)')))
|
||||
self.assertEqual(17, len(city.buildings), 'wrong number of buildings')
|
||||
|
||||
self.assertIsNotNone(city.city_object('15'), 'Building name 15 is missing in the city')
|
||||
city.remove_city_object(city.city_object('15'))
|
||||
self.assertIsNone(city.city_object('15'), 'Building name 15 wasn\'t removed')
|
||||
for building in city.buildings:
|
||||
_building = city.city_object(building.name)
|
||||
self.assertEqual(_building.name, building.name, 'hash map it\'s unsync')
|
||||
|
||||
def test_map_neighbours(self):
|
||||
"""
|
||||
Test neighbours map creation
|
||||
"""
|
||||
file = 'test.geojson'
|
||||
|
||||
city = self._get_city(file, 'geojson',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='LIBELLE_UT')
|
||||
info_lod0 = GeometryHelper.city_mapping(city, plot=False)
|
||||
city = self._get_city(file, 'geojson',
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='LIBELLE_UT')
|
||||
info_lod1 = GeometryHelper.city_mapping(city, plot=False)
|
||||
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
|
||||
self.assertEqual(info_lod0, info_lod1)
|
||||
self.assertEqual(2, len(city.city_object('1').neighbours))
|
||||
self.assertEqual(3, len(city.city_object('2').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('3').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('4').neighbours))
|
||||
self.assertEqual(3, len(city.city_object('5').neighbours))
|
||||
self.assertEqual(3, len(city.city_object('6').neighbours))
|
||||
self.assertEqual(1, len(city.city_object('8').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('9').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('10').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('11').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('12').neighbours))
|
||||
self.assertEqual(1, len(city.city_object('13').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('14').neighbours))
|
||||
self.assertEqual(1, len(city.city_object('15').neighbours))
|
||||
self.assertEqual(1, len(city.city_object('16').neighbours))
|
||||
self.assertEqual(2, len(city.city_object('67').neighbours))
|
||||
self.assertEqual(1, len(city.city_object('68').neighbours))
|
||||
|
||||
self.assertEqual('12', city.city_object('8').neighbours[0].name)
|
||||
self.assertEqual('14', city.city_object('13').neighbours[0].name)
|
||||
self.assertEqual('14', city.city_object('15').neighbours[0].name)
|
37
tests/test_greenery_catalog.py
Normal file
37
tests/test_greenery_catalog.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Test greenery factory test and validate the greenery construction
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from hub.catalog_factories.greenery_catalog_factory import GreeneryCatalogFactory
|
||||
|
||||
|
||||
class TestGreeneryCatalog(TestCase):
|
||||
def test_catalog(self):
|
||||
catalog = GreeneryCatalogFactory('nrel').catalog
|
||||
catalog_categories = catalog.names()
|
||||
vegetations = catalog.names('vegetations')
|
||||
plants = catalog.names('plants')
|
||||
soils = catalog.names('soils')
|
||||
self.assertTrue(len(catalog_categories) == 3)
|
||||
self.assertTrue(len(vegetations['vegetations']) == 4)
|
||||
self.assertTrue(len(plants['plants']) == 14)
|
||||
self.assertTrue(len(soils['soils']) == 6)
|
||||
with self.assertRaises(ValueError):
|
||||
catalog.names('unknown')
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
for value in catalog_categories[category]:
|
||||
catalog.get_entry(value)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
||||
|
||||
self.assertTrue(len(catalog.entries().vegetations) == 4)
|
||||
self.assertTrue(len(catalog.entries().plants) == 14)
|
||||
self.assertTrue(len(catalog.entries().soils) == 6)
|
79
tests/test_greenery_in_idf.py
Normal file
79
tests/test_greenery_in_idf.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
"""
|
||||
Greenery in idf test
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
from hub.city_model_structure.greenery.plant import Plant
|
||||
from hub.city_model_structure.greenery.soil import Soil
|
||||
from hub.city_model_structure.greenery.vegetation import Vegetation
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
|
||||
|
||||
class GreeneryInIdf(TestCase):
|
||||
"""
|
||||
GreeneryInIdf TestCase 1
|
||||
"""
|
||||
def test_greenery_in_idf(self):
|
||||
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
city_file = (self._example_path / "one_building_in_kelowna.gml").resolve()
|
||||
city = GeometryFactory('citygml', path=city_file).city
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
vegetation_name = 'BaseEco'
|
||||
soil_thickness = 0.18
|
||||
soil_name = 'EcoRoofSoil'
|
||||
roughness = 'MediumSmooth'
|
||||
dry_conductivity = 0.4
|
||||
dry_density = 641
|
||||
dry_specific_heat = 1100
|
||||
thermal_absorptance = 0.95
|
||||
solar_absorptance = 0.8
|
||||
visible_absorptance = 0.7
|
||||
saturation_volumetric_moisture_content = 0.4
|
||||
residual_volumetric_moisture_content = 0.01
|
||||
soil = Soil(soil_name, roughness, dry_conductivity, dry_density, dry_specific_heat, thermal_absorptance,
|
||||
solar_absorptance, visible_absorptance, saturation_volumetric_moisture_content,
|
||||
residual_volumetric_moisture_content)
|
||||
soil.initial_volumetric_moisture_content = 0.2
|
||||
plant_name = 'plant'
|
||||
height = 0.5
|
||||
leaf_area_index = 5
|
||||
leaf_reflectivity = 0.2
|
||||
leaf_emissivity = 0.95
|
||||
minimal_stomatal_resistance = 180
|
||||
co2_sequestration = 0
|
||||
grows_on_soils = [soil]
|
||||
plant = Plant(plant_name, height, leaf_area_index, leaf_reflectivity, leaf_emissivity, minimal_stomatal_resistance,
|
||||
co2_sequestration, grows_on_soils)
|
||||
plant.percentage = 1
|
||||
plants = [plant]
|
||||
vegetation = Vegetation(vegetation_name, soil, soil_thickness, plants)
|
||||
for building in city.buildings:
|
||||
for surface in building.surfaces:
|
||||
if surface.type == cte.ROOF:
|
||||
surface.vegetation = vegetation
|
||||
|
||||
_idf = EnergyBuildingsExportsFactory('idf', city, output_path).export()
|
||||
self.assertIsNotNone(_idf)
|
||||
city = GeometryFactory('citygml', path=city_file).city
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
_idf = EnergyBuildingsExportsFactory('idf', city, output_path).export()
|
||||
self.assertIsNotNone(_idf)
|
94
tests/test_results_import.py
Normal file
94
tests/test_results_import.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
"""
|
||||
TestExports test and validate the city export formats
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
|
||||
|
||||
class TestResultsImport(TestCase):
|
||||
"""
|
||||
TestImports class contains the unittest for import functionality
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
file = 'test.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
ConstructionFactory('nrcan', self._city).enrich()
|
||||
UsageFactory('comnet', self._city).enrich()
|
||||
|
||||
def test_sra_import(self):
|
||||
ExportsFactory('sra', self._city, self._output_path).export()
|
||||
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', self._city, self._output_path).enrich()
|
||||
# Check that all the buildings have radiance in the surfaces
|
||||
for building in self._city.buildings:
|
||||
for surface in building.surfaces:
|
||||
self.assertIsNotNone(surface.global_irradiance)
|
||||
|
||||
def test_meb_import(self):
|
||||
ExportsFactory('sra', self._city, self._output_path).export()
|
||||
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', self._city, self._output_path).enrich()
|
||||
EnergyBuildingsExportsFactory('insel_monthly_energy_balance', self._city, self._output_path).export()
|
||||
for building in self._city.buildings:
|
||||
insel_path = (self._output_path / f'{building.name}.insel')
|
||||
subprocess.run(['insel', str(insel_path)])
|
||||
ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich()
|
||||
# Check that all the buildings have heating and cooling values
|
||||
for building in self._city.buildings:
|
||||
self.assertIsNotNone(building.heating_demand[cte.MONTH])
|
||||
self.assertIsNotNone(building.cooling_demand[cte.MONTH])
|
||||
self.assertIsNotNone(building.heating_demand[cte.YEAR])
|
||||
self.assertIsNotNone(building.cooling_demand[cte.YEAR])
|
||||
self.assertIsNotNone(building.lighting_peak_load[cte.MONTH])
|
||||
self.assertIsNotNone(building.lighting_peak_load[cte.YEAR])
|
||||
self.assertIsNotNone(building.appliances_peak_load[cte.MONTH])
|
||||
self.assertIsNotNone(building.appliances_peak_load[cte.YEAR])
|
||||
|
||||
def test_peak_loads(self):
|
||||
# todo: this is not technically a import
|
||||
ExportsFactory('sra', self._city, self._output_path).export()
|
||||
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', self._city, self._output_path).enrich()
|
||||
for building in self._city.buildings:
|
||||
self.assertIsNotNone(building.heating_peak_load)
|
||||
self.assertIsNotNone(building.cooling_peak_load)
|
||||
|
||||
values = [0 for _ in range(8760)]
|
||||
values[0] = 1000
|
||||
expected_monthly_list = [0 for _ in range(12)]
|
||||
expected_monthly_list[0] = 1000
|
||||
for building in self._city.buildings:
|
||||
building.heating_demand[cte.HOUR] = values
|
||||
building.cooling_demand[cte.HOUR] = values
|
||||
self.assertIsNotNone(building.heating_peak_load)
|
||||
self.assertIsNotNone(building.cooling_peak_load)
|
36
tests/test_systems_catalog.py
Normal file
36
tests/test_systems_catalog.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
TestSystemsCatalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory
|
||||
|
||||
|
||||
class TestSystemsCatalog(TestCase):
|
||||
|
||||
def test_montreal_custom_catalog(self):
|
||||
catalog = EnergySystemsCatalogFactory('montreal_custom').catalog
|
||||
catalog_categories = catalog.names()
|
||||
archetypes = catalog.names('archetypes')
|
||||
self.assertEqual(23, len(archetypes['archetypes']))
|
||||
systems = catalog.names('systems')
|
||||
self.assertEqual(18, len(systems['systems']))
|
||||
generation_equipments = catalog.names('generation_equipments')
|
||||
self.assertEqual(7, len(generation_equipments['generation_equipments']))
|
||||
distribution_equipments = catalog.names('distribution_equipments')
|
||||
self.assertEqual(8, len(distribution_equipments['distribution_equipments']))
|
||||
emission_equipments = catalog.names('emission_equipments')
|
||||
self.assertEqual(3, len(emission_equipments['emission_equipments']))
|
||||
with self.assertRaises(ValueError):
|
||||
catalog.names('unknown')
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
for value in catalog_categories[category]:
|
||||
catalog.get_entry(value)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
118
tests/test_systems_factory.py
Normal file
118
tests/test_systems_factory.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
"""
|
||||
TestSystemsFactory
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2023 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
import copy
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||
from hub.city_model_structure.energy_systems.energy_system import EnergySystem
|
||||
from hub.city_model_structure.energy_systems.generation_system import GenerationSystem
|
||||
from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem
|
||||
from hub.city_model_structure.energy_systems.emission_system import EmissionSystem
|
||||
|
||||
|
||||
class TestSystemsFactory(TestCase):
|
||||
"""
|
||||
TestSystemsFactory TestCase
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
file = 'test.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
def test_montreal_custom_system_factory(self):
|
||||
"""
|
||||
Enrich the city with the construction information and verify it
|
||||
"""
|
||||
for building in self._city.buildings:
|
||||
building.energy_systems_archetype_name = 'system 1 gas'
|
||||
|
||||
EnergySystemsFactory('montreal_custom', self._city).enrich()
|
||||
self.assertEqual(17, len(self._city.energy_systems_connection_table))
|
||||
|
||||
def test_montreal_custom_system_results(self):
|
||||
"""
|
||||
Enrich the city with the construction information and verify it
|
||||
"""
|
||||
ConstructionFactory('nrcan', self._city).enrich()
|
||||
UsageFactory('nrcan', self._city).enrich()
|
||||
WeatherFactory('epw', self._city).enrich()
|
||||
ExportsFactory('sra', self._city, self._output_path).export()
|
||||
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', self._city, self._output_path).enrich()
|
||||
EnergyBuildingsExportsFactory('insel_monthly_energy_balance', self._city, self._output_path).export()
|
||||
for building in self._city.buildings:
|
||||
insel_path = (self._output_path / f'{building.name}.insel')
|
||||
subprocess.run(['insel', str(insel_path)])
|
||||
ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich()
|
||||
|
||||
for building in self._city.buildings:
|
||||
building.energy_systems_archetype_name = 'system 1 gas pv'
|
||||
EnergySystemsFactory('montreal_custom', self._city).enrich()
|
||||
# Need to assign energy systems to buildings:
|
||||
energy_systems_connection = self._city.energy_systems_connection_table
|
||||
for building in self._city.buildings:
|
||||
_building_energy_systems = []
|
||||
energy_systems = energy_systems_connection['Energy System Type'][
|
||||
energy_systems_connection['Building'] == building.name]
|
||||
for energy_system in energy_systems:
|
||||
_generic_building_energy_systems = self._city.generic_energy_systems[energy_system]
|
||||
for _generic_building_energy_system in _generic_building_energy_systems:
|
||||
_building_energy_equipment = EnergySystem()
|
||||
_building_energy_equipment.demand_types = _generic_building_energy_system.demand_types
|
||||
|
||||
_building_distribution_system = DistributionSystem()
|
||||
_building_distribution_system.generic_distribution_system = (
|
||||
copy.deepcopy(_generic_building_energy_system.distribution_system)
|
||||
)
|
||||
_building_emission_system = EmissionSystem()
|
||||
_building_emission_system.generic_emission_system = (
|
||||
copy.deepcopy(_generic_building_energy_system.emission_system)
|
||||
)
|
||||
_building_generation_system = GenerationSystem()
|
||||
_building_generation_system.generic_generation_system = (
|
||||
copy.deepcopy(_generic_building_energy_system.generation_system)
|
||||
)
|
||||
if cte.HEATING in _building_energy_equipment.demand_types:
|
||||
_building_generation_system.heat_power = building.heating_peak_load[cte.YEAR][0]
|
||||
if cte.COOLING in _building_energy_equipment.demand_types:
|
||||
_building_generation_system.cooling_power = building.cooling_peak_load[cte.YEAR][0]
|
||||
_building_energy_equipment.generation_system = _building_generation_system
|
||||
_building_energy_equipment.distribution_system = _building_distribution_system
|
||||
_building_energy_equipment.emission_system = _building_emission_system
|
||||
|
||||
_building_energy_systems.append(_building_energy_equipment)
|
||||
building.energy_systems = _building_energy_systems
|
||||
|
||||
for building in self._city.buildings:
|
||||
self.assertLess(0, building.heating_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.cooling_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.domestic_hot_water_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.onsite_electrical_production[cte.YEAR][0])
|
23
tests/test_usage_catalog.py
Normal file
23
tests/test_usage_catalog.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
TestUsageCatalog
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
|
||||
|
||||
|
||||
class TestConstructionCatalog(TestCase):
|
||||
def test_comnet_catalog(self):
|
||||
catalog = UsageCatalogFactory('comnet').catalog
|
||||
self.assertIsNotNone(catalog, 'catalog is none')
|
||||
content = catalog.entries()
|
||||
self.assertEqual(32, len(content.usages), 'Wrong number of usages')
|
||||
|
||||
def test_nrcan_catalog(self):
|
||||
catalog = UsageCatalogFactory('nrcan').catalog
|
||||
self.assertIsNotNone(catalog, 'catalog is none')
|
||||
content = catalog.entries()
|
||||
self.assertEqual(34, len(content.usages), 'Wrong number of usages')
|
184
tests/test_usage_factory.py
Normal file
184
tests/test_usage_factory.py
Normal file
|
@ -0,0 +1,184 @@
|
|||
"""
|
||||
TestUsageFactory test and validate the city model structure usage parameters
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
|
||||
|
||||
class TestUsageFactory(TestCase):
|
||||
"""
|
||||
TestUsageFactory TestCase
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Configure test environment
|
||||
:return:
|
||||
"""
|
||||
self._city = None
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
|
||||
def _get_citygml(self, file):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('citygml', path=file_path).city
|
||||
self.assertIsNotNone(self._city, 'city is none')
|
||||
return self._city
|
||||
|
||||
def _check_buildings(self, city):
|
||||
for building in city.buildings:
|
||||
self.assertIsNotNone(building.name, 'building name is none')
|
||||
self.assertIsNotNone(building.type, 'building type is none')
|
||||
self.assertIsNotNone(building.volume, 'building volume is none')
|
||||
self.assertIsNotNone(building.detailed_polyhedron, 'building detailed polyhedron is none')
|
||||
self.assertIsNotNone(building.simplified_polyhedron, 'building simplified polyhedron is none')
|
||||
self.assertIsNotNone(building.surfaces, 'building surfaces is none')
|
||||
self.assertIsNotNone(building.centroid, 'building centroid is none')
|
||||
self.assertIsNotNone(building.max_height, 'building max_height is none')
|
||||
self.assertEqual(len(building.external_temperature), 0, 'building external temperature is calculated')
|
||||
self.assertEqual(len(building.global_horizontal), 0, 'building global horizontal is calculated')
|
||||
self.assertEqual(len(building.diffuse), 0, 'building diffuse is calculated')
|
||||
self.assertEqual(len(building.beam), 0, 'building beam is calculated')
|
||||
self.assertIsNotNone(building.lower_corner, 'building lower corner is none')
|
||||
self.assertEqual(len(building.sensors), 0, 'building sensors are assigned')
|
||||
self.assertIsNotNone(building.internal_zones, 'no internal zones created')
|
||||
self.assertIsNotNone(building.grounds, 'building grounds is none')
|
||||
self.assertIsNotNone(building.walls, 'building walls is none')
|
||||
self.assertIsNotNone(building.roofs, 'building roofs is none')
|
||||
for internal_zone in building.internal_zones:
|
||||
if internal_zone.usages is not None:
|
||||
self.assertTrue(len(internal_zone.usages) > 0, 'usage zones are not defined')
|
||||
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
||||
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
||||
self.assertIsNone(building.terrains, 'building terrains is not none')
|
||||
self.assertIsNotNone(building.year_of_construction, 'building year_of_construction is none')
|
||||
self.assertIsNotNone(building.function, 'building function is none')
|
||||
self.assertEqual(len(building.heating_demand), 0, 'building heating is not none')
|
||||
self.assertEqual(len(building.cooling_demand), 0, 'building cooling is not none')
|
||||
self.assertIsNotNone(building.eave_height, 'building eave height is none')
|
||||
self.assertIsNotNone(building.roof_type, 'building roof type is none')
|
||||
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
|
||||
|
||||
def _check_usage(self, usage):
|
||||
self.assertIsNotNone(usage.name, 'usage is none')
|
||||
self.assertIsNotNone(usage.percentage, 'usage percentage is none')
|
||||
self.assertIsNotNone(usage.hours_day, 'hours per day is none')
|
||||
self.assertIsNotNone(usage.days_year, 'days per year is none')
|
||||
self.assertIsNotNone(usage.thermal_control, 'thermal control is none')
|
||||
self.assertIsNotNone(usage.thermal_control.mean_heating_set_point, 'control heating set point is none')
|
||||
self.assertIsNotNone(usage.thermal_control.heating_set_back, 'control heating set back is none')
|
||||
self.assertIsNotNone(usage.thermal_control.mean_cooling_set_point, 'control cooling set point is none')
|
||||
|
||||
def test_import_comnet(self):
|
||||
"""
|
||||
Enrich the city with the usage information from comnet and verify it
|
||||
"""
|
||||
file = 'pluto_building.gml'
|
||||
city = self._get_citygml(file)
|
||||
for building in city.buildings:
|
||||
building.function = Dictionaries().pluto_function_to_hub_function[building.function]
|
||||
|
||||
UsageFactory('comnet', city).enrich()
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertIsNot(len(internal_zone.usages), 0, 'no building usage defined')
|
||||
for usage in internal_zone.usages:
|
||||
self._check_usage(usage)
|
||||
self.assertIsNotNone(usage.mechanical_air_change, 'mechanical air change is none')
|
||||
self.assertIsNotNone(usage.thermal_control.heating_set_point_schedules,
|
||||
'control heating set point schedule is none')
|
||||
self.assertIsNotNone(usage.thermal_control.cooling_set_point_schedules,
|
||||
'control cooling set point schedule is none')
|
||||
self.assertIsNotNone(usage.occupancy, 'occupancy is none')
|
||||
occupancy = usage.occupancy
|
||||
self.assertIsNotNone(occupancy.occupancy_density, 'occupancy density is none')
|
||||
self.assertIsNotNone(occupancy.latent_internal_gain, 'occupancy latent internal gain is none')
|
||||
self.assertIsNotNone(occupancy.sensible_convective_internal_gain,
|
||||
'occupancy sensible convective internal gain is none')
|
||||
self.assertIsNotNone(occupancy.sensible_radiative_internal_gain,
|
||||
'occupancy sensible radiant internal gain is none')
|
||||
self.assertIsNotNone(occupancy.occupancy_schedules, 'occupancy schedule is none')
|
||||
self.assertIsNotNone(usage.lighting, 'lighting is none')
|
||||
lighting = usage.lighting
|
||||
self.assertIsNotNone(lighting.density, 'lighting density is none')
|
||||
self.assertIsNotNone(lighting.latent_fraction, 'lighting latent fraction is none')
|
||||
self.assertIsNotNone(lighting.convective_fraction, 'lighting convective fraction is none')
|
||||
self.assertIsNotNone(lighting.radiative_fraction, 'lighting radiant fraction is none')
|
||||
self.assertIsNotNone(lighting.schedules, 'lighting schedule is none')
|
||||
self.assertIsNotNone(usage.appliances, 'appliances is none')
|
||||
appliances = usage.appliances
|
||||
self.assertIsNotNone(appliances.density, 'appliances density is none')
|
||||
self.assertIsNotNone(appliances.latent_fraction, 'appliances latent fraction is none')
|
||||
self.assertIsNotNone(appliances.convective_fraction, 'appliances convective fraction is none')
|
||||
self.assertIsNotNone(appliances.radiative_fraction, 'appliances radiant fraction is none')
|
||||
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')
|
||||
self.assertIsNotNone(usage.thermal_control.hvac_availability_schedules,
|
||||
'control hvac availability is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.density, 'domestic hot water density is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.service_temperature,
|
||||
'domestic hot water service temperature is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.schedules, 'domestic hot water schedules is none')
|
||||
|
||||
def test_import_nrcan(self):
|
||||
"""
|
||||
Enrich the city with the usage information from nrcan and verify it
|
||||
"""
|
||||
file = 'test.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
if internal_zone.usages is not None:
|
||||
self.assertIsNot(len(internal_zone.usages), 0, 'no building usage defined')
|
||||
for usage in internal_zone.usages:
|
||||
self._check_usage(usage)
|
||||
self.assertIsNotNone(usage.mechanical_air_change, 'mechanical air change is none')
|
||||
self.assertIsNotNone(usage.thermal_control.heating_set_point_schedules,
|
||||
'control heating set point schedule is none')
|
||||
self.assertIsNotNone(usage.thermal_control.cooling_set_point_schedules,
|
||||
'control cooling set point schedule is none')
|
||||
self.assertIsNotNone(usage.occupancy, 'occupancy is none')
|
||||
occupancy = usage.occupancy
|
||||
self.assertIsNotNone(occupancy.occupancy_density, 'occupancy density is none')
|
||||
self.assertIsNotNone(occupancy.latent_internal_gain, 'occupancy latent internal gain is none')
|
||||
self.assertIsNotNone(occupancy.sensible_convective_internal_gain,
|
||||
'occupancy sensible convective internal gain is none')
|
||||
self.assertIsNotNone(occupancy.sensible_radiative_internal_gain,
|
||||
'occupancy sensible radiant internal gain is none')
|
||||
self.assertIsNotNone(occupancy.occupancy_schedules, 'occupancy schedule is none')
|
||||
self.assertIsNotNone(usage.lighting, 'lighting is none')
|
||||
lighting = usage.lighting
|
||||
self.assertIsNotNone(lighting.density, 'lighting density is none')
|
||||
self.assertIsNotNone(lighting.latent_fraction, 'lighting latent fraction is none')
|
||||
self.assertIsNotNone(lighting.convective_fraction, 'lighting convective fraction is none')
|
||||
self.assertIsNotNone(lighting.radiative_fraction, 'lighting radiant fraction is none')
|
||||
self.assertIsNotNone(lighting.schedules, 'lighting schedule is none')
|
||||
self.assertIsNotNone(usage.appliances, 'appliances is none')
|
||||
appliances = usage.appliances
|
||||
self.assertIsNotNone(appliances.density, 'appliances density is none')
|
||||
self.assertIsNotNone(appliances.latent_fraction, 'appliances latent fraction is none')
|
||||
self.assertIsNotNone(appliances.convective_fraction, 'appliances convective fraction is none')
|
||||
self.assertIsNotNone(appliances.radiative_fraction, 'appliances radiant fraction is none')
|
||||
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')
|
||||
self.assertIsNotNone(usage.thermal_control.hvac_availability_schedules,
|
||||
'control hvac availability is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.peak_flow, 'domestic hot water peak flow is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.service_temperature,
|
||||
'domestic hot water service temperature is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.schedules, 'domestic hot water schedules is none')
|
3377
tests/tests_data/C40_Final.gml
Normal file
3377
tests/tests_data/C40_Final.gml
Normal file
File diff suppressed because it is too large
Load Diff
240
tests/tests_data/FZK_Haus_LoD_2.gml
Normal file
240
tests/tests_data/FZK_Haus_LoD_2.gml
Normal file
|
@ -0,0 +1,240 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- IFC to CityGML by IFCExplorer KIT --><!-- CityGML to Sketchup by Sketchup CityGML Plugin FH GelsenKirchen --><!--CityGML Dataset produced with CityGML Export Plugin for Sketchup by GeoRES --><!--http://www.geores.de --><!-- Edited Manually in Oxygen 8.2 --><!-- Modified by GMLOffset.xslt at Mon Dec 6 2010 --><!-- Version 2 Building located in the area of KIT Campus North)--><!-- Modified by GMLOffset.xslt at Wed Dec 8 2010 --><!-- Modified by GMLOffset.xslt at Wed Mar 29 2017 --><core:CityModel xsi:schemaLocation="http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns="http://www.opengis.net/citygml/profiles/base/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<!-- Manually edited by KHH 23.01.2017, CityGML 2.0, Address added, Codespaces added -->
|
||||
<gml:name>AC14-FZK-Haus</gml:name>
|
||||
<gml:boundedBy>
|
||||
<gml:Envelope srsDimension="3" srsName="urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH">
|
||||
<gml:lowerCorner srsDimension="3">457842 5439083 111.8 </gml:lowerCorner>
|
||||
<gml:upperCorner srsDimension="3">457854 5439093 118.317669 </gml:upperCorner>
|
||||
</gml:Envelope>
|
||||
</gml:boundedBy>
|
||||
<core:cityObjectMember>
|
||||
<bldg:Building gml:id="UUID_d281adfc-4901-0f52-540b-4cc1a9325f82">
|
||||
<gml:description>FZK-Haus (Forschungszentrum Karlsruhe, now KIT), created by Karl-Heinz
|
||||
Haefele </gml:description>
|
||||
<gml:name>AC14-FZK-Haus</gml:name>
|
||||
<core:creationDate>2017-01-23</core:creationDate>
|
||||
<core:relativeToTerrain>entirelyAboveTerrain</core:relativeToTerrain>
|
||||
<gen:measureAttribute name="GrossPlannedArea">
|
||||
<gen:value uom="m2">120.00</gen:value>
|
||||
</gen:measureAttribute>
|
||||
<gen:stringAttribute name="ConstructionMethod">
|
||||
<gen:value>New Building</gen:value>
|
||||
</gen:stringAttribute>
|
||||
<gen:stringAttribute name="IsLandmarked">
|
||||
<gen:value>NO</gen:value>
|
||||
</gen:stringAttribute>
|
||||
<bldg:class codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_class.xml">1000</bldg:class>
|
||||
<bldg:function codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_function.xml">1000</bldg:function>
|
||||
<bldg:usage codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_usage.xml">1000</bldg:usage>
|
||||
<bldg:yearOfConstruction>2020</bldg:yearOfConstruction>
|
||||
<bldg:roofType codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_roofType.xml">1030</bldg:roofType>
|
||||
<bldg:measuredHeight uom="m">6.52</bldg:measuredHeight>
|
||||
<bldg:storeysAboveGround>2</bldg:storeysAboveGround>
|
||||
<bldg:storeysBelowGround>0</bldg:storeysBelowGround>
|
||||
<bldg:lod2Solid>
|
||||
<gml:Solid>
|
||||
<gml:exterior>
|
||||
<gml:CompositeSurface>
|
||||
<!--Outer Wall 1 (West) -->
|
||||
<gml:surfaceMember xlink:href="#PolyID7350_878_759628_120742"> </gml:surfaceMember>
|
||||
<!--Outer Wall 1 (West) -->
|
||||
<!--Outer Wall 2 (South) -->
|
||||
<gml:surfaceMember xlink:href="#PolyID7351_1722_416019_316876" />
|
||||
<!--Outer Wall 2 (South) -->
|
||||
<!--Outer Wall 3 (East) -->
|
||||
<gml:surfaceMember xlink:href="#PolyID7352_230_209861_355851" />
|
||||
<!--Outer Wall 3 (East) -->
|
||||
<!--Roof 1 (North) -->
|
||||
<gml:surfaceMember xlink:href="#PolyID7353_166_774155_320806" />
|
||||
<!--Roof 1 (North) -->
|
||||
<!--Outer Wall 4 (North) -->
|
||||
<gml:surfaceMember xlink:href="#PolyID7354_1362_450904_410226" />
|
||||
<!--Outer Wall 2 (North) -->
|
||||
<!--Roof 2 (South) -->
|
||||
<gml:surfaceMember xlink:href="#PolyID7355_537_416207_260034" />
|
||||
<!--Roof 2 (South) -->
|
||||
<!--Base Surface -->
|
||||
<gml:surfaceMember xlink:href="#PolyID7356_612_880782_415367" />
|
||||
<!--Base Surface -->
|
||||
</gml:CompositeSurface>
|
||||
</gml:exterior>
|
||||
</gml:Solid>
|
||||
</bldg:lod2Solid>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="GML_5856d7ad-5e34-498a-817b-9544bfbb1475">
|
||||
<gml:name>Outer Wall 1 (West)</gml:name>
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="PolyID7350_878_759628_120742">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing gml:id="PolyID7350_878_759628_120742_0">
|
||||
<gml:pos>457842 5439088 118.317691453624 </gml:pos>
|
||||
<gml:pos>457842 5439093 115.430940107676 </gml:pos>
|
||||
<gml:pos>457842 5439093 111.8 </gml:pos>
|
||||
<gml:pos>457842 5439083 111.8 </gml:pos>
|
||||
<gml:pos>457842 5439083 115.430940107676 </gml:pos>
|
||||
<gml:pos>457842 5439088 118.317691453624 </gml:pos>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="GML_d38cf762-c29d-4491-88c9-bdc89e141978">
|
||||
<gml:name>Outer Wall 2 (South)</gml:name>
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="PolyID7351_1722_416019_316876">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing gml:id="PolyID7351_1722_416019_316876_0">
|
||||
<gml:pos>457854 5439083 115.430940107676 </gml:pos>
|
||||
<gml:pos>457842 5439083 115.430940107676 </gml:pos>
|
||||
<gml:pos>457842 5439083 111.8 </gml:pos>
|
||||
<gml:pos>457854 5439083 111.8 </gml:pos>
|
||||
<gml:pos>457854 5439083 115.430940107676 </gml:pos>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="GML_8e5db638-e46a-4739-a98a-2fc2d39c9069">
|
||||
<gml:name>Outer Wall 3 (East)</gml:name>
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="PolyID7352_230_209861_355851">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing gml:id="PolyID7352_230_209861_355851_0">
|
||||
<gml:pos>457854 5439088 118.317691453624 </gml:pos>
|
||||
<gml:pos>457854 5439083 115.430940107676 </gml:pos>
|
||||
<gml:pos>457854 5439083 111.8 </gml:pos>
|
||||
<gml:pos>457854 5439093 111.8 </gml:pos>
|
||||
<gml:pos>457854 5439093 115.430940107676 </gml:pos>
|
||||
<gml:pos>457854 5439088 118.317691453624 </gml:pos>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="GML_875d470b-32b4-4985-a4c8-0f02caa342a2">
|
||||
<gml:name>Roof 1 (North)</gml:name>
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="PolyID7353_166_774155_320806">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing gml:id="PolyID7353_166_774155_320806_0">
|
||||
<gml:pos>457842 5439088 118.317691453624 </gml:pos>
|
||||
<gml:pos>457854 5439088 118.317691453624 </gml:pos>
|
||||
<gml:pos>457854 5439093 115.430940107676 </gml:pos>
|
||||
<gml:pos>457842 5439093 115.430940107676 </gml:pos>
|
||||
<gml:pos>457842 5439088 118.317691453624 </gml:pos>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="GML_0f30f604-e70d-4dfe-ba35-853bc69609cc">
|
||||
<gml:name>Outer Wall 4 (North)</gml:name>
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="PolyID7354_1362_450904_410226">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing gml:id="PolyID7354_1362_450904_410226_0">
|
||||
<gml:pos>457842 5439093 115.430940107676 </gml:pos>
|
||||
<gml:pos>457854 5439093 115.430940107676 </gml:pos>
|
||||
<gml:pos>457854 5439093 111.8 </gml:pos>
|
||||
<gml:pos>457842 5439093 111.8 </gml:pos>
|
||||
<gml:pos>457842 5439093 115.430940107676 </gml:pos>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="GML_eeb6796a-e261-4d3b-a6f2-475940cca80a">
|
||||
<gml:name>Roof 2 (South)</gml:name>
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="PolyID7355_537_416207_260034">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing gml:id="PolyID7355_537_416207_260034_0">
|
||||
<gml:pos>457854 5439083 115.430940107676 </gml:pos>
|
||||
<gml:pos>457854 5439088 118.317691453624 </gml:pos>
|
||||
<gml:pos>457842 5439088 118.317691453624 </gml:pos>
|
||||
<gml:pos>457842 5439083 115.430940107676 </gml:pos>
|
||||
<gml:pos>457854 5439083 115.430940107676 </gml:pos>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:GroundSurface gml:id="GML_257a8dde-8194-4ca3-b581-abd591dcd6a3">
|
||||
<gml:description>Bodenplatte</gml:description>
|
||||
<gml:name>Base Surface</gml:name>
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="PolyID7356_612_880782_415367">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing gml:id="PolyID7356_612_880782_415367_0">
|
||||
<gml:pos>457854 5439083 111.8 </gml:pos>
|
||||
<gml:pos>457842 5439083 111.8 </gml:pos>
|
||||
<gml:pos>457842 5439093 111.8 </gml:pos>
|
||||
<gml:pos>457854 5439093 111.8 </gml:pos>
|
||||
<gml:pos>457854 5439083 111.8 </gml:pos>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:GroundSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:address>
|
||||
<core:Address>
|
||||
<core:xalAddress>
|
||||
<xAL:AddressDetails>
|
||||
<xAL:Locality Type="Town">
|
||||
<xAL:LocalityName>Eggenstein-Leopoldshafen</xAL:LocalityName>
|
||||
<xAL:Thoroughfare Type="Street">
|
||||
<xAL:ThoroughfareNumber>4711</xAL:ThoroughfareNumber>
|
||||
<xAL:ThoroughfareName>Spöcker Straße</xAL:ThoroughfareName>
|
||||
</xAL:Thoroughfare>
|
||||
<xAL:PostalCode>
|
||||
<xAL:PostalCodeNumber>76344</xAL:PostalCodeNumber>
|
||||
</xAL:PostalCode>
|
||||
</xAL:Locality>
|
||||
</xAL:AddressDetails>
|
||||
</core:xalAddress>
|
||||
</core:Address>
|
||||
</bldg:address>
|
||||
</bldg:Building>
|
||||
</core:cityObjectMember>
|
||||
</core:CityModel>
|
177
tests/tests_data/eilat.geojson
Normal file
177
tests/tests_data/eilat.geojson
Normal file
|
@ -0,0 +1,177 @@
|
|||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": 1,
|
||||
"properties": {
|
||||
"heightmax": 9,
|
||||
"ANNEE_CONS": 1978,
|
||||
"CODE_UTILI": "residential"
|
||||
},
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
34.95217088371581,
|
||||
29.56694805860026
|
||||
],
|
||||
[
|
||||
34.95262396587913,
|
||||
29.566952667742285
|
||||
],
|
||||
[
|
||||
34.95261999147337,
|
||||
29.567024109421467
|
||||
],
|
||||
[
|
||||
34.952169558914704,
|
||||
29.567019500282157
|
||||
],
|
||||
[
|
||||
34.95217088371581,
|
||||
29.56694805860026
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": 3,
|
||||
"properties": {
|
||||
"heightmax": 16,
|
||||
"ANNEE_CONS": 2012,
|
||||
"CODE_UTILI": "dormitory"
|
||||
},
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
34.95176644317411,
|
||||
29.56827388702702
|
||||
],
|
||||
[
|
||||
34.95176550020565,
|
||||
29.568180388329026
|
||||
],
|
||||
[
|
||||
34.95179850408434,
|
||||
29.568180388329026
|
||||
],
|
||||
[
|
||||
34.95179850408434,
|
||||
29.5681303582886
|
||||
],
|
||||
[
|
||||
34.95176644317411,
|
||||
29.5681303582886
|
||||
],
|
||||
[
|
||||
34.95176644317411,
|
||||
29.568038499789708
|
||||
],
|
||||
[
|
||||
34.951874884488376,
|
||||
29.568038499789708
|
||||
],
|
||||
[
|
||||
34.951874884488376,
|
||||
29.568058183760357
|
||||
],
|
||||
[
|
||||
34.95192391882168,
|
||||
29.568058183760357
|
||||
],
|
||||
[
|
||||
34.951922032885705,
|
||||
29.56804178045124
|
||||
],
|
||||
[
|
||||
34.95205216246262,
|
||||
29.568042600617147
|
||||
],
|
||||
[
|
||||
34.952051219494166,
|
||||
29.568129538124154
|
||||
],
|
||||
[
|
||||
34.95201821561636,
|
||||
29.5681303582886
|
||||
],
|
||||
[
|
||||
34.95201821561636,
|
||||
29.568176287507143
|
||||
],
|
||||
[
|
||||
34.95204839059062,
|
||||
29.568176287507143
|
||||
],
|
||||
[
|
||||
34.95205027652662,
|
||||
29.56827552735433
|
||||
],
|
||||
[
|
||||
34.95195503676348,
|
||||
29.568274707190284
|
||||
],
|
||||
[
|
||||
34.95195597973188,
|
||||
29.56825830391628
|
||||
],
|
||||
[
|
||||
34.951849424353696,
|
||||
29.56825830391628
|
||||
],
|
||||
[
|
||||
34.951849424353696,
|
||||
29.568274707190284
|
||||
],
|
||||
[
|
||||
34.95176644317411,
|
||||
29.56827388702702
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": 2,
|
||||
"properties": {
|
||||
"heightmax": 24,
|
||||
"ANNEE_CONS": 2002,
|
||||
"CODE_UTILI": "Hotel employ"
|
||||
},
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
34.94972280674813,
|
||||
29.566224752287738
|
||||
],
|
||||
[
|
||||
34.94974316291999,
|
||||
29.56597561012454
|
||||
],
|
||||
[
|
||||
34.94989147217407,
|
||||
29.565980668855033
|
||||
],
|
||||
[
|
||||
34.94987402402688,
|
||||
29.566233605043536
|
||||
],
|
||||
[
|
||||
34.94972280674813,
|
||||
29.566224752287738
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
81
tests/tests_data/kelowna.obj
Normal file
81
tests/tests_data/kelowna.obj
Normal file
|
@ -0,0 +1,81 @@
|
|||
# https://github.com/mikedh/trimesh
|
||||
v 329238.00000000 5528272.00000000 0.00000000
|
||||
v 329238.00000000 5528272.00000000 3.79999995
|
||||
v 329254.12500000 5528263.00000000 0.00000000
|
||||
v 329254.12500000 5528263.00000000 3.79999995
|
||||
v 329245.12500000 5528267.50000000 4.93084002
|
||||
v 329246.15625000 5528272.50000000 0.00000000
|
||||
v 329246.15625000 5528272.50000000 3.79999995
|
||||
v 329229.15625000 5528271.00000000 0.00000000
|
||||
v 329229.15625000 5528271.00000000 3.79999995
|
||||
v 329242.18750000 5528267.00000000 5.29822016
|
||||
v 329238.31250000 5528266.50000000 4.68875980
|
||||
v 329229.31250000 5528269.50000000 0.00000000
|
||||
v 329229.31250000 5528269.50000000 3.79999995
|
||||
v 329244.34375000 5528267.00000000 4.99910021
|
||||
v 329242.34375000 5528267.00000000 5.30000019
|
||||
v 329233.34375000 5528276.00000000 0.00000000
|
||||
v 329233.34375000 5528276.00000000 3.79999995
|
||||
v 329247.34375000 5528262.50000000 0.00000000
|
||||
v 329247.34375000 5528262.50000000 3.79999995
|
||||
v 329242.40625000 5528257.50000000 0.00000000
|
||||
v 329242.40625000 5528257.50000000 3.79999995
|
||||
v 329231.50000000 5528270.50000000 4.31147003
|
||||
v 329253.53125000 5528273.00000000 0.00000000
|
||||
v 329253.53125000 5528273.00000000 3.79999995
|
||||
v 329241.71875000 5528276.50000000 0.00000000
|
||||
v 329241.71875000 5528276.50000000 3.79999995
|
||||
v 329233.81250000 5528270.50000000 4.68364000
|
||||
v 329248.81250000 5528267.50000000 4.92572021
|
||||
f 22 9 13
|
||||
f 28 4 24
|
||||
f 23 6 7
|
||||
f 7 24 23
|
||||
f 6 25 26
|
||||
f 26 7 6
|
||||
f 25 1 2
|
||||
f 2 26 25
|
||||
f 1 16 17
|
||||
f 17 2 1
|
||||
f 16 8 9
|
||||
f 9 17 16
|
||||
f 8 12 13
|
||||
f 13 9 8
|
||||
f 12 20 21
|
||||
f 21 13 12
|
||||
f 20 18 19
|
||||
f 19 21 20
|
||||
f 18 3 4
|
||||
f 4 19 18
|
||||
f 3 23 24
|
||||
f 24 4 3
|
||||
f 6 23 3
|
||||
f 6 3 18
|
||||
f 6 18 20
|
||||
f 6 20 12
|
||||
f 6 12 8
|
||||
f 8 16 1
|
||||
f 6 8 1
|
||||
f 1 25 6
|
||||
f 24 7 14
|
||||
f 24 14 5
|
||||
f 5 28 24
|
||||
f 7 26 15
|
||||
f 15 14 7
|
||||
f 26 2 11
|
||||
f 26 11 10
|
||||
f 10 15 26
|
||||
f 2 17 27
|
||||
f 27 11 2
|
||||
f 17 9 22
|
||||
f 22 27 17
|
||||
f 21 10 11
|
||||
f 13 21 11
|
||||
f 13 11 27
|
||||
f 27 22 13
|
||||
f 21 19 5
|
||||
f 21 5 14
|
||||
f 21 14 15
|
||||
f 15 10 21
|
||||
f 19 4 28
|
||||
f 28 5 19
|
73
tests/tests_data/levis.geojson
Normal file
73
tests/tests_data/levis.geojson
Normal file
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": 1,
|
||||
"properties": {
|
||||
"OBJECTID_12": 1,
|
||||
"gml_id": 1,
|
||||
"citygml_me": 20,
|
||||
"Z_Min": 46.1162,
|
||||
"Z_Max": 66.1162,
|
||||
"ANNEE_CONS": 2023,
|
||||
"CODE_UTILI": 1000
|
||||
},
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-71.16553932594044,
|
||||
46.7895775031096
|
||||
],
|
||||
[
|
||||
-71.16535210635354,
|
||||
46.78972033813616
|
||||
],
|
||||
[
|
||||
-71.1654671126711,
|
||||
46.78979908036044
|
||||
],
|
||||
[
|
||||
-71.16525314742928,
|
||||
46.78995473325631
|
||||
],
|
||||
[
|
||||
-71.16480114585448,
|
||||
46.7896544143249
|
||||
],
|
||||
[
|
||||
-71.16486533542763,
|
||||
46.789394380725696
|
||||
],
|
||||
[
|
||||
-71.16467544127534,
|
||||
46.78927901330414
|
||||
],
|
||||
[
|
||||
-71.16454171299826,
|
||||
46.78930465053031
|
||||
],
|
||||
[
|
||||
-71.16445612690187,
|
||||
46.789766118513455
|
||||
],
|
||||
[
|
||||
-71.16519698155322,
|
||||
46.79023673853192
|
||||
],
|
||||
[
|
||||
-71.16583887727946,
|
||||
46.78976794972763
|
||||
],
|
||||
[
|
||||
-71.16553932594044,
|
||||
46.7895775031096
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
409
tests/tests_data/one_building_in_kelowna_alkis.gml
Normal file
409
tests/tests_data/one_building_in_kelowna_alkis.gml
Normal file
|
@ -0,0 +1,409 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<core:CityModel xmlns:brid="http://www.opengis.net/citygml/bridge/2.0" xmlns:tran="http://www.opengis.net/citygml/transportation/2.0" xmlns:frn="http://www.opengis.net/citygml/cityfurniture/2.0" xmlns:wtr="http://www.opengis.net/citygml/waterbody/2.0" xmlns:sch="http://www.ascc.net/xml/schematron" xmlns:veg="http://www.opengis.net/citygml/vegetation/2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:tun="http://www.opengis.net/citygml/tunnel/2.0" xmlns:tex="http://www.opengis.net/citygml/texturedsurface/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:luse="http://www.opengis.net/citygml/landuse/2.0" xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil20lang="http://www.w3.org/2001/SMIL20/Language" xmlns:pbase="http://www.opengis.net/citygml/profiles/base/2.0" xmlns:smil20="http://www.w3.org/2001/SMIL20/" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0">
|
||||
<gml:boundedBy>
|
||||
<gml:Envelope srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:lowerCorner>326011.03601000085 5526048.416990001 -1.6000000000058208</gml:lowerCorner>
|
||||
<gml:upperCorner>329466.6600299999 5529018.72205 9.80000000000291</gml:upperCorner>
|
||||
</gml:Envelope>
|
||||
</gml:boundedBy>
|
||||
<core:cityObjectMember>
|
||||
<bldg:Building gml:id="BLD109438">
|
||||
<gen:doubleAttribute name="gross_floor_area">
|
||||
<gen:value>291</gen:value>
|
||||
</gen:doubleAttribute>
|
||||
<gen:stringAttribute name="gross_floor_raea_unit">
|
||||
<gen:value>m2</gen:value>
|
||||
</gen:stringAttribute>
|
||||
<bldg:yearOfConstruction>1996</bldg:yearOfConstruction>
|
||||
<bldg:function>residential</bldg:function>
|
||||
<bldg:measuredHeight>5.3</bldg:measuredHeight>
|
||||
<bldg:storeysAboveGround>1</bldg:storeysAboveGround>
|
||||
<bldg:lod2Solid>
|
||||
<gml:Solid srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:exterior>
|
||||
<gml:CompositeSurface>
|
||||
<gml:surfaceMember xlink:href="#UUID_854e7876-bcb7-43f5-9f4b-7c55803cf04f"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_50045e42-87aa-4aa4-b179-99d03a5569df"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_6138b267-e734-4830-98f8-a79fc4d38da4"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_7e4a20ee-4581-4e9a-a661-3e80c79ae226"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_770546ef-e544-4d39-8747-e5c6c88d5725"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_0f22b07c-8bd5-43d1-8904-c96a5a0456ce"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_b6219259-c948-487a-96dc-25f9ce257974"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_d806c8f3-93e1-4155-ab28-743fed870f6b"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_da660fbf-9aea-4895-8d9c-cf5fab95862e"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_6315337c-3919-423e-9e46-35fc5f005b7d"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_6bed5c5e-9ee9-4b3a-bfbc-fac54c0f2090"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_8f4f6388-d576-4ded-925a-fd01d43e3c11"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_ad685374-7888-41cf-8464-48c037230174"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_1b440294-d10f-49e2-9c65-78aa0a57a389"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_4d4017ed-3a71-43c7-a79c-04acd9f86433"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_b7c0600b-0c3b-4b8c-8f5f-11d8f774966e"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_18f19ab4-f128-41a0-ab05-34d91ad061b9"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_e5b962d8-6186-4e78-ae08-fc0c00484e8c"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_eebbc322-bf68-4c56-a826-392b617db97c"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_16a00d48-90a4-4cd1-94e6-0654a5b9b1d2"/>
|
||||
<gml:surfaceMember xlink:href="#UUID_4832dea6-f237-45ec-a711-ce1fc27b7e3b"/>
|
||||
</gml:CompositeSurface>
|
||||
</gml:exterior>
|
||||
</gml:Solid>
|
||||
</bldg:lod2Solid>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_2e3a196c-b5b1-4ee4-af82-329ced61e624">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_854e7876-bcb7-43f5-9f4b-7c55803cf04f">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329231.5010599997 5528270.404139999 4.311470000000554 329229.15295 5528271.14002 3.8000000000029104 329229.30395000055 5528269.304020001 3.8000000000029104 329231.5010599997 5528270.404139999 4.311470000000554</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_9a4410b3-f53c-468a-aef9-1e9f1ba88748">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_50045e42-87aa-4aa4-b179-99d03a5569df">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329248.8121399991 5528267.658840001 4.925719999999274 329254.11205999926 5528262.99903 3.8000000000029104 329253.52796000056 5528272.956 3.8000000000029104 329248.8121399991 5528267.658840001 4.925719999999274</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_d4f2198a-dd18-4fe2-a1f3-33f47393cb22">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_6138b267-e734-4830-98f8-a79fc4d38da4">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329246.16602000035 5528272.533020001 0 329246.16602000035 5528272.533020001 3.8000000000029104 329253.52796000056 5528272.956 3.8000000000029104 329253.52796000056 5528272.956 0 329246.16602000035 5528272.533020001 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_3d62148d-9d75-455f-86aa-1c0877942853">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_7e4a20ee-4581-4e9a-a661-3e80c79ae226">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329241.7199700009 5528276.307010001 0 329241.7199700009 5528276.307010001 3.8000000000029104 329246.16602000035 5528272.533020001 3.8000000000029104 329246.16602000035 5528272.533020001 0 329241.7199700009 5528276.307010001 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_b59d0530-9980-46ae-8452-e0a07cfdf84d">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_770546ef-e544-4d39-8747-e5c6c88d5725">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329237.9890100006 5528272.159 0 329237.9890100006 5528272.159 3.8000000000029104 329241.7199700009 5528276.307010001 3.8000000000029104 329241.7199700009 5528276.307010001 0 329237.9890100006 5528272.159 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_c0bd57d9-a02c-40d5-b467-3fd57478e93b">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_0f22b07c-8bd5-43d1-8904-c96a5a0456ce">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329233.3360600006 5528276.213989999 0 329233.3360600006 5528276.213989999 3.8000000000029104 329237.9890100006 5528272.159 3.8000000000029104 329237.9890100006 5528272.159 0 329233.3360600006 5528276.213989999 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_2ff7cfd9-a3d1-4c76-b30e-501cc012b663">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_b6219259-c948-487a-96dc-25f9ce257974">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329229.15295 5528271.14002 0 329229.15295 5528271.14002 3.8000000000029104 329233.3360600006 5528276.213989999 3.8000000000029104 329233.3360600006 5528276.213989999 0 329229.15295 5528271.14002 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_4bcf78ac-c688-40f8-86ca-19bd790a6647">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_d806c8f3-93e1-4155-ab28-743fed870f6b">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329229.30395000055 5528269.304020001 0 329229.30395000055 5528269.304020001 3.8000000000029104 329229.15295 5528271.14002 3.8000000000029104 329229.15295 5528271.14002 0 329229.30395000055 5528269.304020001 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_5677b3e5-abef-4bc0-87a3-3366fc38e6f9">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_da660fbf-9aea-4895-8d9c-cf5fab95862e">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329242.40003000014 5528257.71503 0 329242.40003000014 5528257.71503 3.8000000000029104 329229.30395000055 5528269.304020001 3.8000000000029104 329229.30395000055 5528269.304020001 0 329242.40003000014 5528257.71503 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_e32a4a70-ad52-4f92-a7e4-bcaeb38ff7c9">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_6315337c-3919-423e-9e46-35fc5f005b7d">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329247.3289800007 5528262.52503 0 329247.3289800007 5528262.52503 3.8000000000029104 329242.40003000014 5528257.71503 3.8000000000029104 329242.40003000014 5528257.71503 0 329247.3289800007 5528262.52503 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_b1442311-0705-4bec-a28d-a81db9bd2f5d">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_6bed5c5e-9ee9-4b3a-bfbc-fac54c0f2090">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329254.11205999926 5528262.99903 0 329254.11205999926 5528262.99903 3.8000000000029104 329247.3289800007 5528262.52503 3.8000000000029104 329247.3289800007 5528262.52503 0 329254.11205999926 5528262.99903 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:WallSurface gml:id="UUID_63185eaf-4f7b-481b-b912-193cfcb4316a">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_8f4f6388-d576-4ded-925a-fd01d43e3c11">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329253.52796000056 5528272.956 0 329253.52796000056 5528272.956 3.8000000000029104 329254.11205999926 5528262.99903 3.8000000000029104 329254.11205999926 5528262.99903 0 329253.52796000056 5528272.956 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:WallSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:GroundSurface gml:id="UUID_e348daa3-75bc-44c5-b203-aca0902b4034">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_ad685374-7888-41cf-8464-48c037230174">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329253.52796000056 5528272.956 0 329254.11205999926 5528262.99903 0 329247.3289800007 5528262.52503 0 329242.40003000014 5528257.71503 0 329229.30395000055 5528269.304020001 0 329229.15295 5528271.14002 0 329233.3360600006 5528276.213989999 0 329237.9890100006 5528272.159 0 329241.7199700009 5528276.307010001 0 329246.16602000035 5528272.533020001 0 329253.52796000056 5528272.956 0</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:GroundSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_1b3328ee-ecdb-45a9-b6f3-e36247f4929e">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_1b440294-d10f-49e2-9c65-78aa0a57a389">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329246.16602000035 5528272.533020001 3.8000000000029104 329244.33748999983 5528267.074109999 4.999100000000908 329245.1323099993 5528267.42457 4.930840000000899 329248.8121399991 5528267.658840001 4.925719999999274 329253.52796000056 5528272.956 3.8000000000029104 329246.16602000035 5528272.533020001 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_02a78c5a-3d35-4491-9801-64aa42addf7e">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_4d4017ed-3a71-43c7-a79c-04acd9f86433">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329241.7199700009 5528276.307010001 3.8000000000029104 329242.3462899998 5528267.00502 5.30000000000291 329244.33748999983 5528267.074109999 4.999100000000908 329246.16602000035 5528272.533020001 3.8000000000029104 329241.7199700009 5528276.307010001 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_f550a210-6813-4f8a-b826-7f7965b50a4a">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_b7c0600b-0c3b-4b8c-8f5f-11d8f774966e">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329237.9890100006 5528272.159 3.8000000000029104 329238.32637000084 5528266.609999999 4.6887600000045495 329242.1777599994 5528266.829500001 5.298219999996945 329242.3462899998 5528267.00502 5.30000000000291 329241.7199700009 5528276.307010001 3.8000000000029104 329237.9890100006 5528272.159 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_8d65b4c5-fa18-4cee-81c9-45229588115e">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_18f19ab4-f128-41a0-ab05-34d91ad061b9">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329233.3360600006 5528276.213989999 3.8000000000029104 329233.80010999925 5528270.5848900005 4.683640000002924 329238.32637000084 5528266.609999999 4.6887600000045495 329237.9890100006 5528272.159 3.8000000000029104 329233.3360600006 5528276.213989999 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_46e8afe5-fd30-4c7a-88ae-a7ee5b2d2af6">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_e5b962d8-6186-4e78-ae08-fc0c00484e8c">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329229.15295 5528271.14002 3.8000000000029104 329231.5010599997 5528270.404139999 4.311470000000554 329233.80010999925 5528270.5848900005 4.683640000002924 329233.3360600006 5528276.213989999 3.8000000000029104 329229.15295 5528271.14002 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_c535c900-8077-46d6-a267-d3e9f3c34254">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_eebbc322-bf68-4c56-a826-392b617db97c">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329242.40003000014 5528257.71503 3.8000000000029104 329242.1777599994 5528266.829500001 5.298219999996945 329238.32637000084 5528266.609999999 4.6887600000045495 329233.80010999925 5528270.5848900005 4.683640000002924 329231.5010599997 5528270.404139999 4.311470000000554 329229.30395000055 5528269.304020001 3.8000000000029104 329242.40003000014 5528257.71503 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_d6d9c32d-cd29-490e-accc-3ac5decbb289">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_16a00d48-90a4-4cd1-94e6-0654a5b9b1d2">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329247.3289800007 5528262.52503 3.8000000000029104 329245.1323099993 5528267.42457 4.930840000000899 329244.33748999983 5528267.074109999 4.999100000000908 329242.3462899998 5528267.00502 5.30000000000291 329242.1777599994 5528266.829500001 5.298219999996945 329242.40003000014 5528257.71503 3.8000000000029104 329247.3289800007 5528262.52503 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
<bldg:boundedBy>
|
||||
<bldg:RoofSurface gml:id="UUID_d97b1be8-8be7-4a5c-9f4d-3159853b054e">
|
||||
<bldg:lod2MultiSurface>
|
||||
<gml:MultiSurface srsName="EPSG:26911" srsDimension="3">
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon gml:id="UUID_4832dea6-f237-45ec-a711-ce1fc27b7e3b">
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList>329254.11205999926 5528262.99903 3.8000000000029104 329248.8121399991 5528267.658840001 4.925719999999274 329245.1323099993 5528267.42457 4.930840000000899 329247.3289800007 5528262.52503 3.8000000000029104 329254.11205999926 5528262.99903 3.8000000000029104</gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod2MultiSurface>
|
||||
</bldg:RoofSurface>
|
||||
</bldg:boundedBy>
|
||||
</bldg:Building>
|
||||
</core:cityObjectMember>
|
||||
</core:CityModel>
|
420
tests/tests_data/pluto_building.gml
Normal file
420
tests/tests_data/pluto_building.gml
Normal file
|
@ -0,0 +1,420 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CityModel>
|
||||
<name>Gowanus 2050 Best Practice Scenario</name>
|
||||
<boundedBy>
|
||||
<Envelope srsName="EPSG:32118" srsDimension="3" xmlns:brid="http://www.opengis.net/citygml/bridge/2.0" xmlns:tran="http://www.opengis.net/citygml/transportation/2.0" xmlns:frn="http://www.opengis.net/citygml/cityfurniture/2.0" xmlns:wtr="http://www.opengis.net/citygml/waterbody/2.0" xmlns:sch="http://www.ascc.net/xml/schematron" xmlns:veg="http://www.opengis.net/citygml/vegetation/2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:tun="http://www.opengis.net/citygml/tunnel/2.0" xmlns:tex="http://www.opengis.net/citygml/texturedsurface/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:luse="http://www.opengis.net/citygml/landuse/2.0" xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil20lang="http://www.w3.org/2001/SMIL20/Language" xmlns:pbase="http://www.opengis.net/citygml/profiles/base/2.0" xmlns:smil20="http://www.w3.org/2001/SMIL20/" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0">
|
||||
<lowerCorner>299606.4441129853 55348.37638737355 0</lowerCorner>
|
||||
<upperCorner>301879.9050504853 57594.05119206105 62.04879541695123</upperCorner>
|
||||
</Envelope>
|
||||
</boundedBy>
|
||||
<cityObjectMember>
|
||||
<Building id="GBP__169">
|
||||
<lod1Solid>
|
||||
<Solid srsName="EPSG:32118" srsDimension="3">
|
||||
<exterior>
|
||||
<CompositeSurface>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301010.4314176728 57301.3749225298 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301014.183859079 57308.78849674855 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.1125700165 57288.87345768605 10.786276534199727 300992.0398161103 57285.56779362355 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301024.4275114228 57311.0624225298 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301000.3254606415 57281.3758990923 10.786276534199727 300997.2820036103 57275.3758990923 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.1125700165 57288.87345768605 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301017.183859079 57314.7147662798 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727 301017.183859079 57314.7147662798 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301005.9055387665 57312.9716022173 10.786276534199727 301002.1530973603 57305.55900456105 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727 301005.9055387665 57312.9716022173 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300995.8337614228 57293.0555865923 10.786276534199727 300992.0398161103 57285.56779362355 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727 300995.8337614228 57293.0555865923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301014.183859079 57308.78849674855 10.786276534199727 301002.1530973603 57305.55900456105 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301005.9055387665 57312.9716022173 10.786276534199727 301005.9055387665 57312.9716022173 0.0 301002.1530973603 57305.55900456105 10.786276534199727 301005.9055387665 57312.9716022173 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301002.1530973603 57305.55900456105 10.786276534199727 301005.9055387665 57312.9716022173 0.0 301002.1530973603 57305.55900456105 0.0 301002.1530973603 57305.55900456105 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301017.183859079 57314.7147662798 0.0 301024.4275114228 57311.0624225298 0.0 301014.183859079 57308.78849674855 0.0 301017.183859079 57314.7147662798 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301005.9055387665 57312.9716022173 0.0 301014.183859079 57308.78849674855 0.0 301002.1530973603 57305.55900456105 0.0 301005.9055387665 57312.9716022173 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300995.8337614228 57293.0555865923 0.0 301004.1125700165 57288.87345768605 0.0 300992.0398161103 57285.56779362355 0.0 300995.8337614228 57293.0555865923 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301014.183859079 57308.78849674855 0.0 301010.4314176728 57301.3749225298 0.0 301002.1530973603 57305.55900456105 0.0 301014.183859079 57308.78849674855 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301010.4314176728 57301.3749225298 0.0 301024.4275114228 57311.0624225298 0.0 301004.1125700165 57288.87345768605 0.0 301010.4314176728 57301.3749225298 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301014.183859079 57308.78849674855 0.0 301024.4275114228 57311.0624225298 0.0 301010.4314176728 57301.3749225298 0.0 301014.183859079 57308.78849674855 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301024.4275114228 57311.0624225298 0.0 301004.5266325165 57271.70548893605 0.0 301004.1125700165 57288.87345768605 0.0 301024.4275114228 57311.0624225298 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.1125700165 57288.87345768605 0.0 301000.3254606415 57281.3758990923 0.0 300992.0398161103 57285.56779362355 0.0 301004.1125700165 57288.87345768605 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301000.3254606415 57281.3758990923 0.0 301004.5266325165 57271.70548893605 0.0 300997.2820036103 57275.3758990923 0.0 301000.3254606415 57281.3758990923 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.1125700165 57288.87345768605 0.0 301004.5266325165 57271.70548893605 0.0 301000.3254606415 57281.3758990923 0.0 301004.1125700165 57288.87345768605 0.0</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301014.183859079 57308.78849674855 10.786276534199727 301014.183859079 57308.78849674855 0.0 301005.9055387665 57312.9716022173 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301005.9055387665 57312.9716022173 10.786276534199727 301014.183859079 57308.78849674855 0.0 301005.9055387665 57312.9716022173 0.0 301005.9055387665 57312.9716022173 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301017.183859079 57314.7147662798 10.786276534199727 301017.183859079 57314.7147662798 0.0 301014.183859079 57308.78849674855 10.786276534199727 301017.183859079 57314.7147662798 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301014.183859079 57308.78849674855 10.786276534199727 301017.183859079 57314.7147662798 0.0 301014.183859079 57308.78849674855 0.0 301014.183859079 57308.78849674855 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301002.1530973603 57305.55900456105 10.786276534199727 301002.1530973603 57305.55900456105 0.0 301010.4314176728 57301.3749225298 10.786276534199727 301002.1530973603 57305.55900456105 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301010.4314176728 57301.3749225298 10.786276534199727 301002.1530973603 57305.55900456105 0.0 301010.4314176728 57301.3749225298 0.0 301010.4314176728 57301.3749225298 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301024.4275114228 57311.0624225298 10.786276534199727 301024.4275114228 57311.0624225298 0.0 301017.183859079 57314.7147662798 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301017.183859079 57314.7147662798 10.786276534199727 301024.4275114228 57311.0624225298 0.0 301017.183859079 57314.7147662798 0.0 301017.183859079 57314.7147662798 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.5266325165 57271.70548893605 10.786276534199727 301004.5266325165 57271.70548893605 0.0 301024.4275114228 57311.0624225298 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301024.4275114228 57311.0624225298 10.786276534199727 301004.5266325165 57271.70548893605 0.0 301024.4275114228 57311.0624225298 0.0 301024.4275114228 57311.0624225298 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300997.2820036103 57275.3758990923 10.786276534199727 300997.2820036103 57275.3758990923 0.0 301004.5266325165 57271.70548893605 10.786276534199727 300997.2820036103 57275.3758990923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.5266325165 57271.70548893605 10.786276534199727 300997.2820036103 57275.3758990923 0.0 301004.5266325165 57271.70548893605 0.0 301004.5266325165 57271.70548893605 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301010.4314176728 57301.3749225298 10.786276534199727 301010.4314176728 57301.3749225298 0.0 301004.1125700165 57288.87345768605 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.1125700165 57288.87345768605 10.786276534199727 301010.4314176728 57301.3749225298 0.0 301004.1125700165 57288.87345768605 0.0 301004.1125700165 57288.87345768605 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301004.1125700165 57288.87345768605 10.786276534199727 301004.1125700165 57288.87345768605 0.0 300995.8337614228 57293.0555865923 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300995.8337614228 57293.0555865923 10.786276534199727 301004.1125700165 57288.87345768605 0.0 300995.8337614228 57293.0555865923 0.0 300995.8337614228 57293.0555865923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301000.3254606415 57281.3758990923 10.786276534199727 301000.3254606415 57281.3758990923 0.0 300997.2820036103 57275.3758990923 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300997.2820036103 57275.3758990923 10.786276534199727 301000.3254606415 57281.3758990923 0.0 300997.2820036103 57275.3758990923 0.0 300997.2820036103 57275.3758990923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300995.8337614228 57293.0555865923 10.786276534199727 300995.8337614228 57293.0555865923 0.0 300992.0398161103 57285.56779362355 10.786276534199727 300995.8337614228 57293.0555865923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300992.0398161103 57285.56779362355 10.786276534199727 300995.8337614228 57293.0555865923 0.0 300992.0398161103 57285.56779362355 0.0 300992.0398161103 57285.56779362355 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>300992.0398161103 57285.56779362355 10.786276534199727 300992.0398161103 57285.56779362355 0.0 301000.3254606415 57281.3758990923 10.786276534199727 300992.0398161103 57285.56779362355 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
<surfaceMember>
|
||||
<Polygon>
|
||||
<exterior>
|
||||
<LinearRing>
|
||||
<posList>301000.3254606415 57281.3758990923 10.786276534199727 300992.0398161103 57285.56779362355 0.0 301000.3254606415 57281.3758990923 0.0 301000.3254606415 57281.3758990923 10.786276534199727</posList>
|
||||
</LinearRing>
|
||||
</exterior>
|
||||
</Polygon>
|
||||
</surfaceMember>
|
||||
</CompositeSurface>
|
||||
</exterior>
|
||||
</Solid>
|
||||
</lod1Solid>
|
||||
<yearOfConstruction>1965</yearOfConstruction>
|
||||
<function>W4</function>
|
||||
</Building>
|
||||
</cityObjectMember>
|
||||
</CityModel>
|
14
tests/tests_data/w2w_user_output.csv
Normal file
14
tests/tests_data/w2w_user_output.csv
Normal file
|
@ -0,0 +1,14 @@
|
|||
,Monthly HP Electricity Demand (kWh),Monthly Fuel Consumption of Auxiliary Heater (m3)
|
||||
Jan,1031544.62,24276356.0
|
||||
Feb,874352.562,19785768.0
|
||||
Mar,691775.25,117312.656
|
||||
Apr,280416.469,-0.0
|
||||
May,0.0,40314676.0
|
||||
Jun,0.0,5447721.0
|
||||
Jul,0.0,1187115.88
|
||||
Aug,0.0,1961530.88
|
||||
Sept,0.0,20623850.0
|
||||
Oct,191220.531,-0.0
|
||||
Nov,423974.062,-0.0
|
||||
Dec,848334.875,6793204.5
|
||||
Total,4341618.369,120507534.91600001
|
|
Loading…
Reference in New Issue
Block a user