speed up router
This commit is contained in:
parent
f260b52a6e
commit
c71b9b0f8b
1 changed files with 28 additions and 9 deletions
|
@ -1,6 +1,7 @@
|
|||
import operator
|
||||
import os
|
||||
import pickle
|
||||
import threading
|
||||
from collections import deque
|
||||
from functools import reduce
|
||||
from itertools import chain
|
||||
|
@ -15,7 +16,7 @@ from shapely.ops import unary_union
|
|||
|
||||
from c3nav.mapdata.models import AltitudeArea, Area, GraphEdge, Level, LocationGroup, Space, WayType
|
||||
from c3nav.mapdata.models.geometry.space import POI
|
||||
from c3nav.mapdata.utils.geometry import assert_multipolygon, good_representative_point
|
||||
from c3nav.mapdata.utils.geometry import assert_multipolygon, get_rings, good_representative_point
|
||||
from c3nav.mapdata.utils.locations import CustomLocation
|
||||
from c3nav.routing.route import Route
|
||||
|
||||
|
@ -71,7 +72,7 @@ class Router:
|
|||
tuple(obstacle.geometry for obstacle in space.obstacles.all()) +
|
||||
tuple(lineobstacle.buffered_geometry for lineobstacle in space.lineobstacles.all())
|
||||
)
|
||||
clear_geom = accessible_geom.difference(obstacles_geom)
|
||||
clear_geom = unary_union(tuple(get_rings(accessible_geom.difference(obstacles_geom))))
|
||||
clear_geom_prep = prepared.prep(clear_geom)
|
||||
|
||||
for group in space.groups.all():
|
||||
|
@ -103,7 +104,8 @@ class Router:
|
|||
if not space.geometry_prep.intersects(area.geometry):
|
||||
continue
|
||||
for subgeom in assert_multipolygon(accessible_geom.intersection(area.geometry)):
|
||||
area = RouterAltitudeArea(subgeom, subgeom.difference(obstacles_geom),
|
||||
area_clear_geom = unary_union(tuple(get_rings(subgeom.difference(obstacles_geom))))
|
||||
area = RouterAltitudeArea(subgeom, area_clear_geom,
|
||||
area.altitude, area.altitude2, area.point1, area.point2)
|
||||
area_nodes = tuple(node for node in space_nodes if area.geometry_prep.intersects(node.point))
|
||||
area.nodes = set(node.i for node in area_nodes)
|
||||
|
@ -123,7 +125,7 @@ class Router:
|
|||
# todo: check waytypes here
|
||||
for node in space_nodes:
|
||||
line = LineString([(node.x, node.y), (fallback_node.x, fallback_node.y)])
|
||||
if line.length < 5 and not clear_geom_prep.crosses(line):
|
||||
if line.length < 5 and not clear_geom_prep.intersects(line):
|
||||
area.fallback_nodes[node.i] = (
|
||||
fallback_node,
|
||||
RouterEdge(fallback_node, node, 0)
|
||||
|
@ -192,9 +194,23 @@ class Router:
|
|||
return router
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
def load_nocache(cls):
|
||||
return pickle.load(open(cls.filename, 'rb'))
|
||||
|
||||
cached = None
|
||||
cache_key = None
|
||||
cache_lock = threading.Lock()
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
from c3nav.mapdata.models import MapUpdate
|
||||
cache_key = MapUpdate.current_processed_cache_key()
|
||||
if cls.cache_key != cache_key:
|
||||
with cls.cache_lock:
|
||||
cls.cache_key = cache_key
|
||||
cls.cached = cls.load_nocache()
|
||||
return cls.cached
|
||||
|
||||
def get_locations(self, location, permissions=frozenset()):
|
||||
locations = ()
|
||||
if isinstance(location, Level):
|
||||
|
@ -231,10 +247,14 @@ class Router:
|
|||
point = Point(point.x, point.y)
|
||||
level = self.levels[level]
|
||||
for space in level.spaces:
|
||||
if self.spaces[space].geometry_prep.intersects(point):
|
||||
if self.spaces[space].geometry_prep.contains(point):
|
||||
return self.spaces[space]
|
||||
return self.spaces[min(level.spaces, key=lambda space: self.spaces[space].geometry.distance(point))]
|
||||
|
||||
@cached_property
|
||||
def shortest_path(self):
|
||||
return shortest_path(self.graph, directed=True, return_predecessors=True)
|
||||
|
||||
def get_route(self, origin, destination, permissions=frozenset()):
|
||||
# get possible origins and destinations
|
||||
origins = self.get_locations(origin, permissions=permissions)
|
||||
|
@ -243,7 +263,7 @@ class Router:
|
|||
# todo: throw error if route is impossible
|
||||
|
||||
# calculate shortest path matrix
|
||||
distances, predecessors = shortest_path(self.graph, directed=True, return_predecessors=True)
|
||||
distances, predecessors = self.shortest_path
|
||||
|
||||
# find shortest path for our origins and destinations
|
||||
origin_nodes = np.array(tuple(origins.nodes))
|
||||
|
@ -269,7 +289,6 @@ class Router:
|
|||
|
||||
origin_addition = origin.nodes_addition.get(origin_node)
|
||||
destination_addition = destination.nodes_addition.get(destination_node)
|
||||
print(origin_addition, destination_addition)
|
||||
|
||||
return Route(self, origin, destination, distances[origin_node, destination_node], path_nodes,
|
||||
origin_addition, destination_addition)
|
||||
|
@ -354,7 +373,7 @@ class RouterAltitudeArea:
|
|||
for node in self.nodes:
|
||||
node = all_nodes[node]
|
||||
line = LineString([(node.x, node.y), (point.x, point.y)])
|
||||
if line.length < 5 and not self.clear_geometry_prep.crosses(line):
|
||||
if line.length < 5 and not self.clear_geometry_prep.intersects(line):
|
||||
nodes[node.i] = (None, None)
|
||||
if not nodes:
|
||||
nearest_node = min(tuple(all_nodes[node] for node in self.nodes),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue