diff --git a/city_model_structure/city_object.py b/city_model_structure/city_object.py index a139872b..5d368ff1 100644 --- a/city_model_structure/city_object.py +++ b/city_model_structure/city_object.py @@ -49,8 +49,8 @@ class CityObject: # for lod under 4 is just one thermal zone self._thermal_zones.append(ThermalZone(self.surfaces)) - for t in self._thermal_zones: - t.bounded = [ThermalBoundary(s, [t]) for s in t.surfaces] + for t_zones in self._thermal_zones: + t_zones.bounded = [ThermalBoundary(s, [t_zones]) for s in t_zones.surfaces] surface_id = 0 for surface in self._surfaces: surface.lower_corner = self._lower_corner diff --git a/city_model_structure/polyhedron.py b/city_model_structure/polyhedron.py index 358411f1..9fdaa2cd 100644 --- a/city_model_structure/polyhedron.py +++ b/city_model_structure/polyhedron.py @@ -24,7 +24,7 @@ class Polyhedron: def _position_of(self, point): vertices = self.vertices - for i in range(len(vertices)): + for i in enumerate(vertices): if self._geometry.almost_equal(vertices[i], point): return i return -1 @@ -37,16 +37,16 @@ class Polyhedron: """ if self._vertices is None: vertices, self._vertices = [], [] - [vertices.extend(s.points) for s in self._surfaces] - for v1 in vertices: + _ = [vertices.extend(s.points) for s in self._surfaces] + for vertex_1 in vertices: found = False - for v2 in self._vertices: + for vertex_2 in self._vertices: found = False - if self._geometry.almost_equal(v1, v2): + if self._geometry.almost_equal(vertex_1, vertex_2): found = True break if not found: - self._vertices.append(v1) + self._vertices.append(vertex_1) self._vertices = np.asarray(self._vertices) return self._vertices @@ -58,11 +58,11 @@ class Polyhedron: """ if self._faces is None: self._faces = [] - for s in self._surfaces: + for surface in self._surfaces: face = [] - points = s.points - for p in points: - face.append(self._position_of(p)) + points = surface.points + for point in points: + face.append(self._position_of(point)) self._faces.append(face) self._faces = np.asarray(self._faces) return self._faces @@ -71,9 +71,9 @@ class Polyhedron: def _polyhedron_mesh(self): if self._mesh is None: self._mesh = stl.mesh.Mesh(np.zeros(self.faces.shape[0], dtype=stl.mesh.Mesh.dtype)) - for i, f in enumerate(self.faces): + for i, faces in enumerate(self.faces): for j in range(3): - self._mesh.vectors[i][j] = self.vertices[f[j], :] + self._mesh.vectors[i][j] = self.vertices[faces[j], :] return self._mesh @property @@ -83,7 +83,7 @@ class Polyhedron: :return: float """ if self._volume is None: - self._volume, cog, inertia = self._polyhedron_mesh.get_mass_properties() + self._volume, _, _ = self._polyhedron_mesh.get_mass_properties() return self._volume @property diff --git a/city_model_structure/surface.py b/city_model_structure/surface.py index 75d0c6c1..384ea78b 100644 --- a/city_model_structure/surface.py +++ b/city_model_structure/surface.py @@ -11,6 +11,9 @@ from typing import Union class Surface: + """ + Surface class + """ def __init__(self, coordinates, surface_type=None, name=None, swr='0.2', remove_last=True, is_projected=False): self._coordinates = coordinates self._type = surface_type @@ -42,25 +45,48 @@ class Surface: self._ground_coordinates = (self.min_x, self.min_y, self.min_z) def parent(self, parent, surface_id): + """ + Assign a city object as surface parent and a surface id + :param parent: CityObject + :param surface_id: str + :return: None + """ self._parent = parent self._name = str(surface_id) @property def name(self): + """ + Surface name + :return: str + """ if self._name is None: raise Exception('surface has no name') return self._name @property def swr(self): + """ + Get surface short wave reflectance + :return: float + """ return self._swr @swr.setter def swr(self, value): + """ + Set surface short wave reflectance + :param value: float + :return: None + """ self._swr = value @property def points(self) -> np.ndarray: + """ + Surface point matrix + :return: 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) @@ -83,24 +109,40 @@ class Surface: @property def min_x(self): + """ + Surface minimal x value + :return: float + """ if self._min_x is None: self._min_x = self._min_coord('x') return self._min_x @property def min_y(self): + """ + Surface minimal y value + :return: float + """ if self._min_y is None: self._min_y = self._min_coord('y') return self._min_y @property def min_z(self): + """ + Surface minimal z value + :return: float + """ if self._min_z is None: self._min_z = self._min_coord('z') return self._min_z @property def ground_points(self) -> np.ndarray: + """ + Surface grounded points matrix + :return: np.ndarray + """ if self._ground_points is None: coordinates = '' for point in self.points: @@ -116,13 +158,21 @@ class Surface: @property def points_list(self) -> np.ndarray: + """ + Surface point list + :return: 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) -> pn.Polygon: + def polygon(self) -> Union[pn.Polygon, None]: + """ + Surface polygon + :return: None or pyny3d.Polygon + """ if self._polygon is None: try: self._polygon = pn.Polygon(self.points) @@ -133,6 +183,10 @@ class Surface: @property def ground_polygon(self) -> Union[pn.Polygon, None]: + """ + Surface grounded polygon + :return: None or pyny3d.Polygon + """ if self._ground_polygon is None: try: self._ground_polygon = pn.Polygon(self.ground_points) @@ -143,6 +197,10 @@ class Surface: @property def area(self): + """ + Surface area in square meters + :return: float + """ if self._area is None: self._area = self.polygon.get_area() return self._area @@ -164,12 +222,20 @@ class Surface: @property def area_above_ground(self): + """ + Surface area above ground in square meters + :return: float + """ if self._area_above_ground is None: self._area_above_ground = self.area - self.area_below_ground return self._area_above_ground @property def area_below_ground(self): + """ + Surface area below ground in square meters + :return: float + """ if self._area_below_ground is None: self._area_below_ground = 0.0 if self._is_terrain: @@ -178,6 +244,10 @@ class Surface: @property def normal(self) -> np.ndarray: + """ + Surface normal vector + :return: np.ndarray + """ if self._normal is None: points = self.points n = np.cross(points[1] - points[0], points[2] - points[0]) @@ -186,6 +256,10 @@ class Surface: @property def azimuth(self): + """ + Surface azimuth in radians + :return: float + """ if self._azimuth is None: normal = self.normal self._azimuth = np.arctan2(normal[1], normal[0]) @@ -193,12 +267,20 @@ class Surface: @property def inclination(self): + """ + Surface inclination in radians + :return: float + """ if self._inclination is None: self._inclination = np.arccos(self.normal[2]) return self._inclination @property def type(self): + """ + Surface type Ground, Wall or Roof + :return: str + """ if self._type is None: grad = np.rad2deg(self.inclination) if 170 <= grad: @@ -210,36 +292,68 @@ class Surface: return self._type def add_shared(self, surface, intersection_area): + """ + Add a given surface and shared area in percent to this surface. + :param surface: + :param intersection_area: + :return: + """ percent = intersection_area / self.area self._shared_surfaces.append((percent, surface)) def shared(self, surface): + """ + Check if given surface share some area with this surface + :param surface: Surface + :return: None + """ if self.type is not 'Wall' or surface.type is not 'Wall': return 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)) + self.add_shared(surface, intersection_area) surface.add_shared(self, intersection_area) @property def global_irradiance_hour(self): + """ + Get surface global irradiance hour in Wh/m2 + :return: float + """ return self._global_irradiance_hour @global_irradiance_hour.setter def global_irradiance_hour(self, value): + """ + Set surface global irradiance per hour in Wh/m2 + :param value: float + :return: None + """ self._global_irradiance_hour = value @property def global_irradiance_month(self): + """ + Get surface global irradiance per month in Wh/m2 + :return: float + """ return self._global_irradiance_month @global_irradiance_month.setter def global_irradiance_month(self, value): + """ + Set surface global irradiance per month in Wh/m2 + :param value: float + :return: None + """ self._global_irradiance_month = value @property - def shapely(self): + def shapely(self) -> Union[None, pn.Polygon]: + """ + Surface shapely (Z projection) + :return: None or pyny3d.Polygon + """ if self.polygon is None: return None if self._shapely is None: @@ -247,7 +361,7 @@ class Surface: return self._shapely @staticmethod - def _polygon_to_surface(polygon): + def _polygon_to_surface(polygon) -> Surface: coordinates = '' for coordinate in polygon.exterior.coords: if coordinates != '': @@ -257,6 +371,10 @@ class Surface: @property def projection(self) -> Surface: + """ + Projected surface (Z projection) + :return: Surface + """ if self._is_projected: return self if self._projected_surface is None: @@ -264,6 +382,11 @@ class Surface: return self._projected_surface def intersect(self, surface) -> Union[Surface, None]: + """ + Get the intersection surface, if any, between the given surface and this surface + :param surface: Surface + :return: None or Surface + """ 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) diff --git a/city_model_structure/thermal_zone.py b/city_model_structure/thermal_zone.py index b8229063..60c5a0d3 100644 --- a/city_model_structure/thermal_zone.py +++ b/city_model_structure/thermal_zone.py @@ -35,7 +35,7 @@ class ThermalZone: :return: Boolean """ return self._heated - + @property def cooled(self): """ @@ -44,10 +44,10 @@ class ThermalZone: """ return self._cooled - @property + @property def floor_area(self): """ - Get thermal zone floor area in m2 + Get thermal zone floor area in square meters :return: float """ if self._floor_area is None: diff --git a/city_model_structure/usage_zone.py b/city_model_structure/usage_zone.py index e50ab84f..b203825b 100644 --- a/city_model_structure/usage_zone.py +++ b/city_model_structure/usage_zone.py @@ -8,6 +8,9 @@ from typing import List class UsageZone: + """ + UsageZone class + """ def __init__(self): self._usage = None self._internal_gains = None @@ -20,14 +23,27 @@ class UsageZone: @property def internal_gains(self) -> List[InternalGains]: + """ + Get usage zone internal gains + :return: [InternalGains] + """ return self._internal_gains @internal_gains.setter def internal_gains(self, value): + """ + Set usage zone internal gains + :param value: [InternalGains] + :return: None + """ self._internal_gains = value @property def heating_setpoint(self): + """ + + :return: + """ return self._heating_setpoint @heating_setpoint.setter diff --git a/pylintrc b/pylintrc index 999d300e..9f1f7c52 100644 --- a/pylintrc +++ b/pylintrc @@ -318,6 +318,10 @@ good-names=i, k, ex, Run, + x, + y, + z, + s, _ # Good variable names regexes, separated by a comma. If names match any regex,