Ejemplo n.º 1
0
    def test_find_isolated_vertices(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, c], e: [c], f: []}

        graph = Graph(g)
        assert graph.find_isolated_vertices() == [f]
Ejemplo n.º 2
0
    def test_astar_no_valid_path(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, b, c], e: [c], f: []}

        graph = Graph(g)
        path = graph.astar(a, f)

        assert path.path is None
Ejemplo n.º 3
0
    def __init__(
        self,
        grid: AGrid,
        connect_adjacents: bool = True,
        connect_diagonals: bool = True,
    ):
        self._diagonal_connections = {}
        self._connect_adjacents = connect_adjacents
        self._connect_diagonals = connect_diagonals

        self.grid = grid
        self.pos_node_map = self._build_position_node_map(
            ncols=self.grid.nColumns, nrows=self.grid.nRows)
        graph_dict = self.graph_dict_provider(self.pos_node_map)
        self.graph = Graph(graph_dict=graph_dict)
Ejemplo n.º 4
0
    def test_nodes_at__single(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, c], e: [c], f: []}

        graph = Graph(g)

        nodes = graph.nodes_at_point(Vector2(0, 0))

        assert nodes == [a]
Ejemplo n.º 5
0
    def test_closest_node__base(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, b, c], e: [c], f: []}

        graph = Graph(g)

        test = Vector2(0, 1)
        closest = graph.closest_nodes(test)[0]
        assert closest == a
        f"{closest}"
Ejemplo n.º 6
0
    def test__path_length(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, c], e: [c, f], f: []}

        graph = Graph(g)
        path = [a, d, c, e]
        length = graph.path_length(path)

        assert length == d.pos.distance_from(a.pos) + c.pos.distance_from(
            d.pos) + e.pos.distance_from(c.pos)
Ejemplo n.º 7
0
    def test_add_node_with_connnections__base(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, b, c], e: [c], f: []}

        graph = Graph(g)

        h = Node('H', Vector2(100, 100))

        graph.add_node_with_connnections(h, {
            a: EdgeDirection.FROM,
            b: EdgeDirection.TO,
            c: EdgeDirection.TWOWAY
        })

        assert h in graph.nodes

        assert graph.edge_between(a, h) is not None
        assert graph.edge_between(h, a) is None
        assert graph.edge_between(b, h) is None
        assert graph.edge_between(h, b) is not None
        assert graph.edge_between(c, h) is not None
        assert graph.edge_between(h, c) is not None
Ejemplo n.º 8
0
    def test_copy__base(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, b, c], e: [c], f: []}

        graph = Graph(g)

        copy = graph.copy()

        assert len(copy.nodes) == len(graph.nodes)
        assert len(copy.edges) == len(graph.edges)
        assert (edge.disablers() == graph.edge_between(edge.start,
                                                       edge.end).disablers()
                for edge in copy.edges)
Ejemplo n.º 9
0
    def test_add_node(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, c], e: [c, f], f: []}

        graph = Graph(g)

        assert len(graph.nodes) == 6
        assert graph.nodes == [a, b, c, d, e, f]

        h = Node(name='H', pos=Vector2(6, 5))
        graph.add_node(h)

        assert len(graph.nodes) == 7
        assert graph.nodes == [a, b, c, d, e, f, h]
Ejemplo n.º 10
0
    def init_a_test_graph(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, c], e: [c, f], f: []}

        return Graph(g)
Ejemplo n.º 11
0
    def test__edge_by_id(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, b, c], e: [c], f: []}

        graph = Graph(g)

        edge = graph.edge_between(a, d)

        self.assertIsNotNone(edge,
                             "Edge was returned none when expected value")

        edge_ret = graph.edges_by_id([edge.id])[0]

        self.assertEqual(
            edge, edge_ret,
            f"returned edge {edge_ret} [{edge_ret.id}] does not match {edge} [{edge.id}]"
        )
Ejemplo n.º 12
0
    def test_disable_edges(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, b, c], e: [c, f], f: []}

        graph = Graph(g)
        graph.disable_edges(graph.edge_between(d, c), "BLOCK")
        assert graph.edge_between(d, c).disablers() == {"BLOCK"}
Ejemplo n.º 13
0
    def test__astar_with_disablers(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, b, c], e: [c, f], f: []}

        graph = Graph(g)
        graph.disable_edges(graph.edge_between(d, c), "BLOCK")

        path = graph.astar(a, e)

        assert path.path == [a, d, b, c, e]
Ejemplo n.º 14
0
    def test_edges_to_node(self):
        a = Node(name='A', pos=Vector2(0, 0))
        b = Node(name='B', pos=Vector2(3, 3))
        c = Node(name='C', pos=Vector2(2, 0))
        d = Node(name='D', pos=Vector2(2, 1))
        e = Node(name='E', pos=Vector2(3, 4))
        f = Node(name='F', pos=Vector2(5, 5))

        g = {a: [d], b: [c], c: [b, d, e], d: [a, c], e: [c, f], f: []}

        graph = Graph(g)

        assert set(graph.edges_to_node(c)) == {
            graph.edge_between(b, c),
            graph.edge_between(d, c),
            graph.edge_between(e, c),
            graph.edge_between(c, b),
            graph.edge_between(c, d),
            graph.edge_between(c, e)
        }
Ejemplo n.º 15
0
class GridGraph:
    def __init__(
        self,
        grid: AGrid,
        connect_adjacents: bool = True,
        connect_diagonals: bool = True,
    ):
        self._diagonal_connections = {}
        self._connect_adjacents = connect_adjacents
        self._connect_diagonals = connect_diagonals

        self.grid = grid
        self.pos_node_map = self._build_position_node_map(
            ncols=self.grid.nColumns, nrows=self.grid.nRows)
        graph_dict = self.graph_dict_provider(self.pos_node_map)
        self.graph = Graph(graph_dict=graph_dict)

    def _build_position_node_map(self, ncols: int, nrows: int):
        pos_node_map = {}
        for col in range(0, ncols):
            for row in range(0, nrows):
                pos = Vector2(row, col)
                pos_node_map[pos] = Node(str(pos), pos)

        return pos_node_map

    def graph_dict_provider(
            self, pos_node_map: Dict[IVector, Node]) -> Dict[Node, List[Node]]:
        return self.build_graph_dict(pos_node_map,
                                     connect_adjacents=self._connect_adjacents,
                                     connect_diagonals=self._connect_diagonals)

    def build_graph_dict(
            self,
            pos_node_map: Dict[IVector, Node],
            connect_adjacents: bool = True,
            connect_diagonals: bool = True) -> Dict[Node, List[Node]]:
        graph_dict = {}

        for pos in pos_node_map.keys():
            graph_dict[pos_node_map[pos]] = []
            adjacents = [
                Vector2(pos.x - 1, pos.y) if pos_node_map.get(
                    Vector2(pos.x - 1, pos.y), None) else None,  # left
                Vector2(pos.x + 1, pos.y) if pos_node_map.get(
                    Vector2(pos.x + 1, pos.y), None) else None,  # right
                Vector2(pos.x, pos.y - 1) if pos_node_map.get(
                    Vector2(pos.x, pos.y - 1), None) else None,  # up
                Vector2(pos.x, pos.y + 1) if pos_node_map.get(
                    Vector2(pos.x, pos.y + 1), None) else None,  # down
            ]

            diagonals = [
                Vector2(pos.x - 1, pos.y -
                        1) if pos_node_map.get(Vector2(pos.x - 1, pos.y -
                                                       1), None) else None,
                # UpLeft
                Vector2(pos.x + 1, pos.y -
                        1) if pos_node_map.get(Vector2(pos.x + 1, pos.y -
                                                       1), None) else None,
                # UpRight
                Vector2(pos.x - 1, pos.y +
                        1) if pos_node_map.get(Vector2(pos.x - 1, pos.y +
                                                       1), None) else None,
                # DownLeft
                Vector2(pos.x + 1, pos.y +
                        1) if pos_node_map.get(Vector2(pos.x + 1, pos.y +
                                                       1), None) else None
                # DownRight
            ]

            connections = []

            # add adjacents to connections list
            if connect_adjacents:
                connections += adjacents

            # add diagonals to connections list
            if connect_diagonals:
                connections += diagonals

            # add diagonal connections to a saved dict for quick id later
            for connection in diagonals:
                if connection:
                    self._diagonal_connections.setdefault(
                        pos, []).append(connection)

            # add connections to the graph_dict for each node
            for connection_pos in connections:
                try:
                    if connection_pos:
                        graph_dict[pos_node_map[pos]].append(
                            pos_node_map[connection_pos])
                except:
                    print(f"{connection_pos} \n" f"{pos_node_map}")
                    print(f"connection pos: {type(connection_pos)}")
                    print(
                        f"first pos_node_map pos: {type([x for x in pos_node_map.keys()][0])}"
                    )
                    raise
        return graph_dict

    def toggle_allow_diagonal_connections(self, disabler):
        self._allow_diagonal_connections = not self._allow_diagonal_connections

        print(
            f"{len(self._diagonal_connections)}\n {self._diagonal_connections}"
        )
        import time
        print("start")
        tic = time.perf_counter()
        if self._allow_diagonal_connections:
            print("enable")
            self.graph.enable_edges(self._diagonal_connections, disabler)
        else:
            print("disable")
            self.graph.disable_edges(self._diagonal_connections, disabler)

        toc = time.perf_counter()
        print(f"Toggled the diagonal connections in {toc - tic:0.4f} seconds")

    def astar_between_grid_pos(self, start: Vector2,
                               end: Vector2) -> AStarResults:
        start = self.graph.nodes_at_point(start)[0]
        end = self.graph.nodes_at_point(end)[0]
        results = self.graph.astar(start, end)
        return results