better custom location descriptions
This commit is contained in:
parent
f02a90caf6
commit
4bde1e4e1b
2 changed files with 58 additions and 17 deletions
|
@ -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
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue