buildgraph: new internal data handling, new serialization
This commit is contained in:
parent
1f1b28dc99
commit
06ad6a6e31
6 changed files with 159 additions and 91 deletions
|
@ -7,17 +7,27 @@ from c3nav.routing.utils.coords import coord_angle
|
||||||
|
|
||||||
|
|
||||||
class GraphArea():
|
class GraphArea():
|
||||||
def __init__(self, room, mpl_clear, mpl_stairs):
|
def __init__(self, room, mpl_clear, mpl_stairs, points=None):
|
||||||
self.room = room
|
self.room = room
|
||||||
self.graph = room.graph
|
self.graph = room.graph
|
||||||
|
|
||||||
self.mpl_clear = mpl_clear
|
self.mpl_clear = mpl_clear
|
||||||
self.mpl_stairs = mpl_stairs
|
self.mpl_stairs = mpl_stairs
|
||||||
|
|
||||||
self.points = []
|
self.points = points
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
return (
|
||||||
|
self.mpl_clear,
|
||||||
|
self.mpl_stairs,
|
||||||
|
self.points,
|
||||||
|
)
|
||||||
|
|
||||||
|
def prepare_build(self):
|
||||||
|
self._built_points = []
|
||||||
|
|
||||||
def build_connections(self):
|
def build_connections(self):
|
||||||
for point1, point2 in combinations(self.points, 2):
|
for point1, point2 in combinations(self._built_points, 2):
|
||||||
path = Path(np.vstack((point1.xy, point2.xy)))
|
path = Path(np.vstack((point1.xy, point2.xy)))
|
||||||
|
|
||||||
# lies within room
|
# lies within room
|
||||||
|
@ -40,11 +50,14 @@ class GraphArea():
|
||||||
if not valid:
|
if not valid:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.graph.add_connection(point1, point2)
|
point1.connect_to(point2)
|
||||||
self.graph.add_connection(point2, point1)
|
point2.connect_to(point1)
|
||||||
|
|
||||||
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):
|
||||||
return False
|
return False
|
||||||
self.points.append(point)
|
self._built_points.append(point)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def finish_build(self):
|
||||||
|
self.points = np.array(tuple(point.i for point in self._built_points))
|
||||||
|
|
|
@ -2,14 +2,10 @@ import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class GraphConnection():
|
class GraphConnection():
|
||||||
def __init__(self, graph, from_point, to_point, distance=None):
|
def __init__(self, from_point, to_point, distance=None):
|
||||||
self.graph = graph
|
|
||||||
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))
|
||||||
|
|
||||||
if to_point in from_point.connections:
|
def serialize(self):
|
||||||
self.graph.connections.remove(from_point.connections[to_point])
|
return (self.distance, )
|
||||||
|
|
||||||
from_point.connections[to_point] = self
|
|
||||||
to_point.connections_in[from_point] = self
|
|
||||||
|
|
|
@ -2,14 +2,13 @@ import os
|
||||||
import pickle
|
import pickle
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from c3nav.mapdata.models import Level
|
from c3nav.mapdata.models import Level
|
||||||
from c3nav.mapdata.models.geometry import LevelConnector
|
from c3nav.mapdata.models.geometry import LevelConnector
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class Graph:
|
class Graph:
|
||||||
|
@ -20,60 +19,61 @@ 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.rooms = []
|
|
||||||
self.points = []
|
self.points = []
|
||||||
self.connections = []
|
self.level_transfer_points = None
|
||||||
|
|
||||||
self.level_transfer_points = []
|
|
||||||
self.levelconnector_points = {}
|
|
||||||
|
|
||||||
# Building the Graph
|
# Building the Graph
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self._built_level_transfer_points = []
|
||||||
|
self._built_levelconnector_points = {}
|
||||||
|
|
||||||
for level in self.levels.values():
|
for level in self.levels.values():
|
||||||
level.build()
|
level.build()
|
||||||
|
|
||||||
# collect rooms and points
|
# collect rooms and points
|
||||||
self.rooms = sum((level.rooms for level in self.levels.values()), [])
|
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._built_points for level in self.levels.values()), [])
|
||||||
|
|
||||||
# create connections between levels
|
# create connections between levels
|
||||||
print()
|
print()
|
||||||
self.connect_levelconnectors()
|
self.connect_levelconnectors()
|
||||||
|
|
||||||
# convert everything to tuples
|
# finishing build: creating numpy arrays and convert everything else to tuples
|
||||||
self.rooms = tuple(self.rooms)
|
|
||||||
self.points = tuple(self.points)
|
self.points = tuple(self.points)
|
||||||
self.connections = tuple(self.connections)
|
|
||||||
|
|
||||||
# give numbers to rooms and points
|
for i, room in enumerate(rooms):
|
||||||
for i, room in enumerate(self.rooms):
|
|
||||||
room.i = i
|
room.i = i
|
||||||
|
|
||||||
for i, point in enumerate(self.points):
|
for i, point in enumerate(self.points):
|
||||||
point.i = i
|
point.i = i
|
||||||
|
|
||||||
|
self.level_transfer_points = np.array(tuple(point.i for point in self._built_level_transfer_points))
|
||||||
|
|
||||||
|
for level in self.levels.values():
|
||||||
|
level.finish_build()
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print('Total:')
|
print('Total:')
|
||||||
print('%d points' % len(self.points))
|
self.print_stats()
|
||||||
print('%d rooms' % len(self.rooms))
|
|
||||||
print('%d level transfer points' % len(self.level_transfer_points))
|
|
||||||
print('%d connections' % len(self.connections))
|
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print('Points per room:')
|
print('Points per room:')
|
||||||
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):
|
def print_stats(self):
|
||||||
self.connections.append(GraphConnection(self, from_point, to_point, distance))
|
print('%d points' % len(self.points))
|
||||||
|
print('%d rooms' % sum(len(level.rooms) for level in self.levels.values()))
|
||||||
|
print('%d level transfer points' % len(self.level_transfer_points))
|
||||||
|
print('%d connections' % sum(len(point.connections) for point in self.points))
|
||||||
|
|
||||||
def add_levelconnector_point(self, levelconnector, point):
|
def add_levelconnector_point(self, levelconnector, point):
|
||||||
self.levelconnector_points.setdefault(levelconnector.name, []).append(point)
|
self._built_levelconnector_points.setdefault(levelconnector.name, []).append(point)
|
||||||
|
|
||||||
def connect_levelconnectors(self):
|
def connect_levelconnectors(self):
|
||||||
for levelconnector in LevelConnector.objects.all():
|
for levelconnector in LevelConnector.objects.all():
|
||||||
center = levelconnector.geometry.centroid
|
center = levelconnector.geometry.centroid
|
||||||
points = self.levelconnector_points.get(levelconnector.name, [])
|
points = self._built_levelconnector_points.get(levelconnector.name, [])
|
||||||
rooms = tuple(set(sum((point.rooms for point in points), [])))
|
rooms = tuple(set(sum((point.rooms for point in points), [])))
|
||||||
|
|
||||||
if len(rooms) < 2:
|
if len(rooms) < 2:
|
||||||
|
@ -84,26 +84,27 @@ class Graph:
|
||||||
|
|
||||||
center_point = GraphPoint(center.x, center.y, rooms=rooms)
|
center_point = GraphPoint(center.x, center.y, rooms=rooms)
|
||||||
self.points.append(center_point)
|
self.points.append(center_point)
|
||||||
|
self._built_level_transfer_points.append(center_point)
|
||||||
|
|
||||||
levels = tuple(set(room.level for room in rooms))
|
levels = tuple(set(room.level for room in rooms))
|
||||||
for level in levels:
|
for level in levels:
|
||||||
level.room_transfer_points.append(center_point)
|
level._built_room_transfer_points.append(center_point)
|
||||||
level.points.append(center_point)
|
level._built_points.append(center_point)
|
||||||
|
|
||||||
for room in rooms:
|
for room in rooms:
|
||||||
room.points.append(center_point)
|
room._built_points.append(center_point)
|
||||||
|
|
||||||
for point in points:
|
for point in points:
|
||||||
self.add_connection(center_point, point)
|
center_point.connect_to(point)
|
||||||
self.add_connection(point, center_point)
|
point.connect_to(center_point)
|
||||||
|
|
||||||
# Loading/Saving the Graph
|
# Loading/Saving the Graph
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
rooms = tuple((room.level.level.name, room.mpl_clear) for room in self.rooms)
|
return (
|
||||||
points = tuple((point.x, point.y, tuple(room.i for room in point.rooms)) for point in self.points)
|
{name: level.serialize() for name, level in self.levels.items()},
|
||||||
connections = tuple((conn.from_point.i, conn.to_point.i, conn.distance) for conn in self.connections)
|
[point.serialize() for point in self.points],
|
||||||
|
self.level_transfer_points,
|
||||||
return rooms, points, connections
|
)
|
||||||
|
|
||||||
def save(self, filename=None):
|
def save(self, filename=None):
|
||||||
if filename is None:
|
if filename is None:
|
||||||
|
@ -113,24 +114,14 @@ class Graph:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unserialize(cls, data):
|
def unserialize(cls, data):
|
||||||
|
levels, points, level_transfer_points = data
|
||||||
|
|
||||||
graph = cls()
|
graph = cls()
|
||||||
rooms, points, connections = data
|
|
||||||
|
|
||||||
graph.rooms = [GraphRoom(graph.levels[room[0]], mpl_clear=room[1]) for room in rooms]
|
|
||||||
graph.points = [GraphPoint(point[0], point[1], rooms=tuple(graph.rooms[i] for i in point[2]))
|
|
||||||
for point in points]
|
|
||||||
|
|
||||||
for point in graph.points:
|
|
||||||
for room in point.rooms:
|
|
||||||
room.points.append(point)
|
|
||||||
|
|
||||||
for name, level in graph.levels.items():
|
for name, level in graph.levels.items():
|
||||||
level.rooms = [room for room in graph.rooms if room.level == level]
|
level.unserialize(levels[name])
|
||||||
level.points = list(set(sum((room.points for room in level.rooms), [])))
|
|
||||||
level.room_transfer_points = [point for point in level.points if len(point.rooms) > 1]
|
|
||||||
|
|
||||||
for from_point, to_point, distance in connections:
|
graph.points = tuple(GraphPoint(*point) for point in points)
|
||||||
graph.add_connection(graph.points[from_point], graph.points[to_point], distance)
|
graph.level_transfer_points = level_transfer_points
|
||||||
|
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
|
@ -140,6 +131,7 @@ class Graph:
|
||||||
filename = cls.default_filename
|
filename = cls.default_filename
|
||||||
with open(filename, 'rb') as f:
|
with open(filename, 'rb') as f:
|
||||||
graph = cls.unserialize(pickle.load(f))
|
graph = cls.unserialize(pickle.load(f))
|
||||||
|
graph.print_stats()
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
# Drawing
|
# Drawing
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
from shapely.geometry import JOIN_STYLE
|
from shapely.geometry import JOIN_STYLE
|
||||||
|
@ -15,15 +16,32 @@ class GraphLevel():
|
||||||
def __init__(self, graph, level):
|
def __init__(self, graph, level):
|
||||||
self.graph = graph
|
self.graph = graph
|
||||||
self.level = level
|
self.level = level
|
||||||
|
self.rooms = []
|
||||||
|
|
||||||
self.points = []
|
self.points = []
|
||||||
self.room_transfer_points = []
|
self.room_transfer_points = None
|
||||||
self.rooms = []
|
self.level_transfer_points = None
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
return (
|
||||||
|
[room.serialize() for room in self.rooms],
|
||||||
|
self.points,
|
||||||
|
self.room_transfer_points,
|
||||||
|
self.level_transfer_points,
|
||||||
|
)
|
||||||
|
|
||||||
|
def unserialize(self, data):
|
||||||
|
rooms, self.points, self.room_transfer_points, self.level_transfer_points = data
|
||||||
|
self.rooms = tuple(GraphRoom.unserialize(self, room) for room in rooms)
|
||||||
|
|
||||||
# Building the Graph
|
# Building the Graph
|
||||||
def build(self):
|
def build(self):
|
||||||
print()
|
print()
|
||||||
print('Level %s:' % self.level.name)
|
print('Level %s:' % self.level.name)
|
||||||
|
|
||||||
|
self._built_points = []
|
||||||
|
self._built_room_transfer_points = []
|
||||||
|
|
||||||
self.collect_rooms()
|
self.collect_rooms()
|
||||||
print('%d rooms' % len(self.rooms))
|
print('%d rooms' % len(self.rooms))
|
||||||
|
|
||||||
|
@ -34,21 +52,21 @@ class GraphLevel():
|
||||||
self.create_doors()
|
self.create_doors()
|
||||||
self.create_levelconnectors()
|
self.create_levelconnectors()
|
||||||
|
|
||||||
self.points = sum((room.points for room in self.rooms), [])
|
self._built_points = sum((room._built_points for room in self.rooms), [])
|
||||||
self.points.extend(self.room_transfer_points)
|
self._built_points.extend(self._built_room_transfer_points)
|
||||||
|
|
||||||
for room in self.rooms:
|
for room in self.rooms:
|
||||||
room.build_connections()
|
room.build_connections()
|
||||||
|
|
||||||
print('%d points' % len(self.points))
|
print('%d points' % len(self._built_points))
|
||||||
print('%d room transfer points' % len(self.room_transfer_points))
|
print('%d room transfer points' % len(self._built_room_transfer_points))
|
||||||
|
|
||||||
def collect_rooms(self):
|
def collect_rooms(self):
|
||||||
accessibles = self.level.geometries.accessible
|
accessibles = self.level.geometries.accessible
|
||||||
accessibles = assert_multipolygon(accessibles)
|
accessibles = assert_multipolygon(accessibles)
|
||||||
for geometry in accessibles:
|
for geometry in accessibles:
|
||||||
room = GraphRoom(self, geometry)
|
room = GraphRoom(self)
|
||||||
if room.prepare_build():
|
if room.prepare_build(geometry):
|
||||||
self.rooms.append(room)
|
self.rooms.append(room)
|
||||||
|
|
||||||
def create_doors(self):
|
def create_doors(self):
|
||||||
|
@ -62,14 +80,13 @@ class GraphLevel():
|
||||||
connected_rooms = set()
|
connected_rooms = set()
|
||||||
points = []
|
points = []
|
||||||
for room in self.rooms:
|
for room in self.rooms:
|
||||||
if not polygon.intersects(room.geometry):
|
if not polygon.intersects(room._built_geometry):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for subpolygon in assert_multipolygon(polygon.intersection(room.geometry)):
|
for subpolygon in assert_multipolygon(polygon.intersection(room._built_geometry)):
|
||||||
connected_rooms.add(room)
|
connected_rooms.add(room)
|
||||||
nearest_point = get_nearest_point(room.clear_geometry, subpolygon.centroid)
|
nearest_point = get_nearest_point(room.clear_geometry, subpolygon.centroid)
|
||||||
point, = room.add_point(nearest_point.coords[0])
|
point, = room.add_point(nearest_point.coords[0])
|
||||||
room.points.append(point)
|
|
||||||
points.append(point)
|
points.append(point)
|
||||||
|
|
||||||
if len(points) < 2:
|
if len(points) < 2:
|
||||||
|
@ -77,30 +94,39 @@ class GraphLevel():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
center_point = GraphPoint(center.x, center.y, rooms=tuple(connected_rooms))
|
center_point = GraphPoint(center.x, center.y, rooms=tuple(connected_rooms))
|
||||||
self.room_transfer_points.append(center_point)
|
self._built_room_transfer_points.append(center_point)
|
||||||
for room in connected_rooms:
|
for room in connected_rooms:
|
||||||
room.points.append(center_point)
|
room._built_points.append(center_point)
|
||||||
|
|
||||||
for point in points:
|
for point in points:
|
||||||
self.graph.add_connection(center_point, point)
|
center_point.connect_to(point)
|
||||||
self.graph.add_connection(point, center_point)
|
point.connect_to(center_point)
|
||||||
|
|
||||||
def create_levelconnectors(self):
|
def create_levelconnectors(self):
|
||||||
for levelconnector in self.level.levelconnectors.all():
|
for levelconnector in self.level.levelconnectors.all():
|
||||||
polygon = levelconnector.geometry
|
polygon = levelconnector.geometry
|
||||||
|
|
||||||
for room in self.rooms:
|
for room in self.rooms:
|
||||||
if not polygon.intersects(room.geometry):
|
if not polygon.intersects(room._built_geometry):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for subpolygon in assert_multipolygon(polygon.intersection(room.geometry)):
|
for subpolygon in assert_multipolygon(polygon.intersection(room._built_geometry)):
|
||||||
point = subpolygon.centroid
|
point = subpolygon.centroid
|
||||||
if not point.within(room.clear_geometry):
|
if not point.within(room.clear_geometry):
|
||||||
point = get_nearest_point(room.clear_geometry, point)
|
point = get_nearest_point(room.clear_geometry, point)
|
||||||
point, = room.add_point(point.coords[0])
|
point, = room.add_point(point.coords[0])
|
||||||
room.points.append(point)
|
room._built_points.append(point)
|
||||||
self.graph.add_levelconnector_point(levelconnector, point)
|
self.graph.add_levelconnector_point(levelconnector, point)
|
||||||
|
|
||||||
|
def finish_build(self):
|
||||||
|
self.rooms = tuple(self.rooms)
|
||||||
|
self.points = np.array(tuple(point.i for point in self._built_points))
|
||||||
|
self.room_transfer_points = np.array(tuple(point.i for point in self._built_room_transfer_points))
|
||||||
|
self.level_transfer_points = np.array(tuple(i for i in self.points if i in self.graph.level_transfer_points))
|
||||||
|
|
||||||
|
for room in self.rooms:
|
||||||
|
room.finish_build()
|
||||||
|
|
||||||
# Drawing
|
# 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)
|
||||||
|
@ -118,10 +144,10 @@ class GraphLevel():
|
||||||
for point in self.points:
|
for point in self.points:
|
||||||
draw.ellipse(_ellipse_bbox(point.x, point.y, height), (200, 0, 0))
|
draw.ellipse(_ellipse_bbox(point.x, point.y, height), (200, 0, 0))
|
||||||
|
|
||||||
for point in self.room_transfer_points:
|
for point in self._built_room_transfer_points:
|
||||||
draw.ellipse(_ellipse_bbox(point.x, point.y, height), (0, 0, 255))
|
draw.ellipse(_ellipse_bbox(point.x, point.y, height), (0, 0, 255))
|
||||||
|
|
||||||
for point in self.room_transfer_points:
|
for point in self._built_room_transfer_points:
|
||||||
for otherpoint, connection in point.connections.items():
|
for otherpoint, connection in point.connections.items():
|
||||||
draw.line(_line_coords(point, otherpoint, height), fill=(0, 255, 255))
|
draw.line(_line_coords(point, otherpoint, height), fill=(0, 255, 255))
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ import numpy as np
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
from c3nav.routing.connection import GraphConnection
|
||||||
|
|
||||||
|
|
||||||
class GraphPoint():
|
class GraphPoint():
|
||||||
def __init__(self, x, y, room=None, rooms=None):
|
def __init__(self, x, y, room=None, rooms=None):
|
||||||
|
@ -13,8 +15,19 @@ class GraphPoint():
|
||||||
self.connections = {}
|
self.connections = {}
|
||||||
self.connections_in = {}
|
self.connections_in = {}
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
return (
|
||||||
|
self.x,
|
||||||
|
self.y,
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ellipse_bbox(self):
|
def ellipse_bbox(self):
|
||||||
x = self.x * settings.RENDER_SCALE
|
x = self.x * settings.RENDER_SCALE
|
||||||
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):
|
||||||
|
connection = GraphConnection(self, other_point)
|
||||||
|
self.connections[other_point] = connection
|
||||||
|
other_point.connections_in[self] = connection
|
||||||
|
|
|
@ -11,23 +11,41 @@ from c3nav.routing.utils.mpl import shapely_to_mpl
|
||||||
|
|
||||||
|
|
||||||
class GraphRoom():
|
class GraphRoom():
|
||||||
def __init__(self, level, geometry=None, mpl_clear=None):
|
def __init__(self, level):
|
||||||
self.level = level
|
self.level = level
|
||||||
self.graph = level.graph
|
self.graph = level.graph
|
||||||
|
|
||||||
self.geometry = geometry
|
self.mpl_clear = None
|
||||||
self.mpl_clear = mpl_clear
|
|
||||||
|
|
||||||
self.areas = []
|
self.areas = []
|
||||||
self.points = []
|
self.points = None
|
||||||
|
self.room_transfer_points = None
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
return (
|
||||||
|
self.mpl_clear,
|
||||||
|
[area.serialize() for area in self.areas],
|
||||||
|
self.points,
|
||||||
|
self.room_transfer_points,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def unserialize(cls, level, data):
|
||||||
|
room = cls(level)
|
||||||
|
room.mpl_clear, areas, room.points, room.room_transfer_points = data
|
||||||
|
room.areas = tuple(GraphArea(room, *area) for area in areas)
|
||||||
|
return room
|
||||||
|
|
||||||
# Building the Graph
|
# Building the Graph
|
||||||
def prepare_build(self):
|
def prepare_build(self, geometry):
|
||||||
self.clear_geometry = self.geometry.buffer(-0.3, join_style=JOIN_STYLE.mitre)
|
self._built_geometry = geometry
|
||||||
|
self.clear_geometry = self._built_geometry.buffer(-0.3, join_style=JOIN_STYLE.mitre)
|
||||||
|
|
||||||
if self.clear_geometry.is_empty:
|
if self.clear_geometry.is_empty:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
self._built_points = []
|
||||||
|
|
||||||
self.mpl_clear = shapely_to_mpl(self.clear_geometry.buffer(0.01, join_style=JOIN_STYLE.mitre))
|
self.mpl_clear = shapely_to_mpl(self.clear_geometry.buffer(0.01, join_style=JOIN_STYLE.mitre))
|
||||||
self.mpl_stairs = ()
|
self.mpl_stairs = ()
|
||||||
for stair_line in assert_multilinestring(self.level.level.geometries.stairs):
|
for stair_line in assert_multilinestring(self.level.level.geometries.stairs):
|
||||||
|
@ -40,7 +58,7 @@ class GraphRoom():
|
||||||
def build_areas(self):
|
def build_areas(self):
|
||||||
stairs_areas = self.level.level.geometries.stairs
|
stairs_areas = self.level.level.geometries.stairs
|
||||||
stairs_areas = stairs_areas.buffer(0.3, join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat)
|
stairs_areas = stairs_areas.buffer(0.3, join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat)
|
||||||
stairs_areas = stairs_areas.intersection(self.geometry)
|
stairs_areas = stairs_areas.intersection(self._built_geometry)
|
||||||
self.stairs_areas = assert_multipolygon(stairs_areas)
|
self.stairs_areas = assert_multipolygon(stairs_areas)
|
||||||
|
|
||||||
isolated_areas = tuple(assert_multipolygon(stairs_areas.intersection(self.clear_geometry)))
|
isolated_areas = tuple(assert_multipolygon(stairs_areas.intersection(self.clear_geometry)))
|
||||||
|
@ -50,10 +68,12 @@ class GraphRoom():
|
||||||
mpl_clear = shapely_to_mpl(isolated_area.buffer(0.01, join_style=JOIN_STYLE.mitre))
|
mpl_clear = shapely_to_mpl(isolated_area.buffer(0.01, join_style=JOIN_STYLE.mitre))
|
||||||
mpl_stairs = tuple((stair, angle) for stair, angle in self.mpl_stairs
|
mpl_stairs = tuple((stair, angle) for stair, angle in self.mpl_stairs
|
||||||
if mpl_clear.intersects_path(stair, filled=True))
|
if mpl_clear.intersects_path(stair, filled=True))
|
||||||
self.areas.append(GraphArea(self, mpl_clear, mpl_stairs))
|
area = GraphArea(self, mpl_clear, mpl_stairs)
|
||||||
|
area.prepare_build()
|
||||||
|
self.areas.append(area)
|
||||||
|
|
||||||
def build_points(self):
|
def build_points(self):
|
||||||
narrowed_geometry = self.geometry.buffer(-0.6, join_style=JOIN_STYLE.mitre)
|
narrowed_geometry = self._built_geometry.buffer(-0.6, join_style=JOIN_STYLE.mitre)
|
||||||
geometry = narrowed_geometry.buffer(0.31, join_style=JOIN_STYLE.mitre).intersection(self.clear_geometry)
|
geometry = narrowed_geometry.buffer(0.31, join_style=JOIN_STYLE.mitre).intersection(self.clear_geometry)
|
||||||
|
|
||||||
if geometry.is_empty:
|
if geometry.is_empty:
|
||||||
|
@ -150,7 +170,7 @@ class GraphRoom():
|
||||||
if not self.mpl_clear.contains_point(coord):
|
if not self.mpl_clear.contains_point(coord):
|
||||||
return []
|
return []
|
||||||
point = GraphPoint(coord[0], coord[1], self)
|
point = GraphPoint(coord[0], coord[1], self)
|
||||||
self.points.append(point)
|
self._built_points.append(point)
|
||||||
for area in self.areas:
|
for area in self.areas:
|
||||||
area.add_point(point)
|
area.add_point(point)
|
||||||
return [point]
|
return [point]
|
||||||
|
@ -159,7 +179,15 @@ class GraphRoom():
|
||||||
for area in self.areas:
|
for area in self.areas:
|
||||||
area.build_connections()
|
area.build_connections()
|
||||||
|
|
||||||
|
def finish_build(self):
|
||||||
|
self.areas = tuple(self.areas)
|
||||||
|
self.points = np.array(tuple(point.i for point in self._built_points))
|
||||||
|
self.room_transfer_points = np.array(tuple(i for i in self.points if i in self.level.room_transfer_points))
|
||||||
|
|
||||||
|
for area in self.areas:
|
||||||
|
area.finish_build()
|
||||||
|
|
||||||
# Routing
|
# Routing
|
||||||
def build_router(self):
|
def build_router(self):
|
||||||
self.router = Router()
|
self.router = Router()
|
||||||
self.router.build(self.points)
|
self.router.build(self._built_points)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue