columns can have an accessrestriction now

This commit is contained in:
Laura Klünder 2018-12-12 19:37:24 +01:00
parent f05b8f19c5
commit 8936fe5aea
5 changed files with 58 additions and 7 deletions

View file

@ -0,0 +1,19 @@
# Generated by Django 2.1.4 on 2018-12-12 17:47
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mapdata', '0002_fix_broken_spaces'),
]
operations = [
migrations.AddField(
model_name='column',
name='access_restriction',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='columns', to='mapdata.AccessRestriction', verbose_name='Access Restriction'),
),
]

View file

@ -206,7 +206,7 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
if space.outside:
space.geometry = space.geometry.difference(buildings_geom)
space_accessible = space.geometry.difference(
unary_union(tuple(c.geometry for c in space.columns.all()) +
unary_union(tuple(c.geometry for c in space.columns.all() if c.access_restriction_id is None) +
tuple(o.geometry for o in space.obstacles.all()) +
tuple(o.buffered_geometry for o in space.lineobstacles.all()) +
tuple(h.geometry for h in space.holes.all()))

View file

@ -13,6 +13,7 @@ from shapely.geometry import CAP_STYLE, JOIN_STYLE, mapping
from c3nav.mapdata.fields import GeometryField, I18nField, JSONField
from c3nav.mapdata.grid import grid
from c3nav.mapdata.models import Space
from c3nav.mapdata.models.access import AccessRestrictionMixin
from c3nav.mapdata.models.base import SerializableMixin
from c3nav.mapdata.models.geometry.base import GeometryMixin
from c3nav.mapdata.models.locations import SpecificLocation
@ -97,7 +98,7 @@ class SpaceGeometryMixin(GeometryMixin):
super().save(*args, **kwargs)
class Column(SpaceGeometryMixin, models.Model):
class Column(SpaceGeometryMixin, AccessRestrictionMixin, models.Model):
"""
An column in a space, also used to be able to create rooms within rooms.
"""

View file

@ -74,7 +74,7 @@ class LevelGeometries:
subtract = []
if space.outside:
subtract.append(buildings_geom)
columns = [c.geometry for c in space.columns.all()]
columns = [c.geometry for c in space.columns.all() if c.access_restriction_id is None]
if columns:
subtract.extend(columns)
if subtract:
@ -108,14 +108,15 @@ class LevelGeometries:
obstacles = {}
heightareas = {}
for space in level.spaces.all():
buffered = space.geometry.buffer(0.01).union(unary_union(
tuple(door.geometry for door in level.doors.all() if door.geometry.intersects(space.geometry))
).difference(walkable_spaces_geom))
intersects = buildings_geom_prep.intersects(buffered)
access_restriction = space.access_restriction_id
if access_restriction is not None:
access_restriction_affected.setdefault(access_restriction, []).append(space.geometry)
buffered = space.geometry.buffer(0.01).union(unary_union(
tuple(door.geometry for door in level.doors.all() if door.geometry.intersects(space.geometry))
).difference(walkable_spaces_geom))
intersects = buildings_geom_prep.intersects(buffered)
if intersects:
restricted_spaces_indoors.setdefault(access_restriction, []).append(
buffered.intersection(buildings_geom)
@ -134,6 +135,18 @@ class LevelGeometries:
access_restriction_affected.setdefault(access_restriction, []).append(area.geometry)
colors.setdefault(area.get_color(), {}).setdefault(access_restriction, []).append(area.geometry)
for column in space.columns.all():
access_restriction = column.access_restriction_id
if access_restriction is None:
continue
column.geometry = column.geometry.intersection(space.walkable_geom)
buffered_column = column.geometry.buffer(0.01)
if intersects:
restricted_spaces_indoors.setdefault(access_restriction, []).append(buffered_column)
if not intersects or not buildings_geom_prep.contains(buffered):
restricted_spaces_outdoors.setdefault(access_restriction, []).append(buffered_column)
access_restriction_affected.setdefault(access_restriction, []).append(column.geometry)
for obstacle in space.obstacles.all():
if not obstacle.height:
continue

View file

@ -176,6 +176,15 @@ class Router:
pois[poi.pk] = poi
space.pois.add(poi.pk)
for column in space_obj.columns.all():
if column.access_restriction_id is None:
continue
column.geometry_prep = prepared.prep(column.geometry)
column_nodes = tuple(node for node in space_nodes if column.geometry_prep.intersects(node.point))
column_nodes = set(node.i for node in column_nodes)
restrictions.setdefault(column.access_restriction_id,
RouterRestriction()).additional_nodes.update(column_nodes)
space_obj._prefetched_objects_cache = {}
space.src.geometry = accessible_geom
@ -397,6 +406,9 @@ class Router:
space_nodes = tuple(reduce(operator.or_, (self.spaces[space].nodes for space in restrictions.spaces), set()))
graph[space_nodes, :] = np.inf
graph[:, space_nodes] = np.inf
if restrictions.additional_nodes:
graph[restrictions.additional_nodes, :] = np.inf
graph[:, restrictions.additional_nodes] = np.inf
graph[restrictions.edges.transpose().tolist()] = np.inf
distances, predecessors = shortest_path(graph, directed=True, return_predecessors=True)
@ -670,6 +682,7 @@ class RouterLocation:
class RouterRestriction:
def __init__(self, spaces=None):
self.spaces = spaces if spaces else set()
self.additional_nodes = set()
self.edges = deque()
@ -681,6 +694,11 @@ class RouterRestrictionSet:
def spaces(self):
return reduce(operator.or_, (restriction.spaces for restriction in self.restrictions.values()), frozenset())
@cached_property
def additional_nodes(self):
return reduce(operator.or_, (restriction.additional_nodes
for restriction in self.restrictions.values()), frozenset())
@cached_property
def edges(self):
if not self.restrictions: