Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
 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]
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
    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