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