diff --git a/city_model_structure/city.py b/city_model_structure/city.py index 02b095f0..3b4582df 100644 --- a/city_model_structure/city.py +++ b/city_model_structure/city.py @@ -1,5 +1,8 @@ from city_model_structure.city_object import CityObject from typing import List, Union +import pyproj +from pyproj import Transformer +import reverse_geocoder as rg class City: @@ -10,6 +13,33 @@ class City: self._upper_corner = upper_corner self._city_objects = city_objects self._srs_name = srs_name + # todo: right now extracted at city level, in the future should be extracted also at building level if exist + self._location = None + + @property + def location(self): + if self._location is None: + gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth + input_reference = None + try: + input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data + except pyproj.exceptions.CRSError: + print('Invalid projection reference system, please check the input data. (e.g. in CityGML files: srs_name)') + quit() + transformer = Transformer.from_crs(input_reference, gps) + coordinates = transformer.transform(self.lower_corner[0], self.lower_corner[1]) + self._location = rg.search(coordinates) + return self._location + + @property + def country_code(self): + return self.location[0]['cc'] + + @property + def name(self): + if self._name is None: + self._name = self.location[0]['name'] + return self._name @property def city_objects(self) -> Union[List[CityObject], None]: @@ -30,10 +60,9 @@ class City: return None def add_city_object(self, new_city_object): - if self.city_objects is None: + if self._city_objects is None: self._city_objects = [] for city_object in self.city_objects: - # ToDo: Check for shared walls. for surface in city_object.surfaces: for surface2 in new_city_object.surfaces: surface.shared(surface2) @@ -43,10 +72,6 @@ class City: def srs_name(self): return self._srs_name - @property - def name(self): - return self._name - @name.setter def name(self, value): self._name = value diff --git a/city_model_structure/city_object.py b/city_model_structure/city_object.py index 0e9ca95a..47355115 100644 --- a/city_model_structure/city_object.py +++ b/city_model_structure/city_object.py @@ -14,7 +14,8 @@ from typing import Union, List class CityObject: - def __init__(self, name, lod, surfaces, terrains, year_of_construction, function, attic_heated=0, basement_heated=0): + def __init__(self, name, lod, surfaces, terrains, year_of_construction, function, lower_corner, attic_heated=0, + basement_heated=0): self._name = name self._lod = lod self._surfaces = surfaces @@ -24,6 +25,7 @@ class CityObject: self._terrains = terrains self._year_of_construction = year_of_construction self._function = function + self._lower_corner = lower_corner self._geometry = Geometry() self._average_storey_height = None self._storeys_above_ground = None @@ -42,6 +44,7 @@ class CityObject: t.bounded = [ThermalBoundary(s, [t]) for s in t.surfaces] surface_id = 0 for s in self._surfaces: + s.lower_corner = self._lower_corner s.parent(self, surface_id) surface_id += 1 diff --git a/city_model_structure/material.py b/city_model_structure/material.py index 2473c9ad..9a247003 100644 --- a/city_model_structure/material.py +++ b/city_model_structure/material.py @@ -1,6 +1,5 @@ class Material: def __init__(self): - # ToDo: construct this class self._conductivity_wm_k = None self._specific_heat_jkg_k = None self._density_kg_m3 = None diff --git a/city_model_structure/surface.py b/city_model_structure/surface.py index 10b17e76..675c417d 100644 --- a/city_model_structure/surface.py +++ b/city_model_structure/surface.py @@ -2,6 +2,7 @@ from __future__ import annotations import numpy as np import pyny3d.geoms as pn from helpers.geometry import Geometry +from typing import Union class Surface: @@ -14,8 +15,10 @@ class Surface: self._is_projected = is_projected self._geometry = Geometry() self._polygon = None + self._ground_polygon = None self._area = None self._points = None + self._ground_points = None self._points_list = None self._normal = None self._azimuth = None @@ -25,9 +28,13 @@ class Surface: self._parent = None self._shapely = None self._projected_surface = None - self._shared_surfaces = None + self._min_x = None + self._min_y = None + self._min_z = None + self._shared_surfaces = [] self._global_irradiance_hour = np.zeros(8760) self._global_irradiance_month = np.zeros(12) + self._ground_coordinates = (self.min_x, self.min_y, self.min_z) def parent(self, parent, surface_id): self._parent = parent @@ -48,21 +55,69 @@ class Surface: self._swr = value @property - def points(self): + def points(self) -> np.ndarray: if self._points is None: self._points = np.fromstring(self._coordinates, dtype=float, sep=' ') self._points = Geometry.to_points_matrix(self._points, self._remove_last) return self._points + def _min_coord(self, axis): + if axis == 'x': + axis = 0 + elif axis == 'y': + axis = 1 + else: + axis = 2 + min_coordinate = '' + for point in self.points: + if min_coordinate == '': + min_coordinate = point[axis] + elif min_coordinate > point[axis]: + min_coordinate = point[axis] + return min_coordinate + @property - def points_list(self): + def min_x(self): + if self._min_x is None: + self._min_x = self._min_coord('x') + return self._min_x + + @property + def min_y(self): + if self._min_y is None: + self._min_y = self._min_coord('y') + return self._min_y + + @property + def min_z(self): + if self._min_z is None: + self._min_z = self._min_coord('z') + return self._min_z + + @property + def ground_points(self) -> np.ndarray: + if self._ground_points is None: + coordinates = '' + for point in self.points: + x = point[0] - self._ground_coordinates[0] + y = point[1] - self._ground_coordinates[1] + z = point[2] - self._ground_coordinates[2] + if coordinates != '': + coordinates = coordinates + ' ' + coordinates = coordinates + str(x) + ' ' + str(y) + ' ' + str(z) + self._ground_points = np.fromstring(coordinates, dtype=float, sep=' ') + self._ground_points = Geometry.to_points_matrix(self._ground_points, False) + return self._ground_points + + @property + def points_list(self) -> np.ndarray: if self._points_list is None: s = self.points self._points_list = np.reshape(s, len(s) * 3) return self._points_list @property - def polygon(self): + def polygon(self) -> pn.Polygon: if self._polygon is None: try: self._polygon = pn.Polygon(self.points) @@ -71,15 +126,22 @@ class Surface: self._polygon = None return self._polygon + @property + def ground_polygon(self) -> Union[pn.Polygon, None]: + if self._ground_polygon is None: + try: + self._ground_polygon = pn.Polygon(self.ground_points) + except ValueError: + # is not really a polygon but a line so just return none + self._ground_polygon = None + return self._ground_polygon + @property def area(self): if self._area is None: self._area = self.polygon.get_area() return self._area - def _is_shared(self, surface): - return False - def _is_almost_same_terrain(self, terrain_points, ground_points): equal = 0 for t in terrain_points: @@ -110,7 +172,7 @@ class Surface: return self._area_below_ground @property - def normal(self): + def normal(self) -> np.ndarray: if self._normal is None: points = self.points n = np.cross(points[1] - points[0], points[2] - points[0]) @@ -142,12 +204,18 @@ class Surface: self._type = 'Roof' return self._type + def add_shared(self, surface, intersection_area): + percent = intersection_area / self.area + self._shared_surfaces.append((percent, surface)) + def shared(self, surface): - if self.type is not 'Wall': + if self.type is not 'Wall' or surface.type is not 'Wall': return - if self._is_shared(surface): - self._shared_surfaces.append((100, surface)) - surface.shared(self) + if self._geometry.is_almost_same_surface(self, surface): + intersection_area = self.intersect(surface).area + percent = intersection_area / self.area + self._shared_surfaces.append((percent, surface)) + surface.add_shared(self, intersection_area) @property def global_irradiance_hour(self): @@ -173,15 +241,53 @@ class Surface: self._shapely = self.polygon.get_shapely() return self._shapely + @staticmethod + def _polygon_to_surface(polygon): + coordinates = '' + for coordinate in polygon.exterior.coords: + if coordinates != '': + coordinates = coordinates + ' ' + coordinates = coordinates + str(coordinate[0]) + ' ' + str(coordinate[1]) + ' 0.0' + return Surface(coordinates, remove_last=False) + @property def projection(self) -> Surface: if self._is_projected: return self if self._projected_surface is None: + self._projected_surface = self._polygon_to_surface(self.shapely) + return self._projected_surface + + def intersect(self, surface) -> Union[Surface, None]: + min_x = min(self.min_x, surface.min_x) + min_y = min(self.min_y, surface.min_y) + min_z = min(self.min_z, surface.min_z) + self._ground_coordinates = (min_x, min_y, min_z) + surface._ground_coordinates = (min_x, min_y, min_z) + origin = (0, 0, 0) + azimuth = self.azimuth - (np.pi / 2) + while azimuth < 0: + azimuth += (np.pi / 2) + inclination = self.inclination - np.pi + while inclination < 0: + inclination += np.pi + polygon1 = self.ground_polygon.rotate(azimuth, 'z', origin).rotate(inclination, 'x', origin) + polygon2 = surface.ground_polygon.rotate(azimuth, 'z', origin).rotate(inclination, 'x', origin) + try: coordinates = '' - for coordinate in self.shapely.exterior.coords: + intersection = pn.Surface([polygon1]).intersect_with(polygon2) + if len(intersection) == 0: + return None + for coordinate in pn.Surface([polygon1]).intersect_with(polygon2)[0]: if coordinates != '': coordinates = coordinates + ' ' coordinates = coordinates + str(coordinate[0]) + ' ' + str(coordinate[1]) + ' 0.0' - self._projected_surface = Surface(coordinates) - return self._projected_surface + if coordinates == '': + return None + intersect_surface = Surface(coordinates, remove_last=False) + if intersect_surface.polygon is None: + return None + return Surface(coordinates, remove_last=False) + except Exception as err: + print('Error', err) + return None diff --git a/city_model_structure/thermal_zone.py b/city_model_structure/thermal_zone.py index c9749db0..b9efbc30 100644 --- a/city_model_structure/thermal_zone.py +++ b/city_model_structure/thermal_zone.py @@ -1,5 +1,6 @@ from typing import List from city_model_structure.thermal_boundary import ThermalBoundary +from city_model_structure.usage_zone import UsageZone class ThermalZone: @@ -86,10 +87,9 @@ class ThermalZone: self._infiltration_rate_system_off = value @property - def usage_zones(self): + def usage_zones(self) -> List[UsageZone]: return self._usage_zones @usage_zones.setter def usage_zones(self, values): self._usage_zones = values - diff --git a/city_model_structure/window.py b/city_model_structure/window.py index 271a1aa9..36085538 100644 --- a/city_model_structure/window.py +++ b/city_model_structure/window.py @@ -1,6 +1,5 @@ class Window: def __init__(self): - # ToDo: construct this class self._conductivity_wm_k = None self._solar_transmittance_at_normal_incidence = None self._front_side_solar_reflectance_at_normal_incidence = None diff --git a/geometry/geometry_feeders/city_gml.py b/geometry/geometry_feeders/city_gml.py index 57ee84f6..ad7c3104 100644 --- a/geometry/geometry_feeders/city_gml.py +++ b/geometry/geometry_feeders/city_gml.py @@ -98,7 +98,8 @@ class CityGml: year_of_construction = o['Building']['yearOfConstruction'] if 'function' in o['Building']: function = o['Building']['function'] - self._city.add_city_object(CityObject(name, lod, surfaces, terrains, year_of_construction, function)) + self._city.add_city_object(CityObject(name, lod, surfaces, terrains, year_of_construction, function, + self._lower_corner)) return self._city diff --git a/helpers/assumptions.py b/helpers/assumptions.py new file mode 100644 index 00000000..13115d60 --- /dev/null +++ b/helpers/assumptions.py @@ -0,0 +1,9 @@ +# These values are intended as configurable assumptions +# ToDo: these values need to be changed into configurable parameters + +# convective fluxes +h_i = 10 # W/m2K +h_e = 25 # W/m2K + +# windows' default values +frame_ratio = 0 diff --git a/helpers/geometry.py b/helpers/geometry.py index 5474b531..c99dabff 100644 --- a/helpers/geometry.py +++ b/helpers/geometry.py @@ -7,13 +7,42 @@ class Geometry: self._delta = delta def almost_equal(self, v1, v2): - delta = math.sqrt(pow((v1[0]-v2[0]), 2) + pow((v1[1]-v2[1]), 2) + pow((v1[2]-v2[2]), 2)) + delta = math.sqrt(pow((v1[0] - v2[0]), 2) + pow((v1[1] - v2[1]), 2) + pow((v1[2] - v2[2]), 2)) return delta <= self._delta + def is_almost_same_surface(self, s1, s2): + # delta is grads an need to be converted into radians + delta = np.rad2deg(self._delta) + difference = (s1.inclination - s2.inclination) % math.pi + if abs(difference) > delta: + return False + # s1 and s2 are at least almost parallel surfaces + # calculate distance point to plane using all the vertex + # select surface1 value for the point (X,Y,Z) where two of the values are 0 + minimum_distance = self._delta + 1 + parametric = s2.polygon.get_parametric() + n2 = s2.normal + for point in s1.points: + distance = abs( + (point[0] * parametric[0]) + (point[1] * parametric[1]) + (point[2] * parametric[2]) + parametric[3]) + normal_module = math.sqrt(pow(n2[0], 2) + pow(n2[1], 2) + pow(n2[2], 2)) + + if normal_module == 0: + continue + distance = distance / normal_module + if distance < minimum_distance: + minimum_distance = distance + if minimum_distance <= self._delta: + break + if minimum_distance > self._delta or s1.intersect(s2) is None: + return False + else: + return True + @staticmethod def to_points_matrix(points, remove_last=False): - rows = points.size//3 + rows = points.size // 3 points = points.reshape(rows, 3) if remove_last: - points = np.delete(points, rows-1, 0) + points = np.delete(points, rows - 1, 0) return points diff --git a/physics/physics_factory.py b/physics/physics_factory.py index 7ac3a327..af7c89ea 100644 --- a/physics/physics_factory.py +++ b/physics/physics_factory.py @@ -3,16 +3,17 @@ from physics.physics_feeders.us_physics_parameters import UsPhysicsParameters class PhysicsFactory: - def __init__(self, handler, city): + def __init__(self, handler, city, base_path='data/physics'): self._handler = handler.lower().replace(' ', '_') self._city = city + self._base_path = base_path self.factory() def us_new_york_city(self): - UsNewYorkCityPhysicsParameters(self._city) + UsNewYorkCityPhysicsParameters(self._city, self._base_path) def us(self): - UsPhysicsParameters(self._city) + UsPhysicsParameters(self._city, self._base_path) def ca(self): raise Exception('Not implemented') diff --git a/physics/physics_feeders/us_base_physics_parameters.py b/physics/physics_feeders/us_base_physics_parameters.py index bfd00443..b261e4f4 100644 --- a/physics/physics_feeders/us_base_physics_parameters.py +++ b/physics/physics_feeders/us_base_physics_parameters.py @@ -6,17 +6,17 @@ from physics.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes class UsBasePhysicsParameters: - def __init__(self, climate_zone, city_objects, function_to_type): + def __init__(self, climate_zone, city_objects, function_to_type, base_path): self._climate_zone = climate_zone self._city_objects = city_objects # load US Library - path = str(Path.cwd() / 'data/physics/us_constructions.xml') + path = str(Path.cwd() / base_path / 'us_constructions.xml') with open(path) as xml: self._library = xmltodict.parse(xml.read(), force_list='layer') # load US Archetypes - path = str(Path.cwd() / 'data/physics/us_archetypes.xml') + path = str(Path.cwd() / base_path / 'us_archetypes.xml') with open(path) as xml: self._archetypes = xmltodict.parse(xml.read(), force_list='layer') for city_object in self._city_objects: diff --git a/physics/physics_feeders/us_new_york_city_physics_parameters.py b/physics/physics_feeders/us_new_york_city_physics_parameters.py index 67b667ff..9bb5549d 100644 --- a/physics/physics_feeders/us_new_york_city_physics_parameters.py +++ b/physics/physics_feeders/us_new_york_city_physics_parameters.py @@ -3,7 +3,7 @@ from physics.physics_feeders.helpers.us_pluto_to_function import UsPlutoToFuncti class UsNewYorkCityPhysicsParameters(UsBasePhysicsParameters): - def __init__(self, city): + def __init__(self, city, base_path): self._city = city climate_zone = 'ASHRAE_2004:4A' - super().__init__(climate_zone, self._city.city_objects, Pf.function) + super().__init__(climate_zone, self._city.city_objects, Pf.function, base_path) diff --git a/physics/physics_feeders/us_physics_parameters.py b/physics/physics_feeders/us_physics_parameters.py index 79946968..930bc879 100644 --- a/physics/physics_feeders/us_physics_parameters.py +++ b/physics/physics_feeders/us_physics_parameters.py @@ -3,8 +3,8 @@ from physics.physics_feeders.helpers.us_to_library_types import UsToLibraryTypes class UsPhysicsParameters(UsBasePhysicsParameters): - def __init__(self, city): + def __init__(self, city, base_path): self._city = city - self._climate_zone = UsToLibraryTypes.city_to_climate_zone(city.city_name) - super().__init__(self._climate_zone, self._city.city_objects, lambda function: function) + self._climate_zone = UsToLibraryTypes.city_to_climate_zone(city.name) + super().__init__(self._climate_zone, self._city.city_objects, lambda function: function, base_path) diff --git a/tests/test_geometry_factory.py b/tests/test_geometry_factory.py new file mode 100644 index 00000000..bbd36ac4 --- /dev/null +++ b/tests/test_geometry_factory.py @@ -0,0 +1,147 @@ +from unittest import TestCase +from pathlib import Path +from geometry.geometry_factory import GeometryFactory +import os +from city_model_structure.surface import Surface + + +class TestGeometryFactory(TestCase): + def setUp(self) -> None: + self._city_gml = None + self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve() + + def get_citygml(self): + if self._city_gml is None: + file_path = (self._example_path / 'buildings.gml').resolve() + self._city_gml = GeometryFactory('citygml', file_path).city + self.assertIsNotNone(self._city_gml, 'city is none') + return self._city_gml + + def test_citygml_city(self): + city = self.get_citygml() + self.assertIsNotNone(city.city_objects, 'city_objects is none') + for city_object in city.city_objects: + self.assertIsNotNone(city.city_object(city_object.name), 'city_object return none') + self.assertIsNotNone(city.srs_name, 'srs_name is none') + self.assertIsNotNone(city.lower_corner, 'lower_corner is none') + self.assertIsNotNone(city.upper_corner, 'upper_corner is none') + self.assertIsNotNone(city.name, 'name is none') + self.assertIsNotNone(city.country_code, 'country code is none') + self.assertIsNotNone(city.location, 'location is none') + + def test_citygml_city_objects(self): + city = self.get_citygml() + for city_object in city.city_objects: + self.assertIsNotNone(city_object.name, 'city_object name is none') + self.assertIsNotNone(city_object.lod, 'city_object lod is none') + self.assertIsNotNone(city_object.year_of_construction, 'city_object year_of_construction is none') + self.assertIsNotNone(city_object.function, 'city_object function is none') + self.assertIsNotNone(city_object.volume, 'city_object volume is none') + self.assertIsNotNone(city_object.surfaces, 'city_object surfaces is none') + self.assertIsNotNone(city_object.surfaces[0].name, 'surface not found') + self.assertIsNotNone(city_object.basement_heated, 'city_object basement_heated is none') + self.assertIsNotNone(city_object.attic_heated, 'city_object attic_heated is none') + self.assertIsNotNone(city_object.terrains, 'city_object terrains is none') + self.assertIsNotNone(city_object.foot_print, 'city_object foot_print is none') + self.assertIsNotNone(city_object.usage_zones, 'city_object usage_zones is none') + self.assertIsNone(city_object.average_storey_height, 'city_object average_storey_height is not none') + self.assertIsNone(city_object.storeys_above_ground, 'city_object storeys_above_ground is not none') + self.assertIsNotNone(city_object.heated_volume, 'city_object heated_volume is none') + self.assertIsNotNone(city_object.thermal_zones, 'city_object thermal_zones is none') + self.assertIsNotNone(city_object.type, 'city_object type is none') + self.assertIsNotNone(city_object.max_height, 'city_object max_height is none') + city_object.stl_export(self._example_path) + os.remove(Path(self._example_path, city_object.name + '.stl').resolve()) + + def test_citygml_surfaces(self): + city = self.get_citygml() + for city_object in city.city_objects: + for surface in city_object.surfaces: + self.assertIsNotNone(surface.name, 'surface name is none') + self.assertIsNotNone(surface.area, 'surface area is none') + self.assertIsNotNone(surface.type, 'surface type is none') + self.assertIsNotNone(surface.azimuth, 'surface azimuth is none') + self.assertIsNotNone(surface.inclination, 'surface inclination is none') + self.assertIsNotNone(surface.area_below_ground, 'surface area_below_ground is none') + self.assertIsNotNone(surface.area_above_ground, 'surface area_above_ground is none') + self.assertIsNotNone(surface.points, 'surface points is none') + self.assertIsNotNone(surface.points_list, 'surface points_list is none') + self.assertIsNotNone(surface.polygon, 'surface polygon is none') + self.assertIsNotNone(surface.shapely, 'surface shapely is none') + self.assertIsNotNone(surface.global_irradiance_hour, 'surface global_irradiance_hour is none') + self.assertIsNotNone(surface.global_irradiance_month, 'surface global_irradiance_month is none') + self.assertIsNotNone(surface.normal, 'surface normal is none') + self.assertIsNotNone(surface.projection, 'surface projection is none') + self.assertIsNotNone(surface.swr, 'surface swr is none') + self.assertIsNotNone(surface.min_x, 'surface min_x is none') + self.assertIsNotNone(surface.min_y, 'surface min_y is none') + self.assertIsNotNone(surface.min_z, 'surface min_z is none') + self.assertIsNotNone(surface.ground_polygon, 'surface ground_polygon is none') + self.assertIsNotNone(surface.ground_points, 'surface ground_points is none') + self.assertIsNotNone(surface.intersect(surface), 'self intersection is none') + + def test_citygml_thermal_zone(self): + city = self.get_citygml() + for city_object in city.city_objects: + for thermal_zone in city_object.thermal_zones: + self.assertIsNotNone(thermal_zone.surfaces, 'thermal_zone surfaces is none') + self.assertIsNotNone(thermal_zone.bounded, 'thermal_zone bounded is none') + self.assertIsNotNone(thermal_zone.floor_area, 'thermal_zone floor_area is none') + self.assertIsNotNone(thermal_zone.heated, 'thermal_zone heated is none') + self.assertIsNotNone(thermal_zone.cooled, 'thermal_zone cooled is none') + self.assertIsNone(thermal_zone.additional_thermal_bridge_u_value, + 'thermal_zone additional_thermal_bridge_u_value is not none') + self.assertIsNone(thermal_zone.effective_thermal_capacity, + 'thermal_zone effective_thermal_capacity is not none') + self.assertIsNone(thermal_zone.indirectly_heated_area_ratio + , 'thermal_zone indirectly_heated_area_ratio is not none') + self.assertIsNone(thermal_zone.infiltration_rate_system_off, + 'thermal_zone infiltration_rate_system_off is not none') + self.assertIsNone(thermal_zone.infiltration_rate_system_on, + 'thermal_zone infiltration_rate_system_on is not none') + self.assertIsNone(thermal_zone.usage_zones, + 'thermal_zone usage_zones are not none') + + def test_citygml_thermal_boundary(self): + city = self.get_citygml() + for city_object in city.city_objects: + for thermal_zone in city_object.thermal_zones: + for thermal_boundary in thermal_zone.bounded: + self.assertIsNotNone(thermal_boundary.type, 'thermal_boundary type is none') + self.assertIsNotNone(thermal_boundary.area, 'thermal_boundary area is none') + self.assertIsNotNone(thermal_boundary.area_above_ground, 'thermal_boundary area_above_ground is none') + self.assertIsNotNone(thermal_boundary.area_below_ground, 'thermal_boundary area_below_ground is none') + self.assertIsNotNone(thermal_boundary.azimuth, 'thermal_boundary azimuth is none') + self.assertIsNotNone(thermal_boundary.delimits, 'thermal_boundary delimits is none') + self.assertIsNotNone(thermal_boundary.inclination, 'thermal_boundary inclination is none') + self.assertRaises(Exception, lambda: thermal_boundary.u_value, 'thermal_boundary u_value was initialized') + self.assertIsNone(thermal_boundary.layers, 'thermal_boundary layers was initialized') + self.assertRaises(Exception, lambda: thermal_boundary.outside_solar_absorptance, + 'thermal_boundary outside_solar_absorptance was initialized') + self.assertIsNone(thermal_boundary.outside_thermal_absorptance, + 'thermal_boundary outside_thermal_absorptance was initialized') + self.assertIsNone(thermal_boundary.outside_visible_absorptance, + 'thermal_boundary outside_visible_absorptance was initialized') + self.assertRaises(Exception, lambda: thermal_boundary.shortwave_reflectance, + 'thermal_boundary shortwave_reflectance was initialized') + self.assertRaises(Exception, lambda: thermal_boundary.window_area, + 'thermal_boundary window_area was initialized') + self.assertIsNone(thermal_boundary.window_ratio, 'thermal_boundary window_ratio was initialized') + + def test_citygml_thermal_opening(self): + city = self.get_citygml() + for city_object in city.city_objects: + for thermal_zone in city_object.thermal_zones: + for thermal_boundary in thermal_zone.bounded: + for thermal_opening in thermal_boundary.thermal_openings: + self.assertIsNone(thermal_opening.area, 'thermal_opening area was initialized') + self.assertTrue(thermal_opening.frame_ratio == 0, 'thermal_opening frame_ratio was not 0') + self.assertIsNone(thermal_opening.g_value, 'thermal_opening g_value was initialized') + self.assertIsNone(thermal_opening.conductivity_w_mk, 'thermal_opening conductivity_w_mk was initialized') + self.assertIsNone(thermal_opening.inside_reflectance, 'thermal_opening inside_reflectance was initialized') + self.assertRaises(Exception, lambda: thermal_opening.openable_ratio, + 'thermal_opening openable_ratio is not raising an exception') + self.assertIsNone(thermal_opening.outside_reflectance, + 'thermal_opening outside_reflectance was initialized') + self.assertIsNone(thermal_opening.thickness_m, 'thermal_opening thickness_m was initialized') + self.assertRaises(Exception, lambda: thermal_opening.u_value, 'thermal_opening u_value was initialized') diff --git a/tests/test_physics_factory.py b/tests/test_physics_factory.py new file mode 100644 index 00000000..889d6690 --- /dev/null +++ b/tests/test_physics_factory.py @@ -0,0 +1,27 @@ +from unittest import TestCase +from pathlib import Path +from geometry.geometry_factory import GeometryFactory +from physics.physics_factory import PhysicsFactory + + +class TestPhysicsFactory(TestCase): + def setUp(self) -> None: + self._city_gml = None + self._nyc_with_physics = None + self._example_path = (Path(__file__).parent.parent / 'tests_data').resolve() + + def get_citygml(self): + if self._city_gml is None: + file_path = (self._example_path / 'buildings.gml').resolve() + self._city_gml = GeometryFactory('citygml', file_path).city + self.assertIsNotNone(self._city_gml, 'city is none') + return self._city_gml + + def get_city_with_physics(self): + if self._nyc_with_physics is None: + self._nyc_with_physics = self.get_citygml() + PhysicsFactory('us_new_york_city', self._nyc_with_physics, base_path=self._example_path) + return self._nyc_with_physics + + def test_city_with_physics(self): + city = self.get_city_with_physics() \ No newline at end of file diff --git a/tests_data/buildings.gml b/tests_data/buildings.gml new file mode 100644 index 00000000..a86229e2 --- /dev/null +++ b/tests_data/buildings.gml @@ -0,0 +1,626 @@ + + + Gowanus 2050 Best Practice Scenario + + + 301067.2312223603 55182.50627018605 -15.371661394834565 + 301852.9778043915 57588.63517643605 75.67673757672314 + + + + + + 1965 + + + I1 + + + + + + + + + + 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 + I1 + + + + + + 2045 + + + I1 + + + + + + + + + + 300906.4538786103 56181.20939518605 7.9999997168779355 300897.539327829 56167.5155475298 7.9999997168779355 300906.4538786103 56181.20939518605 0.0 300906.4538786103 56181.20939518605 7.9999997168779355 + + + + + + + + + 300897.539327829 56167.5155475298 7.9999997168779355 300897.539327829 56167.5155475298 0.0 300906.4538786103 56181.20939518605 0.0 300897.539327829 56167.5155475298 7.9999997168779355 + + + + + + + + + 300883.334249704 56196.25919987355 7.9999997168779355 300861.299093454 56191.1053912798 7.9999997168779355 300897.539327829 56167.5155475298 7.9999997168779355 300883.334249704 56196.25919987355 7.9999997168779355 + + + + + + + + + 300906.4538786103 56181.20939518605 7.9999997168779355 300883.334249704 56196.25919987355 7.9999997168779355 300897.539327829 56167.5155475298 7.9999997168779355 300906.4538786103 56181.20939518605 7.9999997168779355 + + + + + + + + + 300896.0696012665 56215.82365299855 7.9999997168779355 300882.9489957978 56224.3641803423 7.9999997168779355 300883.334249704 56196.25919987355 7.9999997168779355 300896.0696012665 56215.82365299855 7.9999997168779355 + + + + + + + + + 300882.9489957978 56224.3641803423 7.9999997168779355 300861.299093454 56191.1053912798 7.9999997168779355 300883.334249704 56196.25919987355 7.9999997168779355 300882.9489957978 56224.3641803423 7.9999997168779355 + + + + + + + + + 300883.334249704 56196.25919987355 7.9999997168779355 300883.334249704 56196.25919987355 0.0 300896.0696012665 56215.82365299855 7.9999997168779355 300883.334249704 56196.25919987355 7.9999997168779355 + + + + + + + + + 300896.0696012665 56215.82365299855 7.9999997168779355 300883.334249704 56196.25919987355 0.0 300896.0696012665 56215.82365299855 0.0 300896.0696012665 56215.82365299855 7.9999997168779355 + + + + + + + + + 300883.334249704 56196.25919987355 7.9999997168779355 300906.4538786103 56181.20939518605 7.9999997168779355 300883.334249704 56196.25919987355 0.0 300883.334249704 56196.25919987355 7.9999997168779355 + + + + + + + + + 300906.4538786103 56181.20939518605 7.9999997168779355 300906.4538786103 56181.20939518605 0.0 300883.334249704 56196.25919987355 0.0 300906.4538786103 56181.20939518605 7.9999997168779355 + + + + + + + + + 300896.0696012665 56215.82365299855 0.0 300883.334249704 56196.25919987355 0.0 300882.9489957978 56224.3641803423 0.0 300896.0696012665 56215.82365299855 0.0 + + + + + + + + + 300882.9489957978 56224.3641803423 0.0 300883.334249704 56196.25919987355 0.0 300861.299093454 56191.1053912798 0.0 300882.9489957978 56224.3641803423 0.0 + + + + + + + + + 300883.334249704 56196.25919987355 0.0 300897.539327829 56167.5155475298 0.0 300861.299093454 56191.1053912798 0.0 300883.334249704 56196.25919987355 0.0 + + + + + + + + + 300906.4538786103 56181.20939518605 0.0 300897.539327829 56167.5155475298 0.0 300883.334249704 56196.25919987355 0.0 300906.4538786103 56181.20939518605 0.0 + + + + + + + + + 300882.9489957978 56224.3641803423 7.9999997168779355 300896.0696012665 56215.82365299855 7.9999997168779355 300882.9489957978 56224.3641803423 0.0 300882.9489957978 56224.3641803423 7.9999997168779355 + + + + + + + + + 300896.0696012665 56215.82365299855 7.9999997168779355 300896.0696012665 56215.82365299855 0.0 300882.9489957978 56224.3641803423 0.0 300896.0696012665 56215.82365299855 7.9999997168779355 + + + + + + + + + 300882.9489957978 56224.3641803423 7.9999997168779355 300882.9489957978 56224.3641803423 0.0 300861.299093454 56191.1053912798 7.9999997168779355 300882.9489957978 56224.3641803423 7.9999997168779355 + + + + + + + + + 300861.299093454 56191.1053912798 7.9999997168779355 300882.9489957978 56224.3641803423 0.0 300861.299093454 56191.1053912798 0.0 300861.299093454 56191.1053912798 7.9999997168779355 + + + + + + + + + 300897.539327829 56167.5155475298 7.9999997168779355 300861.299093454 56191.1053912798 7.9999997168779355 300897.539327829 56167.5155475298 0.0 300897.539327829 56167.5155475298 7.9999997168779355 + + + + + + + + + 300861.299093454 56191.1053912798 7.9999997168779355 300861.299093454 56191.1053912798 0.0 300897.539327829 56167.5155475298 0.0 300861.299093454 56191.1053912798 7.9999997168779355 + + + + + + + + + 2045 + I1 + + + \ No newline at end of file diff --git a/tests_data/us_archetypes.xml b/tests_data/us_archetypes.xml new file mode 100644 index 00000000..bbe49e54 --- /dev/null +++ b/tests_data/us_archetypes.xml @@ -0,0 +1,786 @@ + + + + + + 0.21 + 4 + + + 0 + + + + 0 + + + + 3.05 + 2 + 130 + 0.15 + 0.15 + 0.5 + 0 + + + + + 0.33 + 4 + + + 0 + + + + 0 + + + + 3.34 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.38 + 4 + + + 0 + + + + 0 + + + + 3.34 + 3 + 130 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.35 + 4 + + + 0 + + + + 0.0019 + 2 + + + 3.96 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.33 + 4 + + + 0 + + + + 0.0068 + 2 + + + 3.96 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.07 + 4 + + + 0 + + + + 0.0064 + 2 + + + 6.1 + 3 + 130 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.11 + 4 + + + 0 + + + + 0 + + + + 5.18 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.11 + 4 + + + 0 + + + + 0 + + + + 6.1 + 1 + 130 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.14 + 4 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.17 + 4 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.11 + 4 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.3 + 4 + + + 0 + + + + 0 + + + + 3.05 + 3 + 130 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.15 + 4 + + + 0 + + + + 0 + + + + 4.27 + 3 + 130 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.2 + 4 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.006 + 4 + + + 0 + + + + .0032 + 2 + + + 8.53 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.15 + 4 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.3 + 4 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.15 + 0.15 + 0.50 + 0 + + + + + 0.21 + 3 + + + 0 + + + + 0 + + + + 3.05 + 2 + 130 + 0.05 + 0.15 + 0.1 + 0 + + + + + 0.33 + 3 + + + 0 + + + + 0 + + + + 3.34 + 3 + 90 + 0.05 + 0.15 + 0.1 + 0 + + + + + 0.38 + 3 + + + 0 + + + + 0 + + + + 3.34 + 3 + 130 + 0.05 + 0.15 + 0.1 + 0 + + + + + 0.35 + 3 + + + 0 + + + + 0.0019 + 1 + + + 3.96 + 3 + 90 + 0.05 + 0.15 + 0.1 + 0 + + + + + 0.33 + 3 + + + 0 + + + + 0.0068 + 1 + + + 3.96 + 3 + 90 + 0.05 + 0.15 + 0.1 + 0 + + + + + 0.07 + 3 + + + 0 + + + + 0.0064 + 1 + + + 6.1 + 3 + 130 + 0.05 + 0.15 + 0.1 + 0 + + + + + 0.11 + 3 + + + 0 + + + + 0 + + + + 5.18 + 3 + 90 + 0.05 + 0.15 + 0.1 + 0 + + + + + 0.11 + 3 + + + 0 + + + + 0 + + + + 6.1 + 1 + 130 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.14 + 3 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.17 + 3 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.11 + 3 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.3 + 3 + + + 0 + + + + 0 + + + + 3.05 + 3 + 130 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.15 + 3 + + + 0 + + + + 0 + + + + 4.27 + 3 + 130 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.2 + 3 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.006 + 3 + + + 0 + + + + .0032 + 1 + + + 8.53 + 3 + 90 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.15 + 3 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.05 + 0.15 + 0.10 + 0 + + + + + 0.3 + 3 + + + 0 + + + + 0 + + + + 3.05 + 3 + 90 + 0.05 + 0.15 + 0.10 + 0 + + + diff --git a/tests_data/us_constructions.xml b/tests_data/us_constructions.xml new file mode 100644 index 00000000..c18ec613 --- /dev/null +++ b/tests_data/us_constructions.xml @@ -0,0 +1,606 @@ + + + + + 0.32 + 0 + 0.003 + 0.301483 + 0.648517 + 0.648517 + 0.0133144 + + + 0.49 + 0 + 0.003 + 0.481761 + 0.468239 + 0.468239 + 0.03026 + + + 0.35 + 0 + 0.003 + 0.328881 + 0.621119 + 0.621119 + 0.0071399 + + + 0.36 + 0 + 0.003 + 0.354957 + 0.595043 + 0.595043 + 0.0134755 + + + + + 1.311 + 2240 + 836.8 + 0.9 + 0.7 + 0.7 + + + true + 0.21648 + 0.9 + 0.7 + 0.8 + + + 0.045 + 265 + 836.8 + 0.9 + 0.7 + 0.7 + + + 0.6918 + 1858 + 837 + 0.9 + 0.92 + 0.92 + + + 1.7296 + 2243 + 837 + 0.9 + 0.65 + 0.65 + + + 0.0432 + 91 + 837 + 0.9 + 0.5 + 0.5 + + + 0.16 + 784.9 + 830 + 0.9 + 0.92 + 0.92 + + + 0.11 + 544.62 + 1210 + 0.9 + 0.78 + 0.78 + + + 0.115 + 513 + 1255 + 0.9 + 0.78 + 0.78 + + + 0.1211 + 593 + 2510 + 0.9 + 0.78 + 0.78 + + + 0.049 + 265 + 836.8 + 0.9 + 0.7 + 0.7 + + + true + 0.36256 + 0.9 + 0.7 + 0.7 + + + true + 0.36256 + 0.9 + 0.7 + 0.7 + + + 45.006 + 7680 + 418.4 + 0.9 + 0.7 + 0.3 + + + 0.16 + 1121.29 + 1460 + 0.9 + 0.7 + 0.7 + + + true + 0.21648 + 0.9 + 0.7 + 0.8 + + + true + 0.36256 + 0.9 + 0.7 + 0.7 + + + true + 0.21648 + 0.9 + 0.7 + 0.8 + + + true + 0.36256 + 0.9 + 0.7 + 0.7 + + + true + 0.21648 + 0.9 + 0.7 + 0.8 + + + 0.045 + 265 + 836.8 + 0.9 + 0.7 + 0.7 + + + 44.96 + 7688.86 + 410 + 0.9 + 0.2 + 0.2 + + + + + + + + 3 + 0.0795397 + + + 1 + 0.20321 + + + 2 + + + + + 0.92 + 0.9 + 0.92 + + + 4 + 0.0253 + + + 5 + 0.2033 + + + 6 + 0.0680962 + + + 7 + 0.01271 + + + + + 0.92 + 0.9 + 0.92 + + + 8 + 0.01 + + + 3 + 0.0746874 + + + 7 + 0.01271 + + + + + 0.78 + 0.9 + 0.78 + + + 9 + 0.0178 + + + 10 + 0.0254 + + + 11 + 0.375211 + + + 7 + 0.01271 + + + + + 0.78 + 0.9 + 0.78 + + + 9 + 0.0178 + + + 10 + 0.0254 + + + 11 + 0.221604 + + + 7 + 0.01271 + + + + + 0.92 + 0.9 + 0.92 + + + 12 + + + 3 + 0.118387 + + + 7 + 0.01271 + + + + + + + 1 + 0.20321 + + + + + 0.92 + 0.9 + 0.92 + + + 13 + + + 3 + 0.0373223 + + + 7 + 0.01271 + + + + + 0.7 + 0.9 + 0.7 + + + 15 + 0.0095 + + + 11 + 0.210538 + + + 14 + 0.001524 + + + + + + + 1 + 0.1016 + + + + + 0.7 + 0.9 + 0.3 + + + 14 + 0.001524 + + + 11 + 0.23578 + + + + + + + 1 + 0.1016 + + + 16 + + + + + 0.92 + 0.9 + 0.92 + + + 4 + 0.0253 + + + 5 + 0.2033 + + + 6 + 0.0338606 + + + 7 + 0.01271 + + + + + 0.7 + 0.9 + 0.3 + + + 14 + 0.001524 + + + 11 + 0.123533 + + + + + 0.92 + 0.9 + 0.92 + + + 17 + + + 3 + 0.118387 + + + 7 + 0.01271 + + + + + 0.92 + 0.9 + 0.92 + + + 8 + 0.01 + + + 3 + 0.110422 + + + 7 + 0.01271 + + + + + 0.7 + 0.9 + 0.7 + + + 15 + 0.0095 + + + 11 + 0.124958 + + + 14 + 0.001524 + + + + + + + 3 + 0.0463846 + + + 1 + 0.20321 + + + 18 + + + + + 0.92 + 0.9 + 0.92 + + + 19 + + + 3 + 0.0971136 + + + 7 + 0.01271 + + + + + + + 1 + 0.20321 + + + + + + + 1 + 0.1016 + + + + + + + 1 + 0.1016 + + + 20 + + + + + 0.92 + 0.9 + 0.92 + + + 22 + 0.0015 + + + 21 + 0.139618 + + + 7 + 0.01271 + + + + + 0.92 + 0.9 + 0.92 + + + 22 + 0.0015 + + + 21 + 0.0598725 + + + 7 + 0.01271 + + + + + \ No newline at end of file