better custom location descriptions

This commit is contained in:
Laura Klünder 2017-12-20 17:12:54 +01:00
parent f02a90caf6
commit 4bde1e4e1b
2 changed files with 58 additions and 17 deletions

View file

@ -10,7 +10,6 @@ from django.apps import apps
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Prefetch, Q from django.db.models import Prefetch, Q
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from shapely.ops import cascaded_union from shapely.ops import cascaded_union
@ -312,14 +311,48 @@ class CustomLocation:
def altitude(self): def altitude(self):
return self.description.altitude return self.description.altitude
@cached_property
def areas(self):
return self.description.areas
@cached_property
def near_area(self):
return self.description.near_area
@cached_property
def near_poi(self):
return self.description.near_poi
@cached_property
def title_subtitle(self):
title = _('Point')
print(self.space)
if not self.space:
return title, self.level.title,
subtitle = ()
if self.near_poi:
title = _('Point near %(poi)s') % {'poi': self.near_poi.title}
if self.areas:
subtitle = (area.title for area in self.areas[:2])
elif self.near_area:
subtitle = (_('near %(area)s') % {'area': self.near_area.title}, )
elif self.areas:
title = _('Point in %(area)s') % {'area': self.areas[0].title}
if self.areas:
subtitle = (area.title for area in self.areas[1:2])
elif self.near_area:
title = _('Point near %(area)s') % {'area': self.near_area.title}
else:
return _('Point in %(space)s') % {'space': self.space.title}, self.level.title
subtitle = ', '.join(str(title) for title in chain(subtitle, (self.space.title, self.level.title)))
return title, subtitle
@cached_property @cached_property
def title(self): def title(self):
return _('Custom Location') return self.title_subtitle[0]
@cached_property @cached_property
def subtitle(self): def subtitle(self):
if self.space and self.space.can_describe: return self.title_subtitle[1]
return format_lazy(_('{space}, {level}'),
space=self.space.title,
level=self.level.title)
return self.level.title

View file

@ -6,6 +6,7 @@ import threading
from collections import deque, namedtuple from collections import deque, namedtuple
from functools import reduce from functools import reduce
from itertools import chain from itertools import chain
from typing import Optional
import numpy as np import numpy as np
from django.conf import settings from django.conf import settings
@ -297,7 +298,7 @@ class Router:
raise LocationUnreachable raise LocationUnreachable
return result return result
def space_for_point(self, level, point, restrictions=None): def space_for_point(self, level, point, restrictions) -> Optional['RouterSpace']:
point = Point(point.x, point.y) point = Point(point.x, point.y)
level = self.levels[level] level = self.levels[level]
excluded_spaces = restrictions.spaces if restrictions else () excluded_spaces = restrictions.spaces if restrictions else ()
@ -314,9 +315,15 @@ class Router:
return min(spaces, key=operator.itemgetter(1))[0] return min(spaces, key=operator.itemgetter(1))[0]
def describe_custom_location(self, location): def describe_custom_location(self, location):
space = self.space_for_point(location.level.pk, location, self.get_restrictions(location.permissions)) restrictions = self.get_restrictions(location.permissions)
altitude = space.altitudearea_for_point(location).get_altitude(location) if space else None space = self.space_for_point(level=location.level.pk, point=location, restrictions=restrictions)
return CustomLocationDescription(space=space, altitude=altitude) if not space:
return CustomLocationDescription(space=space, altitude=None, areas=None, near_area=None, near_poi=None)
altitude = space.altitudearea_for_point(location).get_altitude(location)
areas, near_area = space.areas_for_point(areas=self.areas, point=location, restrictions=restrictions)
near_poi = space.poi_for_point(pois=self.pois, point=location, restrictions=restrictions)
return CustomLocationDescription(space=space, altitude=altitude,
areas=areas, near_area=near_area, near_poi=near_poi)
def shortest_path(self, restrictions, options): def shortest_path(self, restrictions, options):
options_key = json.dumps(options.data, separators=(',', '='), sort_keys=True)[1:-1] options_key = json.dumps(options.data, separators=(',', '='), sort_keys=True)[1:-1]
@ -419,7 +426,8 @@ class Router:
origin_addition, destination_addition, origin_xyz, destination_xyz) origin_addition, destination_addition, origin_xyz, destination_xyz)
CustomLocationDescription = namedtuple('CustomLocationDescription', ('space', 'altitude')) CustomLocationDescription = namedtuple('CustomLocationDescription', ('space', 'altitude',
'areas', 'near_area', 'near_poi'))
class BaseRouterProxy: class BaseRouterProxy:
@ -465,22 +473,22 @@ class RouterSpace(BaseRouterProxy):
return area return area
return min(self.altitudeareas, key=lambda area: area.geometry.distance(point)) return min(self.altitudeareas, key=lambda area: area.geometry.distance(point))
def areas_for_point(self, areas, point, restrictions=None): def areas_for_point(self, areas, point, restrictions):
point = Point(point.x, point.y) point = Point(point.x, point.y)
areas = {pk: area for pk, area in areas.items() areas = {pk: area for pk, area in areas.items()
if pk in self.areas and area.can_describe and area.access_restriction_id not in restrictions} if pk in self.areas and area.can_describe and area.access_restriction_id not in restrictions}
contained = tuple(area for area in areas.values() if area.geometry_prep.contains(point)) contained = tuple(area for area in areas.values() if area.geometry_prep.contains(point))
if contained: if contained:
return tuple((area, True) for area in sorted(contained, key=lambda area: area.geometry.area)) return tuple(sorted(contained, key=lambda area: area.geometry.area)), ()
near = ((area, area.geometry.distance(point)) for area in areas.values()) near = ((area, area.geometry.distance(point)) for area in areas.values())
near = tuple((area, distance) for area, distance in near if distance < 5) near = tuple((area, distance) for area, distance in near if distance < 5)
if not near: if not near:
return () return (), ()
return ((min(near, key=operator.itemgetter(1))[0], False), ) return (), (min(near, key=operator.itemgetter(1))[0], )
def poi_for_point(self, pois, point, restrictions=None): def poi_for_point(self, pois, point, restrictions):
point = Point(point.x, point.y) point = Point(point.x, point.y)
pois = {pk: poi for pk, poi in pois.items() pois = {pk: poi for pk, poi in pois.items()
if pk in self.pois and poi.can_describe and poi.access_restriction_id not in restrictions} if pk in self.pois and poi.can_describe and poi.access_restriction_id not in restrictions}