refactor graph code
This commit is contained in:
parent
e6978c6e61
commit
57ed2ec368
4 changed files with 65 additions and 51 deletions
|
@ -10,7 +10,6 @@ from c3nav.routing.connection import GraphConnection
|
||||||
from c3nav.routing.level import GraphLevel
|
from c3nav.routing.level import GraphLevel
|
||||||
from c3nav.routing.point import GraphPoint
|
from c3nav.routing.point import GraphPoint
|
||||||
from c3nav.routing.room import GraphRoom
|
from c3nav.routing.room import GraphRoom
|
||||||
from c3nav.routing.router import Router
|
|
||||||
|
|
||||||
|
|
||||||
class Graph:
|
class Graph:
|
||||||
|
@ -21,23 +20,38 @@ class Graph:
|
||||||
for level in Level.objects.all():
|
for level in Level.objects.all():
|
||||||
self.levels[level.name] = GraphLevel(self, level)
|
self.levels[level.name] = GraphLevel(self, level)
|
||||||
|
|
||||||
self.points = []
|
self.rooms = ()
|
||||||
|
self.points = ()
|
||||||
self.connections = []
|
self.connections = []
|
||||||
self.rooms = []
|
|
||||||
|
|
||||||
self.level_transfer_points = []
|
self.level_transfer_points = []
|
||||||
self.levelconnector_points = {}
|
self.levelconnector_points = {}
|
||||||
|
|
||||||
|
# Building the Graph
|
||||||
def build(self):
|
def build(self):
|
||||||
for level in self.levels.values():
|
for level in self.levels.values():
|
||||||
level.build()
|
level.build()
|
||||||
|
|
||||||
|
# collect rooms and points
|
||||||
self.rooms = sum((level.rooms for level in self.levels.values()), [])
|
self.rooms = sum((level.rooms for level in self.levels.values()), [])
|
||||||
self.points = sum((level.points for level in self.levels.values()), [])
|
self.points = sum((level.points for level in self.levels.values()), [])
|
||||||
|
|
||||||
|
# create connections between levels
|
||||||
print()
|
print()
|
||||||
self.connect_levelconnectors()
|
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()
|
||||||
print('Total:')
|
print('Total:')
|
||||||
print('%d points' % len(self.points))
|
print('%d points' % len(self.points))
|
||||||
|
@ -50,13 +64,41 @@ class Graph:
|
||||||
for name, level in self.levels.items():
|
for name, level in self.levels.items():
|
||||||
print(('Level %s:' % name), *(sorted((len(room.points) for room in level.rooms), reverse=True)))
|
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):
|
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)
|
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)
|
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)
|
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))
|
graph = cls.unserialize(pickle.load(f))
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
def build_router(self):
|
# Drawing
|
||||||
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)
|
|
||||||
|
|
||||||
def draw_pngs(self, points=True, lines=True):
|
def draw_pngs(self, points=True, lines=True):
|
||||||
for level in self.levels.values():
|
for level in self.levels.values():
|
||||||
level.draw_png(points, lines)
|
level.draw_png(points, lines)
|
||||||
|
|
||||||
def add_levelconnector_point(self, levelconnector, point):
|
# Router
|
||||||
self.levelconnector_points.setdefault(levelconnector.name, []).append(point)
|
def build_router(self):
|
||||||
|
for level in self.levels.values():
|
||||||
def connect_levelconnectors(self):
|
level.build_router()
|
||||||
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))
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ class GraphLevel():
|
||||||
self.room_transfer_points = []
|
self.room_transfer_points = []
|
||||||
self.rooms = []
|
self.rooms = []
|
||||||
|
|
||||||
|
# Building the Graph
|
||||||
def build(self):
|
def build(self):
|
||||||
print()
|
print()
|
||||||
print('Level %s:' % self.level.name)
|
print('Level %s:' % self.level.name)
|
||||||
|
@ -99,6 +100,7 @@ class GraphLevel():
|
||||||
room.points.append(point)
|
room.points.append(point)
|
||||||
self.graph.add_levelconnector_point(levelconnector, point)
|
self.graph.add_levelconnector_point(levelconnector, point)
|
||||||
|
|
||||||
|
# Drawing
|
||||||
def draw_png(self, points=True, lines=True):
|
def draw_png(self, points=True, lines=True):
|
||||||
filename = os.path.join(settings.RENDER_ROOT, 'level-%s.base.png' % self.level.name)
|
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)
|
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))
|
draw.line(_line_coords(point, otherpoint, height), fill=(0, 255, 255))
|
||||||
|
|
||||||
im.save(graph_filename)
|
im.save(graph_filename)
|
||||||
|
|
||||||
|
# Routing
|
||||||
|
def build_router(self):
|
||||||
|
for room in self.rooms:
|
||||||
|
room.build_router()
|
||||||
|
|
|
@ -21,6 +21,7 @@ class GraphRoom():
|
||||||
|
|
||||||
self.points = []
|
self.points = []
|
||||||
|
|
||||||
|
# Building the Graph
|
||||||
def prepare_build(self):
|
def prepare_build(self):
|
||||||
self.clear_geometry = self.geometry.buffer(-0.3, join_style=JOIN_STYLE.mitre)
|
self.clear_geometry = self.geometry.buffer(-0.3, join_style=JOIN_STYLE.mitre)
|
||||||
|
|
||||||
|
@ -157,6 +158,7 @@ class GraphRoom():
|
||||||
point2.connect_to(point1)
|
point2.connect_to(point1)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
# Routing
|
||||||
def build_router(self):
|
def build_router(self):
|
||||||
self.router = Router()
|
self.router = Router()
|
||||||
self.router.build(self.points)
|
self.router.build(self.points)
|
||||||
|
|
|
@ -27,8 +27,6 @@ class Router():
|
||||||
for point, pk in self.points_pk.items():
|
for point, pk in self.points_pk.items():
|
||||||
for to_point, connection in point.connections.items():
|
for to_point, connection in point.connections.items():
|
||||||
if to_point not in self.points_pk:
|
if to_point not in self.points_pk:
|
||||||
if not global_routing:
|
|
||||||
self.transfer_points.add(point)
|
|
||||||
continue
|
continue
|
||||||
matrix[pk, self.points_pk[to_point]] = connection.distance
|
matrix[pk, self.points_pk[to_point]] = connection.distance
|
||||||
if global_routing:
|
if global_routing:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue