refactor graph code

This commit is contained in:
Laura Klünder 2016-12-10 12:07:52 +01:00
parent e6978c6e61
commit 57ed2ec368
4 changed files with 65 additions and 51 deletions

View file

@ -10,7 +10,6 @@ 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
class Graph:
@ -21,23 +20,38 @@ class Graph:
for level in Level.objects.all():
self.levels[level.name] = GraphLevel(self, level)
self.points = []
self.rooms = ()
self.points = ()
self.connections = []
self.rooms = []
self.level_transfer_points = []
self.levelconnector_points = {}
# Building the Graph
def build(self):
for level in self.levels.values():
level.build()
# collect rooms and points
self.rooms = sum((level.rooms for level in self.levels.values()), [])
self.points = sum((level.points for level in self.levels.values()), [])
# create connections between levels
print()
self.connect_levelconnectors()
# convert everything to tuples
self.rooms = tuple(self.rooms)
self.points = tuple(self.points)
self.connections = tuple(self.connections)
# give numbers to rooms and points
for i, room in enumerate(self.rooms):
room.i = i
for i, point in enumerate(self.points):
point.i = i
print()
print('Total:')
print('%d points' % len(self.points))
@ -50,13 +64,41 @@ class Graph:
for name, level in self.levels.items():
print(('Level %s:' % name), *(sorted((len(room.points) for room in level.rooms), reverse=True)))
def add_connection(self, from_point, to_point, distance=None):
self.connections.append(GraphConnection(self, from_point, to_point, distance))
def add_levelconnector_point(self, levelconnector, point):
self.levelconnector_points.setdefault(levelconnector.name, []).append(point)
def connect_levelconnectors(self):
for levelconnector in LevelConnector.objects.all():
center = levelconnector.geometry.centroid
points = self.levelconnector_points.get(levelconnector.name, [])
rooms = tuple(set(sum((point.rooms for point in points), [])))
if len(rooms) < 2:
print('levelconnector %s on levels %s at (%.2f, %.2f) has <2 rooms (%d%s)!' %
(levelconnector.name, ', '.join(level.name for level in levelconnector.levels.all()),
center.x, center.y, len(rooms), (' on level '+rooms[0].level.level.name) if rooms else ''))
continue
center_point = GraphPoint(center.x, center.y, rooms=rooms)
self.points.append(center_point)
levels = tuple(set(room.level for room in rooms))
for level in levels:
level.room_transfer_points.append(center_point)
level.points.append(center_point)
for room in rooms:
room.points.append(center_point)
for point in points:
center_point.connect_to(point)
point.connect_to(center_point)
# Loading/Saving the Graph
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.mpl_clear) for room in self.rooms)
points = tuple((point.x, point.y, tuple(room.i for room in point.rooms)) for point in self.points)
connections = tuple((conn.from_point.i, conn.to_point.i, conn.distance) for conn in self.connections)
@ -100,47 +142,12 @@ class Graph:
graph = cls.unserialize(pickle.load(f))
return graph
def build_router(self):
for room in self.rooms:
room.build_router()
self.transfer_points.extend(room.router.transfer_points)
self.router = Router()
self.router.build(self.transfer_points, global_routing=True)
# Drawing
def draw_pngs(self, points=True, lines=True):
for level in self.levels.values():
level.draw_png(points, lines)
def add_levelconnector_point(self, levelconnector, point):
self.levelconnector_points.setdefault(levelconnector.name, []).append(point)
def connect_levelconnectors(self):
for levelconnector in LevelConnector.objects.all():
center = levelconnector.geometry.centroid
points = self.levelconnector_points.get(levelconnector.name, [])
rooms = tuple(set(sum((point.rooms for point in points), [])))
if len(rooms) < 2:
print('levelconnector %s on levels %s at (%.2f, %.2f) has <2 rooms (%d%s)!' %
(levelconnector.name, ', '.join(level.name for level in levelconnector.levels.all()),
center.x, center.y, len(rooms), (' on level '+rooms[0].level.level.name) if rooms else ''))
continue
center_point = GraphPoint(center.x, center.y, rooms=rooms)
self.points.append(center_point)
levels = tuple(set(room.level for room in rooms))
for level in levels:
level.room_transfer_points.append(center_point)
level.points.append(center_point)
for room in rooms:
room.points.append(center_point)
for point in points:
center_point.connect_to(point)
point.connect_to(center_point)
def add_connection(self, from_point, to_point, distance=None):
self.connections.append(GraphConnection(self, from_point, to_point, distance))
# Router
def build_router(self):
for level in self.levels.values():
level.build_router()

View file

@ -20,6 +20,7 @@ class GraphLevel():
self.room_transfer_points = []
self.rooms = []
# Building the Graph
def build(self):
print()
print('Level %s:' % self.level.name)
@ -99,6 +100,7 @@ class GraphLevel():
room.points.append(point)
self.graph.add_levelconnector_point(levelconnector, point)
# Drawing
def draw_png(self, points=True, lines=True):
filename = os.path.join(settings.RENDER_ROOT, 'level-%s.base.png' % self.level.name)
graph_filename = os.path.join(settings.RENDER_ROOT, 'level-%s.graph.png' % self.level.name)
@ -123,3 +125,8 @@ class GraphLevel():
draw.line(_line_coords(point, otherpoint, height), fill=(0, 255, 255))
im.save(graph_filename)
# Routing
def build_router(self):
for room in self.rooms:
room.build_router()

View file

@ -21,6 +21,7 @@ class GraphRoom():
self.points = []
# Building the Graph
def prepare_build(self):
self.clear_geometry = self.geometry.buffer(-0.3, join_style=JOIN_STYLE.mitre)
@ -157,6 +158,7 @@ class GraphRoom():
point2.connect_to(point1)
i += 1
# Routing
def build_router(self):
self.router = Router()
self.router.build(self.points)

View file

@ -27,8 +27,6 @@ class Router():
for point, pk in self.points_pk.items():
for to_point, connection in point.connections.items():
if to_point not in self.points_pk:
if not global_routing:
self.transfer_points.add(point)
continue
matrix[pk, self.points_pk[to_point]] = connection.distance
if global_routing: