def create_doors(self): doors = self.level.geometries.doors doors = assert_multipolygon(doors) for door in doors: polygon = door.buffer(0.01, join_style=JOIN_STYLE.mitre) center = door.centroid num_points = 0 connected_rooms = set() points = [] for room in self.rooms: if not polygon.intersects(room._built_geometry): continue for subpolygon in assert_multipolygon(polygon.intersection(room._built_geometry)): connected_rooms.add(room) nearest_point = get_nearest_point(room.clear_geometry, subpolygon.centroid) point, = room.add_point(nearest_point.coords[0]) points.append(point) if len(points) < 2: print('door with <2 points (%d) detected at (%.2f, %.2f)' % (num_points, center.x, center.y)) continue center_point = GraphPoint(center.x, center.y, None) self._built_room_transfer_points.append(center_point) for room in connected_rooms: room._built_points.append(center_point) for point in points: center_point.connect_to(point) point.connect_to(center_point)
def connect_levelconnectors(self): for levelconnector in LevelConnector.objects.all(): center = levelconnector.geometry.centroid points = self._built_levelconnector_points.get( levelconnector.name, []) rooms = set(point.room for point in points if point.room is not None) connected_levels = set(room.level for room in rooms) should_levels = tuple(level.name for level in levelconnector.levels.all()) missing_levels = set(should_levels) - set( level.level.name for level in connected_levels) if missing_levels: print( 'levelconnector %s on levels %s at (%.2f, %.2f) is not connected to levels %s!' % (levelconnector.name, ', '.join(should_levels), center.x, center.y, ', '.join(missing_levels))) continue center_point = GraphPoint(center.x, center.y, None) self.points.append(center_point) self._built_level_transfer_points.append(center_point) for level in connected_levels: level._built_room_transfer_points.append(center_point) level._built_points.append(center_point) for room in rooms: room._built_points.append(center_point) for point in points: center_point.connect_to(point) point.connect_to(center_point)
def add_point(self, coord): if not self.mpl_clear.contains_point(coord): return [] point = GraphPoint(coord[0], coord[1], self) self._built_points.append(point) for area in self.areas: area.add_point(point) return [point]
def create_oneways(self): oneways = self.level.geometries.oneways oneways = assert_multilinestring(oneways) segments = () for oneway in oneways: coords = tuple(oneway.coords) segments += tuple((Path(part), coord_angle(*part)) for part in zip(coords[:-1], coords[1:])) for oneway, oneway_angle in segments: line_string = LineString(tuple(oneway.vertices)) polygon = line_string.buffer(0.10, join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat) center = polygon.centroid num_points = 0 connected_rooms = set() points = [] for room in self.rooms: if not polygon.intersects(room._built_geometry): continue for subpolygon in assert_multipolygon(polygon.intersection(room._built_geometry)): connected_rooms.add(room) nearest_point = get_nearest_point(room.clear_geometry, subpolygon.centroid) point, = room.add_point(nearest_point.coords[0]) points.append(point) if len(points) < 2: print('oneway with <2 points (%d) detected at (%.2f, %.2f)' % (num_points, center.x, center.y)) continue center_point = GraphPoint(center.x, center.y, None) self._built_room_transfer_points.append(center_point) for room in connected_rooms: room._built_points.append(center_point) for point in points: angle = coord_angle(point.xy, center_point.xy) angle_diff = ((oneway_angle - angle + 180) % 360) - 180 direction_up = (angle_diff > 0) if direction_up: point.connect_to(center_point) else: center_point.connect_to(point)
def split(self): connections = self.segmentroute.rawsplit() if self.orig_point: first_point = connections[0].from_point orig_point = GraphPoint(self.orig_point.x, self.orig_point.y, first_point.room) connections = (GraphConnection( orig_point, first_point, ctype=self.orig_ctype), ) + connections if self.dest_point: last_point = connections[-1].to_point dest_point = GraphPoint(self.dest_point.x, self.dest_point.y, last_point.room) connections = connections + (GraphConnection( last_point, dest_point, ctype=self.dest_ctype), ) return Route(connections)
def unserialize(cls, data, mtime): levels, points, level_transfer_points = data graph = cls(mtime=mtime) for name, level in levels.items(): graph.levels[name].unserialize(level) rooms = sum((level.rooms for level in graph.levels.values()), ()) graph.points = tuple( GraphPoint(x, y, None if room is None else rooms[room]) for x, y, room in points) graph.level_transfer_points = level_transfer_points for i, room in enumerate(rooms): room.i = i for i, point in enumerate(graph.points): point.i = i return graph
def connect_elevators(self): for elevator in Elevator.objects.all(): elevatorlevels = tuple(elevator.elevatorlevels.all()) for level1, level2 in combinations(elevatorlevels, 2): point1 = self._built_elevatorlevel_points[level1.name] point2 = self._built_elevatorlevel_points[level2.name] center = GraphPoint((point1.x + point2.x) / 2, (point1.y + point2.y) / 2, None) self.points.append(center) self._built_level_transfer_points.append(center) for room in (point1.room, point2.room): room._built_points.append(center) room.level._built_room_transfer_points.append(center) room.level._built_points.append(center) direction_up = level2.altitude > level1.altitude dist = abs(level2.altitude - level1.altitude) point1.connect_to( center, ctype=('elevator_up' if direction_up else 'elevator_down'), distance=dist) center.connect_to( point2, ctype=('elevator_up' if direction_up else 'elevator_down'), distance=dist) point2.connect_to( center, ctype=('elevator_down' if direction_up else 'elevator_up'), distance=dist) center.connect_to( point1, ctype=('elevator_down' if direction_up else 'elevator_up'), distance=dist)
def get_route(self, origin: Location, destination: Location, allowed_ctypes, allow_nonpublic, avoid, include, visible_nonpublic_areas=None): orig_points_i, orig_distances, orig_ctypes = self.get_location_points( origin, 'orig') dest_points_i, dest_distances, dest_ctypes = self.get_location_points( destination, 'dest') if not len(orig_points_i) or not len(dest_points_i): raise NoRouteFound() if orig_distances is None and dest_distances is None: if set(dest_points_i) & set(orig_points_i): orig_points_i = tuple(set(orig_points_i) - set(dest_points_i)) if set(dest_points_i) & set(orig_points_i): dest_points_i = tuple(set(dest_points_i) - set(orig_points_i)) if not len(orig_points_i) or not len(dest_points_i): raise AlreadyThere() #if set(orig_points_i) & set(dest_points_i): # raise AlreadyThere() add_orig_point = origin if isinstance(origin, PointLocation) else None add_dest_point = destination if isinstance(destination, PointLocation) else None orig_points = self._get_points_by_i(orig_points_i) dest_points = self._get_points_by_i(dest_points_i) common_points = tuple(set(orig_points) & set(dest_points)) best_route = NoRoute # get routers routers = self.build_routers(allowed_ctypes, allow_nonpublic, avoid, include) # route within room orig_rooms = set(point.room for point in orig_points) dest_rooms = set(point.room for point in dest_points) common_rooms = orig_rooms & dest_rooms # rooms are directly connectable if add_orig_point and add_dest_point and common_rooms: room = tuple(common_rooms)[0] ctype = room.check_connection((add_orig_point.x, add_orig_point.y), (add_dest_point.x, add_dest_point.y)) if ctype is not None: from_point = GraphPoint(add_orig_point.x, add_orig_point.y, room) to_point = GraphPoint(add_dest_point.x, add_dest_point.y, room) return Route((GraphConnection(from_point, to_point, ctype=ctype), )) if common_points: # same location if not add_orig_point and not add_dest_point: raise AlreadyThere() # points are connectable with only one via best_point = None best_distance = np.inf for point in common_points: distance = 0 if add_orig_point: distance += abs( np.linalg.norm(add_orig_point.xy - point.xy)) if add_dest_point: distance += abs( np.linalg.norm(add_dest_point.xy - point.xy)) if distance < best_distance: best_distance = distance best_point = point connections = [] if add_orig_point: from_point = GraphPoint(add_orig_point.x, add_orig_point.y, best_point.room) ctype = orig_ctypes[tuple(orig_points_i).index(best_point.i)] connections.append( GraphConnection(from_point, best_point, ctype=ctype)) if add_dest_point: to_point = GraphPoint(add_dest_point.x, add_dest_point.y, best_point.room) ctype = dest_ctypes[tuple(dest_points_i).index(best_point.i)] connections.append( GraphConnection(best_point, to_point, ctype=ctype)) return Route(connections) # get origin points for each room (points as point index within room) orig_room_points = { room: self._allowed_points_index(room.points, orig_points_i) for room in orig_rooms } dest_room_points = { room: self._allowed_points_index(room.points, dest_points_i) for room in dest_rooms } # add distances to room routers if orig_distances is not None: for room in orig_rooms: distances = np.array( tuple(orig_distances[room.points[i]] for i in orig_room_points[room])) routers[room].shortest_paths[ orig_room_points[room], :] += distances[:, None] if dest_distances is not None: for room in dest_rooms: distances = np.array( tuple(dest_distances[room.points[i]] for i in dest_room_points[room])) routers[ room].shortest_paths[:, dest_room_points[room]] += distances # if the points have common rooms, search for routes within those rooms if common_rooms: for room in common_rooms: shortest_paths = routers[room].shortest_paths[ orig_room_points[room][:, None], dest_room_points[room]] distance = shortest_paths.min() # Is this route better than the previous ones? if distance >= best_route.distance: continue # noinspection PyTypeChecker from_point, to_point = np.argwhere( shortest_paths == distance)[0] from_point = orig_room_points[room][from_point] to_point = dest_room_points[room][to_point] best_route = RoomRouteSegment(room, routers, from_point, to_point).as_route() # get reachable room transfer points and their distance # as a dictionary: global transfer point index => RoomRouteSegment orig_room_transfers = self._room_transfers(orig_rooms, orig_room_points, routers, mode='orig') dest_room_transfers = self._room_transfers(dest_rooms, dest_room_points, routers, mode='dest') # route within level orig_levels = set(room.level for room in orig_rooms) dest_levels = set(room.level for room in dest_rooms) common_levels = orig_levels & dest_levels # get reachable roomtransfer points for each level (points as room transfer point index within level) orig_room_transfer_points = { level: self._allowed_points_index(level.room_transfer_points, orig_room_transfers) for level in orig_levels } dest_room_transfer_points = { level: self._allowed_points_index(level.room_transfer_points, dest_room_transfers) for level in dest_levels } # if the points have common levels, search for routes within those levels if common_levels: for level in common_levels: o_points = orig_room_transfer_points[level] d_points = dest_room_transfer_points[level] if not len(o_points) or not len(d_points): continue shortest_paths = routers[level].shortest_paths[o_points[:, None], d_points] # add distances to the the room transfer points to the rows and columns shortest_paths += np.array( tuple(orig_room_transfers[ level.room_transfer_points[in_level_i]].distance for in_level_i in o_points))[:, None] shortest_paths += np.array( tuple(dest_room_transfers[ level.room_transfer_points[in_level_i]].distance for in_level_i in d_points)) distance = shortest_paths.min() # Is this route better than the previous ones? if distance >= best_route.distance: continue # noinspection PyTypeChecker from_point, to_point = np.argwhere( shortest_paths == distance)[0] from_point = o_points[from_point] to_point = d_points[to_point] best_route = SegmentRoute(( orig_room_transfers[ level.room_transfer_points[from_point]], LevelRouteSegment(level, routers, from_point, to_point), dest_room_transfers[level.room_transfer_points[to_point]]), distance=distance) # get reachable level transfer points and their distance # as a dictionary: global transfer point index => Route orig_level_transfers = self._level_transfers(orig_levels, orig_room_transfers, routers, mode='orig') dest_level_transfers = self._level_transfers(dest_levels, dest_room_transfers, routers, mode='dest') # 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) dest_level_transfer_points = self._allowed_points_index( self.level_transfer_points, dest_level_transfers) # search a route within the whole graph o_points = orig_level_transfer_points d_points = dest_level_transfer_points if len(o_points) and len(d_points): shortest_paths = routers[self].shortest_paths[o_points[:, None], d_points] # add distances to the the room transfer points to the rows and columns shortest_paths += np.array( tuple(orig_level_transfers[ self.level_transfer_points[in_graph_i]].distance for in_graph_i in o_points))[:, None] shortest_paths += np.array( tuple(dest_level_transfers[ self.level_transfer_points[in_graph_i]].distance for in_graph_i in d_points)) distance = shortest_paths.min() # Is this route better than the previous ones? if distance < best_route.distance: # noinspection PyTypeChecker from_point, to_point = np.argwhere( shortest_paths == distance)[0] from_point = o_points[from_point] to_point = d_points[to_point] best_route = SegmentRoute( (orig_level_transfers[ self.level_transfer_points[from_point]], GraphRouteSegment(self, routers, from_point, to_point), dest_level_transfers[self.level_transfer_points[to_point]] ), distance=distance) if best_route is NoRoute: raise NoRouteFound() orig_ctype = orig_ctypes[tuple(orig_points_i).index( best_route.from_point)] if add_orig_point else None dest_ctype = dest_ctypes[tuple(dest_points_i).index( best_route.to_point)] if add_dest_point else None best_route = SegmentRouteWrapper(best_route, orig_point=add_orig_point, dest_point=add_dest_point, orig_ctype=orig_ctype, dest_ctype=dest_ctype) best_route = best_route.split() return best_route