From 93cd4f0e779078010f256d72149a3e48dd0c1467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Thu, 14 Dec 2017 23:57:59 +0100 Subject: [PATCH] more comments \o/ --- src/c3nav/control/forms.py | 1 + src/c3nav/control/middleware.py | 3 +++ src/c3nav/mapdata/render/geometry/hybrid.py | 24 +++++++++++++++++++++ src/c3nav/mapdata/render/geometry/level.py | 19 ++++++++++++++++ src/c3nav/mapdata/render/geometry/mesh.py | 6 ++++++ 5 files changed, 53 insertions(+) diff --git a/src/c3nav/control/forms.py b/src/c3nav/control/forms.py index 6570718c..592c4c34 100644 --- a/src/c3nav/control/forms.py +++ b/src/c3nav/control/forms.py @@ -109,6 +109,7 @@ class AccessPermissionForm(Form): for restriction in self.cleaned_data['access_restrictions']: expire_date = self.cleaned_data['expires'] author_expire_date = self.author_access_permissions.get(restriction.pk) + # make sure that each permission is not granted for a longer time than the author has it if author_expire_date is not None: expire_date = author_expire_date if expire_date is None else min(expire_date, author_expire_date) restrictions.append(AccessPermissionTokenItem(pk=restriction.pk, expire_date=expire_date, diff --git a/src/c3nav/control/middleware.py b/src/c3nav/control/middleware.py index 2a3bdb48..0d41b344 100644 --- a/src/c3nav/control/middleware.py +++ b/src/c3nav/control/middleware.py @@ -4,6 +4,9 @@ from c3nav.control.models import UserPermissions class UserPermissionsMiddleware: + """ + This middleware adds request.user_permissions to get the UserPermissions for the current request/user. + """ def __init__(self, get_response): self.get_response = get_response diff --git a/src/c3nav/mapdata/render/geometry/hybrid.py b/src/c3nav/mapdata/render/geometry/hybrid.py index 9c0bab4d..b96f9919 100644 --- a/src/c3nav/mapdata/render/geometry/hybrid.py +++ b/src/c3nav/mapdata/render/geometry/hybrid.py @@ -28,6 +28,14 @@ def hybrid_union(geoms): class HybridGeometry: + """ + A geometry containing a mesh as well as a shapely geometry, + so it can be used for different kinds of render engines. + + This object can be in 2 states: + - 2d mesh state where faces refers to indizes of faces from an external list + - 3d mesh state where faces refers to Mesh instances + """ __slots__ = ('geom', 'faces', 'crop_ids', 'add_faces') def __init__(self, geom, faces, crop_ids=frozenset(), add_faces=None): @@ -38,6 +46,9 @@ class HybridGeometry: @classmethod def create(cls, geom, face_centers): + """ + Create from existing facets and just select the ones that lie inside this polygon. + """ if isinstance(geom, (LineString, MultiLineString)): return HybridGeometry(geom, set()) faces = tuple( @@ -48,6 +59,9 @@ class HybridGeometry: @classmethod def create_full(cls, geom, vertices_offset, faces_offset): + """ + Create by triangulating a polygon and adding the resulting facets to the total list. + """ if isinstance(geom, (LineString, MultiLineString)): return HybridGeometry(geom, set()), np.empty((0, 2), dtype=np.int32), np.empty((0, 3), dtype=np.uint32) @@ -85,6 +99,9 @@ class HybridGeometry: crop_ids=self.crop_ids - other.crop_ids) def fit(self, scale, offset): + """ + Fit this object (when it has minz=0 maxz=1) into a given minz, maxz range. + """ offset = np.array((0, 0, offset)) scale = np.array((1, 1, scale)) return HybridGeometry(geom=self.geom, crop_ids=self.crop_ids, @@ -93,6 +110,9 @@ class HybridGeometry: for crop_id, faces in self.add_faces}) def filter(self, **kwargs): + """ + Remove top, bottom or side facets. + """ return HybridGeometry(geom=self.geom, crop_ids=self.crop_ids, faces=tuple(mesh.filter(**kwargs) for mesh in self.faces), add_faces={crop_id: tuple(mesh.filter(**kwargs) for mesh in faces) @@ -106,6 +126,10 @@ class HybridGeometry: return not self.faces and not any(self.add_faces.values()) def build_polyhedron(self, create_polyhedron, crops=None, **kwargs): + """ + Create polyhedron using an externel function from this object, + which means converting it from a flat mesh to a 3d mesh state. + """ remaining_faces = self.faces for crop, prep in crops or (): if prep.intersects(self.geom): diff --git a/src/c3nav/mapdata/render/geometry/level.py b/src/c3nav/mapdata/render/geometry/level.py index dea50566..9d00a91b 100644 --- a/src/c3nav/mapdata/render/geometry/level.py +++ b/src/c3nav/mapdata/render/geometry/level.py @@ -20,6 +20,9 @@ empty_geometry_collection = GeometryCollection() class LevelGeometries: + """ + Store geometries for a Level. + """ def __init__(self): self.altitudeareas = [] self.heightareas = [] @@ -244,6 +247,9 @@ class LevelGeometries: return item[0].get_altitudes(self.vertices[i_vertices]) - int(0.7 * 1000) def _build_vertex_values(self, items, area_func, value_func): + """ + Interpolate vertice with known altitudes to get altitudes for the remaining ones. + """ vertex_values = np.empty(self.vertices.shape[:1], dtype=np.int32) vertex_value_mask = np.full(self.vertices.shape[:1], fill_value=False, dtype=np.bool) @@ -262,9 +268,15 @@ class LevelGeometries: return vertex_values def _filter_faces(self, faces): + """ + Filter faces so that no zero area faces remain. + """ return faces[np.all(np.any(faces[:, (0, 1, 2), :]-faces[:, (2, 0, 1), :], axis=2), axis=1)] def _create_polyhedron(self, faces, lower, upper, top=True, sides=True, bottom=True): + """ + Callback function for HybridGeometry.create_polyhedron() + """ if not any(faces): return () @@ -351,6 +363,11 @@ class LevelGeometries: return tuple((Mesh(top, sides, bottom),)) def build_mesh(self, interpolator=None): + """ + Build the entire mesh + """ + + # first we triangulate most polygons in one go rings = tuple(chain(*(get_rings(geom) for geom in self.get_geometries()))) self.vertices, self.faces = triangulate_rings(rings) self.create_hybrid_geometries(face_centers=self.vertices[self.faces].sum(axis=1) / 3000) @@ -369,6 +386,7 @@ class LevelGeometries: area.remove_faces(reduce(operator.or_, self.walls.faces, set())) # create polyhedrons + # we build the walls to often so we can extend them to create leveled 3d model bases. self.walls_base = HybridGeometry(self.all_walls.geom, self.all_walls.faces) self.walls_bottom = HybridGeometry(self.all_walls.geom, self.all_walls.faces) self.walls_extended = HybridGeometry(self.walls.geom, self.walls.faces) @@ -384,6 +402,7 @@ class LevelGeometries: value_func=self._get_short_wall_vertex_values)) self.short_walls = tuple(geom for altitude, geom in self.short_walls) + # make sure we are able to crop spaces when a access restriction is apply for key, geometry in self.restricted_spaces_indoors.items(): geometry.crop_ids = frozenset(('in:%s' % key, )) for key, geometry in self.restricted_spaces_outdoors.items(): diff --git a/src/c3nav/mapdata/render/geometry/mesh.py b/src/c3nav/mapdata/render/geometry/mesh.py index 36266eff..5b8a6335 100644 --- a/src/c3nav/mapdata/render/geometry/mesh.py +++ b/src/c3nav/mapdata/render/geometry/mesh.py @@ -4,6 +4,9 @@ import numpy as np class Mesh(namedtuple('Mesh', ('top', 'sides', 'bottom'))): + """ + Store a mesh, divided into top, bottom and side facets. + """ __slots__ = () empty_faces = np.empty((0, 3, 3)).astype(np.int32) @@ -21,6 +24,9 @@ class Mesh(namedtuple('Mesh', ('top', 'sides', 'bottom'))): np.rint(self.bottom+other).astype(np.int32)) def filter(self, top=True, sides=True, bottom=True): + """ + Remove top, bottom or side facets. + """ return Mesh(top=self.top if top else self.empty_faces, sides=self.sides if sides else self.empty_faces, bottom=self.bottom if bottom else self.empty_faces)