Overall code quality review for the city_model_structure

This commit is contained in:
Guille Gutierrez 2021-08-26 09:19:38 -04:00
parent 61447e4d99
commit 338adb399e
28 changed files with 107 additions and 436 deletions

View File

@ -5,9 +5,8 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
Contributor Milad milad.aghamohamadnia@concordia.ca
"""
import uuid
from city_model_structure.attributes.node import Node
from typing import List
from city_model_structure.attributes.node import Node
class Edge:

View File

@ -6,9 +6,8 @@ Contributor Milad milad.aghamohamadnia@concordia.ca
"""
import uuid
from city_model_structure.attributes.edge import Edge
from typing import List
from city_model_structure.attributes.edge import Edge
class Node:
@ -45,4 +44,3 @@ class Node:
Edges delimited by the node
"""
return self._edges

View File

@ -17,6 +17,9 @@ class Point:
@property
def coordinates(self):
"""
Point coordinates
"""
return self._coordinates
def distance_to_point(self, other_point):

View File

@ -4,14 +4,15 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from __future__ import annotations
from typing import List
import sys
import numpy as np
import math
from city_model_structure.attributes.point import Point
import sys
from typing import List
import numpy as np
from trimesh import Trimesh
import trimesh.intersections
from city_model_structure.attributes.point import Point
class Polygon:
@ -65,6 +66,9 @@ class Polygon:
@property
def edges(self):
"""
Polygon edges list
"""
if self._edges is None:
self._edges = []
for i in range(0, len(self.points)-1):
@ -203,7 +207,6 @@ class Polygon:
delta_normals += cross_product[j] - cross_product_next[j]
if np.abs(delta_normals) < accepted_normal_difference:
return alpha
else:
return -alpha
def triangulate(self) -> List[Polygon]:
@ -220,7 +223,7 @@ class Polygon:
points_list = self.points_list
normal = self.normal
if np.linalg.norm(normal) == 0:
sys.stderr.write(f'Not able to triangulate polygon\n')
sys.stderr.write('Not able to triangulate polygon\n')
return [self]
# are points concave or convex?
total_points_list, concave_points, convex_points = self._starting_lists(points_list, normal)
@ -233,8 +236,8 @@ class Polygon:
for i in range(0, len(concave_points)):
ear = self._triangle(points_list, total_points_list, concave_points[i])
rest_points = []
for p in total_points_list:
rest_points.append(list(self.coordinates[p]))
for points in total_points_list:
rest_points.append(list(self.coordinates[points]))
if self._is_ear(ear, rest_points):
ears.append(ear)
point_to_remove = concave_points[i]
@ -245,7 +248,8 @@ class Polygon:
for convex_point in convex_points:
if convex_point == previous_point_in_list:
concave_points, convex_points, end_loop = self._if_concave_change_status(normal, points_list,
convex_point, total_points_list,
convex_point,
total_points_list,
concave_points, convex_points,
previous_point_in_list)
if end_loop:
@ -253,7 +257,8 @@ class Polygon:
continue
if convex_point == next_point_in_list:
concave_points, convex_points, end_loop = self._if_concave_change_status(normal, points_list,
convex_point, total_points_list,
convex_point,
total_points_list,
concave_points, convex_points,
next_point_in_list)
if end_loop:
@ -261,10 +266,10 @@ class Polygon:
continue
break
if len(total_points_list) <= 3 and len(convex_points) > 0:
sys.stderr.write(f'Not able to triangulate polygon\n')
sys.stderr.write('Not able to triangulate polygon\n')
return [self]
if j >= 100:
sys.stderr.write(f'Not able to triangulate polygon\n')
sys.stderr.write('Not able to triangulate polygon\n')
return [self]
last_ear = self._triangle(points_list, total_points_list, concave_points[1])
ears.append(last_ear)
@ -446,9 +451,9 @@ class Polygon:
elif concave_points[len(concave_points) - 1] < convex_point:
concave_points.append(convex_point)
else:
for p in range(0, len(concave_points) - 1):
if concave_points[p] < convex_point < concave_points[p + 1]:
concave_points.insert(p + 1, convex_point)
for point_index in range(0, len(concave_points) - 1):
if concave_points[point_index] < convex_point < concave_points[point_index + 1]:
concave_points.insert(point_index + 1, convex_point)
convex_points.remove(convex_point)
end_loop = True
return concave_points, convex_points, end_loop
@ -539,9 +544,9 @@ class Polygon:
@staticmethod
def _edge_in_edges_list(edge, edges_list):
for ed in edges_list:
if (ed[0].distance_to_point(edge[0]) == 0 and ed[1].distance_to_point(edge[1]) == 0) or\
(ed[1].distance_to_point(edge[0]) == 0 and ed[0].distance_to_point(edge[1]) == 0):
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
@ -564,10 +569,10 @@ class Polygon:
@staticmethod
def _remove_from_list(edge, edges_list):
new_list = []
for ed in edges_list:
if not((ed[0].distance_to_point(edge[0]) == 0 and ed[1].distance_to_point(edge[1]) == 0) or
(ed[1].distance_to_point(edge[0]) == 0 and ed[0].distance_to_point(edge[1]) == 0)):
new_list.append(ed)
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

View File

@ -7,8 +7,8 @@ Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
from typing import List, Union
import sys
import numpy as np
import math
import numpy as np
from trimesh import Trimesh
from helpers.configuration_helper import ConfigurationHelper
@ -114,7 +114,7 @@ class Polyhedron:
if self._trimesh is None:
for face in self.faces:
if len(face) != 3:
sys.stderr.write(f'Not able to generate trimesh\n')
sys.stderr.write('Not able to generate trimesh\n')
return None
self._trimesh = Trimesh(vertices=self.vertices, faces=self.faces)
return self._trimesh
@ -246,4 +246,7 @@ class Polyhedron:
self.trimesh.export(full_path, 'obj')
def show(self):
"""
Auxiliary function to render the polyhedron
"""
self.trimesh.show()

View File

@ -10,6 +10,7 @@ import sys
from typing import List
import numpy as np
import math
from city_model_structure.building_demand.surface import Surface
from city_model_structure.building_demand.thermal_zone import ThermalZone
from city_model_structure.building_demand.usage_zone import UsageZone
@ -306,7 +307,7 @@ class Building(CityObject):
return [Storey('storey_0', self.surfaces, [None, None], self.volume)]
if number_of_storeys == 0:
raise Exception(f'Number of storeys cannot be 0')
raise Exception('Number of storeys cannot be 0')
storeys = []
surfaces_child_last_storey = []

View File

@ -7,7 +7,6 @@ Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.mons
from __future__ import annotations
from typing import List
import numpy as np
from city_model_structure.building_demand.surface import Surface
from city_model_structure.building_demand.thermal_boundary import ThermalBoundary
from city_model_structure.building_demand.thermal_zone import ThermalZone

View File

@ -6,8 +6,8 @@ contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from __future__ import annotations
import numpy as np
import uuid
import numpy as np
from city_model_structure.attributes.polygon import Polygon
from city_model_structure.attributes.plane import Plane
from city_model_structure.attributes.point import Point
@ -19,8 +19,7 @@ class Surface:
"""
Surface class
"""
def __init__(self, solid_polygon, perimeter_polygon, holes_polygons=None, name=None, surface_type=None, swr=None,
is_child=False):
def __init__(self, solid_polygon, perimeter_polygon, holes_polygons=None, name=None, surface_type=None, swr=None):
self._type = surface_type
self._swr = swr
self._name = name
@ -62,10 +61,16 @@ class Surface:
@property
def share_surfaces(self):
"""
Raises not implemented error
"""
raise NotImplementedError
@id.setter
def id(self, value):
"""
Surface id
"""
self._id = value
@property
@ -268,16 +273,22 @@ class Surface:
return self._inverse
def shared_surfaces(self):
"""
Raises not implemented error
"""
# todo: check https://trimsh.org/trimesh.collision.html as an option to implement this method
raise NotImplementedError
def divide(self, z):
"""
Divides a surface at Z plane
"""
# todo: recheck this method for LoD3 (windows)
origin = Point([0, 0, z])
normal = np.array([0, 0, 1])
plane = Plane(normal=normal, origin=origin)
polygon = self.perimeter_polygon
part_1, part_2, intersection = polygon.divide(plane)
surface_child = Surface(part_1, part_1, name=self.name, surface_type=self.type, is_child=True)
rest_surface = Surface(part_2, part_2, name=self.name, surface_type=self.type, is_child=True)
surface_child = Surface(part_1, part_1, name=self.name, surface_type=self.type)
rest_surface = Surface(part_2, part_2, name=self.name, surface_type=self.type)
return surface_child, rest_surface, intersection

View File

@ -7,7 +7,6 @@ Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
from typing import List, TypeVar, Union
from city_model_structure.building_demand.layer import Layer
from city_model_structure.building_demand.thermal_opening import ThermalOpening
ThermalZone = TypeVar('ThermalZone')
Polygon = TypeVar('Polygon')
Surface = TypeVar('Surface')
@ -232,7 +231,7 @@ class ThermalBoundary:
r_value = r_value + float(layer.material.conductivity) / float(layer.thickness)
self._u_value = 1.0/r_value
except TypeError:
raise Exception('Constructions layers are not initialized')
raise Exception('Constructions layers are not initialized') from TypeError
return self._u_value
@u_value.setter

View File

@ -377,4 +377,3 @@ class UsageZone:
:param value: Boolean
"""
self._is_cooled = value

View File

@ -4,9 +4,10 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from city_model_structure.city_objects_cluster import CityObjectsCluster
from typing import List, TypeVar
from city_model_structure.city_objects_cluster import CityObjectsCluster
CityObject = TypeVar('CityObject')

View File

@ -6,11 +6,12 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
from __future__ import annotations
import sys
import pickle
import math
from typing import List, Union, TypeVar
import pyproj
from pyproj import Transformer
from city_model_structure.building import Building
from city_model_structure.city_object import CityObject
from city_model_structure.city_objects_cluster import CityObjectsCluster
@ -18,7 +19,7 @@ from city_model_structure.buildings_cluster import BuildingsCluster
from city_model_structure.parts_consisting_building import PartsConsistingBuilding
from helpers.geometry_helper import GeometryHelper
from helpers.location import Location
import math
Path = TypeVar('Path')
@ -236,8 +237,8 @@ class City:
:param city_filename: city filename
:return: City
"""
with open(city_filename, 'rb') as f:
return pickle.load(f)
with open(city_filename, 'rb') as file:
return pickle.load(file)
def save(self, city_filename):
"""
@ -245,8 +246,8 @@ class City:
:param city_filename: destination city filename
:return:
"""
with open(city_filename, 'wb') as f:
pickle.dump(self, f)
with open(city_filename, 'wb') as file:
pickle.dump(self, file)
def region(self, center, radius) -> City:
"""

View File

@ -3,14 +3,16 @@ CityObject module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from city_model_structure.iot.sensor import Sensor
import math
from typing import List, Union
from city_model_structure.iot.sensor import Sensor
from city_model_structure.building_demand.surface import Surface
from city_model_structure.attributes.polyhedron import Polyhedron
from helpers.configuration_helper import ConfigurationHelper
import math
class CityObject:
"""

View File

@ -20,7 +20,7 @@ class CityObjectsCluster(ABC, CityObject):
self._city_objects = city_objects
self._sensors = []
self._lod = ''
super(ABC, self).__init__(name, self._lod, None, None)
super().__init__(name, self._lod, None, None)
@property
def name(self):
@ -32,10 +32,16 @@ class CityObjectsCluster(ABC, CityObject):
@property
def type(self):
"""
City object cluster type raises NotImplemented error
"""
raise NotImplementedError
@property
def city_objects(self):
"""
City objects raises NotImplemented error
"""
raise NotImplementedError
def add_city_object(self, city_object) -> List[CityObject]:

View File

@ -4,8 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
from city_model_structure.iot.sensor import Sensor
import pandas as pd
from city_model_structure.iot.sensor import Sensor
class ConcordiaEnergySensor(Sensor):
@ -40,4 +40,3 @@ class ConcordiaEnergySensor(Sensor):
"""
measures = self._measures.append(measures, ignore_index=True)
self._measures = measures.drop_duplicates('Date time', keep='last')

View File

@ -4,8 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from city_model_structure.iot.sensor import Sensor
import pandas as pd
from city_model_structure.iot.sensor import Sensor
class ConcordiaGasFlowSensor(Sensor):

View File

@ -4,8 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from city_model_structure.iot.sensor import Sensor
import pandas as pd
from city_model_structure.iot.sensor import Sensor
class ConcordiaTemperatureSensor(Sensor):
@ -40,4 +40,3 @@ class ConcordiaTemperatureSensor(Sensor):
"""
measures = self._measures.append(measures, ignore_index=True)
self._measures = measures.drop_duplicates('Date time', keep='last')

View File

@ -67,4 +67,7 @@ class Sensor:
@property
def measures(self):
"""
Sensor measures
"""
raise NotImplementedError

View File

@ -5,11 +5,11 @@ Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@conc
Contributor Milad milad.aghamohamadnia@concordia.ca
"""
import uuid
from typing import List
from city_model_structure.city_object import CityObject
from city_model_structure.attributes.edge import Edge
from city_model_structure.attributes.node import Node
from typing import List
class Network(CityObject):
@ -45,4 +45,7 @@ class Network(CityObject):
@property
def nodes(self) -> List[Node]:
"""
Network nodes
"""
return self._nodes

View File

@ -1,38 +0,0 @@
"""
Join Exclude module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Contributor Milad milad.aghamohamadnia@concordia.ca
"""
from typing import List, TypeVar
Node = TypeVar['Node']
# todo: check if this class makes sense????
class JoinExclude:
"""
JoinExclude class
"""
def __init__(self):
self._nodes = None
self._nodes_ids = None
@property
def nodes(self) -> List[Node]:
"""
List of nodes which are excluded from the big cluster
:return: [Node]
"""
return self._nodes
@nodes.setter
def nodes(self, value):
"""
List of nodes setter
:param value: [Node]
"""
self._nodes = value

View File

@ -1,166 +0,0 @@
"""
Road Type module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Contributor Milad milad.aghamohamadnia@concordia.ca
"""
from typing import List, TypeVar
Lane = TypeVar['Lane']
class RoadType:
"""
RoadType class
"""
def __init__(self):
self._id = None
self._allow = None
self._disallow = None
self._discard = False
self._lanes = None
self._number_lanes = None
self._priority = None
self._speed = None
self._sidewalk_width = -1
@property
def id(self):
"""
Type id
:return: str
"""
return self._id
@id.setter
def id(self, value):
"""
Type id setter
:param value: str
"""
self._id = value
@property
def allow(self) -> List[str]:
"""
List of allowed vehicle classes
:return: [str]
"""
return self._allow
@allow.setter
def allow(self, value):
"""
List of allowed vehicle classes setter
:param value: [str]
"""
self._allow = value
@property
def disallow(self) -> List[str]:
"""
List of not allowed vehicle classes
:return: [str]
"""
return self._disallow
@disallow.setter
def disallow(self, value):
"""
List of not allowed vehicle classes setter
:param value: [str]
"""
self._disallow = value
@property
def discard(self) -> bool:
"""
If "yes", edges of that type are not imported
:return: bool
"""
return self._discard
@discard.setter
def discard(self, value):
"""
Discard setter
:param value: bool
"""
self._discard = value
@property
def lanes(self) -> List[Lane]:
"""
List of default lanes on an edge
:return: List[Lane]
"""
return self._lanes
@lanes.setter
def lanes(self, value):
"""
List of default lanes on an edge setter
:param value: List[Lane]
"""
self._lanes = value
@property
def number_lanes(self):
"""
Number of default lanes on an edge
:return: int
"""
if self._number_lanes is None:
self._number_lanes = len(self.lanes)
return self._number_lanes
@property
def priority(self):
"""
A number, which determines the priority between different road types.
It starts with one; higher numbers represent more important roads.
:return: int
"""
return self._priority
@priority.setter
def priority(self, value):
"""
Priority setter
:param value: int
"""
self._priority = value
@property
def speed(self):
"""
The default (implicit) speed limit in m/s
:return: float
"""
return self._speed
@speed.setter
def speed(self, value):
"""
The default (implicit) speed limit in m/s setter
:param value: float
"""
self._speed = value
@property
def sidewalk_width(self):
"""
The default width for added sidewalks in m
:return: float
"""
return self._sidewalk_width
@sidewalk_width.setter
def sidewalk_width(self, value):
"""
The default width for added sidewalks in m setter
:param value: float
"""
self._sidewalk_width = value

View File

@ -1,36 +0,0 @@
"""
Roundabout module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Contributor Milad milad.aghamohamadnia@concordia.ca
Contributor Guille guille.gutierrezmorote@concordia.ca
"""
from city_model_structure.transport.traffic_node import TrafficNode
from city_model_structure.attributes.edge import Edge
from typing import List
class Roundabout(TrafficNode):
"""
Roundabout class
"""
def __init__(self, name, coordinates, edges=None):
super().__init__(name, coordinates, edges)
@property
def edges(self) -> List[Edge]:
"""
Edges that conform the roundabout
:return: [Edge]
"""
return self._edges
@edges.setter
def edges(self, value):
"""
Edges that conform the roundabout setter
:param value: [Edge]
"""
self._edges = value

View File

@ -1,122 +0,0 @@
"""
Split module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Contributor Milad milad.aghamohamadnia@concordia.ca
"""
from typing import List, TypeVar
Lane = TypeVar['Lane']
Edge = TypeVar['Edge']
class Split:
"""
Split class
"""
def __init__(self):
self._position = None
self._lanes = None
self._speed = None
self._id = None
self._edge_before = None
self._edge_after = None
@property
def position(self):
"""
The position along the edge at which the split shall be done (in m);
if a negative position is given, the split is inserted counting from the end of the edge
:return: float
"""
return self._position
@position.setter
def position(self, value):
"""
Position setter
:param value: float
"""
self._position = value
@property
def lanes(self) -> List[Lane]:
"""
List of lanes after the split
:return: List[Lane]
"""
return self._lanes
@lanes.setter
def lanes(self, value):
"""
List of lanes setter
:param value: List[Lane]
"""
self._lanes = value
@property
def speed(self):
"""
Speed limit after the split in m/s
:return: float
"""
return self._speed
@speed.setter
def speed(self, value):
"""
Speed limit in m/s setter
:param value: float
"""
self._speed = value
@property
def id(self):
"""
Type id
:return: str
"""
return self._id
@id.setter
def id(self, value):
"""
Type id setter
:param value: str
"""
self._id = value
@property
def edge_before(self) -> Edge:
"""
Edge before the split
:return: Edge
"""
return self._edge_before
@edge_before.setter
def edge_before(self, value):
"""
edge_before setter
:param value: Edge
"""
self._edge_before = value
@property
def edge_after(self) -> Edge:
"""
Edge after the split
:return: Edge
"""
return self._edge_after
@edge_after.setter
def edge_after(self, value):
"""
edge_after setter
:param value: Edge
"""
self._edge_after = value

View File

@ -6,9 +6,6 @@ Contributor Milad milad.aghamohamadnia@concordia.ca
Contributor Guille guille.gutierrezmorote@concordia.ca
"""
from typing import List
from city_model_structure.attributes.node import Node
from city_model_structure.transport.traffic_node import TrafficNode

View File

@ -25,10 +25,16 @@ class TrafficLight(TrafficNode):
@property
def right_on_red(self):
"""
Return if is possible to turn right if the traffic light is red
"""
return self._right_on_red
@right_on_red.setter
def right_on_red(self, value):
"""
Set if is possible to turn right if the traffic light is red
"""
self._right_on_red = value
@property

View File

@ -15,3 +15,11 @@ class TrafficNetwork(Network):
"""
def __init__(self, name, edges=None, nodes=None):
super().__init__(name, edges, nodes)
self._type = "TrafficNetwork"
@property
def type(self):
"""
Network type
"""
return self._type

View File

@ -82,12 +82,3 @@ class TrafficNode(Node):
Set the connections for this node
"""
self._connections = value
"""
Type
enum ( "priority", "traffic_light", "right_before_left", "unregulated", "priority_stop", "traffic_light_unregulated", "allway_stop", "rail_signal", "zipper", "traffic_light_right_on_red", "rail_crossing")
:return: enum
"""