diff --git a/src/c3nav/routing/api.py b/src/c3nav/routing/api.py index bd1c8b0e..9add2dcc 100644 --- a/src/c3nav/routing/api.py +++ b/src/c3nav/routing/api.py @@ -38,7 +38,8 @@ class RoutingViewSet(ViewSet): try: route = Router.load().get_route(origin=form.cleaned_data['origin'], destination=form.cleaned_data['destination'], - permissions=AccessPermission.get_for_request(request)) + permissions=AccessPermission.get_for_request(request), + options=options) except NotYetRoutable: return Response({ 'error': _('Not yet routable, try again shortly.'), diff --git a/src/c3nav/routing/models.py b/src/c3nav/routing/models.py index 82833600..ba99bf7e 100644 --- a/src/c3nav/routing/models.py +++ b/src/c3nav/routing/models.py @@ -137,6 +137,12 @@ class RouteOptions(models.Model): def __setitem__(self, key, value): self.update({key: value}) + def get(self, key, default): + try: + return self[key] + except AttributeError: + return default + def serialize(self): return [ { diff --git a/src/c3nav/routing/router.py b/src/c3nav/routing/router.py index f9a5096b..5f65bb66 100644 --- a/src/c3nav/routing/router.py +++ b/src/c3nav/routing/router.py @@ -1,3 +1,4 @@ +import json import operator import os import pickle @@ -302,9 +303,11 @@ class Router: self.get_restrictions(location.permissions)) ) - def shortest_path(self, restrictions): - cache_key = 'router:shortest_path:%s:%s' % (MapUpdate.current_processed_cache_key(), - restrictions.cache_key) + def shortest_path(self, restrictions, options): + options_key = json.dumps(options.data, separators=(',', '='), sort_keys=True)[1:-1] + cache_key = 'router:shortest_path:%s:%s:%s' % (MapUpdate.current_processed_cache_key(), + restrictions.cache_key, + options_key) result = cache.get(cache_key) if result: return result @@ -314,6 +317,13 @@ class Router: graph[:, tuple(restrictions.spaces)] = np.inf graph[restrictions.edges.transpose().tolist()] = np.inf + for waytype in self.waytypes[1:]: + value = options.get('waytype_%s' % waytype.pk, 'allow') + if value in ('avoid', 'avoid_up'): + graph[waytype.upwards_indices.transpose().tolist()] *= 100000 + if value in ('avoid', 'avoid_down'): + graph[waytype.nonupwards_indices.transpose().tolist()] *= 100000 + result = shortest_path(graph, directed=True, return_predecessors=True) cache.set(cache_key, result, 600) return result @@ -323,7 +333,7 @@ class Router: pk: restriction for pk, restriction in self.restrictions.items() if pk not in permissions }) - def get_route(self, origin, destination, permissions=frozenset()): + def get_route(self, origin, destination, permissions, options): restrictions = self.get_restrictions(permissions) # get possible origins and destinations @@ -331,7 +341,7 @@ class Router: destinations = self.get_locations(destination, restrictions) # calculate shortest path matrix - distances, predecessors = self.shortest_path(restrictions) + distances, predecessors = self.shortest_path(restrictions, options=options) # find shortest path for our origins and destinations origin_nodes = np.array(tuple(origins.nodes))