team-3/src/c3nav/routing/route.py

153 lines
5.9 KiB
Python
Raw Normal View History

2016-12-17 14:46:15 +01:00
from abc import ABC, abstractmethod
2016-12-17 13:24:42 +01:00
import numpy as np
from django.utils.functional import cached_property
class RouteSegment(ABC):
2016-12-17 14:46:15 +01:00
def __init__(self, routers, router, from_point, to_point):
2016-12-17 13:24:42 +01:00
"""
:param router: a Router (RoomRouter, GraphRouter, )
:param from_point: in-router index of first point
:param to_point: in-router index of last point
"""
2016-12-17 14:46:15 +01:00
self.routers = routers
2016-12-17 13:24:42 +01:00
self.router = router
self.from_point = int(from_point)
self.to_point = int(to_point)
def as_route(self):
2016-12-17 14:46:15 +01:00
return SegmentRoute([self])
2016-12-17 13:24:42 +01:00
2016-12-17 14:09:38 +01:00
def _get_points(self):
points = [self.to_point]
first = self.from_point
current = self.to_point
while current != first:
current = self.router.predecessors[first, current]
points.append(current)
return tuple(reversed(points))
2016-12-17 14:46:15 +01:00
@abstractmethod
def get_connections(self):
pass
2016-12-17 13:24:42 +01:00
@cached_property
def distance(self):
return self.router.shortest_paths[self.from_point, self.to_point]
class RoomRouteSegment(RouteSegment):
2016-12-17 14:09:38 +01:00
def __init__(self, room, routers, from_point, to_point):
2016-12-17 13:24:42 +01:00
"""
Route segment within a Room
:param room: GraphRoom
"""
2016-12-17 14:46:15 +01:00
super().__init__(routers, routers[room], from_point, to_point)
2016-12-17 13:24:42 +01:00
self.room = room
self.global_from_point = room.points[from_point]
self.global_to_point = room.points[to_point]
2016-12-17 14:46:15 +01:00
def get_connections(self):
points = self._get_points()
return tuple(self.room.get_connection(from_point, to_point)
for from_point, to_point in zip(points[:-1], points[1:]))
2016-12-17 13:24:42 +01:00
def __repr__(self):
return ('<RoomRouteSegment in %r from points %d to %d with distance %f>' %
(self.room, self.from_point, self.to_point, self.distance))
class LevelRouteSegment(RouteSegment):
2016-12-17 14:09:38 +01:00
def __init__(self, level, routers, from_point, to_point):
2016-12-17 13:24:42 +01:00
"""
Route segment within a Level (from room transfer point to room transfer point)
:param level: GraphLevel
"""
2016-12-17 14:46:15 +01:00
super().__init__(routers, routers[level], from_point, to_point)
2016-12-17 13:24:42 +01:00
self.level = level
self.global_from_point = level.room_transfer_points[from_point]
self.global_to_point = level.room_transfer_points[to_point]
2016-12-17 14:46:15 +01:00
def split(self):
segments = []
points = self._get_points()
for from_point, to_point in zip(points[:-1], points[1:]):
room = self.level.rooms[self.router.room_transfers[from_point, to_point]]
global_from_point = self.level.room_transfer_points[from_point]
global_to_point = self.level.room_transfer_points[to_point]
segments.append(RoomRouteSegment(room, self.routers,
from_point=room.points.index(global_from_point),
to_point=room.points.index(global_to_point)))
return tuple(segments)
def get_connections(self):
return sum((segment.get_connections() for segment in self.split()), ())
2016-12-17 13:24:42 +01:00
def __repr__(self):
return ('<LevelRouteSegment in %r from points %d to %d with distance %f>' %
(self.level, self.from_point, self.to_point, self.distance))
class GraphRouteSegment(RouteSegment):
2016-12-17 14:09:38 +01:00
def __init__(self, graph, routers, from_point, to_point):
2016-12-17 13:24:42 +01:00
"""
Route segment within a Graph (from level transfer point to level transfer point)
:param graph: Graph
"""
2016-12-17 14:46:15 +01:00
super().__init__(routers, routers[graph], from_point, to_point)
2016-12-17 13:24:42 +01:00
self.graph = graph
self.global_from_point = graph.level_transfer_points[from_point]
self.global_to_point = graph.level_transfer_points[to_point]
2016-12-17 14:46:15 +01:00
def split(self):
segments = []
points = self._get_points()
for from_point, to_point in zip(points[:-1], points[1:]):
level = self.graph.levels[self.router.level_transfers[from_point, to_point]]
global_from_point = self.graph.level_transfer_points[from_point]
global_to_point = self.graph.level_transfer_points[to_point]
segments.append(LevelRouteSegment(level, self.routers,
from_point=level.room_transfer_points.index(global_from_point),
to_point=level.room_transfer_points.index(global_to_point)))
return tuple(segments)
def get_connections(self):
return sum((segment.get_connections() for segment in self.split()), ())
2016-12-17 13:24:42 +01:00
def __repr__(self):
return ('<GraphRouteSegment in %r from points %d to %d with distance %f>' %
(self.graph, self.from_point, self.to_point, self.distance))
2016-12-17 14:46:15 +01:00
class SegmentRoute:
2016-12-17 13:24:42 +01:00
def __init__(self, segments, distance=None):
2016-12-17 14:46:15 +01:00
self.segments = sum(((item.segments if isinstance(item, SegmentRoute) else (item,))
for item in segments if item.from_point != item.to_point), ())
2016-12-17 13:24:42 +01:00
self.distance = sum(segment.distance for segment in self.segments)
2016-12-17 14:46:15 +01:00
self.from_point = segments[0].global_from_point
self.to_point = segments[-1].global_to_point
2016-12-17 13:24:42 +01:00
def __repr__(self):
2016-12-17 14:46:15 +01:00
return ('<SegmentedRoute (\n %s\n) distance=%f>' %
2016-12-17 13:24:42 +01:00
('\n '.join(repr(segment) for segment in self.segments), self.distance))
2016-12-17 14:46:15 +01:00
def split(self):
return Route(sum((segment.get_connections() for segment in self.segments), ()))
class Route:
def __init__(self, connections, distance=None):
self.connections = tuple(connections)
self.distance = sum(connection.distance for connection in self.connections)
self.from_point = connections[0].from_point
self.to_point = connections[-1].to_point
def __repr__(self):
return ('<Route (\n %s\n) distance=%f>' %
('\n '.join(repr(connection) for connection in self.connections), self.distance))
2016-12-17 13:24:42 +01:00
class NoRoute:
distance = np.inf