diff --git a/tests/test_city_merge.py b/tests/test_city_merge.py
new file mode 100644
index 0000000..24bdc80
--- /dev/null
+++ b/tests/test_city_merge.py
@@ -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)
+
diff --git a/tests/test_construction_catalog.py b/tests/test_construction_catalog.py
new file mode 100644
index 0000000..5c5a0e9
--- /dev/null
+++ b/tests/test_construction_catalog.py
@@ -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')
diff --git a/tests/test_construction_factory.py b/tests/test_construction_factory.py
new file mode 100644
index 0000000..710894b
--- /dev/null
+++ b/tests/test_construction_factory.py
@@ -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)
\ No newline at end of file
diff --git a/tests/test_costs_catalog.py b/tests/test_costs_catalog.py
new file mode 100644
index 0000000..8f87385
--- /dev/null
+++ b/tests/test_costs_catalog.py
@@ -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')
diff --git a/tests/test_custom_insel_block.py b/tests/test_custom_insel_block.py
new file mode 100644
index 0000000..822b74b
--- /dev/null
+++ b/tests/test_custom_insel_block.py
@@ -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!")
diff --git a/tests/test_enrichement.py b/tests/test_enrichement.py
new file mode 100644
index 0000000..531acd6
--- /dev/null
+++ b/tests/test_enrichement.py
@@ -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)
diff --git a/tests/test_exports.py b/tests/test_exports.py
new file mode 100644
index 0000000..e719790
--- /dev/null
+++ b/tests/test_exports.py
@@ -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!")
diff --git a/tests/test_geometry_factory.py b/tests/test_geometry_factory.py
new file mode 100644
index 0000000..3b5bd8f
--- /dev/null
+++ b/tests/test_geometry_factory.py
@@ -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)
diff --git a/tests/test_greenery_catalog.py b/tests/test_greenery_catalog.py
new file mode 100644
index 0000000..291aeb1
--- /dev/null
+++ b/tests/test_greenery_catalog.py
@@ -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)
diff --git a/tests/test_greenery_in_idf.py b/tests/test_greenery_in_idf.py
new file mode 100644
index 0000000..857b96c
--- /dev/null
+++ b/tests/test_greenery_in_idf.py
@@ -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)
diff --git a/tests/test_results_import.py b/tests/test_results_import.py
new file mode 100644
index 0000000..76be587
--- /dev/null
+++ b/tests/test_results_import.py
@@ -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)
diff --git a/tests/test_systems_catalog.py b/tests/test_systems_catalog.py
new file mode 100644
index 0000000..48af728
--- /dev/null
+++ b/tests/test_systems_catalog.py
@@ -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')
diff --git a/tests/test_systems_factory.py b/tests/test_systems_factory.py
new file mode 100644
index 0000000..8d19104
--- /dev/null
+++ b/tests/test_systems_factory.py
@@ -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])
diff --git a/tests/test_usage_catalog.py b/tests/test_usage_catalog.py
new file mode 100644
index 0000000..2d92737
--- /dev/null
+++ b/tests/test_usage_catalog.py
@@ -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')
diff --git a/tests/test_usage_factory.py b/tests/test_usage_factory.py
new file mode 100644
index 0000000..6b6d821
--- /dev/null
+++ b/tests/test_usage_factory.py
@@ -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')
diff --git a/tests/tests_data/C40_Final.gml b/tests/tests_data/C40_Final.gml
new file mode 100644
index 0000000..34126bd
--- /dev/null
+++ b/tests/tests_data/C40_Final.gml
@@ -0,0 +1,3377 @@
+
+
+
+
+610610.7547462888 5035770.347264212 566.5784301757819
+610818.6731258357 5035968.504367453 598.217651367188
+
+
+
+
+
+
+residential
+1996
+12.822875976562045
+2
+4.5
+
+
+
+
+
+
+
+
+610731.736095011 5035823.038792845 579.401306152344 610710.8787736718 5035807.662177984 579.401306152344 610731.736095011 5035823.038792845 566.5784301757819 610731.736095011 5035823.038792845 579.401306152344
+
+
+
+
+
+
+
+
+610710.8787736718 5035807.662177984 579.401306152344 610710.8787736718 5035807.662177984 566.5784301757819 610731.736095011 5035823.038792845 566.5784301757819 610710.8787736718 5035807.662177984 579.401306152344
+
+
+
+
+
+
+
+
+610731.736095011 5035823.038792845 579.401306152344 610685.9119691952 5035884.728175624 566.5784301757819 610685.9119691952 5035884.728175624 579.401306152344 610731.736095011 5035823.038792845 579.401306152344
+
+
+
+
+
+
+
+
+610731.736095011 5035823.038792845 566.5784301757819 610685.9119691952 5035884.728175624 566.5784301757819 610731.736095011 5035823.038792845 579.401306152344 610731.736095011 5035823.038792845 566.5784301757819
+
+
+
+
+
+
+
+
+610731.736095011 5035823.038792845 566.5784301757819 610710.8787736718 5035807.662177984 566.5784301757819 610685.9119691952 5035884.728175624 566.5784301757819 610731.736095011 5035823.038792845 566.5784301757819
+
+
+
+
+
+
+
+
+610685.9119691952 5035884.728175624 566.5784301757819 610710.8787736718 5035807.662177984 566.5784301757819 610665.0659159254 5035869.341116842 566.5784301757819 610685.9119691952 5035884.728175624 566.5784301757819
+
+
+
+
+
+
+
+
+610685.9119691952 5035884.728175624 579.401306152344 610665.0659159254 5035869.341116842 579.401306152344 610710.8787736718 5035807.662177984 579.401306152344 610685.9119691952 5035884.728175624 579.401306152344
+
+
+
+
+
+
+
+
+610731.736095011 5035823.038792845 579.401306152344 610685.9119691952 5035884.728175624 579.401306152344 610710.8787736718 5035807.662177984 579.401306152344 610731.736095011 5035823.038792845 579.401306152344
+
+
+
+
+
+
+
+
+610710.8787736718 5035807.662177984 566.5784301757819 610710.8787736718 5035807.662177984 579.401306152344 610665.0659159254 5035869.341116842 579.401306152344 610710.8787736718 5035807.662177984 566.5784301757819
+
+
+
+
+
+
+
+
+610710.8787736718 5035807.662177984 566.5784301757819 610665.0659159254 5035869.341116842 579.401306152344 610665.0659159254 5035869.341116842 566.5784301757819 610710.8787736718 5035807.662177984 566.5784301757819
+
+
+
+
+
+
+
+
+610665.0659159254 5035869.341116842 579.401306152344 610685.9119691952 5035884.728175624 579.401306152344 610665.0659159254 5035869.341116842 566.5784301757819 610665.0659159254 5035869.341116842 579.401306152344
+
+
+
+
+
+
+
+
+610685.9119691952 5035884.728175624 579.401306152344 610685.9119691952 5035884.728175624 566.5784301757819 610665.0659159254 5035869.341116842 566.5784301757819 610685.9119691952 5035884.728175624 579.401306152344
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+17.09716796875
+2
+6
+
+
+
+
+
+
+
+
+610703.3889290215 5035897.594541908 583.6755981445319 610684.1980603877 5035923.445129678 566.5784301757819 610684.1980603877 5035923.445129678 583.6755981445319 610703.3889290215 5035897.594541908 583.6755981445319
+
+
+
+
+
+
+
+
+610703.3889290215 5035897.594541908 566.5784301757819 610684.1980603877 5035923.445129678 566.5784301757819 610703.3889290215 5035897.594541908 583.6755981445319 610703.3889290215 5035897.594541908 566.5784301757819
+
+
+
+
+
+
+
+
+610703.3889290215 5035897.594541908 583.6755981445319 610665.0659159254 5035869.341116842 583.6755981445319 610703.3889290215 5035897.594541908 566.5784301757819 610703.3889290215 5035897.594541908 583.6755981445319
+
+
+
+
+
+
+
+
+610665.0659159254 5035869.341116842 583.6755981445319 610665.0659159254 5035869.341116842 566.5784301757819 610703.3889290215 5035897.594541908 566.5784301757819 610665.0659159254 5035869.341116842 583.6755981445319
+
+
+
+
+
+
+
+
+610684.1980603877 5035923.445129678 583.6755981445319 610645.9080433963 5035895.192514391 583.6755981445319 610703.3889290215 5035897.594541908 583.6755981445319 610684.1980603877 5035923.445129678 583.6755981445319
+
+
+
+
+
+
+
+
+610703.3889290215 5035897.594541908 583.6755981445319 610645.9080433963 5035895.192514391 583.6755981445319 610665.0659159254 5035869.341116842 583.6755981445319 610703.3889290215 5035897.594541908 583.6755981445319
+
+
+
+
+
+
+
+
+610665.0659159254 5035869.341116842 566.5784301757819 610665.0659159254 5035869.341116842 583.6755981445319 610645.9080433963 5035895.192514391 583.6755981445319 610665.0659159254 5035869.341116842 566.5784301757819
+
+
+
+
+
+
+
+
+610665.0659159254 5035869.341116842 566.5784301757819 610645.9080433963 5035895.192514391 583.6755981445319 610645.9080433963 5035895.192514391 566.5784301757819 610665.0659159254 5035869.341116842 566.5784301757819
+
+
+
+
+
+
+
+
+610645.9080433963 5035895.192514391 583.6755981445319 610684.1980603877 5035923.445129678 583.6755981445319 610645.9080433963 5035895.192514391 566.5784301757819 610645.9080433963 5035895.192514391 583.6755981445319
+
+
+
+
+
+
+
+
+610684.1980603877 5035923.445129678 583.6755981445319 610684.1980603877 5035923.445129678 566.5784301757819 610645.9080433963 5035895.192514391 566.5784301757819 610684.1980603877 5035923.445129678 583.6755981445319
+
+
+
+
+
+
+
+
+610684.1980603877 5035923.445129678 566.5784301757819 610703.3889290215 5035897.594541908 566.5784301757819 610645.9080433963 5035895.192514391 566.5784301757819 610684.1980603877 5035923.445129678 566.5784301757819
+
+
+
+
+
+
+
+
+610703.3889290215 5035897.594541908 566.5784301757819 610665.0659159254 5035869.341116842 566.5784301757819 610645.9080433963 5035895.192514391 566.5784301757819 610703.3889290215 5035897.594541908 566.5784301757819
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+6.411376953125
+1
+4.5
+
+
+
+
+
+
+
+
+610621.7522854737 5035912.554446138 572.989868164063 610646.6181083214 5035930.900036323 572.989868164063 610621.7522854737 5035912.554446138 566.578491210938 610621.7522854737 5035912.554446138 572.989868164063
+
+
+
+
+
+
+
+
+610646.6181083214 5035930.900036323 572.989868164063 610646.6181083214 5035930.900036323 566.578491210938 610621.7522854737 5035912.554446138 566.578491210938 610646.6181083214 5035930.900036323 572.989868164063
+
+
+
+
+
+
+
+
+610663.4816818945 5035908.180781324 572.989868164063 610646.6181083214 5035930.900036323 566.578491210938 610646.6181083214 5035930.900036323 572.989868164063 610663.4816818945 5035908.180781324 572.989868164063
+
+
+
+
+
+
+
+
+610663.4816818945 5035908.180781324 566.578491210938 610646.6181083214 5035930.900036323 566.578491210938 610663.4816818945 5035908.180781324 572.989868164063 610663.4816818945 5035908.180781324 566.578491210938
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 572.989868164063 610668.1231967269 5035865.259882145 566.578491210938 610668.1231967269 5035865.259882145 572.989868164063 610710.889553302 5035807.673307475 572.989868164063
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 566.578491210938 610668.1231967269 5035865.259882145 566.578491210938 610710.889553302 5035807.673307475 572.989868164063 610710.889553302 5035807.673307475 566.578491210938
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 572.989868164063 610692.6219659926 5035794.191143957 572.989868164063 610710.889553302 5035807.673307475 566.578491210938 610710.889553302 5035807.673307475 572.989868164063
+
+
+
+
+
+
+
+
+610692.6219659926 5035794.191143957 572.989868164063 610692.6219659926 5035794.191143957 566.578491210938 610710.889553302 5035807.673307475 566.578491210938 610692.6219659926 5035794.191143957 572.989868164063
+
+
+
+
+
+
+
+
+610621.7522854737 5035912.554446138 572.989868164063 610619.3578221387 5035915.772196898 566.578491210938 610619.3578221387 5035915.772196898 572.989868164063 610621.7522854737 5035912.554446138 572.989868164063
+
+
+
+
+
+
+
+
+610621.7522854737 5035912.554446138 566.578491210938 610619.3578221387 5035915.772196898 566.578491210938 610621.7522854737 5035912.554446138 572.989868164063 610621.7522854737 5035912.554446138 566.578491210938
+
+
+
+
+
+
+
+
+610614.1462577312 5035911.9282374615 572.989868164063 610619.3578221387 5035915.772196898 572.989868164063 610614.1462577312 5035911.9282374615 566.578491210938 610614.1462577312 5035911.9282374615 572.989868164063
+
+
+
+
+
+
+
+
+610619.3578221387 5035915.772196898 572.989868164063 610619.3578221387 5035915.772196898 566.578491210938 610614.1462577312 5035911.9282374615 566.578491210938 610619.3578221387 5035915.772196898 572.989868164063
+
+
+
+
+
+
+
+
+610649.8555010457 5035851.7888990585 566.578491210938 610649.8555010457 5035851.7888990585 572.989868164063 610610.7547462888 5035904.451651935 572.989868164063 610649.8555010457 5035851.7888990585 566.578491210938
+
+
+
+
+
+
+
+
+610692.6219659926 5035794.191143957 566.578491210938 610692.6219659926 5035794.191143957 572.989868164063 610649.8555010457 5035851.7888990585 572.989868164063 610692.6219659926 5035794.191143957 566.578491210938
+
+
+
+
+
+
+
+
+610649.8555010457 5035851.7888990585 566.578491210938 610610.7547462888 5035904.451651935 572.989868164063 610610.7547462888 5035904.451651935 566.578491210938 610649.8555010457 5035851.7888990585 566.578491210938
+
+
+
+
+
+
+
+
+610692.6219659926 5035794.191143957 566.578491210938 610649.8555010457 5035851.7888990585 572.989868164063 610649.8555010457 5035851.7888990585 566.578491210938 610692.6219659926 5035794.191143957 566.578491210938
+
+
+
+
+
+
+
+
+610619.3578221387 5035915.772196898 572.989868164063 610616.5297475372 5035908.71028959 572.989868164063 610621.7522854737 5035912.554446138 572.989868164063 610619.3578221387 5035915.772196898 572.989868164063
+
+
+
+
+
+
+
+
+610621.7522854737 5035912.554446138 572.989868164063 610616.5297475372 5035908.71028959 572.989868164063 610645.8968785583 5035895.203257089 572.989868164063 610621.7522854737 5035912.554446138 572.989868164063
+
+
+
+
+
+
+
+
+610616.5297475372 5035908.71028959 572.989868164063 610610.7547462888 5035904.451651935 572.989868164063 610645.8968785583 5035895.203257089 572.989868164063 610616.5297475372 5035908.71028959 572.989868164063
+
+
+
+
+
+
+
+
+610668.1231967269 5035865.259882145 572.989868164063 610645.8968785583 5035895.203257089 572.989868164063 610649.8555010457 5035851.7888990585 572.989868164063 610668.1231967269 5035865.259882145 572.989868164063
+
+
+
+
+
+
+
+
+610645.8968785583 5035895.203257089 572.989868164063 610610.7547462888 5035904.451651935 572.989868164063 610649.8555010457 5035851.7888990585 572.989868164063 610645.8968785583 5035895.203257089 572.989868164063
+
+
+
+
+
+
+
+
+610646.6181083214 5035930.900036323 572.989868164063 610645.8968785583 5035895.203257089 572.989868164063 610663.4816818945 5035908.180781324 572.989868164063 610646.6181083214 5035930.900036323 572.989868164063
+
+
+
+
+
+
+
+
+610646.6181083214 5035930.900036323 572.989868164063 610621.7522854737 5035912.554446138 572.989868164063 610645.8968785583 5035895.203257089 572.989868164063 610646.6181083214 5035930.900036323 572.989868164063
+
+
+
+
+
+
+
+
+610668.1231967269 5035865.259882145 572.989868164063 610649.8555010457 5035851.7888990585 572.989868164063 610710.889553302 5035807.673307475 572.989868164063 610668.1231967269 5035865.259882145 572.989868164063
+
+
+
+
+
+
+
+
+610619.3578221387 5035915.772196898 572.989868164063 610614.1462577312 5035911.9282374615 572.989868164063 610616.5297475372 5035908.71028959 572.989868164063 610619.3578221387 5035915.772196898 572.989868164063
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 572.989868164063 610649.8555010457 5035851.7888990585 572.989868164063 610692.6219659926 5035794.191143957 572.989868164063 610710.889553302 5035807.673307475 572.989868164063
+
+
+
+
+
+
+
+
+610663.4816818945 5035908.180781324 572.989868164063 610645.8968785583 5035895.203257089 572.989868164063 610663.4816818945 5035908.180781324 566.578491210938 610663.4816818945 5035908.180781324 572.989868164063
+
+
+
+
+
+
+
+
+610645.8968785583 5035895.203257089 572.989868164063 610645.8968785583 5035895.203257089 566.578491210938 610663.4816818945 5035908.180781324 566.578491210938 610645.8968785583 5035895.203257089 572.989868164063
+
+
+
+
+
+
+
+
+610616.5297475372 5035908.71028959 566.578491210938 610616.5297475372 5035908.71028959 572.989868164063 610614.1462577312 5035911.9282374615 572.989868164063 610616.5297475372 5035908.71028959 566.578491210938
+
+
+
+
+
+
+
+
+610616.5297475372 5035908.71028959 566.578491210938 610614.1462577312 5035911.9282374615 572.989868164063 610614.1462577312 5035911.9282374615 566.578491210938 610616.5297475372 5035908.71028959 566.578491210938
+
+
+
+
+
+
+
+
+610619.3578221387 5035915.772196898 566.578491210938 610621.7522854737 5035912.554446138 566.578491210938 610616.5297475372 5035908.71028959 566.578491210938 610619.3578221387 5035915.772196898 566.578491210938
+
+
+
+
+
+
+
+
+610621.7522854737 5035912.554446138 566.578491210938 610645.8968785583 5035895.203257089 566.578491210938 610616.5297475372 5035908.71028959 566.578491210938 610621.7522854737 5035912.554446138 566.578491210938
+
+
+
+
+
+
+
+
+610616.5297475372 5035908.71028959 566.578491210938 610645.8968785583 5035895.203257089 566.578491210938 610610.7547462888 5035904.451651935 566.578491210938 610616.5297475372 5035908.71028959 566.578491210938
+
+
+
+
+
+
+
+
+610668.1231967269 5035865.259882145 566.578491210938 610649.8555010457 5035851.7888990585 566.578491210938 610645.8968785583 5035895.203257089 566.578491210938 610668.1231967269 5035865.259882145 566.578491210938
+
+
+
+
+
+
+
+
+610645.8968785583 5035895.203257089 566.578491210938 610649.8555010457 5035851.7888990585 566.578491210938 610610.7547462888 5035904.451651935 566.578491210938 610645.8968785583 5035895.203257089 566.578491210938
+
+
+
+
+
+
+
+
+610646.6181083214 5035930.900036323 566.578491210938 610663.4816818945 5035908.180781324 566.578491210938 610645.8968785583 5035895.203257089 566.578491210938 610646.6181083214 5035930.900036323 566.578491210938
+
+
+
+
+
+
+
+
+610646.6181083214 5035930.900036323 566.578491210938 610645.8968785583 5035895.203257089 566.578491210938 610621.7522854737 5035912.554446138 566.578491210938 610646.6181083214 5035930.900036323 566.578491210938
+
+
+
+
+
+
+
+
+610668.1231967269 5035865.259882145 566.578491210938 610710.889553302 5035807.673307475 566.578491210938 610649.8555010457 5035851.7888990585 566.578491210938 610668.1231967269 5035865.259882145 566.578491210938
+
+
+
+
+
+
+
+
+610619.3578221387 5035915.772196898 566.578491210938 610616.5297475372 5035908.71028959 566.578491210938 610614.1462577312 5035911.9282374615 566.578491210938 610619.3578221387 5035915.772196898 566.578491210938
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 566.578491210938 610692.6219659926 5035794.191143957 566.578491210938 610649.8555010457 5035851.7888990585 566.578491210938 610710.889553302 5035807.673307475 566.578491210938
+
+
+
+
+
+
+
+
+610668.1231967269 5035865.259882145 572.989868164063 610645.8968785583 5035895.203257089 566.578491210938 610645.8968785583 5035895.203257089 572.989868164063 610668.1231967269 5035865.259882145 572.989868164063
+
+
+
+
+
+
+
+
+610668.1231967269 5035865.259882145 566.578491210938 610645.8968785583 5035895.203257089 566.578491210938 610668.1231967269 5035865.259882145 572.989868164063 610668.1231967269 5035865.259882145 566.578491210938
+
+
+
+
+
+
+
+
+610610.7547462888 5035904.451651935 572.989868164063 610616.5297475372 5035908.71028959 572.989868164063 610610.7547462888 5035904.451651935 566.578491210938 610610.7547462888 5035904.451651935 572.989868164063
+
+
+
+
+
+
+
+
+610616.5297475372 5035908.71028959 572.989868164063 610616.5297475372 5035908.71028959 566.578491210938 610610.7547462888 5035904.451651935 566.578491210938 610616.5297475372 5035908.71028959 572.989868164063
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+6.411376953125
+1
+4.5
+
+
+
+
+
+
+
+
+610621.7524780579 5035912.543510207 579.401306152344 610623.0743290926 5035913.518509444 579.401306152344 610621.7524780579 5035912.543510207 572.989929199219 610621.7524780579 5035912.543510207 579.401306152344
+
+
+
+
+
+
+
+
+610623.0743290926 5035913.518509444 579.401306152344 610623.0743290926 5035913.518509444 572.989929199219 610621.7524780579 5035912.543510207 572.989929199219 610623.0743290926 5035913.518509444 579.401306152344
+
+
+
+
+
+
+
+
+610619.3362629502 5035915.74993861 572.989929199219 610621.7524780579 5035912.543510207 572.989929199219 610616.5191605 5035908.688224501 572.989929199219 610619.3362629502 5035915.74993861 572.989929199219
+
+
+
+
+
+
+
+
+610616.5191605 5035908.688224501 572.989929199219 610692.6329383818 5035794.1913372995 572.989929199219 610610.7547462888 5035904.451651935 572.989929199219 610616.5191605 5035908.688224501 572.989929199219
+
+
+
+
+
+
+
+
+610621.7524780579 5035912.543510207 572.989929199219 610704.9412724827 5035803.280188803 572.989929199219 610616.5191605 5035908.688224501 572.989929199219 610621.7524780579 5035912.543510207 572.989929199219
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 572.989929199219 610692.6329383818 5035794.1913372995 572.989929199219 610616.5191605 5035908.688224501 572.989929199219 610704.9412724827 5035803.280188803 572.989929199219
+
+
+
+
+
+
+
+
+610623.0743290926 5035913.518509444 572.989929199219 610704.9412724827 5035803.280188803 572.989929199219 610621.7524780579 5035912.543510207 572.989929199219 610623.0743290926 5035913.518509444 572.989929199219
+
+
+
+
+
+
+
+
+610619.3362629502 5035915.74993861 572.989929199219 610616.5191605 5035908.688224501 572.989929199219 610614.1350929802 5035911.9389801845 572.989929199219 610619.3362629502 5035915.74993861 572.989929199219
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 579.401306152344 610623.0743290926 5035913.518509444 572.989929199219 610623.0743290926 5035913.518509444 579.401306152344 610704.9412724827 5035803.280188803 579.401306152344
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 572.989929199219 610623.0743290926 5035913.518509444 572.989929199219 610704.9412724827 5035803.280188803 579.401306152344 610704.9412724827 5035803.280188803 572.989929199219
+
+
+
+
+
+
+
+
+610619.3362629502 5035915.74993861 579.401306152344 610616.5191605 5035908.688224501 579.401306152344 610621.7524780579 5035912.543510207 579.401306152344 610619.3362629502 5035915.74993861 579.401306152344
+
+
+
+
+
+
+
+
+610616.5191605 5035908.688224501 579.401306152344 610610.7547462888 5035904.451651935 579.401306152344 610692.6329383818 5035794.1913372995 579.401306152344 610616.5191605 5035908.688224501 579.401306152344
+
+
+
+
+
+
+
+
+610621.7524780579 5035912.543510207 579.401306152344 610616.5191605 5035908.688224501 579.401306152344 610704.9412724827 5035803.280188803 579.401306152344 610621.7524780579 5035912.543510207 579.401306152344
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 579.401306152344 610616.5191605 5035908.688224501 579.401306152344 610692.6329383818 5035794.1913372995 579.401306152344 610704.9412724827 5035803.280188803 579.401306152344
+
+
+
+
+
+
+
+
+610623.0743290926 5035913.518509444 579.401306152344 610621.7524780579 5035912.543510207 579.401306152344 610704.9412724827 5035803.280188803 579.401306152344 610623.0743290926 5035913.518509444 579.401306152344
+
+
+
+
+
+
+
+
+610619.3362629502 5035915.74993861 579.401306152344 610614.1350929802 5035911.9389801845 579.401306152344 610616.5191605 5035908.688224501 579.401306152344 610619.3362629502 5035915.74993861 579.401306152344
+
+
+
+
+
+
+
+
+610621.7524780579 5035912.543510207 579.401306152344 610619.3362629502 5035915.74993861 572.989929199219 610619.3362629502 5035915.74993861 579.401306152344 610621.7524780579 5035912.543510207 579.401306152344
+
+
+
+
+
+
+
+
+610621.7524780579 5035912.543510207 572.989929199219 610619.3362629502 5035915.74993861 572.989929199219 610621.7524780579 5035912.543510207 579.401306152344 610621.7524780579 5035912.543510207 572.989929199219
+
+
+
+
+
+
+
+
+610614.1350929802 5035911.9389801845 579.401306152344 610619.3362629502 5035915.74993861 579.401306152344 610614.1350929802 5035911.9389801845 572.989929199219 610614.1350929802 5035911.9389801845 579.401306152344
+
+
+
+
+
+
+
+
+610619.3362629502 5035915.74993861 579.401306152344 610619.3362629502 5035915.74993861 572.989929199219 610614.1350929802 5035911.9389801845 572.989929199219 610619.3362629502 5035915.74993861 579.401306152344
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 579.401306152344 610692.6329383818 5035794.1913372995 579.401306152344 610704.9412724827 5035803.280188803 572.989929199219 610704.9412724827 5035803.280188803 579.401306152344
+
+
+
+
+
+
+
+
+610692.6329383818 5035794.1913372995 579.401306152344 610692.6329383818 5035794.1913372995 572.989929199219 610704.9412724827 5035803.280188803 572.989929199219 610692.6329383818 5035794.1913372995 579.401306152344
+
+
+
+
+
+
+
+
+610616.5191605 5035908.688224501 572.989929199219 610616.5191605 5035908.688224501 579.401306152344 610614.1350929802 5035911.9389801845 579.401306152344 610616.5191605 5035908.688224501 572.989929199219
+
+
+
+
+
+
+
+
+610616.5191605 5035908.688224501 572.989929199219 610614.1350929802 5035911.9389801845 579.401306152344 610614.1350929802 5035911.9389801845 572.989929199219 610616.5191605 5035908.688224501 572.989929199219
+
+
+
+
+
+
+
+
+610692.6329383818 5035794.1913372995 572.989929199219 610692.6329383818 5035794.1913372995 579.401306152344 610610.7547462888 5035904.451651935 579.401306152344 610692.6329383818 5035794.1913372995 572.989929199219
+
+
+
+
+
+
+
+
+610692.6329383818 5035794.1913372995 572.989929199219 610610.7547462888 5035904.451651935 579.401306152344 610610.7547462888 5035904.451651935 572.989929199219 610692.6329383818 5035794.1913372995 572.989929199219
+
+
+
+
+
+
+
+
+610610.7547462888 5035904.451651935 579.401306152344 610616.5191605 5035908.688224501 579.401306152344 610610.7547462888 5035904.451651935 572.989929199219 610610.7547462888 5035904.451651935 579.401306152344
+
+
+
+
+
+
+
+
+610616.5191605 5035908.688224501 579.401306152344 610616.5191605 5035908.688224501 572.989929199219 610610.7547462888 5035904.451651935 572.989929199219 610616.5191605 5035908.688224501 579.401306152344
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+6.411437988281023
+1
+4.5
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 572.989868164063 610629.0223648318 5035917.922411644 572.989868164063 610629.0223648318 5035917.922411644 579.401306152344 610710.889553302 5035807.673307475 572.989868164063
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 572.989868164063 610629.0223648318 5035917.922411644 579.401306152344 610710.889553302 5035807.673307475 579.401306152344 610710.889553302 5035807.673307475 572.989868164063
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 579.401306152344 610704.9412724827 5035803.280188803 572.989868164063 610710.889553302 5035807.673307475 572.989868164063 610710.889553302 5035807.673307475 579.401306152344
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 579.401306152344 610704.9412724827 5035803.280188803 572.989868164063 610710.889553302 5035807.673307475 579.401306152344 610704.9412724827 5035803.280188803 579.401306152344
+
+
+
+
+
+
+
+
+610629.0223648318 5035917.922411644 579.401306152344 610623.0741365062 5035913.5294453725 579.401306152344 610704.9412724827 5035803.280188803 579.401306152344 610629.0223648318 5035917.922411644 579.401306152344
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 579.401306152344 610629.0223648318 5035917.922411644 579.401306152344 610704.9412724827 5035803.280188803 579.401306152344 610710.889553302 5035807.673307475 579.401306152344
+
+
+
+
+
+
+
+
+610629.0223648318 5035917.922411644 572.989868164063 610704.9412724827 5035803.280188803 572.989868164063 610623.0741365062 5035913.5294453725 572.989868164063 610629.0223648318 5035917.922411644 572.989868164063
+
+
+
+
+
+
+
+
+610710.889553302 5035807.673307475 572.989868164063 610704.9412724827 5035803.280188803 572.989868164063 610629.0223648318 5035917.922411644 572.989868164063 610710.889553302 5035807.673307475 572.989868164063
+
+
+
+
+
+
+
+
+610623.0741365062 5035913.5294453725 579.401306152344 610629.0223648318 5035917.922411644 572.989868164063 610623.0741365062 5035913.5294453725 572.989868164063 610623.0741365062 5035913.5294453725 579.401306152344
+
+
+
+
+
+
+
+
+610629.0223648318 5035917.922411644 579.401306152344 610629.0223648318 5035917.922411644 572.989868164063 610623.0741365062 5035913.5294453725 579.401306152344 610629.0223648318 5035917.922411644 579.401306152344
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 572.989868164063 610704.9412724827 5035803.280188803 579.401306152344 610623.0741365062 5035913.5294453725 572.989868164063 610704.9412724827 5035803.280188803 572.989868164063
+
+
+
+
+
+
+
+
+610704.9412724827 5035803.280188803 579.401306152344 610623.0741365062 5035913.5294453725 579.401306152344 610623.0741365062 5035913.5294453725 572.989868164063 610704.9412724827 5035803.280188803 579.401306152344
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+6.411376953125
+1
+4.5
+
+
+
+
+
+
+
+
+610681.0666060724 5035921.147394737 572.989929199219 610664.20319311 5035943.855621107 572.989929199219 610664.20319311 5035943.855621107 579.401306152344 610681.0666060724 5035921.147394737 572.989929199219
+
+
+
+
+
+
+
+
+610681.0666060724 5035921.147394737 572.989929199219 610664.20319311 5035943.855621107 579.401306152344 610681.0666060724 5035921.147394737 579.401306152344 610681.0666060724 5035921.147394737 572.989929199219
+
+
+
+
+
+
+
+
+610681.0666060724 5035921.147394737 579.401306152344 610645.9080433963 5035895.192514391 572.989929199219 610681.0666060724 5035921.147394737 572.989929199219 610681.0666060724 5035921.147394737 579.401306152344
+
+
+
+
+
+
+
+
+610645.9080433963 5035895.192514391 579.401306152344 610645.9080433963 5035895.192514391 572.989929199219 610681.0666060724 5035921.147394737 579.401306152344 610645.9080433963 5035895.192514391 579.401306152344
+
+
+
+
+
+
+
+
+610664.20319311 5035943.855621107 579.401306152344 610629.0113926606 5035917.922218408 579.401306152344 610645.9080433963 5035895.192514391 579.401306152344 610664.20319311 5035943.855621107 579.401306152344
+
+
+
+
+
+
+
+
+610664.20319311 5035943.855621107 579.401306152344 610645.9080433963 5035895.192514391 579.401306152344 610681.0666060724 5035921.147394737 579.401306152344 610664.20319311 5035943.855621107 579.401306152344
+
+
+
+
+
+
+
+
+610664.20319311 5035943.855621107 572.989929199219 610681.0666060724 5035921.147394737 572.989929199219 610645.9080433963 5035895.192514391 572.989929199219 610664.20319311 5035943.855621107 572.989929199219
+
+
+
+
+
+
+
+
+610664.20319311 5035943.855621107 572.989929199219 610645.9080433963 5035895.192514391 572.989929199219 610629.0113926606 5035917.922218408 572.989929199219 610664.20319311 5035943.855621107 572.989929199219
+
+
+
+
+
+
+
+
+610629.0113926606 5035917.922218408 579.401306152344 610664.20319311 5035943.855621107 572.989929199219 610629.0113926606 5035917.922218408 572.989929199219 610629.0113926606 5035917.922218408 579.401306152344
+
+
+
+
+
+
+
+
+610664.20319311 5035943.855621107 579.401306152344 610664.20319311 5035943.855621107 572.989929199219 610629.0113926606 5035917.922218408 579.401306152344 610664.20319311 5035943.855621107 579.401306152344
+
+
+
+
+
+
+
+
+610645.9080433963 5035895.192514391 572.989929199219 610645.9080433963 5035895.192514391 579.401306152344 610629.0113926606 5035917.922218408 572.989929199219 610645.9080433963 5035895.192514391 572.989929199219
+
+
+
+
+
+
+
+
+610645.9080433963 5035895.192514391 579.401306152344 610629.0113926606 5035917.922218408 579.401306152344 610629.0113926606 5035917.922218408 572.989929199219 610645.9080433963 5035895.192514391 579.401306152344
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+14.532531738281023
+3
+3.4
+
+
+
+
+
+
+
+
+610730.5091460128 5035898.247573101 578.840942382813 610730.5091460128 5035898.247573101 573.996765136719 610734.9514596879 5035901.520172936 573.996765136719 610730.5091460128 5035898.247573101 578.840942382813
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 578.840942382813 610730.5091460128 5035898.247573101 578.840942382813 610734.9514596879 5035901.520172936 573.996765136719 610734.9514596879 5035901.520172936 578.840942382813
+
+
+
+
+
+
+
+
+610730.5091460128 5035898.247573101 573.996765136719 610709.3888679559 5035920.847918315 578.840942382813 610709.3888679559 5035920.847918315 573.996765136719 610730.5091460128 5035898.247573101 573.996765136719
+
+
+
+
+
+
+
+
+610730.5091460128 5035898.247573101 573.996765136719 610730.5091460128 5035898.247573101 578.840942382813 610709.3888679559 5035920.847918315 578.840942382813 610730.5091460128 5035898.247573101 573.996765136719
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 573.996765136719 610734.9514596879 5035901.520172936 573.996765136719 610733.181859054 5035938.39824457 573.996765136719 610753.0128684435 5035914.845466099 573.996765136719
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 573.996765136719 610730.5091460128 5035898.247573101 573.996765136719 610709.3888679559 5035920.847918315 573.996765136719 610734.9514596879 5035901.520172936 573.996765136719
+
+
+
+
+
+
+
+
+610733.181859054 5035938.39824457 573.996765136719 610734.9514596879 5035901.520172936 573.996765136719 610709.3888679559 5035920.847918315 573.996765136719 610733.181859054 5035938.39824457 573.996765136719
+
+
+
+
+
+
+
+
+610716.5712022368 5035954.229941277 573.996765136719 610696.2016912752 5035938.599727995 573.996765136719 610695.9420089822 5035939.010844626 573.996765136719 610716.5712022368 5035954.229941277 573.996765136719
+
+
+
+
+
+
+
+
+610716.5712022368 5035954.229941277 573.996765136719 610709.3888679559 5035920.847918315 573.996765136719 610696.2016912752 5035938.599727995 573.996765136719 610716.5712022368 5035954.229941277 573.996765136719
+
+
+
+
+
+
+
+
+610716.5712022368 5035954.229941277 573.996765136719 610733.181859054 5035938.39824457 573.996765136719 610709.3888679559 5035920.847918315 573.996765136719 610716.5712022368 5035954.229941277 573.996765136719
+
+
+
+
+
+
+
+
+610696.2016912752 5035938.599727995 573.996765136719 610695.9420089822 5035939.010844626 578.648071289063 610695.9420089822 5035939.010844626 573.996765136719 610696.2016912752 5035938.599727995 573.996765136719
+
+
+
+
+
+
+
+
+610696.2016912752 5035938.599727995 573.996765136719 610696.1905264247 5035938.610470531 578.835571289063 610695.9420089822 5035939.010844626 578.648071289063 610696.2016912752 5035938.599727995 573.996765136719
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 588.529296875 610733.181859054 5035938.39824457 583.6851196289069 610733.181859054 5035938.39824457 588.529296875 610753.0128684435 5035914.845466099 588.529296875
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 583.6851196289069 610733.181859054 5035938.39824457 578.840942382813 610733.181859054 5035938.39824457 583.6851196289069 610753.0128684435 5035914.845466099 583.6851196289069
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 573.996765136719 610733.181859054 5035938.39824457 573.996765136719 610753.0128684435 5035914.845466099 578.840942382813 610753.0128684435 5035914.845466099 573.996765136719
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 583.6851196289069 610733.181859054 5035938.39824457 583.6851196289069 610753.0128684435 5035914.845466099 588.529296875 610753.0128684435 5035914.845466099 583.6851196289069
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 578.840942382813 610733.181859054 5035938.39824457 578.840942382813 610753.0128684435 5035914.845466099 583.6851196289069 610753.0128684435 5035914.845466099 578.840942382813
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 578.840942382813 610733.181859054 5035938.39824457 573.996765136719 610733.181859054 5035938.39824457 578.840942382813 610753.0128684435 5035914.845466099 578.840942382813
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 588.529296875 610734.9514596879 5035901.520172936 588.529296875 610753.0128684435 5035914.845466099 583.6851196289069 610753.0128684435 5035914.845466099 588.529296875
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 583.6851196289069 610734.9514596879 5035901.520172936 583.6851196289069 610753.0128684435 5035914.845466099 578.840942382813 610753.0128684435 5035914.845466099 583.6851196289069
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 578.840942382813 610734.9514596879 5035901.520172936 578.840942382813 610753.0128684435 5035914.845466099 573.996765136719 610753.0128684435 5035914.845466099 578.840942382813
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 588.529296875 610734.9514596879 5035901.520172936 583.6851196289069 610753.0128684435 5035914.845466099 583.6851196289069 610734.9514596879 5035901.520172936 588.529296875
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 583.6851196289069 610734.9514596879 5035901.520172936 578.840942382813 610753.0128684435 5035914.845466099 578.840942382813 610734.9514596879 5035901.520172936 583.6851196289069
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 578.840942382813 610734.9514596879 5035901.520172936 573.996765136719 610753.0128684435 5035914.845466099 573.996765136719 610734.9514596879 5035901.520172936 578.840942382813
+
+
+
+
+
+
+
+
+610696.2016912752 5035938.599727995 578.839050292969 610696.1905264247 5035938.610470531 578.835571289063 610696.2016912752 5035938.599727995 573.996765136719 610696.2016912752 5035938.599727995 578.839050292969
+
+
+
+
+
+
+
+
+610709.3888679559 5035920.847918315 573.996765136719 610696.2016912752 5035938.599727995 578.839050292969 610696.2016912752 5035938.599727995 573.996765136719 610709.3888679559 5035920.847918315 573.996765136719
+
+
+
+
+
+
+
+
+610709.3888679559 5035920.847918315 578.840942382813 610696.2016912752 5035938.599727995 578.840942382813 610696.2016912752 5035938.599727995 578.839050292969 610709.3888679559 5035920.847918315 578.840942382813
+
+
+
+
+
+
+
+
+610709.3888679559 5035920.847918315 573.996765136719 610709.3888679559 5035920.847918315 578.840942382813 610696.2016912752 5035938.599727995 578.839050292969 610709.3888679559 5035920.847918315 573.996765136719
+
+
+
+
+
+
+
+
+610716.5712022368 5035954.229941277 578.840942382813 610703.5371131136 5035944.614331181 578.840942382813 610694.2664484897 5035963.091453249 578.840942382813 610716.5712022368 5035954.229941277 578.840942382813
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 578.840942382813 610713.8311757242 5035924.120491701 578.840942382813 610730.5091460128 5035898.247573101 578.840942382813 610734.9514596879 5035901.520172936 578.840942382813
+
+
+
+
+
+
+
+
+610713.8311757242 5035924.120491701 578.840942382813 610709.3888679559 5035920.847918315 578.840942382813 610730.5091460128 5035898.247573101 578.840942382813 610713.8311757242 5035924.120491701 578.840942382813
+
+
+
+
+
+
+
+
+610713.8311757242 5035924.120491701 578.840942382813 610696.2016912752 5035938.599727995 578.840942382813 610709.3888679559 5035920.847918315 578.840942382813 610713.8311757242 5035924.120491701 578.840942382813
+
+
+
+
+
+
+
+
+610703.7644574965 5035944.1698274845 578.840942382813 610696.2016912752 5035938.599727995 578.840942382813 610713.8311757242 5035924.120491701 578.840942382813 610703.7644574965 5035944.1698274845 578.840942382813
+
+
+
+
+
+
+
+
+610701.6014704753 5035968.504367453 578.840942382813 610716.5712022368 5035954.229941277 578.840942382813 610694.2664484897 5035963.091453249 578.840942382813 610701.6014704753 5035968.504367453 578.840942382813
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 583.6851196289069 610734.9514596879 5035901.520172936 588.529296875 610713.8311757242 5035924.120491701 588.529296875 610734.9514596879 5035901.520172936 583.6851196289069
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 578.840942382813 610734.9514596879 5035901.520172936 583.6851196289069 610713.8311757242 5035924.120491701 583.6851196289069 610734.9514596879 5035901.520172936 578.840942382813
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 583.6851196289069 610713.8311757242 5035924.120491701 588.529296875 610713.8311757242 5035924.120491701 583.6851196289069 610734.9514596879 5035901.520172936 583.6851196289069
+
+
+
+
+
+
+
+
+610734.9514596879 5035901.520172936 578.840942382813 610713.8311757242 5035924.120491701 583.6851196289069 610713.8311757242 5035924.120491701 578.840942382813 610734.9514596879 5035901.520172936 578.840942382813
+
+
+
+
+
+
+
+
+610703.5371131136 5035944.614331181 578.648071289063 610716.5712022368 5035954.229941277 573.996765136719 610695.9420089822 5035939.010844626 573.996765136719 610703.5371131136 5035944.614331181 578.648071289063
+
+
+
+
+
+
+
+
+610695.9420089822 5035939.010844626 578.648071289063 610703.5371131136 5035944.614331181 578.648071289063 610695.9420089822 5035939.010844626 573.996765136719 610695.9420089822 5035939.010844626 578.648071289063
+
+
+
+
+
+
+
+
+610703.7530999134 5035944.1915058745 578.835571289063 610703.5371131136 5035944.614331181 578.713562011719 610703.5371131136 5035944.614331181 578.648071289063 610703.7530999134 5035944.1915058745 578.835571289063
+
+
+
+
+
+
+
+
+610703.7530999134 5035944.1915058745 578.835571289063 610703.5371131136 5035944.614331181 578.840942382813 610703.5371131136 5035944.614331181 578.713562011719 610703.7530999134 5035944.1915058745 578.835571289063
+
+
+
+
+
+
+
+
+610703.5371131136 5035944.614331181 578.648071289063 610695.9420089822 5035939.010844626 578.648071289063 610703.7530999134 5035944.1915058745 578.835571289063 610703.5371131136 5035944.614331181 578.648071289063
+
+
+
+
+
+
+
+
+610703.7530999134 5035944.1915058745 578.835571289063 610695.9420089822 5035939.010844626 578.648071289063 610696.1905264247 5035938.610470531 578.835571289063 610703.7530999134 5035944.1915058745 578.835571289063
+
+
+
+
+
+
+
+
+610703.7530999134 5035944.1915058745 578.835571289063 610696.1905264247 5035938.610470531 578.835571289063 610696.2016912752 5035938.599727995 578.839050292969 610703.7530999134 5035944.1915058745 578.835571289063
+
+
+
+
+
+
+
+
+610733.181859054 5035938.39824457 583.6851196289069 610733.181859054 5035938.39824457 578.840942382813 610716.9284778136 5035953.886182148 578.840942382813 610733.181859054 5035938.39824457 583.6851196289069
+
+
+
+
+
+
+
+
+610733.181859054 5035938.39824457 578.840942382813 610733.181859054 5035938.39824457 573.996765136719 610716.9284778136 5035953.886182148 578.840942382813 610733.181859054 5035938.39824457 578.840942382813
+
+
+
+
+
+
+
+
+610716.9284778136 5035953.886182148 578.840942382813 610733.181859054 5035938.39824457 573.996765136719 610716.5712022368 5035954.229941277 573.996765136719 610716.9284778136 5035953.886182148 578.840942382813
+
+
+
+
+
+
+
+
+610753.0128684435 5035914.845466099 588.529296875 610733.181859054 5035938.39824457 588.529296875 610734.9514596879 5035901.520172936 588.529296875 610753.0128684435 5035914.845466099 588.529296875
+
+
+
+
+
+
+
+
+610733.181859054 5035938.39824457 588.529296875 610713.8311757242 5035924.120491701 588.529296875 610734.9514596879 5035901.520172936 588.529296875 610733.181859054 5035938.39824457 588.529296875
+
+
+
+
+
+
+
+
+610701.6014704753 5035968.504367453 588.529296875 610694.2664484897 5035963.091453249 588.529296875 610733.181859054 5035938.39824457 588.529296875 610701.6014704753 5035968.504367453 588.529296875
+
+
+
+
+
+
+
+
+610733.181859054 5035938.39824457 588.529296875 610694.2664484897 5035963.091453249 588.529296875 610713.8311757242 5035924.120491701 588.529296875 610733.181859054 5035938.39824457 588.529296875
+
+
+
+
+
+
+
+
+610703.7530999134 5035944.1915058745 578.835571289063 610696.2016912752 5035938.599727995 578.839050292969 610703.7644574965 5035944.1698274845 578.840942382813 610703.7530999134 5035944.1915058745 578.835571289063
+
+
+
+
+
+
+
+
+610696.2016912752 5035938.599727995 578.840942382813 610703.7644574965 5035944.1698274845 578.840942382813 610696.2016912752 5035938.599727995 578.839050292969 610696.2016912752 5035938.599727995 578.840942382813
+
+
+
+
+
+
+
+
+610713.8311757242 5035924.120491701 578.840942382813 610713.8311757242 5035924.120491701 583.6851196289069 610703.7644574965 5035944.1698274845 578.840942382813 610713.8311757242 5035924.120491701 578.840942382813
+
+
+
+
+
+
+
+
+610713.8311757242 5035924.120491701 583.6851196289069 610713.8311757242 5035924.120491701 588.529296875 610694.2664484897 5035963.091453249 588.529296875 610713.8311757242 5035924.120491701 583.6851196289069
+
+
+
+
+
+
+
+
+610713.8311757242 5035924.120491701 583.6851196289069 610694.2664484897 5035963.091453249 588.529296875 610694.2664484897 5035963.091453249 583.6851196289069 610713.8311757242 5035924.120491701 583.6851196289069
+
+
+
+
+
+
+
+
+610716.5712022368 5035954.229941277 578.840942382813 610716.9284778136 5035953.886182148 578.840942382813 610716.5712022368 5035954.229941277 573.996765136719 610716.5712022368 5035954.229941277 578.840942382813
+
+
+
+
+
+
+
+
+610716.5712022368 5035954.229941277 578.840942382813 610716.5712022368 5035954.229941277 573.996765136719 610703.5371131136 5035944.614331181 578.648071289063 610716.5712022368 5035954.229941277 578.840942382813
+
+
+
+
+
+
+
+
+610703.5371131136 5035944.614331181 578.713562011719 610716.5712022368 5035954.229941277 578.840942382813 610703.5371131136 5035944.614331181 578.648071289063 610703.5371131136 5035944.614331181 578.713562011719
+
+
+
+
+
+
+
+
+610703.5371131136 5035944.614331181 578.840942382813 610716.5712022368 5035954.229941277 578.840942382813 610703.5371131136 5035944.614331181 578.713562011719 610703.5371131136 5035944.614331181 578.840942382813
+
+
+
+
+
+
+
+
+610703.7530999134 5035944.1915058745 578.835571289063 610703.7644574965 5035944.1698274845 578.840942382813 610703.5371131136 5035944.614331181 578.840942382813 610703.7530999134 5035944.1915058745 578.835571289063
+
+
+
+
+
+
+
+
+610701.6014704753 5035968.504367453 588.529296875 610733.181859054 5035938.39824457 588.529296875 610701.6014704753 5035968.504367453 583.6851196289069 610701.6014704753 5035968.504367453 588.529296875
+
+
+
+
+
+
+
+
+610733.181859054 5035938.39824457 588.529296875 610733.181859054 5035938.39824457 583.6851196289069 610701.6014704753 5035968.504367453 583.6851196289069 610733.181859054 5035938.39824457 588.529296875
+
+
+
+
+
+
+
+
+610733.181859054 5035938.39824457 583.6851196289069 610716.9284778136 5035953.886182148 578.840942382813 610701.6014704753 5035968.504367453 583.6851196289069 610733.181859054 5035938.39824457 583.6851196289069
+
+
+
+
+
+
+
+
+610716.9284778136 5035953.886182148 578.840942382813 610716.5712022368 5035954.229941277 578.840942382813 610701.6014704753 5035968.504367453 583.6851196289069 610716.9284778136 5035953.886182148 578.840942382813
+
+
+
+
+
+
+
+
+610701.6014704753 5035968.504367453 583.6851196289069 610716.5712022368 5035954.229941277 578.840942382813 610701.6014704753 5035968.504367453 578.840942382813 610701.6014704753 5035968.504367453 583.6851196289069
+
+
+
+
+
+
+
+
+610694.2664484897 5035963.091453249 588.529296875 610701.6014704753 5035968.504367453 588.529296875 610694.2664484897 5035963.091453249 583.6851196289069 610694.2664484897 5035963.091453249 588.529296875
+
+
+
+
+
+
+
+
+610694.2664484897 5035963.091453249 583.6851196289069 610701.6014704753 5035968.504367453 583.6851196289069 610694.2664484897 5035963.091453249 578.840942382813 610694.2664484897 5035963.091453249 583.6851196289069
+
+
+
+
+
+
+
+
+610701.6014704753 5035968.504367453 588.529296875 610701.6014704753 5035968.504367453 583.6851196289069 610694.2664484897 5035963.091453249 583.6851196289069 610701.6014704753 5035968.504367453 588.529296875
+
+
+
+
+
+
+
+
+610701.6014704753 5035968.504367453 583.6851196289069 610701.6014704753 5035968.504367453 578.840942382813 610694.2664484897 5035963.091453249 578.840942382813 610701.6014704753 5035968.504367453 583.6851196289069
+
+
+
+
+
+
+
+
+610703.5371131136 5035944.614331181 578.840942382813 610703.7644574965 5035944.1698274845 578.840942382813 610694.2664484897 5035963.091453249 583.6851196289069 610703.5371131136 5035944.614331181 578.840942382813
+
+
+
+
+
+
+
+
+610703.7644574965 5035944.1698274845 578.840942382813 610713.8311757242 5035924.120491701 583.6851196289069 610694.2664484897 5035963.091453249 583.6851196289069 610703.7644574965 5035944.1698274845 578.840942382813
+
+
+
+
+
+
+
+
+610703.5371131136 5035944.614331181 578.840942382813 610694.2664484897 5035963.091453249 583.6851196289069 610694.2664484897 5035963.091453249 578.840942382813 610703.5371131136 5035944.614331181 578.840942382813
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+7.002624511718977
+1
+5
+
+
+
+
+
+
+
+
+610730.4983665772 5035898.236443731 573.996704101563 610730.4983665772 5035898.236443731 566.994079589844 610753.0132540688 5035914.823594236 566.994079589844 610730.4983665772 5035898.236443731 573.996704101563
+
+
+
+
+
+
+
+
+610753.0132540688 5035914.823594236 573.996704101563 610730.4983665772 5035898.236443731 573.996704101563 610753.0132540688 5035914.823594236 566.994079589844 610753.0132540688 5035914.823594236 573.996704101563
+
+
+
+
+
+
+
+
+610753.0132540688 5035914.823594236 566.994079589844 610733.1708869145 5035938.398051152 566.994079589844 610753.0132540688 5035914.823594236 573.996704101563 610753.0132540688 5035914.823594236 566.994079589844
+
+
+
+
+
+
+
+
+610753.0132540688 5035914.823594236 573.996704101563 610733.1708869145 5035938.398051152 566.994079589844 610733.1708869145 5035938.398051152 573.996704101563 610753.0132540688 5035914.823594236 573.996704101563
+
+
+
+
+
+
+
+
+610733.1708869145 5035938.398051152 566.994079589844 610753.0132540688 5035914.823594236 566.994079589844 610730.4983665772 5035898.236443731 566.994079589844 610733.1708869145 5035938.398051152 566.994079589844
+
+
+
+
+
+
+
+
+610733.1708869145 5035938.398051152 566.994079589844 610730.4983665772 5035898.236443731 566.994079589844 610709.4004183351 5035920.81530393 566.994079589844 610733.1708869145 5035938.398051152 566.994079589844
+
+
+
+
+
+
+
+
+610716.9173129515 5035953.896924622 566.994079589844 610709.4004183351 5035920.81530393 566.994079589844 610696.1799397165 5035938.5884054005 566.994079589844 610716.9173129515 5035953.896924622 566.994079589844
+
+
+
+
+
+
+
+
+610716.9173129515 5035953.896924622 566.994079589844 610733.1708869145 5035938.398051152 566.994079589844 610709.4004183351 5035920.81530393 566.994079589844 610716.9173129515 5035953.896924622 566.994079589844
+
+
+
+
+
+
+
+
+610733.1708869145 5035938.398051152 573.996704101563 610730.4983665772 5035898.236443731 573.996704101563 610753.0132540688 5035914.823594236 573.996704101563 610733.1708869145 5035938.398051152 573.996704101563
+
+
+
+
+
+
+
+
+610733.1708869145 5035938.398051152 573.996704101563 610709.4004183351 5035920.81530393 573.996704101563 610730.4983665772 5035898.236443731 573.996704101563 610733.1708869145 5035938.398051152 573.996704101563
+
+
+
+
+
+
+
+
+610716.9173129515 5035953.896924622 573.996704101563 610696.1799397165 5035938.5884054005 573.996704101563 610709.4004183351 5035920.81530393 573.996704101563 610716.9173129515 5035953.896924622 573.996704101563
+
+
+
+
+
+
+
+
+610716.9173129515 5035953.896924622 573.996704101563 610709.4004183351 5035920.81530393 573.996704101563 610733.1708869145 5035938.398051152 573.996704101563 610716.9173129515 5035953.896924622 573.996704101563
+
+
+
+
+
+
+
+
+610730.4983665772 5035898.236443731 566.994079589844 610709.4004183351 5035920.81530393 573.996704101563 610709.4004183351 5035920.81530393 566.994079589844 610730.4983665772 5035898.236443731 566.994079589844
+
+
+
+
+
+
+
+
+610730.4983665772 5035898.236443731 566.994079589844 610730.4983665772 5035898.236443731 573.996704101563 610709.4004183351 5035920.81530393 573.996704101563 610730.4983665772 5035898.236443731 566.994079589844
+
+
+
+
+
+
+
+
+610733.1708869145 5035938.398051152 573.996704101563 610733.1708869145 5035938.398051152 566.994079589844 610716.9173129515 5035953.896924622 566.994079589844 610733.1708869145 5035938.398051152 573.996704101563
+
+
+
+
+
+
+
+
+610716.9173129515 5035953.896924622 573.996704101563 610733.1708869145 5035938.398051152 573.996704101563 610716.9173129515 5035953.896924622 566.994079589844 610716.9173129515 5035953.896924622 573.996704101563
+
+
+
+
+
+
+
+
+610709.4004183351 5035920.81530393 566.994079589844 610696.1799397165 5035938.5884054005 573.996704101563 610696.1799397165 5035938.5884054005 566.994079589844 610709.4004183351 5035920.81530393 566.994079589844
+
+
+
+
+
+
+
+
+610709.4004183351 5035920.81530393 566.994079589844 610709.4004183351 5035920.81530393 573.996704101563 610696.1799397165 5035938.5884054005 573.996704101563 610709.4004183351 5035920.81530393 566.994079589844
+
+
+
+
+
+
+
+
+610716.9173129515 5035953.896924622 573.996704101563 610716.9173129515 5035953.896924622 566.994079589844 610696.1799397165 5035938.5884054005 566.994079589844 610716.9173129515 5035953.896924622 573.996704101563
+
+
+
+
+
+
+
+
+610696.1799397165 5035938.5884054005 573.996704101563 610716.9173129515 5035953.896924622 573.996704101563 610696.1799397165 5035938.5884054005 566.994079589844 610696.1799397165 5035938.5884054005 573.996704101563
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+24.220886230468977
+5
+3.4
+
+
+
+
+
+
+
+
+610778.5757756741 5035838.250034396 598.217651367188 610798.1650870934 5035852.6964745615 593.373474121094 610778.5757756741 5035838.250034396 593.373474121094 610778.5757756741 5035838.250034396 598.217651367188
+
+
+
+
+
+
+
+
+610798.1650870934 5035852.6964745615 598.217651367188 610798.1650870934 5035852.6964745615 593.373474121094 610778.5757756741 5035838.250034396 598.217651367188 610798.1650870934 5035852.6964745615 598.217651367188
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 593.373474121094 610798.1650870934 5035852.6964745615 593.373474121094 610812.6156817194 5035835.524813268 598.217651367188 610812.6156817194 5035835.524813268 593.373474121094
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 588.529296875 610798.1650870934 5035852.6964745615 588.529296875 610812.6156817194 5035835.524813268 593.373474121094 610812.6156817194 5035835.524813268 588.529296875
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 598.217651367188 610798.1650870934 5035852.6964745615 593.373474121094 610798.1650870934 5035852.6964745615 598.217651367188 610812.6156817194 5035835.524813268 598.217651367188
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 593.373474121094 610798.1650870934 5035852.6964745615 588.529296875 610798.1650870934 5035852.6964745615 593.373474121094 610812.6156817194 5035835.524813268 593.373474121094
+
+
+
+
+
+
+
+
+610796.093459915 5035775.995860917 598.217651367188 610796.093459915 5035775.995860917 593.373474121094 610812.6156817194 5035835.524813268 593.373474121094 610796.093459915 5035775.995860917 598.217651367188
+
+
+
+
+
+
+
+
+610796.093459915 5035775.995860917 593.373474121094 610796.093459915 5035775.995860917 588.529296875 610812.6156817194 5035835.524813268 588.529296875 610796.093459915 5035775.995860917 593.373474121094
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 598.217651367188 610796.093459915 5035775.995860917 598.217651367188 610812.6156817194 5035835.524813268 593.373474121094 610812.6156817194 5035835.524813268 598.217651367188
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 593.373474121094 610796.093459915 5035775.995860917 593.373474121094 610812.6156817194 5035835.524813268 588.529296875 610812.6156817194 5035835.524813268 593.373474121094
+
+
+
+
+
+
+
+
+610778.6192792265 5035838.272680501 588.529296875 610784.3296125665 5035829.392075743 588.529296875 610778.5757756741 5035838.250034396 588.529296875 610778.6192792265 5035838.272680501 588.529296875
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 588.529296875 610796.093459915 5035775.995860917 588.529296875 610818.6731258357 5035836.83501248 588.529296875 610812.6156817194 5035835.524813268 588.529296875
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 588.529296875 610798.1650870934 5035852.6964745615 588.529296875 610812.6156817194 5035835.524813268 588.529296875 610818.6731258357 5035836.83501248 588.529296875
+
+
+
+
+
+
+
+
+610796.093459915 5035775.995860917 588.529296875 610734.2943063623 5035773.177748277 588.529296875 610800.2212214476 5035770.347264212 588.529296875 610796.093459915 5035775.995860917 588.529296875
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 588.529296875 610796.093459915 5035775.995860917 588.529296875 610800.2212214476 5035770.347264212 588.529296875 610818.6731258357 5035836.83501248 588.529296875
+
+
+
+
+
+
+
+
+610734.538063405 5035778.651829647 588.529296875 610734.2943063623 5035773.177748277 588.529296875 610796.093459915 5035775.995860917 588.529296875 610734.538063405 5035778.651829647 588.529296875
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 588.529296875 610761.9515425221 5035864.167794568 588.529296875 610798.1650870934 5035852.6964745615 588.529296875 610782.6784284493 5035879.454642432 588.529296875
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 588.529296875 610782.6784284493 5035879.454642432 588.529296875 610798.1650870934 5035852.6964745615 588.529296875 610818.6731258357 5035836.83501248 588.529296875
+
+
+
+
+
+
+
+
+610798.1650870934 5035852.6964745615 588.529296875 610761.9515425221 5035864.167794568 588.529296875 610778.6192792265 5035838.272680501 588.529296875 610798.1650870934 5035852.6964745615 588.529296875
+
+
+
+
+
+
+
+
+610778.5757756741 5035838.250034396 593.373474121094 610778.6192792265 5035838.272680501 588.529296875 610778.5757756741 5035838.250034396 588.529296875 610778.5757756741 5035838.250034396 593.373474121094
+
+
+
+
+
+
+
+
+610798.1650870934 5035852.6964745615 593.373474121094 610778.6192792265 5035838.272680501 588.529296875 610778.5757756741 5035838.250034396 593.373474121094 610798.1650870934 5035852.6964745615 593.373474121094
+
+
+
+
+
+
+
+
+610798.1650870934 5035852.6964745615 593.373474121094 610798.1650870934 5035852.6964745615 588.529296875 610778.6192792265 5035838.272680501 588.529296875 610798.1650870934 5035852.6964745615 593.373474121094
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 598.217651367188 610734.538063405 5035778.651829647 598.217651367188 610776.8375347028 5035802.381591275 598.217651367188 610735.6689161435 5035804.160897724 598.217651367188
+
+
+
+
+
+
+
+
+610812.6156817194 5035835.524813268 598.217651367188 610776.8375347028 5035802.381591275 598.217651367188 610796.093459915 5035775.995860917 598.217651367188 610812.6156817194 5035835.524813268 598.217651367188
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 598.217651367188 610734.538063405 5035778.651829647 598.217651367188 610796.093459915 5035775.995860917 598.217651367188 610776.8375347028 5035802.381591275 598.217651367188
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 598.217651367188 610776.8375347028 5035802.381591275 598.217651367188 610812.6156817194 5035835.524813268 598.217651367188 610784.3296125665 5035829.392075743 598.217651367188
+
+
+
+
+
+
+
+
+610798.1650870934 5035852.6964745615 598.217651367188 610778.5757756741 5035838.250034396 598.217651367188 610784.3296125665 5035829.392075743 598.217651367188 610798.1650870934 5035852.6964745615 598.217651367188
+
+
+
+
+
+
+
+
+610798.1650870934 5035852.6964745615 598.217651367188 610784.3296125665 5035829.392075743 598.217651367188 610812.6156817194 5035835.524813268 598.217651367188 610798.1650870934 5035852.6964745615 598.217651367188
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 593.373474121094 610778.5757756741 5035838.250034396 598.217651367188 610778.5757756741 5035838.250034396 593.373474121094 610784.3296125665 5035829.392075743 593.373474121094
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 588.529296875 610784.3296125665 5035829.392075743 593.373474121094 610778.5757756741 5035838.250034396 588.529296875 610784.3296125665 5035829.392075743 588.529296875
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 593.373474121094 610784.3296125665 5035829.392075743 598.217651367188 610778.5757756741 5035838.250034396 598.217651367188 610784.3296125665 5035829.392075743 593.373474121094
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 593.373474121094 610778.5757756741 5035838.250034396 593.373474121094 610778.5757756741 5035838.250034396 588.529296875 610784.3296125665 5035829.392075743 593.373474121094
+
+
+
+
+
+
+
+
+610734.538063405 5035778.651829647 598.217651367188 610734.538063405 5035778.651829647 593.373474121094 610796.093459915 5035775.995860917 593.373474121094 610734.538063405 5035778.651829647 598.217651367188
+
+
+
+
+
+
+
+
+610734.538063405 5035778.651829647 593.373474121094 610734.538063405 5035778.651829647 588.529296875 610796.093459915 5035775.995860917 588.529296875 610734.538063405 5035778.651829647 593.373474121094
+
+
+
+
+
+
+
+
+610796.093459915 5035775.995860917 598.217651367188 610734.538063405 5035778.651829647 598.217651367188 610796.093459915 5035775.995860917 593.373474121094 610796.093459915 5035775.995860917 598.217651367188
+
+
+
+
+
+
+
+
+610796.093459915 5035775.995860917 593.373474121094 610734.538063405 5035778.651829647 593.373474121094 610796.093459915 5035775.995860917 588.529296875 610796.093459915 5035775.995860917 593.373474121094
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 583.6851196289069 610782.6784284493 5035879.454642432 583.6851196289069 610818.6731258357 5035836.83501248 588.529296875 610818.6731258357 5035836.83501248 583.6851196289069
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 578.840942382813 610782.6784284493 5035879.454642432 578.840942382813 610818.6731258357 5035836.83501248 583.6851196289069 610818.6731258357 5035836.83501248 578.840942382813
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 573.996765136719 610782.6784284493 5035879.454642432 573.996765136719 610818.6731258357 5035836.83501248 578.840942382813 610818.6731258357 5035836.83501248 573.996765136719
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 588.529296875 610782.6784284493 5035879.454642432 583.6851196289069 610782.6784284493 5035879.454642432 588.529296875 610818.6731258357 5035836.83501248 588.529296875
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 583.6851196289069 610782.6784284493 5035879.454642432 578.840942382813 610782.6784284493 5035879.454642432 583.6851196289069 610818.6731258357 5035836.83501248 583.6851196289069
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 578.840942382813 610782.6784284493 5035879.454642432 573.996765136719 610782.6784284493 5035879.454642432 578.840942382813 610818.6731258357 5035836.83501248 578.840942382813
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 588.529296875 610782.6784284493 5035879.454642432 583.6851196289069 610761.9515425221 5035864.167794568 583.6851196289069 610782.6784284493 5035879.454642432 588.529296875
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 583.6851196289069 610782.6784284493 5035879.454642432 578.840942382813 610761.9515425221 5035864.167794568 578.840942382813 610782.6784284493 5035879.454642432 583.6851196289069
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 578.840942382813 610782.6784284493 5035879.454642432 573.996765136719 610761.9515425221 5035864.167794568 578.840942382813 610782.6784284493 5035879.454642432 578.840942382813
+
+
+
+
+
+
+
+
+610761.9515425221 5035864.167794568 588.529296875 610782.6784284493 5035879.454642432 588.529296875 610761.9515425221 5035864.167794568 583.6851196289069 610761.9515425221 5035864.167794568 588.529296875
+
+
+
+
+
+
+
+
+610761.9515425221 5035864.167794568 583.6851196289069 610782.6784284493 5035879.454642432 583.6851196289069 610761.9515425221 5035864.167794568 578.840942382813 610761.9515425221 5035864.167794568 583.6851196289069
+
+
+
+
+
+
+
+
+610778.6192792265 5035838.272680501 588.529296875 610761.9515425221 5035864.167794568 588.529296875 610761.9515425221 5035864.167794568 583.6851196289069 610778.6192792265 5035838.272680501 588.529296875
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 583.6851196289069 610784.3296125665 5035829.392075743 588.529296875 610778.6192792265 5035838.272680501 588.529296875 610784.3296125665 5035829.392075743 583.6851196289069
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 583.6851196289069 610778.6192792265 5035838.272680501 588.529296875 610761.9515425221 5035864.167794568 583.6851196289069 610784.3296125665 5035829.392075743 583.6851196289069
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 598.217651367188 610784.3296125665 5035829.392075743 593.373474121094 610776.8375347028 5035802.381591275 593.373474121094 610784.3296125665 5035829.392075743 598.217651367188
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 593.373474121094 610784.3296125665 5035829.392075743 588.529296875 610776.8375347028 5035802.381591275 588.529296875 610784.3296125665 5035829.392075743 593.373474121094
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 588.529296875 610784.3296125665 5035829.392075743 583.6851196289069 610776.8375347028 5035802.381591275 588.529296875 610784.3296125665 5035829.392075743 588.529296875
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 583.6851196289069 610784.3296125665 5035829.392075743 578.840942382813 610776.8375347028 5035802.381591275 578.840942382813 610784.3296125665 5035829.392075743 583.6851196289069
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 598.217651367188 610784.3296125665 5035829.392075743 598.217651367188 610776.8375347028 5035802.381591275 593.373474121094 610776.8375347028 5035802.381591275 598.217651367188
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 593.373474121094 610784.3296125665 5035829.392075743 593.373474121094 610776.8375347028 5035802.381591275 588.529296875 610776.8375347028 5035802.381591275 593.373474121094
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 588.529296875 610784.3296125665 5035829.392075743 583.6851196289069 610776.8375347028 5035802.381591275 583.6851196289069 610776.8375347028 5035802.381591275 588.529296875
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 583.6851196289069 610784.3296125665 5035829.392075743 583.6851196289069 610776.8375347028 5035802.381591275 578.840942382813 610776.8375347028 5035802.381591275 583.6851196289069
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 598.217651367188 610735.6689161435 5035804.160897724 593.373474121094 610734.538063405 5035778.651829647 593.373474121094 610735.6689161435 5035804.160897724 598.217651367188
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 593.373474121094 610735.6689161435 5035804.160897724 588.529296875 610734.538063405 5035778.651829647 588.529296875 610735.6689161435 5035804.160897724 593.373474121094
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 588.529296875 610735.6689161435 5035804.160897724 583.6851196289069 610734.538063405 5035778.651829647 588.529296875 610735.6689161435 5035804.160897724 588.529296875
+
+
+
+
+
+
+
+
+610734.538063405 5035778.651829647 598.217651367188 610735.6689161435 5035804.160897724 598.217651367188 610734.538063405 5035778.651829647 593.373474121094 610734.538063405 5035778.651829647 598.217651367188
+
+
+
+
+
+
+
+
+610734.538063405 5035778.651829647 593.373474121094 610735.6689161435 5035804.160897724 593.373474121094 610734.538063405 5035778.651829647 588.529296875 610734.538063405 5035778.651829647 593.373474121094
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 598.217651367188 610776.8375347028 5035802.381591275 593.373474121094 610735.6689161435 5035804.160897724 593.373474121094 610776.8375347028 5035802.381591275 598.217651367188
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 593.373474121094 610776.8375347028 5035802.381591275 588.529296875 610735.6689161435 5035804.160897724 588.529296875 610776.8375347028 5035802.381591275 593.373474121094
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 588.529296875 610776.8375347028 5035802.381591275 583.6851196289069 610735.6689161435 5035804.160897724 588.529296875 610776.8375347028 5035802.381591275 588.529296875
+
+
+
+
+
+
+
+
+610776.8375347028 5035802.381591275 583.6851196289069 610776.8375347028 5035802.381591275 578.840942382813 610735.6689161435 5035804.160897724 578.840942382813 610776.8375347028 5035802.381591275 583.6851196289069
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 598.217651367188 610776.8375347028 5035802.381591275 598.217651367188 610735.6689161435 5035804.160897724 593.373474121094 610735.6689161435 5035804.160897724 598.217651367188
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 593.373474121094 610776.8375347028 5035802.381591275 593.373474121094 610735.6689161435 5035804.160897724 588.529296875 610735.6689161435 5035804.160897724 593.373474121094
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 588.529296875 610776.8375347028 5035802.381591275 583.6851196289069 610735.6689161435 5035804.160897724 583.6851196289069 610735.6689161435 5035804.160897724 588.529296875
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 583.6851196289069 610776.8375347028 5035802.381591275 583.6851196289069 610735.6689161435 5035804.160897724 578.840942382813 610735.6689161435 5035804.160897724 583.6851196289069
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 588.529296875 610800.2212214476 5035770.347264212 583.6851196289069 610818.6731258357 5035836.83501248 583.6851196289069 610800.2212214476 5035770.347264212 588.529296875
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 583.6851196289069 610800.2212214476 5035770.347264212 578.840942382813 610818.6731258357 5035836.83501248 578.840942382813 610800.2212214476 5035770.347264212 583.6851196289069
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 578.840942382813 610800.2212214476 5035770.347264212 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719 610800.2212214476 5035770.347264212 578.840942382813
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 588.529296875 610800.2212214476 5035770.347264212 588.529296875 610818.6731258357 5035836.83501248 583.6851196289069 610818.6731258357 5035836.83501248 588.529296875
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 583.6851196289069 610800.2212214476 5035770.347264212 583.6851196289069 610818.6731258357 5035836.83501248 578.840942382813 610818.6731258357 5035836.83501248 583.6851196289069
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 578.840942382813 610800.2212214476 5035770.347264212 578.840942382813 610818.6731258357 5035836.83501248 573.996765136719 610818.6731258357 5035836.83501248 578.840942382813
+
+
+
+
+
+
+
+
+610757.530966894 5035860.906479697 578.840942382813 610761.9515425221 5035864.167794568 578.840942382813 610757.530966894 5035860.906479697 573.996765136719 610757.530966894 5035860.906479697 578.840942382813
+
+
+
+
+
+
+
+
+610761.9515425221 5035864.167794568 578.840942382813 610782.6784284493 5035879.454642432 573.996765136719 610757.530966894 5035860.906479697 573.996765136719 610761.9515425221 5035864.167794568 578.840942382813
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 578.840942382813 610761.9515425221 5035864.167794568 583.6851196289069 610761.9515425221 5035864.167794568 578.840942382813 610784.3296125665 5035829.392075743 578.840942382813
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 578.840942382813 610784.3296125665 5035829.392075743 583.6851196289069 610761.9515425221 5035864.167794568 583.6851196289069 610784.3296125665 5035829.392075743 578.840942382813
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 588.529296875 610734.2943063623 5035773.177748277 583.6851196289069 610800.2212214476 5035770.347264212 583.6851196289069 610734.2943063623 5035773.177748277 588.529296875
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 583.6851196289069 610734.2943063623 5035773.177748277 578.840942382813 610800.2212214476 5035770.347264212 578.840942382813 610734.2943063623 5035773.177748277 583.6851196289069
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 578.840942382813 610734.2943063623 5035773.177748277 573.996765136719 610800.2212214476 5035770.347264212 573.996765136719 610734.2943063623 5035773.177748277 578.840942382813
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 588.529296875 610734.2943063623 5035773.177748277 588.529296875 610800.2212214476 5035770.347264212 583.6851196289069 610800.2212214476 5035770.347264212 588.529296875
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 583.6851196289069 610734.2943063623 5035773.177748277 583.6851196289069 610800.2212214476 5035770.347264212 578.840942382813 610800.2212214476 5035770.347264212 583.6851196289069
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 578.840942382813 610734.2943063623 5035773.177748277 578.840942382813 610800.2212214476 5035770.347264212 573.996765136719 610800.2212214476 5035770.347264212 578.840942382813
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 578.840942382813 610772.7202085907 5035808.0631751185 578.840942382813 610776.8375347028 5035802.381591275 578.840942382813 610784.3296125665 5035829.392075743 578.840942382813
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 578.840942382813 610735.6689161435 5035804.160897724 578.840942382813 610776.8375347028 5035802.381591275 578.840942382813 610772.7202085907 5035808.0631751185 578.840942382813
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 578.840942382813 610772.7202085907 5035808.0631751185 578.840942382813 610784.3296125665 5035829.392075743 578.840942382813 610778.2721552142 5035828.081908587 578.840942382813
+
+
+
+
+
+
+
+
+610761.9515425221 5035864.167794568 578.840942382813 610757.530966894 5035860.906479697 578.840942382813 610778.2721552142 5035828.081908587 578.840942382813 610761.9515425221 5035864.167794568 578.840942382813
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 578.840942382813 610735.6689161435 5035804.160897724 578.840942382813 610772.7202085907 5035808.0631751185 578.840942382813 610735.9011191447 5035809.667567344 578.840942382813
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 578.840942382813 610734.2943063623 5035773.177748277 578.840942382813 610735.6689161435 5035804.160897724 578.840942382813 610735.9011191447 5035809.667567344 578.840942382813
+
+
+
+
+
+
+
+
+610784.3296125665 5035829.392075743 578.840942382813 610761.9515425221 5035864.167794568 578.840942382813 610778.2721552142 5035828.081908587 578.840942382813 610784.3296125665 5035829.392075743 578.840942382813
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 573.996765136719 610757.530966894 5035860.906479697 578.840942382813 610757.530966894 5035860.906479697 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 573.996765136719 610778.2721552142 5035828.081908587 578.840942382813 610757.530966894 5035860.906479697 578.840942382813 610778.2721552142 5035828.081908587 573.996765136719
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 573.996765136719 610800.2212214476 5035770.347264212 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 573.996765136719 610800.2212214476 5035770.347264212 573.996765136719 610734.2943063623 5035773.177748277 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719 610734.2943063623 5035773.177748277 573.996765136719 610735.9011191447 5035809.667567344 573.996765136719
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719 610757.530966894 5035860.906479697 573.996765136719 610782.6784284493 5035879.454642432 573.996765136719
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719 610782.6784284493 5035879.454642432 573.996765136719
+
+
+
+
+
+
+
+
+610734.538063405 5035778.651829647 588.529296875 610735.6689161435 5035804.160897724 583.6851196289069 610734.2943063623 5035773.177748277 583.6851196289069 610734.538063405 5035778.651829647 588.529296875
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 588.529296875 610734.538063405 5035778.651829647 588.529296875 610734.2943063623 5035773.177748277 583.6851196289069 610734.2943063623 5035773.177748277 588.529296875
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 578.840942382813 610772.7202085907 5035808.0631751185 573.996765136719 610735.9011191447 5035809.667567344 573.996765136719 610772.7202085907 5035808.0631751185 578.840942382813
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 578.840942382813 610772.7202085907 5035808.0631751185 578.840942382813 610735.9011191447 5035809.667567344 573.996765136719 610735.9011191447 5035809.667567344 578.840942382813
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 578.840942382813 610778.2721552142 5035828.081908587 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719 610778.2721552142 5035828.081908587 578.840942382813
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 578.840942382813 610778.2721552142 5035828.081908587 578.840942382813 610772.7202085907 5035808.0631751185 573.996765136719 610772.7202085907 5035808.0631751185 578.840942382813
+
+
+
+
+
+
+
+
+610735.6689161435 5035804.160897724 583.6851196289069 610735.6689161435 5035804.160897724 578.840942382813 610734.2943063623 5035773.177748277 578.840942382813 610735.6689161435 5035804.160897724 583.6851196289069
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 583.6851196289069 610735.6689161435 5035804.160897724 583.6851196289069 610734.2943063623 5035773.177748277 578.840942382813 610734.2943063623 5035773.177748277 583.6851196289069
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 578.840942382813 610735.9011191447 5035809.667567344 573.996765136719 610734.2943063623 5035773.177748277 573.996765136719 610735.9011191447 5035809.667567344 578.840942382813
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 578.840942382813 610735.9011191447 5035809.667567344 578.840942382813 610734.2943063623 5035773.177748277 573.996765136719 610734.2943063623 5035773.177748277 578.840942382813
+
+
+
+
+
+
+
+
+
+
+
+
+residential
+1996
+7.002685546875
+1
+5
+
+
+
+
+
+
+
+
+610757.530966894 5035860.906479697 573.996765136719 610782.6784284493 5035879.454642432 566.994079589844 610757.530966894 5035860.906479697 566.994079589844 610757.530966894 5035860.906479697 573.996765136719
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 573.996765136719 610782.6784284493 5035879.454642432 566.994079589844 610757.530966894 5035860.906479697 573.996765136719 610782.6784284493 5035879.454642432 573.996765136719
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719 610800.2212214476 5035770.347264212 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 573.996765136719 610734.2943063623 5035773.177748277 573.996765136719 610800.2212214476 5035770.347264212 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 573.996765136719 610734.2943063623 5035773.177748277 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719 610735.9011191447 5035809.667567344 573.996765136719
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 573.996765136719 610757.530966894 5035860.906479697 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719 610782.6784284493 5035879.454642432 573.996765136719
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719 610782.6784284493 5035879.454642432 573.996765136719
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 566.994079589844 610778.2721552142 5035828.081908587 573.996765136719 610757.530966894 5035860.906479697 566.994079589844 610778.2721552142 5035828.081908587 566.994079589844
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 573.996765136719 610757.530966894 5035860.906479697 573.996765136719 610757.530966894 5035860.906479697 566.994079589844 610778.2721552142 5035828.081908587 573.996765136719
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 566.994079589844 610800.2212214476 5035770.347264212 566.994079589844 610772.7202085907 5035808.0631751185 566.994079589844 610818.6731258357 5035836.83501248 566.994079589844
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 566.994079589844 610818.6731258357 5035836.83501248 566.994079589844 610772.7202085907 5035808.0631751185 566.994079589844 610778.2721552142 5035828.081908587 566.994079589844
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 566.994079589844 610800.2212214476 5035770.347264212 566.994079589844 610734.2943063623 5035773.177748277 566.994079589844 610772.7202085907 5035808.0631751185 566.994079589844
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 566.994079589844 610772.7202085907 5035808.0631751185 566.994079589844 610734.2943063623 5035773.177748277 566.994079589844 610735.9011191447 5035809.667567344 566.994079589844
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 566.994079589844 610778.2721552142 5035828.081908587 566.994079589844 610757.530966894 5035860.906479697 566.994079589844 610782.6784284493 5035879.454642432 566.994079589844
+
+
+
+
+
+
+
+
+610782.6784284493 5035879.454642432 566.994079589844 610818.6731258357 5035836.83501248 566.994079589844 610778.2721552142 5035828.081908587 566.994079589844 610782.6784284493 5035879.454642432 566.994079589844
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 566.994079589844 610782.6784284493 5035879.454642432 566.994079589844 610782.6784284493 5035879.454642432 573.996765136719 610818.6731258357 5035836.83501248 566.994079589844
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 566.994079589844 610782.6784284493 5035879.454642432 573.996765136719 610818.6731258357 5035836.83501248 573.996765136719 610818.6731258357 5035836.83501248 566.994079589844
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 573.996765136719 610778.2721552142 5035828.081908587 566.994079589844 610772.7202085907 5035808.0631751185 566.994079589844 610772.7202085907 5035808.0631751185 573.996765136719
+
+
+
+
+
+
+
+
+610778.2721552142 5035828.081908587 573.996765136719 610778.2721552142 5035828.081908587 566.994079589844 610772.7202085907 5035808.0631751185 573.996765136719 610778.2721552142 5035828.081908587 573.996765136719
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 573.996765136719 610772.7202085907 5035808.0631751185 566.994079589844 610735.9011191447 5035809.667567344 566.994079589844 610735.9011191447 5035809.667567344 573.996765136719
+
+
+
+
+
+
+
+
+610772.7202085907 5035808.0631751185 573.996765136719 610772.7202085907 5035808.0631751185 566.994079589844 610735.9011191447 5035809.667567344 573.996765136719 610772.7202085907 5035808.0631751185 573.996765136719
+
+
+
+
+
+
+
+
+610818.6731258357 5035836.83501248 573.996765136719 610800.2212214476 5035770.347264212 566.994079589844 610818.6731258357 5035836.83501248 566.994079589844 610818.6731258357 5035836.83501248 573.996765136719
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 573.996765136719 610800.2212214476 5035770.347264212 566.994079589844 610818.6731258357 5035836.83501248 573.996765136719 610800.2212214476 5035770.347264212 573.996765136719
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 573.996765136719 610735.9011191447 5035809.667567344 566.994079589844 610734.2943063623 5035773.177748277 566.994079589844 610734.2943063623 5035773.177748277 573.996765136719
+
+
+
+
+
+
+
+
+610735.9011191447 5035809.667567344 573.996765136719 610735.9011191447 5035809.667567344 566.994079589844 610734.2943063623 5035773.177748277 573.996765136719 610735.9011191447 5035809.667567344 573.996765136719
+
+
+
+
+
+
+
+
+610800.2212214476 5035770.347264212 573.996765136719 610734.2943063623 5035773.177748277 566.994079589844 610800.2212214476 5035770.347264212 566.994079589844 610800.2212214476 5035770.347264212 573.996765136719
+
+
+
+
+
+
+
+
+610734.2943063623 5035773.177748277 573.996765136719 610734.2943063623 5035773.177748277 566.994079589844 610800.2212214476 5035770.347264212 573.996765136719 610734.2943063623 5035773.177748277 573.996765136719
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/tests_data/FZK_Haus_LoD_2.gml b/tests/tests_data/FZK_Haus_LoD_2.gml
new file mode 100644
index 0000000..eaea23f
--- /dev/null
+++ b/tests/tests_data/FZK_Haus_LoD_2.gml
@@ -0,0 +1,240 @@
+
+
+ AC14-FZK-Haus
+
+
+ 457842 5439083 111.8
+ 457854 5439093 118.317669
+
+
+
+
+ FZK-Haus (Forschungszentrum Karlsruhe, now KIT), created by Karl-Heinz
+ Haefele
+ AC14-FZK-Haus
+ 2017-01-23
+ entirelyAboveTerrain
+
+ 120.00
+
+
+ New Building
+
+
+ NO
+
+ 1000
+ 1000
+ 1000
+ 2020
+ 1030
+ 6.52
+ 2
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Outer Wall 1 (West)
+
+
+
+
+
+
+ 457842 5439088 118.317691453624
+ 457842 5439093 115.430940107676
+ 457842 5439093 111.8
+ 457842 5439083 111.8
+ 457842 5439083 115.430940107676
+ 457842 5439088 118.317691453624
+
+
+
+
+
+
+
+
+
+
+ Outer Wall 2 (South)
+
+
+
+
+
+
+ 457854 5439083 115.430940107676
+ 457842 5439083 115.430940107676
+ 457842 5439083 111.8
+ 457854 5439083 111.8
+ 457854 5439083 115.430940107676
+
+
+
+
+
+
+
+
+
+
+ Outer Wall 3 (East)
+
+
+
+
+
+
+ 457854 5439088 118.317691453624
+ 457854 5439083 115.430940107676
+ 457854 5439083 111.8
+ 457854 5439093 111.8
+ 457854 5439093 115.430940107676
+ 457854 5439088 118.317691453624
+
+
+
+
+
+
+
+
+
+
+ Roof 1 (North)
+
+
+
+
+
+
+ 457842 5439088 118.317691453624
+ 457854 5439088 118.317691453624
+ 457854 5439093 115.430940107676
+ 457842 5439093 115.430940107676
+ 457842 5439088 118.317691453624
+
+
+
+
+
+
+
+
+
+
+ Outer Wall 4 (North)
+
+
+
+
+
+
+ 457842 5439093 115.430940107676
+ 457854 5439093 115.430940107676
+ 457854 5439093 111.8
+ 457842 5439093 111.8
+ 457842 5439093 115.430940107676
+
+
+
+
+
+
+
+
+
+
+ Roof 2 (South)
+
+
+
+
+
+
+ 457854 5439083 115.430940107676
+ 457854 5439088 118.317691453624
+ 457842 5439088 118.317691453624
+ 457842 5439083 115.430940107676
+ 457854 5439083 115.430940107676
+
+
+
+
+
+
+
+
+
+
+ Bodenplatte
+ Base Surface
+
+
+
+
+
+
+ 457854 5439083 111.8
+ 457842 5439083 111.8
+ 457842 5439093 111.8
+ 457854 5439093 111.8
+ 457854 5439083 111.8
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eggenstein-Leopoldshafen
+
+ 4711
+ Spöcker Straße
+
+
+ 76344
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/tests_data/eilat.geojson b/tests/tests_data/eilat.geojson
new file mode 100644
index 0000000..2e4efd3
--- /dev/null
+++ b/tests/tests_data/eilat.geojson
@@ -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"
+ }
+ }
+ ]
+}
diff --git a/tests/tests_data/kelowna.obj b/tests/tests_data/kelowna.obj
new file mode 100644
index 0000000..ef0ebad
--- /dev/null
+++ b/tests/tests_data/kelowna.obj
@@ -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
\ No newline at end of file
diff --git a/tests/tests_data/levis.geojson b/tests/tests_data/levis.geojson
new file mode 100644
index 0000000..04ed34e
--- /dev/null
+++ b/tests/tests_data/levis.geojson
@@ -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"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/tests_data/one_building_in_kelowna_alkis.gml b/tests/tests_data/one_building_in_kelowna_alkis.gml
new file mode 100644
index 0000000..05926e5
--- /dev/null
+++ b/tests/tests_data/one_building_in_kelowna_alkis.gml
@@ -0,0 +1,409 @@
+
+
+
+
+326011.03601000085 5526048.416990001 -1.6000000000058208
+329466.6600299999 5529018.72205 9.80000000000291
+
+
+
+
+
+291
+
+
+m2
+
+1996
+residential
+5.3
+1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+329231.5010599997 5528270.404139999 4.311470000000554 329229.15295 5528271.14002 3.8000000000029104 329229.30395000055 5528269.304020001 3.8000000000029104 329231.5010599997 5528270.404139999 4.311470000000554
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+329248.8121399991 5528267.658840001 4.925719999999274 329254.11205999926 5528262.99903 3.8000000000029104 329253.52796000056 5528272.956 3.8000000000029104 329248.8121399991 5528267.658840001 4.925719999999274
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/tests_data/pluto_building.gml b/tests/tests_data/pluto_building.gml
new file mode 100644
index 0000000..400eaec
--- /dev/null
+++ b/tests/tests_data/pluto_building.gml
@@ -0,0 +1,420 @@
+
+
+ Gowanus 2050 Best Practice Scenario
+
+
+ 299606.4441129853 55348.37638737355 0
+ 301879.9050504853 57594.05119206105 62.04879541695123
+
+
+
+
+
+
+
+
+
+
+
+
+ 301010.4314176728 57301.3749225298 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727
+
+
+
+
+
+
+
+
+ 301014.183859079 57308.78849674855 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727
+
+
+
+
+
+
+
+
+ 301004.1125700165 57288.87345768605 10.786276534199727 300992.0398161103 57285.56779362355 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727
+
+
+
+
+
+
+
+
+ 301024.4275114228 57311.0624225298 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727
+
+
+
+
+
+
+
+
+ 301000.3254606415 57281.3758990923 10.786276534199727 300997.2820036103 57275.3758990923 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727
+
+
+
+
+
+
+
+
+ 301004.1125700165 57288.87345768605 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727
+
+
+
+
+
+
+
+
+ 301017.183859079 57314.7147662798 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727 301017.183859079 57314.7147662798 10.786276534199727
+
+
+
+
+
+
+
+
+ 301005.9055387665 57312.9716022173 10.786276534199727 301002.1530973603 57305.55900456105 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727 301005.9055387665 57312.9716022173 10.786276534199727
+
+
+
+
+
+
+
+
+ 300995.8337614228 57293.0555865923 10.786276534199727 300992.0398161103 57285.56779362355 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727 300995.8337614228 57293.0555865923 10.786276534199727
+
+
+
+
+
+
+
+
+ 301014.183859079 57308.78849674855 10.786276534199727 301002.1530973603 57305.55900456105 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727
+
+
+
+
+
+
+
+
+ 301005.9055387665 57312.9716022173 10.786276534199727 301005.9055387665 57312.9716022173 0.0 301002.1530973603 57305.55900456105 10.786276534199727 301005.9055387665 57312.9716022173 10.786276534199727
+
+
+
+
+
+
+
+
+ 301002.1530973603 57305.55900456105 10.786276534199727 301005.9055387665 57312.9716022173 0.0 301002.1530973603 57305.55900456105 0.0 301002.1530973603 57305.55900456105 10.786276534199727
+
+
+
+
+
+
+
+
+ 301017.183859079 57314.7147662798 0.0 301024.4275114228 57311.0624225298 0.0 301014.183859079 57308.78849674855 0.0 301017.183859079 57314.7147662798 0.0
+
+
+
+
+
+
+
+
+ 301005.9055387665 57312.9716022173 0.0 301014.183859079 57308.78849674855 0.0 301002.1530973603 57305.55900456105 0.0 301005.9055387665 57312.9716022173 0.0
+
+
+
+
+
+
+
+
+ 300995.8337614228 57293.0555865923 0.0 301004.1125700165 57288.87345768605 0.0 300992.0398161103 57285.56779362355 0.0 300995.8337614228 57293.0555865923 0.0
+
+
+
+
+
+
+
+
+ 301014.183859079 57308.78849674855 0.0 301010.4314176728 57301.3749225298 0.0 301002.1530973603 57305.55900456105 0.0 301014.183859079 57308.78849674855 0.0
+
+
+
+
+
+
+
+
+ 301010.4314176728 57301.3749225298 0.0 301024.4275114228 57311.0624225298 0.0 301004.1125700165 57288.87345768605 0.0 301010.4314176728 57301.3749225298 0.0
+
+
+
+
+
+
+
+
+ 301014.183859079 57308.78849674855 0.0 301024.4275114228 57311.0624225298 0.0 301010.4314176728 57301.3749225298 0.0 301014.183859079 57308.78849674855 0.0
+
+
+
+
+
+
+
+
+ 301024.4275114228 57311.0624225298 0.0 301004.5266325165 57271.70548893605 0.0 301004.1125700165 57288.87345768605 0.0 301024.4275114228 57311.0624225298 0.0
+
+
+
+
+
+
+
+
+ 301004.1125700165 57288.87345768605 0.0 301000.3254606415 57281.3758990923 0.0 300992.0398161103 57285.56779362355 0.0 301004.1125700165 57288.87345768605 0.0
+
+
+
+
+
+
+
+
+ 301000.3254606415 57281.3758990923 0.0 301004.5266325165 57271.70548893605 0.0 300997.2820036103 57275.3758990923 0.0 301000.3254606415 57281.3758990923 0.0
+
+
+
+
+
+
+
+
+ 301004.1125700165 57288.87345768605 0.0 301004.5266325165 57271.70548893605 0.0 301000.3254606415 57281.3758990923 0.0 301004.1125700165 57288.87345768605 0.0
+
+
+
+
+
+
+
+
+ 301014.183859079 57308.78849674855 10.786276534199727 301014.183859079 57308.78849674855 0.0 301005.9055387665 57312.9716022173 10.786276534199727 301014.183859079 57308.78849674855 10.786276534199727
+
+
+
+
+
+
+
+
+ 301005.9055387665 57312.9716022173 10.786276534199727 301014.183859079 57308.78849674855 0.0 301005.9055387665 57312.9716022173 0.0 301005.9055387665 57312.9716022173 10.786276534199727
+
+
+
+
+
+
+
+
+ 301017.183859079 57314.7147662798 10.786276534199727 301017.183859079 57314.7147662798 0.0 301014.183859079 57308.78849674855 10.786276534199727 301017.183859079 57314.7147662798 10.786276534199727
+
+
+
+
+
+
+
+
+ 301014.183859079 57308.78849674855 10.786276534199727 301017.183859079 57314.7147662798 0.0 301014.183859079 57308.78849674855 0.0 301014.183859079 57308.78849674855 10.786276534199727
+
+
+
+
+
+
+
+
+ 301002.1530973603 57305.55900456105 10.786276534199727 301002.1530973603 57305.55900456105 0.0 301010.4314176728 57301.3749225298 10.786276534199727 301002.1530973603 57305.55900456105 10.786276534199727
+
+
+
+
+
+
+
+
+ 301010.4314176728 57301.3749225298 10.786276534199727 301002.1530973603 57305.55900456105 0.0 301010.4314176728 57301.3749225298 0.0 301010.4314176728 57301.3749225298 10.786276534199727
+
+
+
+
+
+
+
+
+ 301024.4275114228 57311.0624225298 10.786276534199727 301024.4275114228 57311.0624225298 0.0 301017.183859079 57314.7147662798 10.786276534199727 301024.4275114228 57311.0624225298 10.786276534199727
+
+
+
+
+
+
+
+
+ 301017.183859079 57314.7147662798 10.786276534199727 301024.4275114228 57311.0624225298 0.0 301017.183859079 57314.7147662798 0.0 301017.183859079 57314.7147662798 10.786276534199727
+
+
+
+
+
+
+
+
+ 301004.5266325165 57271.70548893605 10.786276534199727 301004.5266325165 57271.70548893605 0.0 301024.4275114228 57311.0624225298 10.786276534199727 301004.5266325165 57271.70548893605 10.786276534199727
+
+
+
+
+
+
+
+
+ 301024.4275114228 57311.0624225298 10.786276534199727 301004.5266325165 57271.70548893605 0.0 301024.4275114228 57311.0624225298 0.0 301024.4275114228 57311.0624225298 10.786276534199727
+
+
+
+
+
+
+
+
+ 300997.2820036103 57275.3758990923 10.786276534199727 300997.2820036103 57275.3758990923 0.0 301004.5266325165 57271.70548893605 10.786276534199727 300997.2820036103 57275.3758990923 10.786276534199727
+
+
+
+
+
+
+
+
+ 301004.5266325165 57271.70548893605 10.786276534199727 300997.2820036103 57275.3758990923 0.0 301004.5266325165 57271.70548893605 0.0 301004.5266325165 57271.70548893605 10.786276534199727
+
+
+
+
+
+
+
+
+ 301010.4314176728 57301.3749225298 10.786276534199727 301010.4314176728 57301.3749225298 0.0 301004.1125700165 57288.87345768605 10.786276534199727 301010.4314176728 57301.3749225298 10.786276534199727
+
+
+
+
+
+
+
+
+ 301004.1125700165 57288.87345768605 10.786276534199727 301010.4314176728 57301.3749225298 0.0 301004.1125700165 57288.87345768605 0.0 301004.1125700165 57288.87345768605 10.786276534199727
+
+
+
+
+
+
+
+
+ 301004.1125700165 57288.87345768605 10.786276534199727 301004.1125700165 57288.87345768605 0.0 300995.8337614228 57293.0555865923 10.786276534199727 301004.1125700165 57288.87345768605 10.786276534199727
+
+
+
+
+
+
+
+
+ 300995.8337614228 57293.0555865923 10.786276534199727 301004.1125700165 57288.87345768605 0.0 300995.8337614228 57293.0555865923 0.0 300995.8337614228 57293.0555865923 10.786276534199727
+
+
+
+
+
+
+
+
+ 301000.3254606415 57281.3758990923 10.786276534199727 301000.3254606415 57281.3758990923 0.0 300997.2820036103 57275.3758990923 10.786276534199727 301000.3254606415 57281.3758990923 10.786276534199727
+
+
+
+
+
+
+
+
+ 300997.2820036103 57275.3758990923 10.786276534199727 301000.3254606415 57281.3758990923 0.0 300997.2820036103 57275.3758990923 0.0 300997.2820036103 57275.3758990923 10.786276534199727
+
+
+
+
+
+
+
+
+ 300995.8337614228 57293.0555865923 10.786276534199727 300995.8337614228 57293.0555865923 0.0 300992.0398161103 57285.56779362355 10.786276534199727 300995.8337614228 57293.0555865923 10.786276534199727
+
+
+
+
+
+
+
+
+ 300992.0398161103 57285.56779362355 10.786276534199727 300995.8337614228 57293.0555865923 0.0 300992.0398161103 57285.56779362355 0.0 300992.0398161103 57285.56779362355 10.786276534199727
+
+
+
+
+
+
+
+
+ 300992.0398161103 57285.56779362355 10.786276534199727 300992.0398161103 57285.56779362355 0.0 301000.3254606415 57281.3758990923 10.786276534199727 300992.0398161103 57285.56779362355 10.786276534199727
+
+
+
+
+
+
+
+
+ 301000.3254606415 57281.3758990923 10.786276534199727 300992.0398161103 57285.56779362355 0.0 301000.3254606415 57281.3758990923 0.0 301000.3254606415 57281.3758990923 10.786276534199727
+
+
+
+
+
+
+
+
+ 1965
+ W4
+
+
+
\ No newline at end of file
diff --git a/tests/tests_data/w2w_user_output.csv b/tests/tests_data/w2w_user_output.csv
new file mode 100644
index 0000000..bb3612f
--- /dev/null
+++ b/tests/tests_data/w2w_user_output.csv
@@ -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