add support for connection types and excluding steps_down or steps_up
This commit is contained in:
parent
f6129d621c
commit
5183b8fa7d
11 changed files with 125 additions and 76 deletions
|
@ -282,7 +282,7 @@ editor = {
|
||||||
'levelconnector': '#FFFF00',
|
'levelconnector': '#FFFF00',
|
||||||
'shadow': '#000000',
|
'shadow': '#000000',
|
||||||
'stair': '#FF0000',
|
'stair': '#FF0000',
|
||||||
'areaofinterest': '#0099FF'
|
'arealocation': '#0099FF'
|
||||||
},
|
},
|
||||||
_line_draw_geometry_style: function(style) {
|
_line_draw_geometry_style: function(style) {
|
||||||
style.stroke = true;
|
style.stroke = true;
|
||||||
|
@ -304,10 +304,10 @@ editor = {
|
||||||
var result = {
|
var result = {
|
||||||
stroke: false,
|
stroke: false,
|
||||||
fillColor: editor._geometry_colors[mapitem_type],
|
fillColor: editor._geometry_colors[mapitem_type],
|
||||||
fillOpacity: (mapitem_type == 'areaofinterest') ? 0.2 : 0.6,
|
fillOpacity: (mapitem_type == 'arealocation') ? 0.2 : 0.6,
|
||||||
smoothFactor: 0
|
smoothFactor: 0
|
||||||
};
|
};
|
||||||
if (mapitem_type == 'areaofinterest') {
|
if (mapitem_type == 'arealocation') {
|
||||||
result.fillOpacity = 0.02;
|
result.fillOpacity = 0.02;
|
||||||
result.color = result.fillColor;
|
result.color = result.fillColor;
|
||||||
result.stroke = true;
|
result.stroke = true;
|
||||||
|
|
|
@ -37,12 +37,20 @@ class GraphArea():
|
||||||
# stair checker
|
# stair checker
|
||||||
angle = coord_angle(point1.xy, point2.xy)
|
angle = coord_angle(point1.xy, point2.xy)
|
||||||
valid = True
|
valid = True
|
||||||
|
direction_up = None
|
||||||
for stair_path, stair_angle in self.mpl_stairs:
|
for stair_path, stair_angle in self.mpl_stairs:
|
||||||
if not path.intersects_path(stair_path):
|
if not path.intersects_path(stair_path):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
angle_diff = ((stair_angle - angle + 180) % 360) - 180
|
angle_diff = ((stair_angle - angle + 180) % 360) - 180
|
||||||
up = angle_diff < 0 # noqa
|
|
||||||
|
new_direction_up = (angle_diff > 0)
|
||||||
|
if direction_up is None:
|
||||||
|
direction_up = new_direction_up
|
||||||
|
elif direction_up != new_direction_up:
|
||||||
|
valid = False
|
||||||
|
break
|
||||||
|
|
||||||
if not (40 < abs(angle_diff) < 150):
|
if not (40 < abs(angle_diff) < 150):
|
||||||
valid = False
|
valid = False
|
||||||
break
|
break
|
||||||
|
@ -50,8 +58,8 @@ class GraphArea():
|
||||||
if not valid:
|
if not valid:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
point1.connect_to(point2)
|
point1.connect_to(point2, ctype={True: 'steps_up', False: 'steps_down'}.get(direction_up, ''))
|
||||||
point2.connect_to(point1)
|
point2.connect_to(point1, ctype={True: 'steps_down', False: 'steps_up'}.get(direction_up, ''))
|
||||||
|
|
||||||
def add_point(self, point):
|
def add_point(self, point):
|
||||||
if not self.mpl_clear.contains_point(point.xy):
|
if not self.mpl_clear.contains_point(point.xy):
|
||||||
|
|
|
@ -2,10 +2,12 @@ import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class GraphConnection():
|
class GraphConnection():
|
||||||
def __init__(self, from_point, to_point, distance=None):
|
def __init__(self, from_point, to_point, distance=None, ctype=''):
|
||||||
self.from_point = from_point
|
self.from_point = from_point
|
||||||
self.to_point = to_point
|
self.to_point = to_point
|
||||||
self.distance = distance if distance is not None else abs(np.linalg.norm(from_point.xy - to_point.xy))
|
self.distance = distance if distance is not None else abs(np.linalg.norm(from_point.xy - to_point.xy))
|
||||||
|
self.ctype = ctype
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<GraphConnection %r %r distance=%f>' % (self.from_point, self.to_point, self.distance)
|
return ('<GraphConnection %r %r distance=%f ctype=%s>' %
|
||||||
|
(self.from_point, self.to_point, self.distance, self.ctype))
|
||||||
|
|
|
@ -174,7 +174,7 @@ class Graph:
|
||||||
level.draw_png(points, lines)
|
level.draw_png(points, lines)
|
||||||
|
|
||||||
# Router
|
# Router
|
||||||
def build_routers(self):
|
def build_routers(self, allowed_ctypes):
|
||||||
routers = {}
|
routers = {}
|
||||||
|
|
||||||
empty_distances = np.empty(shape=(len(self.level_transfer_points),) * 2, dtype=np.float16)
|
empty_distances = np.empty(shape=(len(self.level_transfer_points),) * 2, dtype=np.float16)
|
||||||
|
@ -186,7 +186,7 @@ class Graph:
|
||||||
level_transfers[:] = -1
|
level_transfers[:] = -1
|
||||||
|
|
||||||
for i, level in enumerate(self.levels.values()):
|
for i, level in enumerate(self.levels.values()):
|
||||||
routers.update(level.build_routers())
|
routers.update(level.build_routers(allowed_ctypes))
|
||||||
router = routers[level]
|
router = routers[level]
|
||||||
|
|
||||||
level_distances = empty_distances.copy()
|
level_distances = empty_distances.copy()
|
||||||
|
@ -220,7 +220,7 @@ class Graph:
|
||||||
def _allowed_points_index(self, points, allowed_points_i):
|
def _allowed_points_index(self, points, allowed_points_i):
|
||||||
return np.array(tuple(i for i, point in enumerate(points) if point in allowed_points_i))
|
return np.array(tuple(i for i, point in enumerate(points) if point in allowed_points_i))
|
||||||
|
|
||||||
def get_route(self, origin: Location, destination: Location):
|
def get_route(self, origin: Location, destination: Location, allowed_ctypes):
|
||||||
orig_points_i = set(self.get_location_points(origin))
|
orig_points_i = set(self.get_location_points(origin))
|
||||||
dest_points_i = set(self.get_location_points(destination))
|
dest_points_i = set(self.get_location_points(destination))
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ class Graph:
|
||||||
best_route = NoRoute
|
best_route = NoRoute
|
||||||
|
|
||||||
# get routers
|
# get routers
|
||||||
routers = self.build_routers()
|
routers = self.build_routers(allowed_ctypes)
|
||||||
|
|
||||||
# route within room
|
# route within room
|
||||||
orig_rooms = set(point.room for point in orig_points)
|
orig_rooms = set(point.room for point in orig_points)
|
||||||
|
@ -273,6 +273,7 @@ class Graph:
|
||||||
for level in orig_levels}
|
for level in orig_levels}
|
||||||
dest_room_transfer_points = {level: self._allowed_points_index(level.room_transfer_points, dest_room_transfers)
|
dest_room_transfer_points = {level: self._allowed_points_index(level.room_transfer_points, dest_room_transfers)
|
||||||
for level in dest_levels}
|
for level in dest_levels}
|
||||||
|
print(dest_room_transfer_points)
|
||||||
|
|
||||||
# if the points have common rooms, search for routes within thos levels
|
# if the points have common rooms, search for routes within thos levels
|
||||||
if common_levels:
|
if common_levels:
|
||||||
|
@ -305,10 +306,12 @@ class Graph:
|
||||||
# as a dictionary: global transfer point index => Route
|
# as a dictionary: global transfer point index => Route
|
||||||
orig_level_transfers = self._level_transfers(orig_levels, orig_room_transfers, routers, mode='orig')
|
orig_level_transfers = self._level_transfers(orig_levels, orig_room_transfers, routers, mode='orig')
|
||||||
dest_level_transfers = self._level_transfers(orig_levels, dest_room_transfers, routers, mode='dest')
|
dest_level_transfers = self._level_transfers(orig_levels, dest_room_transfers, routers, mode='dest')
|
||||||
|
print(orig_levels, dest_room_transfers, dest_level_transfers)
|
||||||
|
|
||||||
# get reachable roomtransfer points for each level (points as room transfer point index within level)
|
# get reachable leveltransfer points (points as level transfer point index within graph)
|
||||||
orig_level_transfer_points = self._allowed_points_index(self.level_transfer_points, orig_level_transfers)
|
orig_level_transfer_points = self._allowed_points_index(self.level_transfer_points, orig_level_transfers)
|
||||||
dest_level_transfer_points = self._allowed_points_index(self.level_transfer_points, dest_level_transfers)
|
dest_level_transfer_points = self._allowed_points_index(self.level_transfer_points, dest_level_transfers)
|
||||||
|
print(dest_level_transfer_points)
|
||||||
|
|
||||||
# search a route within the whole graph
|
# search a route within the whole graph
|
||||||
if True:
|
if True:
|
||||||
|
|
|
@ -156,6 +156,12 @@ class GraphLevel():
|
||||||
if mpl_arealocation.contains_point(point.xy))
|
if mpl_arealocation.contains_point(point.xy))
|
||||||
|
|
||||||
# Drawing
|
# Drawing
|
||||||
|
ctype_colors = {
|
||||||
|
'': (50, 200, 0),
|
||||||
|
'steps_up': (255, 50, 50),
|
||||||
|
'steps_down': (255, 50, 50),
|
||||||
|
}
|
||||||
|
|
||||||
def draw_png(self, points=True, lines=True):
|
def draw_png(self, points=True, lines=True):
|
||||||
filename = os.path.join(settings.RENDER_ROOT, 'base-level-%s.png' % self.level.name)
|
filename = os.path.join(settings.RENDER_ROOT, 'base-level-%s.png' % self.level.name)
|
||||||
graph_filename = os.path.join(settings.RENDER_ROOT, 'graph-level-%s.png' % self.level.name)
|
graph_filename = os.path.join(settings.RENDER_ROOT, 'graph-level-%s.png' % self.level.name)
|
||||||
|
@ -163,12 +169,17 @@ class GraphLevel():
|
||||||
im = Image.open(filename)
|
im = Image.open(filename)
|
||||||
height = im.size[1]
|
height = im.size[1]
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
if lines:
|
if lines:
|
||||||
for room in self.rooms:
|
for room in self.rooms:
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
for from_i, to_i in np.argwhere(room.distances != np.inf):
|
for ctype, from_i, to_i in np.argwhere(room.distances != np.inf):
|
||||||
draw.line(_line_coords(self.graph.points[room.points[from_i]],
|
draw.line(_line_coords(self.graph.points[room.points[from_i]],
|
||||||
self.graph.points[room.points[to_i]], height), fill=(255, 100, 100))
|
self.graph.points[room.points[to_i]], height),
|
||||||
|
fill=self.ctype_colors[room.ctypes[ctype]])
|
||||||
|
if room.ctypes[ctype] == 'steps_up':
|
||||||
|
point = self.graph.points[room.points[from_i]]
|
||||||
|
draw.ellipse(_ellipse_bbox(point.x, point.y, height), (0, 255, 255))
|
||||||
|
|
||||||
if points:
|
if points:
|
||||||
for point_i in self.points:
|
for point_i in self.points:
|
||||||
|
@ -186,7 +197,7 @@ class GraphLevel():
|
||||||
if lines:
|
if lines:
|
||||||
for room in self.rooms:
|
for room in self.rooms:
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
for from_i, to_i in np.argwhere(room.distances != np.inf):
|
for ctype, from_i, to_i in np.argwhere(room.distances != np.inf):
|
||||||
if room.points[from_i] in room.room_transfer_points:
|
if room.points[from_i] in room.room_transfer_points:
|
||||||
draw.line(_line_coords(self.graph.points[room.points[from_i]],
|
draw.line(_line_coords(self.graph.points[room.points[from_i]],
|
||||||
self.graph.points[room.points[to_i]], height), fill=(0, 255, 255))
|
self.graph.points[room.points[to_i]], height), fill=(0, 255, 255))
|
||||||
|
@ -194,7 +205,7 @@ class GraphLevel():
|
||||||
im.save(graph_filename)
|
im.save(graph_filename)
|
||||||
|
|
||||||
# Routing
|
# Routing
|
||||||
def build_routers(self):
|
def build_routers(self, allowed_ctypes):
|
||||||
routers = {}
|
routers = {}
|
||||||
|
|
||||||
empty_distances = np.empty(shape=(len(self.room_transfer_points),) * 2, dtype=np.float16)
|
empty_distances = np.empty(shape=(len(self.room_transfer_points),) * 2, dtype=np.float16)
|
||||||
|
@ -206,7 +217,7 @@ class GraphLevel():
|
||||||
room_transfers[:] = -1
|
room_transfers[:] = -1
|
||||||
|
|
||||||
for i, room in enumerate(self.rooms):
|
for i, room in enumerate(self.rooms):
|
||||||
router = room.build_router()
|
router = room.build_router(allowed_ctypes)
|
||||||
routers[room] = router
|
routers[room] = router
|
||||||
|
|
||||||
room_distances = empty_distances.copy()
|
room_distances = empty_distances.copy()
|
||||||
|
|
|
@ -11,6 +11,7 @@ class GraphPoint():
|
||||||
self.y = y
|
self.y = y
|
||||||
self.room = room
|
self.room = room
|
||||||
self.xy = np.array((x, y))
|
self.xy = np.array((x, y))
|
||||||
|
self.i = None
|
||||||
|
|
||||||
self.connections = {}
|
self.connections = {}
|
||||||
self.connections_in = {}
|
self.connections_in = {}
|
||||||
|
@ -32,8 +33,8 @@ class GraphPoint():
|
||||||
y = self.y * settings.RENDER_SCALE
|
y = self.y * settings.RENDER_SCALE
|
||||||
return ((x-5, y-5), (x+5, y+5))
|
return ((x-5, y-5), (x+5, y+5))
|
||||||
|
|
||||||
def connect_to(self, other_point):
|
def connect_to(self, other_point, ctype=''):
|
||||||
connection = GraphConnection(self, other_point)
|
connection = GraphConnection(self, other_point, ctype=ctype)
|
||||||
self.connections[other_point] = connection
|
self.connections[other_point] = connection
|
||||||
other_point.connections_in[self] = connection
|
other_point.connections_in[self] = connection
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,12 @@ class GraphRoom():
|
||||||
|
|
||||||
self.mpl_clear = None
|
self.mpl_clear = None
|
||||||
|
|
||||||
|
self.i = None
|
||||||
self.areas = []
|
self.areas = []
|
||||||
self.points = None
|
self.points = None
|
||||||
self.room_transfer_points = None
|
self.room_transfer_points = None
|
||||||
self.distances = np.zeros((1, ))
|
self.distances = np.zeros((1, ))
|
||||||
|
self.ctypes = None
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
return (
|
return (
|
||||||
|
@ -34,12 +36,13 @@ class GraphRoom():
|
||||||
self.points,
|
self.points,
|
||||||
self.room_transfer_points,
|
self.room_transfer_points,
|
||||||
self.distances,
|
self.distances,
|
||||||
|
self.ctypes,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unserialize(cls, level, data):
|
def unserialize(cls, level, data):
|
||||||
room = cls(level)
|
room = cls(level)
|
||||||
room.mpl_clear, areas, room.points, room.room_transfer_points, room.distances = data
|
room.mpl_clear, areas, room.points, room.room_transfer_points, room.distances, room.ctypes = data
|
||||||
room.areas = tuple(GraphArea(room, *area) for area in areas)
|
room.areas = tuple(GraphArea(room, *area) for area in areas)
|
||||||
return room
|
return room
|
||||||
|
|
||||||
|
@ -183,6 +186,8 @@ class GraphRoom():
|
||||||
return [point]
|
return [point]
|
||||||
|
|
||||||
def build_connections(self):
|
def build_connections(self):
|
||||||
|
print('\n\n')
|
||||||
|
print('room')
|
||||||
for area in self.areas:
|
for area in self.areas:
|
||||||
area.build_connections()
|
area.build_connections()
|
||||||
|
|
||||||
|
@ -195,32 +200,49 @@ class GraphRoom():
|
||||||
self.room_transfer_points = tuple(i for i in self.points if i in self.level.room_transfer_points)
|
self.room_transfer_points = tuple(i for i in self.points if i in self.level.room_transfer_points)
|
||||||
|
|
||||||
mapping = {point.i: i for i, point in enumerate(self._built_points)}
|
mapping = {point.i: i for i, point in enumerate(self._built_points)}
|
||||||
self.distances = np.empty(shape=(len(self._built_points), len(self._built_points)), dtype=np.float16)
|
|
||||||
self.distances[:] = np.inf
|
empty = np.empty(shape=(len(self._built_points), len(self._built_points)), dtype=np.float16)
|
||||||
|
empty[:] = np.inf
|
||||||
|
|
||||||
|
ctypes = []
|
||||||
|
distances = {}
|
||||||
for from_point in self._built_points:
|
for from_point in self._built_points:
|
||||||
for to_point, connection in from_point.connections.items():
|
for to_point, connection in from_point.connections.items():
|
||||||
if to_point.i in mapping:
|
if to_point.i in mapping:
|
||||||
self.distances[mapping[from_point.i], mapping[to_point.i]] = connection.distance
|
if connection.ctype not in distances:
|
||||||
|
ctypes.append(connection.ctype)
|
||||||
|
distances[connection.ctype] = empty.copy()
|
||||||
|
distances[connection.ctype][mapping[from_point.i], mapping[to_point.i]] = connection.distance
|
||||||
|
|
||||||
|
self.ctypes = tuple(ctypes)
|
||||||
|
self.distances = np.array(tuple(distances[ctype] for ctype in ctypes))
|
||||||
|
|
||||||
for area in self.areas:
|
for area in self.areas:
|
||||||
area.finish_build()
|
area.finish_build()
|
||||||
|
|
||||||
# Routing
|
# Routing
|
||||||
def build_router(self):
|
def build_router(self, allowed_ctypes):
|
||||||
cache_key = 'c3nav__graph__roomrouter__%s__%s' % (self.graph.mtime, self.i)
|
ctypes = tuple(i for i, ctype in enumerate(self.ctypes) if ctype in allowed_ctypes)
|
||||||
|
cache_key = ('c3nav__graph__roomrouter__%s__%s__%s' %
|
||||||
|
(self.graph.mtime, self.i, ','.join(str(i) for i in ctypes)))
|
||||||
roomrouter = cache.get(cache_key)
|
roomrouter = cache.get(cache_key)
|
||||||
if not roomrouter:
|
if not roomrouter:
|
||||||
roomrouter = self._build_router()
|
roomrouter = self._build_router(ctypes)
|
||||||
cache.set(cache_key, roomrouter, 600)
|
cache.set(cache_key, roomrouter, 600)
|
||||||
return roomrouter
|
return roomrouter
|
||||||
|
|
||||||
def _build_router(self):
|
def _build_router(self, ctypes):
|
||||||
g_sparse = csgraph_from_dense(self.distances, null_value=np.inf)
|
g_sparse = csgraph_from_dense(np.amin(self.distances[ctypes, :, :], 0), null_value=np.inf)
|
||||||
shortest_paths, predecessors = shortest_path(g_sparse, return_predecessors=True)
|
shortest_paths, predecessors = shortest_path(g_sparse, return_predecessors=True)
|
||||||
return RoomRouter(shortest_paths, predecessors)
|
return RoomRouter(shortest_paths, predecessors)
|
||||||
|
|
||||||
def get_connection(self, from_i, to_i):
|
def get_connection(self, from_i, to_i):
|
||||||
return GraphConnection(self.graph.points[self.points[from_i]], self.graph.points[self.points[to_i]])
|
stack = self.distances[:, from_i, to_i]
|
||||||
|
min_i = stack.argmin()
|
||||||
|
distance = stack[min_i]
|
||||||
|
ctype = self.ctypes[min_i]
|
||||||
|
return GraphConnection(self.graph.points[self.points[from_i]], self.graph.points[self.points[to_i]],
|
||||||
|
distance=distance, ctype=ctype)
|
||||||
|
|
||||||
|
|
||||||
RoomRouter = namedtuple('RoomRouter', ('shortest_paths', 'predecessors', ))
|
RoomRouter = namedtuple('RoomRouter', ('shortest_paths', 'predecessors', ))
|
||||||
|
|
|
@ -41,36 +41,36 @@ class RoutePart:
|
||||||
self.level_name = level.level.name
|
self.level_name = level.level.name
|
||||||
self.connections = connections
|
self.connections = connections
|
||||||
|
|
||||||
width, height = get_dimensions()
|
svg_width, svg_height = get_dimensions()
|
||||||
|
|
||||||
points = (connections[0].from_point, ) + tuple(connection.to_point for connection in connections)
|
points = (connections[0].from_point, ) + tuple(connection.to_point for connection in connections)
|
||||||
for point in points:
|
for point in points:
|
||||||
point.svg_x = point.x * 6
|
point.svg_x = point.x * 6
|
||||||
point.svg_y = (height - point.y) * 6
|
point.svg_y = (svg_height - point.y) * 6
|
||||||
|
|
||||||
x, y = zip(*((point.svg_x, point.svg_y) for point in points if point.level == level))
|
x, y = zip(*((point.svg_x, point.svg_y) for point in points if point.level == level))
|
||||||
|
|
||||||
self.distance = sum(connection.distance for connection in connections)
|
self.distance = sum(connection.distance for connection in connections)
|
||||||
|
|
||||||
# bounds for rendering
|
# bounds for rendering
|
||||||
self.min_x = min(x) - 20
|
self.svg_min_x = min(x) - 20
|
||||||
self.max_x = max(x) + 20
|
self.svg_max_x = max(x) + 20
|
||||||
self.min_y = min(y) - 20
|
self.svg_min_y = min(y) - 20
|
||||||
self.max_y = max(y) + 20
|
self.svg_max_y = max(y) + 20
|
||||||
|
|
||||||
width = self.max_x - self.min_x
|
svg_width = self.svg_max_x - self.svg_min_x
|
||||||
height = self.max_y - self.min_y
|
svg_height = self.svg_max_y - self.svg_min_y
|
||||||
|
|
||||||
if width < 150:
|
if svg_width < 150:
|
||||||
self.min_x -= (10 - width) / 2
|
self.svg_min_x -= (10 - svg_width) / 2
|
||||||
self.max_x += (10 - width) / 2
|
self.svg_max_x += (10 - svg_width) / 2
|
||||||
|
|
||||||
if height < 150:
|
if svg_height < 150:
|
||||||
self.min_y -= (10 - height) / 2
|
self.svg_min_y += (10 - svg_height) / 2
|
||||||
self.max_y += (10 - height) / 2
|
self.svg_max_y -= (10 - svg_height) / 2
|
||||||
|
|
||||||
self.width = self.max_x - self.min_x
|
self.svg_width = self.svg_max_x - self.svg_min_x
|
||||||
self.height = self.max_y - self.min_y
|
self.svg_height = self.svg_max_y - self.svg_min_y
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr(self.__dict__)
|
return repr(self.__dict__)
|
||||||
|
|
28
src/c3nav/site/templates/site/fragment_route.html
Normal file
28
src/c3nav/site/templates/site/fragment_route.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{% load route_render %}
|
||||||
|
|
||||||
|
<h2>Your Route</h2>
|
||||||
|
<div class="routeparts">
|
||||||
|
{% for routepart in route.routeparts %}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="map" data-level="{{ routepart.level_name }}"
|
||||||
|
viewBox="0 0 {{ routepart.svg_width }} {{ routepart.svg_height }}"
|
||||||
|
style="max-height:{% if routepart.svg_height > 300 %}300{% else %}{{ routepart.svg_height }}{% endif %}px">
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow-{{ forloop.counter0 }}" markerWidth="4" markerHeight="4" refX="2.5" refY="2" orient="auto">
|
||||||
|
<path d="M0,0 L3,2 L0,4 L0,0" style="fill: #FF0000; stroke: 0;"></path>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<image width="{{ svg_width }}" height="{{ svg_height }}" x="{{ routepart.svg_min_x | negate }}" y="{{ routepart.svg_min_y | negate }}" xlink:href="/map/{{ routepart.level_name }}.png"></image>
|
||||||
|
|
||||||
|
<g class="connections">
|
||||||
|
{% for c in routepart.connections %}
|
||||||
|
<line x1="{{ c.from_point.svg_x | subtract:routepart.svg_min_x }}"
|
||||||
|
y1="{{ c.from_point.svg_y | subtract:routepart.svg_min_y }}"
|
||||||
|
x2="{{ c.to_point.svg_x | subtract:routepart.svg_min_x }}"
|
||||||
|
y2="{{ c.to_point.svg_y | subtract:routepart.svg_min_y }}"
|
||||||
|
marker-end="url(#arrow-{{ forloop.parentloop.counter0 }})"></line>
|
||||||
|
{% endfor %}
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load route_render %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form>
|
<form>
|
||||||
|
@ -15,32 +14,7 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% if route %}
|
{% if route %}
|
||||||
<h2>Your Route</h2>
|
{% include 'site/fragment_route.html' %}
|
||||||
<div class="routeparts">
|
{% endif %}
|
||||||
{% for routepart in route.routeparts %}
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="map" data-level="{{ routepart.level_name }}"
|
|
||||||
viewBox="0 0 {{ routepart.width }} {{ routepart.height }}"
|
|
||||||
style="max-height:{% if routepart.height > 300 %}300{% else %}{{ routepart.height }}{% endif %}px">
|
|
||||||
<defs>
|
|
||||||
<marker id="arrow-{{ forloop.counter0 }}" markerWidth="4" markerHeight="4" refX="2.5" refY="2" orient="auto">
|
|
||||||
<path d="M0,0 L3,2 L0,4 L0,0" style="fill: #FF0000; stroke: 0;"></path>
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
|
|
||||||
<image width="{{ svg_width }}" height="{{ svg_height }}" x="{{ routepart.min_x | negate }}" y="{{ routepart.min_y | negate }}" xlink:href="/map/{{ routepart.level_name }}.png"></image>
|
|
||||||
|
|
||||||
<g class="connections">
|
|
||||||
{% for c in routepart.connections %}
|
|
||||||
<line x1="{{ c.from_point.svg_x | subtract:routepart.min_x }}"
|
|
||||||
y1="{{ c.from_point.svg_y | subtract:routepart.min_y }}"
|
|
||||||
x2="{{ c.to_point.svg_x | subtract:routepart.min_x }}"
|
|
||||||
y2="{{ c.to_point.svg_y | subtract:routepart.min_y }}"
|
|
||||||
marker-end="url(#arrow-{{ forloop.parentloop.counter0 }})"></line>
|
|
||||||
{% endfor %}
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -42,7 +42,7 @@ def main(request, origin=None, destination=None):
|
||||||
route = None
|
route = None
|
||||||
if origin and destination:
|
if origin and destination:
|
||||||
graph = Graph.load()
|
graph = Graph.load()
|
||||||
route = graph.get_route(origin, destination)
|
route = graph.get_route(origin, destination, ('', 'steps_down', 'steps_up'))
|
||||||
route = route.split()
|
route = route.split()
|
||||||
print(route)
|
print(route)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue