more comments \o/
This commit is contained in:
parent
89ea3fec16
commit
93cd4f0e77
5 changed files with 53 additions and 0 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue