replace geometry helper with package

This commit is contained in:
Peter Yefi 2023-05-22 20:01:46 -04:00
parent 360b2e3636
commit 79e79f48c4
22 changed files with 25868 additions and 1269 deletions

View File

@ -1,80 +0,0 @@
"""
Plane module
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 typing import TypeVar
import numpy as np
Point = TypeVar('Point')
class Plane:
"""
Plane class
"""
def __init__(self, origin, normal):
self._origin = origin
self._normal = normal
self._equation = None
self._opposite_normal = None
@property
def origin(self) -> Point:
"""
Get plane origin point
:return: Point
"""
return self._origin
@property
def normal(self):
"""
Get plane normal [x, y, z]
:return: np.ndarray
"""
return self._normal
@property
def equation(self) -> (float, float, float, float):
"""
Get the plane equation components Ax + By + Cz + D = 0
:return: (A, B, C, D)
"""
if self._equation is None:
a = self.normal[0]
b = self.normal[1]
c = self.normal[2]
d = ((-1 * self.origin.coordinates[0]) * self.normal[0])
d += ((-1 * self.origin.coordinates[1]) * self.normal[1])
d += ((-1 * self.origin.coordinates[2]) * self.normal[2])
self._equation = (a, b, c, d)
return self._equation
def distance_to_point(self, point):
"""
Distance between the given point and the plane
:return: float
"""
p = point
e = self.equation
denominator = np.abs((p[0] * e[0]) + (p[1] * e[1]) + (p[2] * e[2]) + e[3])
numerator = np.sqrt((e[0]**2) + (e[1]**2) + (e[2]**2))
return float(denominator / numerator)
@property
def opposite_normal(self):
"""
get plane normal in the opposite direction [x, y, z]
:return: np.ndarray
"""
if self._opposite_normal is None:
coordinates = []
for coordinate in self.normal:
coordinates.append(-coordinate)
self._opposite_normal = np.array(coordinates)
return self._opposite_normal

View File

@ -1,37 +0,0 @@
"""
Point module
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 math
class Point:
"""
Point class
"""
def __init__(self, coordinates):
self._coordinates = coordinates
@property
def coordinates(self):
"""
Get point coordinates
:return: [ndarray]
"""
return self._coordinates
def distance_to_point(self, other_point):
"""
Calculates distance between points in an n-D Euclidean space
:param other_point: point or vertex
:return: float
"""
power = 0
for dimension in range(0, len(self.coordinates)):
power += math.pow(other_point.coordinates[dimension]-self.coordinates[dimension], 2)
distance = math.sqrt(power)
return distance

View File

@ -1,452 +0,0 @@
"""
Polygon module
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 __future__ import annotations
import math
import sys
from typing import List
from hub.hub_logger import logger
import numpy as np
from trimesh import Trimesh
import trimesh.intersections
import trimesh.creation
import trimesh.geometry
from shapely.geometry.polygon import Polygon as shapley_polygon
from hub.city_model_structure.attributes.plane import Plane
from hub.city_model_structure.attributes.point import Point
import hub.helpers.constants as cte
class Polygon:
"""
Polygon class
"""
def __init__(self, coordinates):
self._area = None
self._points = None
self._points_list = None
self._normal = None
self._inverse = None
self._edges = None
self._coordinates = coordinates
self._triangles = None
self._vertices = None
self._faces = None
self._plane = None
@property
def points(self) -> List[Point]:
"""
Get the points belonging to the polygon [[x, y, z],...]
:return: [Point]
"""
if self._points is None:
self._points = []
for coordinate in self.coordinates:
self._points.append(Point(coordinate))
return self._points
@property
def plane(self) -> Plane:
"""
Get the polygon plane
:return: Plane
"""
if self._plane is None:
self._plane = Plane(normal=self.normal, origin=self.points[0])
return self._plane
@property
def coordinates(self) -> List[np.ndarray]:
"""
Get the points in the shape of its coordinates belonging to the polygon [[x, y, z],...]
:return: [np.ndarray]
"""
return self._coordinates
def contains_point(self, point):
"""
Determines if the given point is contained by the current polygon
:return: boolean
"""
# fixme: This method doesn't seems to work.
n = len(self.vertices)
angle_sum = 0
for i in range(0, n):
vector_0 = self.vertices[i]
vector_1 = self.vertices[(i+1) % n]
# set to origin
vector_0[0] = vector_0[0] - point.coordinates[0]
vector_0[1] = vector_0[1] - point.coordinates[1]
vector_0[2] = vector_0[2] - point.coordinates[2]
vector_1[0] = vector_1[0] - point.coordinates[0]
vector_1[1] = vector_1[1] - point.coordinates[1]
vector_1[2] = vector_1[2] - point.coordinates[2]
module = np.linalg.norm(vector_0) * np.linalg.norm(vector_1)
scalar_product = np.dot(vector_0, vector_1)
angle = np.pi/2
if module != 0:
angle = abs(np.arcsin(scalar_product / module))
angle_sum += angle
return abs(angle_sum - math.pi*2) < cte.EPSILON
def contains_polygon(self, polygon):
"""
Determines if the given polygon is contained by the current polygon
:return: boolean
"""
for point in polygon.points:
if not self.contains_point(point):
return False
return True
@property
def points_list(self) -> np.ndarray:
"""
Get the solid surface point coordinates list [x, y, z, x, y, z,...]
:return: np.ndarray
"""
if self._points_list is None:
s = self.coordinates
self._points_list = np.reshape(s, len(s) * 3)
return self._points_list
@property
def edges(self) -> List[List[Point]]:
"""
Get polygon edges list
:return: [[Point]]
"""
if self._edges is None:
self._edges = []
for i in range(0, len(self.points) - 1):
point_1 = self.points[i]
point_2 = self.points[i + 1]
self._edges.append([point_1, point_2])
self._edges.append([self.points[len(self.points) - 1], self.points[0]])
return self._edges
@property
def area(self):
"""
Get surface area in square meters
:return: float
"""
if self._area is None:
self._area = 0
for triangle in self.triangles:
ab = np.zeros(3)
ac = np.zeros(3)
for i in range(0, 3):
ab[i] = triangle.coordinates[1][i] - triangle.coordinates[0][i]
ac[i] = triangle.coordinates[2][i] - triangle.coordinates[0][i]
self._area += np.linalg.norm(np.cross(ab, ac)) / 2
return self._area
@area.setter
def area(self, value):
self._area = value
@property
def normal(self) -> np.ndarray:
"""
Get surface normal vector
:return: np.ndarray
"""
if self._normal is None:
points = self.coordinates
# todo: IF THE FIRST ONE IS 0, START WITH THE NEXT
point_origin = points[len(points) - 2]
vector_1 = points[len(points) - 1] - point_origin
vector_2 = points[0] - point_origin
vector_3 = points[1] - point_origin
cross_product = np.cross(vector_1, vector_2)
if np.linalg.norm(cross_product) != 0:
cross_product = cross_product / np.linalg.norm(cross_product)
alpha = self._angle_between_vectors(vector_1, vector_2)
else:
cross_product = [0, 0, 0]
alpha = 0
if len(points) == 3:
return cross_product
if np.linalg.norm(cross_product) == 0:
return cross_product
alpha += self._angle(vector_2, vector_3, cross_product)
for i in range(0, len(points) - 4):
vector_1 = points[i + 1] - point_origin
vector_2 = points[i + 2] - point_origin
alpha += self._angle(vector_1, vector_2, cross_product)
vector_1 = points[len(points) - 1] - point_origin
vector_2 = points[0] - point_origin
if alpha < 0:
cross_product = np.cross(vector_2, vector_1)
else:
cross_product = np.cross(vector_1, vector_2)
self._normal = cross_product / np.linalg.norm(cross_product)
return self._normal
@staticmethod
def _angle(vector_1, vector_2, cross_product):
"""
alpha angle in radians
:param vector_1: [float]
:param vector_2: [float]
:param cross_product: [float]
:return: float
"""
accepted_normal_difference = 0.01
cross_product_next = np.cross(vector_1, vector_2)
if np.linalg.norm(cross_product_next) != 0:
cross_product_next = cross_product_next / np.linalg.norm(cross_product_next)
alpha = Polygon._angle_between_vectors(vector_1, vector_2)
else:
cross_product_next = [0, 0, 0]
alpha = 0
delta_normals = 0
for j in range(0, 3):
delta_normals += cross_product[j] - cross_product_next[j]
if np.abs(delta_normals) < accepted_normal_difference:
return alpha
return -alpha
@staticmethod
def triangle_mesh(vertices, normal):
min_x = 1e16
min_y = 1e16
min_z = 1e16
for vertex in vertices:
if vertex[0] < min_x:
min_x = vertex[0]
if vertex[1] < min_y:
min_y = vertex[1]
if vertex[2] < min_z:
min_z = vertex[2]
new_vertices = []
for vertex in vertices:
vertex = [vertex[0]-min_x, vertex[1]-min_y, vertex[2]-min_z]
new_vertices.append(vertex)
transformation_matrix = trimesh.geometry.plane_transform(origin=new_vertices[0], normal=normal)
coordinates = []
for vertex in vertices:
transformed_vertex = [vertex[0]-min_x, vertex[1]-min_y, vertex[2]-min_z, 1]
transformed_vertex = np.dot(transformation_matrix, transformed_vertex)
coordinate = [transformed_vertex[0], transformed_vertex[1]]
coordinates.append(coordinate)
polygon = shapley_polygon(coordinates)
try:
vertices_2d, faces = trimesh.creation.triangulate_polygon(polygon, engine='triangle')
mesh = Trimesh(vertices=vertices, faces=faces)
# check orientation
normal_sum = 0
for i in range(0, 3):
normal_sum += normal[i] + mesh.face_normals[0][i]
if abs(normal_sum) <= 1E-10:
new_faces = []
for face in faces:
new_face = []
for i in range(0, len(face)):
new_face.append(face[len(face)-i-1])
new_faces.append(new_face)
mesh = Trimesh(vertices=vertices, faces=new_faces)
return mesh
except ValueError:
logger.error(f'Not able to triangulate polygon\n')
sys.stderr.write(f'Not able to triangulate polygon\n')
_vertices = [[0, 0, 0], [0, 0, 1], [0, 1, 0]]
_faces = [[0, 1, 2]]
return Trimesh(vertices=_vertices, faces=_faces)
@property
def triangles(self) -> List[Polygon]:
if self._triangles is None:
self._triangles = []
_mesh = self.triangle_mesh(self.coordinates, self.normal)
for face in _mesh.faces:
points = []
for vertex in face:
points.append(self.coordinates[vertex])
polygon = Polygon(points)
self._triangles.append(polygon)
return self._triangles
@staticmethod
def _angle_between_vectors(vec_1, vec_2):
"""
angle between vectors in radians
:param vec_1: vector
:param vec_2: vector
:return: float
"""
if np.linalg.norm(vec_1) == 0 or np.linalg.norm(vec_2) == 0:
sys.stderr.write("Warning: impossible to calculate angle between planes' normal. Return 0\n")
return 0
cosine = np.dot(vec_1, vec_2) / np.linalg.norm(vec_1) / np.linalg.norm(vec_2)
if cosine > 1 and cosine - 1 < 1e-5:
cosine = 1
elif cosine < -1 and cosine + 1 > -1e-5:
cosine = -1
alpha = math.acos(cosine)
return alpha
@property
def inverse(self):
"""
Get the polygon coordinates in reversed order
:return: [np.ndarray]
"""
if self._inverse is None:
self._inverse = self.coordinates[::-1]
return self._inverse
def divide(self, plane):
"""
Divides the polygon in two by a plane
:param plane: plane that intersects with self to divide it in two parts (Plane)
:return: Polygon, Polygon, [Point]
"""
tri_polygons = Trimesh(vertices=self.vertices, faces=self.faces)
intersection = trimesh.intersections.mesh_plane(tri_polygons, plane.normal, plane.origin.coordinates)
polys_1 = trimesh.intersections.slice_mesh_plane(tri_polygons, plane.opposite_normal, plane.origin.coordinates)
polys_2 = trimesh.intersections.slice_mesh_plane(tri_polygons, plane.normal, plane.origin.coordinates)
triangles_1 = []
for triangle in polys_1.triangles:
triangles_1.append(Polygon(triangle))
polygon_1 = self._reshape(triangles_1)
triangles_2 = []
for triangle in polys_2.triangles:
triangles_2.append(Polygon(triangle))
polygon_2 = self._reshape(triangles_2)
return polygon_1, polygon_2, intersection
def _reshape(self, triangles) -> Polygon:
edges_list = []
for i in range(0, len(triangles)):
for edge in triangles[i].edges:
if not self._edge_in_edges_list(edge, edges_list):
edges_list.append(edge)
else:
edges_list = self._remove_from_list(edge, edges_list)
points = self._order_points(edges_list)
return Polygon(points)
@staticmethod
def _edge_in_edges_list(edge, edges_list):
for edge_element in edges_list:
if (edge_element[0].distance_to_point(edge[0]) == 0 and edge_element[1].distance_to_point(edge[1]) == 0) or \
(edge_element[1].distance_to_point(edge[0]) == 0 and edge_element[0].distance_to_point(
edge[1]) == 0):
return True
return False
@staticmethod
def _order_points(edges_list):
# todo: not sure that this method works for any case -> RECHECK
points = edges_list[0]
for _ in range(0, len(points)):
for i in range(1, len(edges_list)):
point_1 = edges_list[i][0]
point_2 = points[len(points) - 1]
if point_1.distance_to_point(point_2) == 0:
points.append(edges_list[i][1])
points.remove(points[len(points) - 1])
array_points = []
for point in points:
array_points.append(point.coordinates)
return np.array(array_points)
@staticmethod
def _remove_from_list(edge, edges_list):
new_list = []
for edge_element in edges_list:
if not ((edge_element[0].distance_to_point(edge[0]) == 0 and edge_element[1].distance_to_point(
edge[1]) == 0) or
(edge_element[1].distance_to_point(edge[0]) == 0 and edge_element[0].distance_to_point(
edge[1]) == 0)):
new_list.append(edge_element)
return new_list
@property
def vertices(self) -> np.ndarray:
"""
Get polygon vertices
:return: np.ndarray(int)
"""
if self._vertices is None:
vertices, self._vertices = [], []
_ = [vertices.extend(s.coordinates) for s in self.triangles]
for vertex_1 in vertices:
found = False
for vertex_2 in self._vertices:
found = False
power = 0
for dimension in range(0, 3):
power += math.pow(vertex_2[dimension] - vertex_1[dimension], 2)
distance = math.sqrt(power)
if distance == 0:
found = True
break
if not found:
self._vertices.append(vertex_1)
self._vertices = np.asarray(self._vertices)
return self._vertices
@property
def faces(self) -> List[List[int]]:
"""
Get polygon triangular faces
:return: [face]
"""
if self._faces is None:
self._faces = []
for polygon in self.triangles:
face = []
points = polygon.coordinates
if len(points) != 3:
sub_polygons = polygon.triangles
# todo: I modified this! To be checked @Guille
if len(sub_polygons) >= 1:
for sub_polygon in sub_polygons:
face = []
points = sub_polygon.coordinates
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
else:
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
return self._faces
def _position_of(self, point, face):
"""
position of a specific point in the list of points that define a face
:return: int
"""
vertices = self.vertices
for i in range(len(vertices)):
# ensure not duplicated vertex
power = 0
vertex2 = vertices[i]
for dimension in range(0, 3):
power += math.pow(vertex2[dimension] - point[dimension], 2)
distance = math.sqrt(power)
if i not in face and distance == 0:
return i
return -1

View File

@ -1,254 +0,0 @@
"""
Polyhedron module
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
"""
from typing import List, Union
import sys
import math
import numpy as np
from trimesh import Trimesh
from hub.helpers.configuration_helper import ConfigurationHelper
class Polyhedron:
"""
Polyhedron class
"""
def __init__(self, polygons):
self._polygons = polygons
self._polyhedron = None
self._triangulated_polyhedron = None
self._volume = None
self._faces = None
self._vertices = None
self._trimesh = None
self._centroid = None
self._max_z = None
self._max_y = None
self._max_x = None
self._min_z = None
self._min_y = None
self._min_x = None
def _position_of(self, point, face):
"""
position of a specific point in the list of points that define a face
:return: int
"""
vertices = self.vertices
for i in range(len(vertices)):
# ensure not duplicated vertex
power = 0
vertex2 = vertices[i]
for dimension in range(0, 3):
power += math.pow(vertex2[dimension] - point[dimension], 2)
distance = math.sqrt(power)
if i not in face and distance == 0:
return i
return -1
@property
def vertices(self) -> np.ndarray:
"""
Get polyhedron vertices
:return: np.ndarray(int)
"""
if self._vertices is None:
vertices, self._vertices = [], []
_ = [vertices.extend(s.coordinates) for s in self._polygons]
for vertex_1 in vertices:
found = False
for vertex_2 in self._vertices:
found = False
power = 0
for dimension in range(0, 3):
power += math.pow(vertex_2[dimension] - vertex_1[dimension], 2)
distance = math.sqrt(power)
if distance == 0:
found = True
break
if not found:
self._vertices.append(vertex_1)
self._vertices = np.asarray(self._vertices)
return self._vertices
@property
def faces(self) -> List[List[int]]:
"""
Get polyhedron triangular faces
:return: [face]
"""
if self._faces is None:
self._faces = []
for polygon in self._polygons:
face = []
points = polygon.coordinates
if len(points) != 3:
sub_polygons = polygon.triangles
# todo: I modified this! To be checked @Guille
if len(sub_polygons) >= 1:
for sub_polygon in sub_polygons:
face = []
points = sub_polygon.coordinates
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
else:
for point in points:
face.append(self._position_of(point, face))
self._faces.append(face)
return self._faces
@property
def trimesh(self) -> Union[Trimesh, None]:
"""
Get polyhedron trimesh
:return: Trimesh
"""
if self._trimesh is None:
for face in self.faces:
if len(face) != 3:
sys.stderr.write('Not able to generate trimesh\n')
return None
self._trimesh = Trimesh(vertices=self.vertices, faces=self.faces)
return self._trimesh
@property
def volume(self):
"""
Get polyhedron volume in cubic meters
:return: float
"""
if self._volume is None:
if self.trimesh is None:
self._volume = np.inf
elif not self.trimesh.is_volume:
self._volume = np.inf
else:
self._volume = self.trimesh.volume
return self._volume
@property
def max_z(self):
"""
Get polyhedron maximal z value in meters
:return: float
"""
if self._max_z is None:
self._max_z = ConfigurationHelper().min_coordinate
for polygon in self._polygons:
for point in polygon.coordinates:
self._max_z = max(self._max_z, point[2])
return self._max_z
@property
def max_y(self):
"""
Get polyhedron maximal y value in meters
:return: float
"""
if self._max_y is None:
self._max_y = ConfigurationHelper().min_coordinate
for polygon in self._polygons:
for point in polygon.coordinates:
if self._max_y < point[1]:
self._max_y = point[1]
return self._max_y
@property
def max_x(self):
"""
Get polyhedron maximal x value in meters
:return: float
"""
if self._max_x is None:
self._max_x = ConfigurationHelper().min_coordinate
for polygon in self._polygons:
for point in polygon.coordinates:
self._max_x = max(self._max_x, point[0])
return self._max_x
@property
def min_z(self):
"""
Get polyhedron minimal z value in meters
:return: float
"""
if self._min_z is None:
self._min_z = self.max_z
for polygon in self._polygons:
for point in polygon.coordinates:
if self._min_z > point[2]:
self._min_z = point[2]
return self._min_z
@property
def min_y(self):
"""
Get polyhedron minimal y value in meters
:return: float
"""
if self._min_y is None:
self._min_y = self.max_y
for polygon in self._polygons:
for point in polygon.coordinates:
if self._min_y > point[1]:
self._min_y = point[1]
return self._min_y
@property
def min_x(self):
"""
Get polyhedron minimal x value in meters
:return: float
"""
if self._min_x is None:
self._min_x = self.max_x
for polygon in self._polygons:
for point in polygon.coordinates:
if self._min_x > point[0]:
self._min_x = point[0]
return self._min_x
@property
def centroid(self) -> Union[None, List[float]]:
"""
Get polyhedron centroid
:return: [x,y,z]
"""
if self._centroid is None:
trimesh = self.trimesh
if trimesh is None:
return None
self._centroid = self.trimesh.centroid
return self._centroid
def stl_export(self, full_path):
"""
Export the polyhedron to stl given file
:param full_path: str
:return: None
"""
self.trimesh.export(full_path, 'stl_ascii')
def obj_export(self, full_path):
"""
Export the polyhedron to obj given file
:param full_path: str
:return: None
"""
self.trimesh.export(full_path, 'obj')
def show(self):
"""
Auxiliary function to render the polyhedron
:return: None
"""
self.trimesh.show()

View File

@ -9,7 +9,7 @@ import uuid
from typing import Union, List from typing import Union, List
from hub.city_model_structure.building_demand.usage import Usage from hub.city_model_structure.building_demand.usage import Usage
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
from hub.city_model_structure.attributes.polyhedron import Polyhedron from geometry import Polyhedron
from hub.city_model_structure.energy_systems.hvac_system import HvacSystem from hub.city_model_structure.energy_systems.hvac_system import HvacSystem

View File

@ -25,7 +25,7 @@ from hub.city_model_structure.iot.station import Station
from hub.city_model_structure.level_of_detail import LevelOfDetail from hub.city_model_structure.level_of_detail import LevelOfDetail
from hub.city_model_structure.machine import Machine from hub.city_model_structure.machine import Machine
from hub.city_model_structure.parts_consisting_building import PartsConsistingBuilding from hub.city_model_structure.parts_consisting_building import PartsConsistingBuilding
from hub.helpers.geometry_helper import GeometryHelper from geometry import Library as GeometryHelper
from hub.helpers.location import Location from hub.helpers.location import Location
from hub.city_model_structure.energy_system import EnergySystem from hub.city_model_structure.energy_system import EnergySystem
from hub.city_model_structure.lca_material import LcaMaterial from hub.city_model_structure.lca_material import LcaMaterial

View File

@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca Project Coder Atiya atiya.atiya@mail.concordia.ca
""" """
class Fuel: class Fuel:
def __init__(self, fuel_id, name, carbon_emission_factor, unit): def __init__(self, fuel_id, name, carbon_emission_factor, unit):
self._fuel_id = fuel_id self._fuel_id = fuel_id

View File

@ -7,6 +7,7 @@ Project Coder atiya.atiya@mail.concordia.ca
from typing import Union from typing import Union
class LcaMaterial: class LcaMaterial:
def __init__(self): def __init__(self):
self._id = None self._id = None

View File

@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca Project Coder Atiya atiya.atiya@mail.concordia.ca
""" """
class Vehicle: class Vehicle:
""" """
Vehicle class Vehicle class

View File

@ -1,301 +0,0 @@
"""
Geometry helper
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 math
from pathlib import Path
import numpy as np
from PIL import Image
from trimesh import Trimesh
from trimesh import intersections
from hub.city_model_structure.attributes.polygon import Polygon
from hub.city_model_structure.attributes.polyhedron import Polyhedron
from hub.helpers.location import Location
class MapPoint:
def __init__(self, x, y):
self._x = int(x)
self._y = int(y)
@property
def x(self):
return self._x
@property
def y(self):
return self._y
def __str__(self):
return f'({self.x}, {self.y})'
def __len__(self):
return 1
def __getitem__(self, index):
if index == 0:
return self._x
elif index == 1:
return self._y
else:
raise IndexError('Index error')
class GeometryHelper:
"""
Geometry helper class
"""
# todo: complete dictionary
srs_transformations = {
'urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH': 'epsg:25832'
}
@staticmethod
def factor():
return 0.5
def __init__(self, delta=0, area_delta=0):
self._delta = delta
self._area_delta = area_delta
@staticmethod
def coordinate_to_map_point(coordinate, city):
factor = GeometryHelper.factor()
return MapPoint(((coordinate[0] - city.lower_corner[0]) * factor), ((coordinate[1] - city.lower_corner[1]) * factor))
@staticmethod
def city_mapping(city, building_names=None, plot=False):
"""
Returns a shared_information dictionary like
{
"building_name" : [{line: 0 coordinate_1: [x,y,z], coordinate_2:[x, y, z], points: 0}]
}
"""
lines_information = {}
if building_names is None:
building_names = [b.name for b in city.buildings]
factor = GeometryHelper.factor()
x = math.ceil((city.upper_corner[0] - city.lower_corner[0]) * factor) + 1
y = math.ceil((city.upper_corner[1] - city.lower_corner[1]) * factor) + 1
city_map = [['' for _ in range(y + 1)] for _ in range(x + 1)]
map_info = [[{} for _ in range(y + 1)] for _ in range(x + 1)]
img = Image.new('RGB', (x + 1, y + 1), "black") # create a new black image
city_image = img.load() # create the pixel map
for building_name in building_names:
building = city.city_object(building_name)
line = 0
for ground in building.grounds:
length = len(ground.perimeter_polygon.coordinates) - 1
for i, coordinate in enumerate(ground.perimeter_polygon.coordinates):
j = i + 1
if i == length:
j = 0
next_coordinate = ground.perimeter_polygon.coordinates[j]
distance = GeometryHelper.distance_between_points(coordinate, next_coordinate)
steps = int(distance * factor * 2)
if steps == 0:
continue
delta_x = (next_coordinate[0] - coordinate[0]) / steps
delta_y = (next_coordinate[1] - coordinate[1]) / steps
for k in range(0, steps):
new_coordinate = (coordinate[0] + (delta_x * k), coordinate[1] + (delta_y * k))
point = GeometryHelper.coordinate_to_map_point(new_coordinate, city)
x = point.x
y = point.y
if city_map[x][y] == '':
city_map[x][y] = building.name
map_info[x][y] = {
'line_start': (coordinate[0], coordinate[1]),
'line_end': (next_coordinate[0], next_coordinate[1]),
}
city_image[x, y] = (100, 0, 0)
elif city_map[x][y] != building.name:
neighbour = city.city_object(city_map[x][y])
neighbour_info = map_info[x][y]
# prepare the keys
neighbour_start_coordinate = f'{GeometryHelper.coordinate_to_map_point(neighbour_info["line_start"], city)}'
building_start_coordinate = f'{GeometryHelper.coordinate_to_map_point(coordinate, city)}'
neighbour_key = f'{neighbour.name}_{neighbour_start_coordinate}_{building_start_coordinate}'
building_key = f'{building.name}_{building_start_coordinate}_{neighbour_start_coordinate}'
# Add my neighbour info to my shared lines
if building.name in lines_information.keys() and neighbour_key in lines_information[building.name]:
shared_points = int(lines_information[building.name][neighbour_key]['shared_points'])
lines_information[building.name][neighbour_key]['shared_points'] = shared_points + 1
else:
if building.name not in lines_information.keys():
lines_information[building.name] = {}
lines_information[building.name][neighbour_key] = {
'neighbour_name': neighbour.name,
'line_start': (coordinate[0], coordinate[1]),
'line_end': (next_coordinate[0], next_coordinate[1]),
'neighbour_line_start': neighbour_info['line_start'],
'neighbour_line_end': neighbour_info['line_end'],
'coordinate_start': f"{GeometryHelper.coordinate_to_map_point(coordinate, city)}",
'coordinate_end': f"{GeometryHelper.coordinate_to_map_point(next_coordinate, city)}",
'neighbour_start': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_start'], city)}",
'neighbour_end': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_end'], city)}",
'shared_points': 1
}
# Add my info to my neighbour shared lines
if neighbour.name in lines_information.keys() and building_key in lines_information[neighbour.name]:
shared_points = int(lines_information[neighbour.name][building_key]['shared_points'])
lines_information[neighbour.name][building_key]['shared_points'] = shared_points + 1
else:
if neighbour.name not in lines_information.keys():
lines_information[neighbour.name] = {}
lines_information[neighbour.name][building_key] = {
'neighbour_name': building.name,
'line_start': neighbour_info['line_start'],
'line_end': neighbour_info['line_end'],
'neighbour_line_start': (coordinate[0], coordinate[1]),
'neighbour_line_end': (next_coordinate[0], next_coordinate[1]),
'neighbour_start': f"{GeometryHelper.coordinate_to_map_point(coordinate, city)}",
'neighbour_end': f"{GeometryHelper.coordinate_to_map_point(next_coordinate, city)}",
'coordinate_start': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_start'], city)}",
'coordinate_end': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_end'], city)}",
'shared_points': 1
}
if building.neighbours is None:
building.neighbours = [neighbour]
elif neighbour not in building.neighbours:
building.neighbours.append(neighbour)
if neighbour.neighbours is None:
neighbour.neighbours = [building]
elif building not in neighbour.neighbours:
neighbour.neighbours.append(building)
line += 1
if plot:
img.show()
return lines_information
@staticmethod
def segment_list_to_trimesh(lines) -> Trimesh:
"""
Transform a list of segments into a Trimesh
"""
# todo: trimesh has a method for this
line_points = [lines[0][0], lines[0][1]]
lines.remove(lines[0])
while len(lines) > 1:
i = 0
for line in lines:
i += 1
if GeometryHelper.distance_between_points(line[0], line_points[len(line_points) - 1]) < 1e-8:
line_points.append(line[1])
lines.pop(i - 1)
break
if GeometryHelper.distance_between_points(line[1], line_points[len(line_points) - 1]) < 1e-8:
line_points.append(line[0])
lines.pop(i - 1)
break
polyhedron = Polyhedron(Polygon(line_points).triangles)
trimesh = Trimesh(polyhedron.vertices, polyhedron.faces)
return trimesh
@staticmethod
def _merge_meshes(mesh1, mesh2):
v_1 = mesh1.vertices
f_1 = mesh1.faces
v_2 = mesh2.vertices
f_2 = mesh2.faces
length = len(v_1)
v_merge = np.concatenate((v_1, v_2))
f_merge = np.asarray(f_1)
for item in f_2:
point1 = item.item(0) + length
point2 = item.item(1) + length
point3 = item.item(2) + length
surface = np.asarray([point1, point2, point3])
f_merge = np.concatenate((f_merge, [surface]))
mesh_merge = Trimesh(vertices=v_merge, faces=f_merge)
mesh_merge.fix_normals()
return mesh_merge
@staticmethod
def divide_mesh_by_plane(trimesh, normal_plane, point_plane):
"""
Divide a mesh by a plane
:param trimesh: Trimesh
:param normal_plane: [x, y, z]
:param point_plane: [x, y, z]
:return: [Trimesh]
"""
# The first mesh returns the positive side of the plane and the second the negative side.
# If the plane does not divide the mesh (i.e. it does not touch it or it is coplanar with one or more faces),
# then it returns only the original mesh.
# todo: review split method in https://github.com/mikedh/trimesh/issues/235,
# once triangulate_polygon in Polygon class is solved
normal_plane_opp = [None] * len(normal_plane)
for i in range(0, len(normal_plane)):
normal_plane_opp[i] = - normal_plane[i]
section_1 = intersections.slice_mesh_plane(trimesh, normal_plane, point_plane)
if section_1 is None:
return [trimesh]
lines = list(intersections.mesh_plane(trimesh, normal_plane, point_plane))
cap = GeometryHelper.segment_list_to_trimesh(lines)
trimesh_1 = GeometryHelper._merge_meshes(section_1, cap)
section_2 = intersections.slice_mesh_plane(trimesh, normal_plane_opp, point_plane)
if section_2 is None:
return [trimesh_1]
trimesh_2 = GeometryHelper._merge_meshes(section_2, cap)
return [trimesh_1, trimesh_2]
@staticmethod
def get_location(latitude, longitude) -> Location:
"""
Get Location from latitude and longitude
"""
_data_path = Path(Path(__file__).parent.parent / 'data/geolocation/cities15000.txt').resolve()
latitude = float(latitude)
longitude = float(longitude)
distance = math.inf
country = 'Unknown'
city = 'Unknown'
with open(_data_path, 'r', encoding='utf-8') as f:
for line_number, line in enumerate(f):
fields = line.split('\t')
file_city_name = fields[2]
file_latitude = float(fields[4])
file_longitude = float(fields[5])
file_country_code = fields[8]
new_distance = math.sqrt(pow((latitude - file_latitude), 2) + pow((longitude - file_longitude), 2))
if distance > new_distance:
distance = new_distance
country = file_country_code
city = file_city_name
return Location(country, city)
@staticmethod
def distance_between_points(vertex1, vertex2):
"""
distance between points in an n-D Euclidean space
:param vertex1: point or vertex
:param vertex2: point or vertex
:return: float
"""
power = 0
for dimension in range(0, len(vertex1)):
power += math.pow(vertex2[dimension] - vertex1[dimension], 2)
distance = math.sqrt(power)
return distance

View File

@ -1,30 +0,0 @@
"""
Location module
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
"""
class Location:
"""
Location
"""
def __init__(self, country, city):
self._country = country
self._city = city
@property
def city(self):
"""
City name
"""
return self._city
@property
def country(self):
"""
Country code
"""
return self._country

View File

@ -11,8 +11,8 @@ import numpy as np
from typing import List from typing import List
from hub.helpers import constants as cte from hub.helpers import constants as cte
from hub.city_model_structure.attributes.polygon import Polygon from geometry import Polygon
from hub.city_model_structure.attributes.point import Point from geometry import Point
from hub.city_model_structure.building_demand.storey import Storey from hub.city_model_structure.building_demand.storey import Storey
from hub.city_model_structure.building_demand.surface import Surface from hub.city_model_structure.building_demand.surface import Surface
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone from hub.city_model_structure.building_demand.thermal_zone import ThermalZone

View File

@ -12,8 +12,8 @@ import numpy as np
from pyproj import Transformer from pyproj import Transformer
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.helpers.geometry_helper import GeometryHelper from geometry import Library as GeometryHelper
from hub.imports.geometry.helpers.geometry_helper import GeometryHelper as igh from geometry import Helper as igh
from hub.city_model_structure.building import Building from hub.city_model_structure.building import Building
from hub.city_model_structure.building_demand.surface import Surface from hub.city_model_structure.building_demand.surface import Surface
from hub.city_model_structure.city import City from hub.city_model_structure.city import City

View File

@ -1,107 +0,0 @@
"""
Geometry helper
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 math
import sys
import numpy as np
class GeometryHelper:
"""
Geometry helper
"""
@staticmethod
def to_points_matrix(points):
"""
Transform a point vector into a point matrix
:param points: [x, y, z, x, y, z ...]
:return: [[x,y,z],[x,y,z]...]
"""
rows = points.size // 3
points = points.reshape(rows, 3)
return points
@staticmethod
def gml_surface_to_libs(surface):
"""
Transform citygml surface names into hub names
"""
if surface == 'WallSurface':
return 'Wall'
if surface == 'GroundSurface':
return 'Ground'
return 'Roof'
@staticmethod
def points_from_string(coordinates) -> np.ndarray:
points = np.fromstring(coordinates, dtype=float, sep=' ')
points = GeometryHelper.to_points_matrix(points)
return points
@staticmethod
def remove_last_point_from_string(points):
array = points.split(' ')
res = " "
return res.join(array[0:len(array) - 3])
@staticmethod
def invert_points(points):
res = []
for point in points:
res.insert(0, point)
return res
@staticmethod
def ground_area(points):
"""
Get ground surface area in square meters
:return: float
"""
# New method to calculate area
if len(points) < 3:
sys.stderr.write('Warning: the area of a line or point cannot be calculated 1. Area = 0\n')
return 0
alpha = 0
vec_1 = points[1] - points[0]
for i in range(2, len(points)):
vec_2 = points[i] - points[0]
alpha += GeometryHelper.angle_between_vectors(vec_1, vec_2)
if alpha == 0:
sys.stderr.write('Warning: the area of a line or point cannot be calculated 2. Area = 0\n')
return 0
#
horizontal_points = points
area = 0
for i in range(0, len(horizontal_points) - 1):
point = horizontal_points[i]
next_point = horizontal_points[i + 1]
area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0])
next_point = horizontal_points[0]
point = horizontal_points[len(horizontal_points) - 1]
area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0])
_area = abs(area)
return _area
@staticmethod
def angle_between_vectors(vec_1, vec_2):
"""
angle between vectors in radians
:param vec_1: vector
:param vec_2: vector
:return: float
"""
if np.linalg.norm(vec_1) == 0 or np.linalg.norm(vec_2) == 0:
sys.stderr.write("Warning: impossible to calculate angle between planes' normal. Return 0\n")
return 0
cosine = np.dot(vec_1, vec_2) / np.linalg.norm(vec_1) / np.linalg.norm(vec_2)
if cosine > 1 and cosine - 1 < 1e-5:
cosine = 1
elif cosine < -1 and cosine + 1 > -1e-5:
cosine = -1
alpha = math.acos(cosine)
return alpha

View File

@ -2,7 +2,7 @@
Insel Heap pump energy demand and fossil fuel consumption Insel Heap pump energy demand and fossil fuel consumption
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder peter.yefi@gmail.cm Project Coder peter.yefi@gmail.com
""" """
from pathlib import Path from pathlib import Path

View File

@ -11,6 +11,7 @@ from sqlalchemy import Column, Integer, String, Sequence, ForeignKey, Float
from sqlalchemy import DateTime from sqlalchemy import DateTime
from hub.persistence.configuration import Models from hub.persistence.configuration import Models
class CityObject(Models): class CityObject(Models):
""" """
A model representation of an application A model representation of an application

View File

@ -12,7 +12,7 @@ from hub.imports.usage_factory import UsageFactory
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
from hub.helpers.dictionaries import MontrealFunctionToHubFunction, Dictionaries from hub.helpers.dictionaries import MontrealFunctionToHubFunction, Dictionaries
from hub.helpers.geometry_helper import GeometryHelper from geometry import Library as GeometryHelper
from hub.imports.construction_factory import ConstructionFactory from hub.imports.construction_factory import ConstructionFactory
from hub.imports.geometry_factory import GeometryFactory from hub.imports.geometry_factory import GeometryFactory

View File

@ -0,0 +1,483 @@
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id":159,
"geometry":{
"type":"MultiPolygon",
"coordinates":[
[
[
[
-73.577698789303398,
45.495622856681265
],
[
-73.577695682391294,
45.495624487512899
],
[
-73.577694801537987,
45.495625936861458
],
[
-73.577693920684638,
45.49562738621006
],
[
-73.577694615888902,
45.495630499198704
],
[
-73.577697062628715,
45.495632621167189
],
[
-73.577698848255025,
45.495633159859175
],
[
-73.577700633881378,
45.495633698551167
],
[
-73.577705085987418,
45.495633326586457
],
[
-73.577708563468136,
45.495631344563115
],
[
-73.577709259030797,
45.495630066310945
],
[
-73.577709954593416,
45.495628788058717
],
[
-73.577709490252843,
45.49562607984307
],
[
-73.577706812660736,
45.495623562100398
],
[
-73.577702627180884,
45.495622431143737
],
[
-73.577698789303398,
45.495622856681265
]
]
],
[
[
[
-73.57791718974444,
45.495793264412136
],
[
-73.577966456490742,
45.495742218619156
],
[
-73.577878164750075,
45.495700076149248
],
[
-73.577859178652233,
45.49571975069135
],
[
-73.577861956965407,
45.495721071568774
],
[
-73.577879805943169,
45.495702576597608
],
[
-73.577962515440873,
45.49574205933709
],
[
-73.577916838945768,
45.495789395320777
],
[
-73.57787497843664,
45.495769415828214
],
[
-73.577833117957056,
45.495749436320196
],
[
-73.577851465247122,
45.495730428102746
],
[
-73.577849480737555,
45.495729484618735
],
[
-73.577828693118363,
45.495751032059708
],
[
-73.57791718974444,
45.495793264412136
]
]
],
[
[
[
-73.578428233148927,
45.495941982883387
],
[
-73.578530103183425,
45.495838322814635
],
[
-73.578499329919453,
45.49582345154311
],
[
-73.578468556671695,
45.495808580263336
],
[
-73.578447353643782,
45.495830285574655
],
[
-73.578426150599569,
45.495851990882095
],
[
-73.578417604248173,
45.495847857465606
],
[
-73.578409057898043,
45.495843724048513
],
[
-73.578452403084299,
45.495799363455262
],
[
-73.578495748202485,
45.495755002845257
],
[
-73.578433049485312,
45.495724703162658
],
[
-73.578459637880272,
45.495697491606336
],
[
-73.578486226249623,
45.495670280043669
],
[
-73.578541754972733,
45.495697111228424
],
[
-73.578605197672417,
45.495632179810727
],
[
-73.578668640226383,
45.49556724835714
],
[
-73.578644249614086,
45.495555468192734
],
[
-73.578649591722638,
45.495551055277119
],
[
-73.578654933830336,
45.495546642361241
],
[
-73.578658928415678,
45.495548502288408
],
[
-73.578662923001303,
45.495550362215432
],
[
-73.578665886920362,
45.495547138731361
],
[
-73.578366044120955,
45.495412170209917
],
[
-73.578319210166981,
45.495390187637788
],
[
-73.578272376249373,
45.49536820504634
],
[
-73.578023430733111,
45.495259386206158
],
[
-73.578020811505979,
45.495262069531542
],
[
-73.577943110783622,
45.495226466242045
],
[
-73.57786541015912,
45.495190862899364
],
[
-73.577617016117856,
45.495445076029839
],
[
-73.577546091624328,
45.495517669656074
],
[
-73.57763021606263,
45.495558325973803
],
[
-73.577714340621938,
45.495598982229176
],
[
-73.577712104671733,
45.495601273854334
],
[
-73.577709868721371,
45.495603565479428
],
[
-73.578004398472899,
45.49574590907234
],
[
-73.578007567133241,
45.495742667468747
],
[
-73.578017041689648,
45.495747250204211
],
[
-73.578002412186507,
45.495762215608373
],
[
-73.578330770393634,
45.495920903418444
],
[
-73.578336762732036,
45.495914780367642
],
[
-73.578314727876958,
45.495904132321797
],
[
-73.578326009792079,
45.49589257958354
],
[
-73.578428233148927,
45.495941982883387
]
]
]
]
},
"properties":{
"OBJECTID_12":159,
"gml_id":"1066157",
"gml_parent":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_ta":"http://www.opengis.net/citygml/building/2.0",
"citygml_fe":"cityObjectMember",
"citygml__1":" ",
"citygml__2":" ",
"gml_descri":" ",
"gml_name":" ",
"citygml_cr":" ",
"citygml_te":" ",
"externalRe":" ",
"external_1":" ",
"external_2":" ",
"citygml_ge":" ",
"citygml_re":" ",
"citygml__3":" ",
"citygml_ap":" ",
"citygml_cl":" ",
"citygml__4":" ",
"citygml_fu":" ",
"citygml__5":" ",
"citygml_us":" ",
"citygml__6":" ",
"citygml_ye":" ",
"citygml__7":" ",
"citygml_ro":" ",
"citygml__8":" ",
"citygml_me":84.731999999999999,
"citygml__9":"#m",
"citygml_st":" ",
"citygml_10":" ",
"citygml_11":" ",
"citygml_12":" ",
"citygml_13":" ",
"citygml_14":" ",
"citygml_ou":" ",
"citygml_in":" ",
"citygml_bo":" ",
"citygml_le":" ",
"citygml_15":" ",
"citygml_co":" ",
"citygml_ad":" ",
"Volume":"204394.697",
"parcelle":" ",
"OBJECTID":7583,
"gml_id_1":"722b1b20-dfce-4154-a8e6-569f8188f693",
"gml_pare_1":"1066157",
"citygml_16":"http://www.opengis.net/citygml/building/2.0",
"citygml_17":"boundedBy",
"citygml_18":" ",
"citygml_19":" ",
"gml_desc_1":" ",
"gml_name_1":" ",
"citygml_20":" ",
"citygml_21":" ",
"external_3":" ",
"external_4":" ",
"external_5":" ",
"citygml_22":" ",
"citygml_23":" ",
"citygml_24":" ",
"citygml_25":" ",
"citygml_26":" ",
"citygml_op":" ",
"Area":"3600.391",
"FID_":0,
"Join_Count":2,
"TARGET_FID":7588,
"gml_id_12":"1066157",
"gml_pare_2":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_27":"http://www.opengis.net/citygml/building/2.0",
"citygml_28":"cityObjectMember",
"citygml_29":" ",
"citygml_30":" ",
"gml_desc_2":" ",
"gml_name_2":" ",
"citygml_31":" ",
"citygml_32":" ",
"external_6":" ",
"external_7":" ",
"external_8":" ",
"citygml_33":" ",
"citygml_34":" ",
"citygml_35":" ",
"citygml_36":" ",
"citygml_37":" ",
"citygml_38":" ",
"citygml_39":" ",
"citygml_40":" ",
"citygml_41":" ",
"citygml_42":" ",
"citygml_43":" ",
"citygml_44":" ",
"citygml_45":" ",
"citygml_46":" ",
"citygml_47":84.731999999999999,
"citygml_48":"#m",
"citygml_49":" ",
"citygml_50":" ",
"citygml_51":" ",
"citygml_52":" ",
"citygml_53":" ",
"citygml_54":" ",
"citygml_55":" ",
"citygml_56":" ",
"citygml_57":" ",
"citygml_58":" ",
"citygml_59":" ",
"citygml_60":" ",
"citygml_61":" ",
"Volume_1":"204394.697",
"Field":0,
"Field1":0,
"OBJECTID_1":7583,
"gml_id_12_":"722b1b20-dfce-4154-a8e6-569f8188f693",
"gml_pare_3":"1066157",
"citygml_62":"http://www.opengis.net/citygml/building/2.0",
"citygml_63":"boundedBy",
"citygml_64":" ",
"citygml_65":" ",
"gml_desc_3":" ",
"gml_name_3":" ",
"citygml_66":" ",
"citygml_67":" ",
"external_9":" ",
"externa_10":" ",
"externa_11":" ",
"citygml_68":" ",
"citygml_69":" ",
"citygml_70":" ",
"citygml_71":" ",
"citygml_72":" ",
"citygml_73":" ",
"Area_1":"3600.391",
"cityGML_hi":0,
"Z_Min":41.366500000000002,
"Z_Max":126.099,
"Shape_Leng":352.31158223,
"ID_UEV":"01111020",
"CIVIQUE_DE":" 1515",
"CIVIQUE_FI":" 1515",
"NOM_RUE":"rue Sainte-Catherine Ouest (MTL+WMT)",
"MUNICIPALI":"50",
"ETAGE_HORS":17,
"NOMBRE_LOG":1,
"ANNEE_CONS":2005,
"CODE_UTILI":"6821",
"LIBELLE_UT":"Université",
"CATEGORIE_":"Régulier",
"MATRICULE8":"9839-75-0526-8-000-0000",
"SUPERFICIE":5949,
"SUPERFIC_1":259,
"NO_ARROND_":"REM19",
"Shape_Le_1":0.0037693215640499998,
"Shape_Ar_1":6.8474298198599997e-07,
"Z_Min_1":null,
"Z_Max_1":null,
"Shape_Length":352.31158223020242,
"Shape_Area":3597.4347830048478
}
}
]}

View File

@ -0,0 +1,209 @@
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id":164,
"geometry":{
"type":"Polygon",
"coordinates":[
[
[
-73.577465563026294,
45.495808553995417
],
[
-73.577627737571262,
45.49588695081647
],
[
-73.577789912566104,
45.4959653474059
],
[
-73.577897155727669,
45.495855628290393
],
[
-73.578004398472899,
45.49574590907234
],
[
-73.577709868721371,
45.495603565479428
],
[
-73.577680024034251,
45.495589134278653
],
[
-73.577465563026294,
45.495808553995417
]
]
]
},
"properties":{
"OBJECTID_12":164,
"gml_id":"1066826",
"gml_parent":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_ta":"http://www.opengis.net/citygml/building/2.0",
"citygml_fe":"cityObjectMember",
"citygml__1":" ",
"citygml__2":" ",
"gml_descri":" ",
"gml_name":" ",
"citygml_cr":" ",
"citygml_te":" ",
"externalRe":" ",
"external_1":" ",
"external_2":" ",
"citygml_ge":" ",
"citygml_re":" ",
"citygml__3":" ",
"citygml_ap":" ",
"citygml_cl":" ",
"citygml__4":" ",
"citygml_fu":" ",
"citygml__5":" ",
"citygml_us":" ",
"citygml__6":" ",
"citygml_ye":" ",
"citygml__7":" ",
"citygml_ro":" ",
"citygml__8":" ",
"citygml_me":65.929000000000002,
"citygml__9":"#m",
"citygml_st":" ",
"citygml_10":" ",
"citygml_11":" ",
"citygml_12":" ",
"citygml_13":" ",
"citygml_14":" ",
"citygml_ou":" ",
"citygml_in":" ",
"citygml_bo":" ",
"citygml_le":" ",
"citygml_15":" ",
"citygml_co":" ",
"citygml_ad":" ",
"Volume":"52877.804",
"parcelle":" ",
"OBJECTID":7589,
"gml_id_1":"46c9507d-33c9-40e9-9bda-00ad6fa8cd8f",
"gml_pare_1":"1066826",
"citygml_16":"http://www.opengis.net/citygml/building/2.0",
"citygml_17":"boundedBy",
"citygml_18":" ",
"citygml_19":" ",
"gml_desc_1":" ",
"gml_name_1":" ",
"citygml_20":" ",
"citygml_21":" ",
"external_3":" ",
"external_4":" ",
"external_5":" ",
"citygml_22":" ",
"citygml_23":" ",
"citygml_24":" ",
"citygml_25":" ",
"citygml_26":" ",
"citygml_op":" ",
"Area":"911.899",
"FID_":0,
"Join_Count":1,
"TARGET_FID":7594,
"gml_id_12":"1066826",
"gml_pare_2":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_27":"http://www.opengis.net/citygml/building/2.0",
"citygml_28":"cityObjectMember",
"citygml_29":" ",
"citygml_30":" ",
"gml_desc_2":" ",
"gml_name_2":" ",
"citygml_31":" ",
"citygml_32":" ",
"external_6":" ",
"external_7":" ",
"external_8":" ",
"citygml_33":" ",
"citygml_34":" ",
"citygml_35":" ",
"citygml_36":" ",
"citygml_37":" ",
"citygml_38":" ",
"citygml_39":" ",
"citygml_40":" ",
"citygml_41":" ",
"citygml_42":" ",
"citygml_43":" ",
"citygml_44":" ",
"citygml_45":" ",
"citygml_46":" ",
"citygml_47":65.929000000000002,
"citygml_48":"#m",
"citygml_49":" ",
"citygml_50":" ",
"citygml_51":" ",
"citygml_52":" ",
"citygml_53":" ",
"citygml_54":" ",
"citygml_55":" ",
"citygml_56":" ",
"citygml_57":" ",
"citygml_58":" ",
"citygml_59":" ",
"citygml_60":" ",
"citygml_61":" ",
"Volume_1":"52877.804",
"Field":0,
"Field1":0,
"OBJECTID_1":7589,
"gml_id_12_":"46c9507d-33c9-40e9-9bda-00ad6fa8cd8f",
"gml_pare_3":"1066826",
"citygml_62":"http://www.opengis.net/citygml/building/2.0",
"citygml_63":"boundedBy",
"citygml_64":" ",
"citygml_65":" ",
"gml_desc_3":" ",
"gml_name_3":" ",
"citygml_66":" ",
"citygml_67":" ",
"external_9":" ",
"externa_10":" ",
"externa_11":" ",
"citygml_68":" ",
"citygml_69":" ",
"citygml_70":" ",
"citygml_71":" ",
"citygml_72":" ",
"citygml_73":" ",
"Area_1":"911.899",
"cityGML_hi":0,
"Z_Min":41.631399999999999,
"Z_Max":107.56,
"Shape_Leng":120.703852102,
"ID_UEV":"01111020",
"CIVIQUE_DE":" 1515",
"CIVIQUE_FI":" 1515",
"NOM_RUE":"rue Sainte-Catherine Ouest (MTL+WMT)",
"MUNICIPALI":"50",
"ETAGE_HORS":17,
"NOMBRE_LOG":1,
"ANNEE_CONS":2005,
"CODE_UTILI":"6821",
"LIBELLE_UT":"Université",
"CATEGORIE_":"Régulier",
"MATRICULE8":"9839-75-0526-8-000-0000",
"SUPERFICIE":5949,
"SUPERFIC_1":259,
"NO_ARROND_":"REM19",
"Shape_Le_1":0.0037693215640499998,
"Shape_Ar_1":6.8474298198599997e-07,
"Z_Min_1":null,
"Z_Max_1":null,
"Shape_Length":120.70385210151841,
"Shape_Area":910.23684745179321
}
}
]}

View File

@ -0,0 +1,751 @@
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id":71,
"geometry":{
"type":"MultiPolygon",
"coordinates":[
[
[
[
-73.577175184964275,
45.493009748049133
],
[
-73.577175709879739,
45.493010004150236
],
[
-73.577176234795175,
45.493010260251353
],
[
-73.577180541619128,
45.493012329683943
],
[
-73.57718401883858,
45.493014007344591
],
[
-73.577185017447064,
45.493014486287095
],
[
-73.57718589443131,
45.493014907721673
],
[
-73.57718677141429,
45.493015328256433
],
[
-73.577189129927973,
45.493012904280477
],
[
-73.577191795074896,
45.493010166051512
],
[
-73.57718903993181,
45.493008838842606
],
[
-73.57718557167837,
45.49300716837481
],
[
-73.577181255888817,
45.49300509174968
],
[
-73.577180204793308,
45.493004590346501
],
[
-73.577175184964275,
45.493009748049133
]
]
],
[
[
[
-73.577161621930131,
45.49300707387485
],
[
-73.57716126163794,
45.493007444854243
],
[
-73.577158338413994,
45.493010453210324
],
[
-73.577158245146066,
45.493010548656898
],
[
-73.577158153157541,
45.493010644102561
],
[
-73.577155935178141,
45.493012920408361
],
[
-73.577154054500497,
45.493014854545287
],
[
-73.577157722475633,
45.493016621162525
],
[
-73.577161391729192,
45.493018386878951
],
[
-73.577162330787303,
45.493017418911435
],
[
-73.5771632698454,
45.493016450943962
],
[
-73.577165494226676,
45.493014178233089
],
[
-73.577165684595926,
45.493013983737988
],
[
-73.57716714748787,
45.493012480008922
],
[
-73.577168610379744,
45.493010976279884
],
[
-73.577168968115487,
45.493010607101823
],
[
-73.577169325851216,
45.493010237923791
],
[
-73.577165654036648,
45.493008470409642
],
[
-73.577161983502947,
45.493006703794386
],
[
-73.577161621930131,
45.49300707387485
]
]
],
[
[
[
-73.577186751468034,
45.49301945855742
],
[
-73.577186393732333,
45.493019827735587
],
[
-73.577183467949027,
45.493022835194147
],
[
-73.577182260574006,
45.493024068797311
],
[
-73.577181053198899,
45.493025302400483
],
[
-73.577180114140987,
45.493026270368098
],
[
-73.577179175083018,
45.493027238335756
],
[
-73.577186512314881,
45.493030770667808
],
[
-73.577188399384184,
45.493028832926697
],
[
-73.577190803899896,
45.49302636662695
],
[
-73.57719372968306,
45.493023359168184
],
[
-73.57719444643503,
45.493022621710921
],
[
-73.577190778458359,
45.493020855094827
],
[
-73.57718710920372,
45.493019089379374
],
[
-73.577186751468034,
45.49301945855742
]
]
],
[
[
[
-73.577158105526706,
45.493027294862564
],
[
-73.577158630437324,
45.493027547364392
],
[
-73.577159154067289,
45.493027798967226
],
[
-73.577163468582043,
45.493029878293505
],
[
-73.577166936833777,
45.493031546962328
],
[
-73.577168313129235,
45.493032212817511
],
[
-73.577169689423513,
45.493032877772869
],
[
-73.577172765980194,
45.493029723538051
],
[
-73.577174723326266,
45.493027718261317
],
[
-73.577173195960071,
45.493026980520661
],
[
-73.577172583988087,
45.493026683985356
],
[
-73.577171970737936,
45.493026388350778
],
[
-73.57717023085408,
45.493025553570391
],
[
-73.577168489690877,
45.493024718790927
],
[
-73.5771663324348,
45.493023680027704
],
[
-73.577164173899348,
45.493022641265334
],
[
-73.577163648989981,
45.493022389663381
],
[
-73.577163124080599,
45.493022138061441
],
[
-73.577158105526706,
45.493027294862564
]
]
],
[
[
[
-73.576295787761836,
45.493913665926286
],
[
-73.576296837589425,
45.493914169138101
],
[
-73.576301039479546,
45.493916197280711
],
[
-73.576302830589938,
45.49391705723562
],
[
-73.57630462169918,
45.493917916290606
],
[
-73.576305247758725,
45.493918219120054
],
[
-73.57630587381702,
45.493918521049629
],
[
-73.57630737431063,
45.493919246221878
],
[
-73.576309884937643,
45.493916661990525
],
[
-73.576312395564457,
45.493914077759158
],
[
-73.576311646601368,
45.493913718321629
],
[
-73.57631089891899,
45.493913359783129
],
[
-73.576309642965299,
45.493912756826411
],
[
-73.576307858246111,
45.493911892368182
],
[
-73.576306072248741,
45.493911028810601
],
[
-73.576303966191389,
45.493910018792064
],
[
-73.576301858855928,
45.493909009674262
],
[
-73.576301333936073,
45.493908753569144
],
[
-73.576300809016217,
45.493908497464098
],
[
-73.576295787761836,
45.493913665926286
]
]
],
[
[
[
-73.576281868077018,
45.493911355423414
],
[
-73.576278944759551,
45.493914363756595
],
[
-73.576278760774173,
45.49391455284681
],
[
-73.576276536337616,
45.493916837238075
],
[
-73.576274654320343,
45.493918771361088
],
[
-73.57628199417168,
45.493922304648777
],
[
-73.57628293325989,
45.493921336688672
],
[
-73.576283872348057,
45.493920368728524
],
[
-73.576286287163398,
45.493917892543038
],
[
-73.576289213052945,
45.493914894106311
],
[
-73.576289570800171,
45.493914524931085
],
[
-73.576289928547396,
45.493914155755824
],
[
-73.576286259255554,
45.493912384612671
],
[
-73.576282589965118,
45.493910614369184
],
[
-73.576281868077018,
45.493911355423414
]
]
],
[
[
[
-73.576307347890392,
45.493923367527955
],
[
-73.576306983746036,
45.493923736707529
],
[
-73.576304085996327,
45.493926728826999
],
[
-73.576302870921879,
45.493927974123842
],
[
-73.576301655848624,
45.493929220320432
],
[
-73.576300716760628,
45.493930188280771
],
[
-73.57629977767256,
45.49393115624099
],
[
-73.576307112405672,
45.493934686830961
],
[
-73.576308055330799,
45.493933717968225
],
[
-73.576308998255868,
45.493932749105475
],
[
-73.576310210772562,
45.493931504710126
],
[
-73.57631142200978,
45.493930260315651
],
[
-73.576314332565914,
45.493927277185904
],
[
-73.576315046779513,
45.493926537936289
],
[
-73.576307712034833,
45.493922998348388
],
[
-73.576307347890392,
45.493923367527955
]
]
],
[
[
[
-73.576281214567445,
45.493928627477864
],
[
-73.57627870393371,
45.493931208109188
],
[
-73.576279757605903,
45.493931715817787
],
[
-73.57628396717584,
45.493933745755605
],
[
-73.576287542993938,
45.493935461170913
],
[
-73.576288916739799,
45.493936125238591
],
[
-73.576290290484408,
45.493936788406444
],
[
-73.576295325825015,
45.493931627133833
],
[
-73.576292573225402,
45.49393030620076
],
[
-73.576290782108643,
45.493929441746488
],
[
-73.576288990993191,
45.49392857819204
],
[
-73.576286883649999,
45.493927563674859
],
[
-73.576284776308086,
45.493926550057552
],
[
-73.57628425139427,
45.493926298451555
],
[
-73.576283726480384,
45.493926046845594
],
[
-73.576281214567445,
45.493928627477864
]
]
]
]
},
"properties":{
"OBJECTID_12":71,
"gml_id":"Groupe9998743",
"gml_parent":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_ta":"http://www.opengis.net/citygml/building/2.0",
"citygml_fe":"cityObjectMember",
"citygml__1":" ",
"citygml__2":" ",
"gml_descri":" ",
"gml_name":" ",
"citygml_cr":" ",
"citygml_te":" ",
"externalRe":" ",
"external_1":" ",
"external_2":" ",
"citygml_ge":" ",
"citygml_re":" ",
"citygml__3":" ",
"citygml_ap":" ",
"citygml_cl":" ",
"citygml__4":" ",
"citygml_fu":" ",
"citygml__5":" ",
"citygml_us":" ",
"citygml__6":" ",
"citygml_ye":" ",
"citygml__7":" ",
"citygml_ro":" ",
"citygml__8":" ",
"citygml_me":33.756,
"citygml__9":"#m",
"citygml_st":" ",
"citygml_10":" ",
"citygml_11":" ",
"citygml_12":" ",
"citygml_13":" ",
"citygml_14":" ",
"citygml_ou":" ",
"citygml_in":" ",
"citygml_bo":" ",
"citygml_le":" ",
"citygml_15":" ",
"citygml_co":" ",
"citygml_ad":" ",
"Volume":"198.772",
"parcelle":" ",
"OBJECTID":7095,
"gml_id_1":"8c3496a9-534a-49c2-80ee-8ef0651c1675",
"gml_pare_1":"Groupe9998743",
"citygml_16":"http://www.opengis.net/citygml/building/2.0",
"citygml_17":"boundedBy",
"citygml_18":" ",
"citygml_19":" ",
"gml_desc_1":" ",
"gml_name_1":" ",
"citygml_20":" ",
"citygml_21":" ",
"external_3":" ",
"external_4":" ",
"external_5":" ",
"citygml_22":" ",
"citygml_23":" ",
"citygml_24":" ",
"citygml_25":" ",
"citygml_26":" ",
"citygml_op":" ",
"Area":"11.527",
"FID_":0,
"Join_Count":2,
"TARGET_FID":7100,
"gml_id_12":"Groupe9998743",
"gml_pare_2":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_27":"http://www.opengis.net/citygml/building/2.0",
"citygml_28":"cityObjectMember",
"citygml_29":" ",
"citygml_30":" ",
"gml_desc_2":" ",
"gml_name_2":" ",
"citygml_31":" ",
"citygml_32":" ",
"external_6":" ",
"external_7":" ",
"external_8":" ",
"citygml_33":" ",
"citygml_34":" ",
"citygml_35":" ",
"citygml_36":" ",
"citygml_37":" ",
"citygml_38":" ",
"citygml_39":" ",
"citygml_40":" ",
"citygml_41":" ",
"citygml_42":" ",
"citygml_43":" ",
"citygml_44":" ",
"citygml_45":" ",
"citygml_46":" ",
"citygml_47":33.756,
"citygml_48":"#m",
"citygml_49":" ",
"citygml_50":" ",
"citygml_51":" ",
"citygml_52":" ",
"citygml_53":" ",
"citygml_54":" ",
"citygml_55":" ",
"citygml_56":" ",
"citygml_57":" ",
"citygml_58":" ",
"citygml_59":" ",
"citygml_60":" ",
"citygml_61":" ",
"Volume_1":"198.772",
"Field":0,
"Field1":0,
"OBJECTID_1":7095,
"gml_id_12_":"8c3496a9-534a-49c2-80ee-8ef0651c1675",
"gml_pare_3":"Groupe9998743",
"citygml_62":"http://www.opengis.net/citygml/building/2.0",
"citygml_63":"boundedBy",
"citygml_64":" ",
"citygml_65":" ",
"gml_desc_3":" ",
"gml_name_3":" ",
"citygml_66":" ",
"citygml_67":" ",
"external_9":" ",
"externa_10":" ",
"externa_11":" ",
"citygml_68":" ",
"citygml_69":" ",
"citygml_70":" ",
"citygml_71":" ",
"citygml_72":" ",
"citygml_73":" ",
"Area_1":"11.527",
"cityGML_hi":0,
"Z_Min":39.7303,
"Z_Max":72.902000000000001,
"Shape_Leng":28.686961738400001,
"ID_UEV":"05221230",
"CIVIQUE_DE":" 1190",
"CIVIQUE_FI":" 1200",
"NOM_RUE":"rue Guy (MTL)",
"MUNICIPALI":"50",
"ETAGE_HORS":3,
"NOMBRE_LOG":3,
"ANNEE_CONS":2012,
"CODE_UTILI":"6243",
"LIBELLE_UT":"Mausolée",
"CATEGORIE_":"Régulier",
"MATRICULE8":"9839-72-8598-6-000-0000",
"SUPERFICIE":511,
"SUPERFIC_1":165,
"NO_ARROND_":"REM19",
"Shape_Le_1":0.0080267092725800002,
"Shape_Ar_1":3.7307864896800001e-06,
"Z_Min_1":null,
"Z_Max_1":null,
"Shape_Length":28.686961738422657,
"Shape_Area":6.1056950551354507
}
}
]}

View File

@ -0,0 +1,257 @@
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id":80,
"geometry":{
"type":"Polygon",
"coordinates":[
[
[
-73.577708862173409,
45.496062468779222
],
[
-73.578002412186507,
45.495762215608373
],
[
-73.578017041689648,
45.495747250204211
],
[
-73.578007567133241,
45.495742667468747
],
[
-73.578004398472899,
45.49574590907234
],
[
-73.577897155727669,
45.495855628290393
],
[
-73.577789912566104,
45.4959653474059
],
[
-73.577627737571262,
45.49588695081647
],
[
-73.577465563026294,
45.495808553995417
],
[
-73.577680024034251,
45.495589134278653
],
[
-73.577709868721371,
45.495603565479428
],
[
-73.577712104671733,
45.495601273854334
],
[
-73.577714340621938,
45.495598982229176
],
[
-73.57763021606263,
45.495558325973803
],
[
-73.577546091624328,
45.495517669656074
],
[
-73.57754291633033,
45.49551608808553
],
[
-73.577229611850498,
45.49583656395032
],
[
-73.577608042788611,
45.496019551760313
],
[
-73.577611901425541,
45.496015589823621
],
[
-73.577708862173409,
45.496062468779222
]
]
]
},
"properties":{
"OBJECTID_12":80,
"gml_id":"1066177",
"gml_parent":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_ta":"http://www.opengis.net/citygml/building/2.0",
"citygml_fe":"cityObjectMember",
"citygml__1":" ",
"citygml__2":" ",
"gml_descri":" ",
"gml_name":" ",
"citygml_cr":" ",
"citygml_te":" ",
"externalRe":" ",
"external_1":" ",
"external_2":" ",
"citygml_ge":" ",
"citygml_re":" ",
"citygml__3":" ",
"citygml_ap":" ",
"citygml_cl":" ",
"citygml__4":" ",
"citygml_fu":" ",
"citygml__5":" ",
"citygml_us":" ",
"citygml__6":" ",
"citygml_ye":" ",
"citygml__7":" ",
"citygml_ro":" ",
"citygml__8":" ",
"citygml_me":46.639000000000003,
"citygml__9":"#m",
"citygml_st":" ",
"citygml_10":" ",
"citygml_11":" ",
"citygml_12":" ",
"citygml_13":" ",
"citygml_14":" ",
"citygml_ou":" ",
"citygml_in":" ",
"citygml_bo":" ",
"citygml_le":" ",
"citygml_15":" ",
"citygml_co":" ",
"citygml_ad":" ",
"Volume":"47396.897",
"parcelle":" ",
"OBJECTID":7117,
"gml_id_1":"d2de57c7-c360-4f28-9695-dc1be766360b",
"gml_pare_1":"1066177",
"citygml_16":"http://www.opengis.net/citygml/building/2.0",
"citygml_17":"boundedBy",
"citygml_18":" ",
"citygml_19":" ",
"gml_desc_1":" ",
"gml_name_1":" ",
"citygml_20":" ",
"citygml_21":" ",
"external_3":" ",
"external_4":" ",
"external_5":" ",
"citygml_22":" ",
"citygml_23":" ",
"citygml_24":" ",
"citygml_25":" ",
"citygml_26":" ",
"citygml_op":" ",
"Area":"1016.244",
"FID_":0,
"Join_Count":1,
"TARGET_FID":7122,
"gml_id_12":"1066177",
"gml_pare_2":"fme-gen-57964590-baa9-48a7-99b0-fa11ca012d7c",
"citygml_27":"http://www.opengis.net/citygml/building/2.0",
"citygml_28":"cityObjectMember",
"citygml_29":" ",
"citygml_30":" ",
"gml_desc_2":" ",
"gml_name_2":" ",
"citygml_31":" ",
"citygml_32":" ",
"external_6":" ",
"external_7":" ",
"external_8":" ",
"citygml_33":" ",
"citygml_34":" ",
"citygml_35":" ",
"citygml_36":" ",
"citygml_37":" ",
"citygml_38":" ",
"citygml_39":" ",
"citygml_40":" ",
"citygml_41":" ",
"citygml_42":" ",
"citygml_43":" ",
"citygml_44":" ",
"citygml_45":" ",
"citygml_46":" ",
"citygml_47":46.639000000000003,
"citygml_48":"#m",
"citygml_49":" ",
"citygml_50":" ",
"citygml_51":" ",
"citygml_52":" ",
"citygml_53":" ",
"citygml_54":" ",
"citygml_55":" ",
"citygml_56":" ",
"citygml_57":" ",
"citygml_58":" ",
"citygml_59":" ",
"citygml_60":" ",
"citygml_61":" ",
"Volume_1":"47396.897",
"Field":0,
"Field1":0,
"OBJECTID_1":7117,
"gml_id_12_":"d2de57c7-c360-4f28-9695-dc1be766360b",
"gml_pare_3":"1066177",
"citygml_62":"http://www.opengis.net/citygml/building/2.0",
"citygml_63":"boundedBy",
"citygml_64":" ",
"citygml_65":" ",
"gml_desc_3":" ",
"gml_name_3":" ",
"citygml_66":" ",
"citygml_67":" ",
"external_9":" ",
"externa_10":" ",
"externa_11":" ",
"citygml_68":" ",
"citygml_69":" ",
"citygml_70":" ",
"citygml_71":" ",
"citygml_72":" ",
"citygml_73":" ",
"Area_1":"1016.244",
"cityGML_hi":0,
"Z_Min":41.489699999999999,
"Z_Max":88.129000000000005,
"Shape_Leng":242.34118937100001,
"ID_UEV":"01111020",
"CIVIQUE_DE":" 1515",
"CIVIQUE_FI":" 1515",
"NOM_RUE":"rue Sainte-Catherine Ouest (MTL+WMT)",
"MUNICIPALI":"50",
"ETAGE_HORS":17,
"NOMBRE_LOG":1,
"ANNEE_CONS":2005,
"CODE_UTILI":"6821",
"LIBELLE_UT":"Université",
"CATEGORIE_":"Régulier",
"MATRICULE8":"9839-75-0526-8-000-0000",
"SUPERFICIE":5949,
"SUPERFIC_1":259,
"NO_ARROND_":"REM19",
"Shape_Le_1":0.0037693215640499998,
"Shape_Ar_1":6.8474298198599997e-07,
"Z_Min_1":null,
"Z_Max_1":null,
"Shape_Length":242.34118937110796,
"Shape_Area":1016.243978548841
}
}
]}

File diff suppressed because it is too large Load Diff