def edges_to_graph(edges): """Construct an `open_cp.network` style graph from an "edges" input. Merges very close vertices (<0.1 meters). From "edges" data there should not be repeated edges. :param roads: Iterable of `(name, geo)` :return: `(graph, names)` where `names` is a dictionary from the edge index to an instance of `EdgeNoLine`. """ edges = list(edges) all_nodes = [] for edge in edges: for pt in edge.line: all_nodes.append(pt) b = _network.PlanarGraphNodeOneShot(all_nodes) name_lookup = _collections.defaultdict(set) for edge in edges: for e in b.add_path(edge.line): name_lookup[e].add(_to_edge_noline(edge)) graph = b.build() names = dict() for e, ns in name_lookup.items(): index, _ = graph.find_edge(*e) if index in names: raise Exception("Repeated edge: {}".format(e)) if len(ns) > 1: raise Exception("Edge {} has multiple data: {}".format(e, ns)) names[index] = list(ns)[0] return graph, names
def roads_to_graph(roads): """Construct an `open_cp.network` style graph from a "roads" input. Merges very close vertices (<0.1 meters) and repeated edges. :param roads: Iterable of `(name, geo)` :return: `(graph, names)` where `names` is a dictionary from the edge index to the set of road names which make use of that edge (in either direction). """ roads = list(roads) all_nodes = [] for _, geo in roads: for pt in geo: all_nodes.append(pt) b = _network.PlanarGraphNodeOneShot(all_nodes) name_lookup = _collections.defaultdict(set) for name, geo in roads: for e in b.add_path(geo): name_lookup[e].add(name) b.remove_duplicate_edges() graph = b.build() names = _collections.defaultdict(set) for e, ns in name_lookup.items(): index, _ = graph.find_edge(*e) names[index].update(ns) return graph, dict(names)
def test_PlanarGraphNodeOneShot(): nodes = [(0, 0), (1, 1), (5.1, 1.2), (0.1, 0.01), (2, 2)] b = network.PlanarGraphNodeOneShot(nodes, 0.2) r = b.add_path([(0, 0), (1, 1), (5.1, 1.2)]) assert r == [(0, 1), (1, 2)] r = b.add_edge(0.1, 0.01, 2, 2) assert r == (0, 3) g = b.build() assert set(g.vertices.values()) == {(0, 0), (1, 1), (5.1, 1.2), (2, 2)} assert len(g.edges) == 3 assert [g.vertices[x] for x in g.edges[0]] == [(0, 0), (1, 1)] assert [g.vertices[x] for x in g.edges[1]] == [(1, 1), (5.1, 1.2)] assert [g.vertices[x] for x in g.edges[2]] == [(0, 0), (2, 2)]
def test_PlanarGraphNodeOneShot_remove_duplicates(): nodes = [(0, 0), (1, 1), (5.1, 1.2), (0.1, 0.01), (2, 2)] b = network.PlanarGraphNodeOneShot(nodes, 0.2) b.add_path([(0, 0), (1, 1), (5.1, 1.2)]) b.add_edge(0.1, 0.01, 2, 2) b.add_edge(1, 1, 1, 1) b.add_edge(0.1, 0.01, 2, 2) with pytest.raises(ValueError): b.build() b.remove_duplicate_edges() g = b.build() assert set(g.vertices.values()) == {(0, 0), (1, 1), (5.1, 1.2), (2, 2)} assert len(g.edges) == 3 assert [g.vertices[x] for x in g.edges[0]] == [(0, 0), (1, 1)] assert [g.vertices[x] for x in g.edges[1]] == [(1, 1), (5.1, 1.2)] assert [g.vertices[x] for x in g.edges[2]] == [(0, 0), (2, 2)]
def graph_from_streets(streets, to_projected_line): """Constructs a graph from a generic collection of "streets". :param streets: Iterator of "street" objects :param to_projected_line: Callable object which takes a "street" object as from the iterable `streets`, and returns a "line" which is suitable projected (if necessary). A "line" is an iterable of points, where each point is a pair `(x,y)`. :return: Pair `(graph, names)` where `graph` is a graph object, and `names` is a dictionary from edge index (in graph) to a list of "street" instances which are the street(s) associated with that edge. """ all_streets, projected_lines = [], [] for street in streets: all_streets.append(street) projected_lines.append(to_projected_line(street)) all_nodes = [] for line in projected_lines: for pt in line: all_nodes.append(pt) b = _network.PlanarGraphNodeOneShot(all_nodes) name_lookup = _collections.defaultdict(list) for street, line in zip(all_streets, projected_lines): for e in b.add_path(line): name_lookup[e].append(street) b.remove_duplicate_edges() graph = b.build() names = _collections.defaultdict(list) for e, ns in name_lookup.items(): if e[0] == e[1]: # These have been removed continue index, _ = graph.find_edge(*e) names[index].extend(ns) return graph, names