2016-12-05 12:09:43 +01:00
|
|
|
import os
|
|
|
|
import pickle
|
|
|
|
from collections import OrderedDict
|
2016-12-04 12:50:32 +01:00
|
|
|
from itertools import permutations
|
|
|
|
|
2016-12-05 12:09:43 +01:00
|
|
|
from django.conf import settings
|
|
|
|
|
2016-12-03 19:09:39 +01:00
|
|
|
from c3nav.mapdata.models import Level
|
2016-12-05 13:56:54 +01:00
|
|
|
from c3nav.routing.connection import GraphConnection
|
|
|
|
from c3nav.routing.level import GraphLevel
|
|
|
|
from c3nav.routing.point import GraphPoint
|
|
|
|
from c3nav.routing.room import GraphRoom
|
|
|
|
from c3nav.routing.router import Router
|
2016-12-03 19:09:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Graph():
|
2016-12-05 12:09:43 +01:00
|
|
|
default_filename = os.path.join(settings.DATA_DIR, 'graph.pickle')
|
|
|
|
|
2016-12-03 19:09:39 +01:00
|
|
|
def __init__(self):
|
2016-12-05 12:09:43 +01:00
|
|
|
self.levels = OrderedDict()
|
2016-12-04 14:03:11 +01:00
|
|
|
for level in Level.objects.all():
|
|
|
|
self.levels[level.name] = GraphLevel(self, level)
|
|
|
|
|
2016-12-05 12:09:43 +01:00
|
|
|
self.points = []
|
2016-12-03 19:09:39 +01:00
|
|
|
self.connections = []
|
2016-12-05 12:09:43 +01:00
|
|
|
self.rooms = []
|
2016-12-04 12:50:32 +01:00
|
|
|
self.levelconnector_points = {}
|
2016-12-03 19:09:39 +01:00
|
|
|
|
2016-12-05 13:39:22 +01:00
|
|
|
self.transfer_points = []
|
|
|
|
self.router = Router()
|
|
|
|
|
2016-12-03 19:09:39 +01:00
|
|
|
def build(self):
|
|
|
|
for level in self.levels.values():
|
|
|
|
level.build()
|
2016-12-04 12:50:32 +01:00
|
|
|
|
2016-12-05 12:09:43 +01:00
|
|
|
print('Total:')
|
|
|
|
self.points = sum((level.points for level in self.levels.values()), [])
|
|
|
|
print('%d points' % len(self.points))
|
|
|
|
|
|
|
|
self.rooms = sum((level.rooms for level in self.levels.values()), [])
|
|
|
|
print('%d rooms' % len(self.rooms))
|
|
|
|
|
2016-12-04 12:50:32 +01:00
|
|
|
self.connect_levelconnectors()
|
|
|
|
|
2016-12-05 12:09:43 +01:00
|
|
|
print('%d connections' % len(self.connections))
|
|
|
|
print()
|
|
|
|
|
|
|
|
def serialize(self):
|
|
|
|
for i, room in enumerate(self.rooms):
|
|
|
|
room.i = i
|
|
|
|
|
|
|
|
for i, point in enumerate(self.points):
|
|
|
|
point.i = i
|
|
|
|
|
|
|
|
rooms = tuple((room.level.level.name, room.geometry, room.mpl_paths) for room in self.rooms)
|
|
|
|
points = tuple((point.room.i, point.x, point.y) for point in self.points)
|
2016-12-05 13:49:23 +01:00
|
|
|
connections = tuple((conn.from_point.i, conn.to_point.i, conn.distance) for conn in self.connections)
|
2016-12-05 12:09:43 +01:00
|
|
|
|
|
|
|
return (rooms, points, connections)
|
|
|
|
|
|
|
|
def save(self, filename=None):
|
|
|
|
if filename is None:
|
|
|
|
filename = self.default_filename
|
|
|
|
with open(filename, 'wb') as f:
|
|
|
|
pickle.dump(self.serialize(), f)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unserialize(cls, data):
|
|
|
|
graph = cls()
|
|
|
|
rooms, points, connections = data
|
|
|
|
|
|
|
|
graph.rooms = [GraphRoom(graph.levels[room[0]], room[1], room[2]) for room in rooms]
|
|
|
|
graph.points = [GraphPoint(graph.rooms[point[0]], point[1], point[2]) for point in points]
|
|
|
|
|
|
|
|
for point in graph.points:
|
|
|
|
point.room.points.append(point)
|
|
|
|
|
|
|
|
for room in graph.rooms:
|
|
|
|
room.level.rooms.append(room)
|
|
|
|
room.level.points.extend(room.points)
|
|
|
|
|
2016-12-05 13:49:23 +01:00
|
|
|
for from_point, to_point, distance in connections:
|
|
|
|
graph.add_connection(graph.points[from_point], graph.points[to_point], distance)
|
2016-12-05 12:09:43 +01:00
|
|
|
|
|
|
|
return graph
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def load(cls, filename=None):
|
|
|
|
if filename is None:
|
|
|
|
filename = cls.default_filename
|
|
|
|
with open(filename, 'rb') as f:
|
|
|
|
graph = cls.unserialize(pickle.load(f))
|
|
|
|
return graph
|
|
|
|
|
2016-12-05 13:39:22 +01:00
|
|
|
def build_router(self):
|
|
|
|
for room in self.rooms:
|
|
|
|
room.build_router()
|
|
|
|
self.transfer_points.extend(room.router.transfer_points)
|
|
|
|
|
|
|
|
self.router.build(self.transfer_points, global_routing=True)
|
|
|
|
|
|
|
|
def draw_pngs(self, points=True, lines=True, transfer_points=False, transfer_lines=False):
|
2016-12-04 12:50:32 +01:00
|
|
|
for level in self.levels.values():
|
2016-12-05 13:39:22 +01:00
|
|
|
level.draw_png(points, lines, transfer_points, transfer_lines)
|
2016-12-03 19:09:39 +01:00
|
|
|
|
2016-12-04 12:50:32 +01:00
|
|
|
def add_levelconnector_point(self, levelconnector, point):
|
|
|
|
self.levelconnector_points.setdefault(levelconnector.name, []).append(point)
|
|
|
|
|
|
|
|
def connect_levelconnectors(self):
|
|
|
|
for levelconnector_name, points in self.levelconnector_points.items():
|
|
|
|
for from_point, to_point in permutations(points, 2):
|
|
|
|
self.add_connection(from_point, to_point)
|
|
|
|
|
2016-12-05 13:49:23 +01:00
|
|
|
def add_connection(self, from_point, to_point, distance=None):
|
|
|
|
self.connections.append(GraphConnection(self, from_point, to_point, distance))
|