def test_invalid_half_edge(): with pytest.raises(nx.NetworkXException): embedding_data = { 1: [2, 3, 4], 2: [1, 3, 4], 3: [1, 2, 4], 4: [1, 2, 3] } embedding = nx.PlanarEmbedding() embedding.set_data(embedding_data) nx.combinatorial_embedding_to_pos(embedding)
def check_embedding_data(embedding_data): """Checks that the planar embedding of the input is correct""" embedding = nx.PlanarEmbedding() embedding.set_data(embedding_data) pos_fully = nx.combinatorial_embedding_to_pos(embedding, False) msg = "Planar drawing does not conform to the embedding (fully " "triangulation)" assert planar_drawing_conforms_to_embedding(embedding, pos_fully), msg check_edge_intersections(embedding, pos_fully) pos_internally = nx.combinatorial_embedding_to_pos(embedding, True) msg = "Planar drawing does not conform to the embedding (internal " "triangulation)" assert planar_drawing_conforms_to_embedding(embedding, pos_internally), msg check_edge_intersections(embedding, pos_internally)
def __init__(self, G: Graph, pos: POSITIONS = None): if nx.number_of_selfloops(G) != 0: raise OrthogonalException( 'There can be no self loops in the graph') if nx.is_connected(G) is False: raise OrthogonalException( 'The graph or parts of it are not connected.') self.logger: Logger = getLogger(__name__) if pos is None: is_planar, self.embedding = nx.check_planarity(G) assert is_planar pos = nx.combinatorial_embedding_to_pos(self.embedding) else: if self.numberOfCrossings(G, pos) != 0: raise OrthogonalException( 'The graph has edges that cross each other') self.embedding: nx.PlanarEmbedding = self.convert_pos_to_embedding( G, pos) self.G: Graph = G.copy() self.pos = pos # is only used to find the ext_face now. self.dcel: Dcel = Dcel(G, self.embedding) self.ext_face = self.get_external_face()
def main(): # Cycle graph _, embedding = nx.check_planarity(nx.cycle_graph(20)) embedding_fully, _ = nx.triangulate_embedding(embedding, True) diff_fully = nx.Graph(list(embedding_fully.edges - embedding.edges)) embedding_internal, _ = nx.triangulate_embedding(embedding, False) diff_internal = nx.Graph(list(embedding_internal.edges - embedding.edges)) pos = nx.combinatorial_embedding_to_pos(embedding_fully) nx.draw(diff_fully, pos, alpha=0.5, width=1, style="dotted", node_size=30) nx.draw(embedding, pos, width=2 , node_size=30) plt.savefig("drawing_cycle_fully_triangulated.png", format="PNG") plt.show() pos = nx.combinatorial_embedding_to_pos(embedding_internal) nx.draw(diff_internal, pos, alpha=0.5, width=1, style="dotted", node_size=30) nx.draw(embedding, pos, width=2, node_size=30) plt.savefig("drawing_cycle_internally_triangulated.png", format="PNG") plt.show() # Other graph G = nx.Graph([(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (1, 4), (4, 3)]) is_planar, embedding = nx.check_planarity(G) print(is_planar) embedding_fully, _ = nx.triangulate_embedding(embedding, True) diff_fully = nx.Graph(list(embedding_fully.edges - embedding.edges)) embedding_internal, _ = nx.triangulate_embedding(embedding, False) diff_internal = nx.Graph(list(embedding_internal.edges - embedding.edges)) pos = nx.combinatorial_embedding_to_pos(embedding_fully) nx.draw(diff_fully, pos, alpha=0.5, width=1, style="dotted", node_size=30) nx.draw(embedding, pos, width=2, node_size=30) plt.savefig("drawing_other_fully_triangulated.png", format="PNG") plt.show() pos = nx.combinatorial_embedding_to_pos(embedding_internal) nx.draw(diff_internal, pos, alpha=0.5, width=1, style="dotted", node_size=30) nx.draw(embedding, pos, width=2, node_size=30) plt.savefig("drawing_other_internally_triangulated.png", format="PNG") plt.show() embedding_data = {0: [36, 42], 1: [], 2: [23, 16], 3: [19], 4: [23, 17], 5: [45, 18], 6: [42, 29, 40], 7: [48, 26, 32], 8: [15, 44, 23], 9: [11, 27], 10: [39, 11, 32, 47, 26, 15], 11: [10, 9], 12: [41, 34, 35], 13: [48], 14: [28, 45], 15: [34, 8, 10], 16: [2, 39, 21], 17: [4], 18: [5], 19: [22, 3], 20: [], 21: [16, 49], 22: [26, 47, 19], 23: [8, 2, 4], 24: [46], 25: [], 26: [7, 34, 10, 22, 38], 27: [9, 48], 28: [36, 41, 14], 29: [6], 30: [48], 31: [], 32: [7, 10, 46], 33: [48], 34: [12, 15, 26], 35: [12, 41], 36: [0, 28, 43], 37: [47], 38: [26], 39: [16, 10], 40: [6], 41: [28, 12, 35], 42: [44, 0, 6], 43: [36], 44: [8, 42], 45: [14, 5], 46: [32, 24], 47: [22, 10, 37], 48: [27, 7, 13, 30, 33], 49: [21]} embedding = nx.PlanarEmbedding() embedding.set_data(embedding_data) pos = nx.combinatorial_embedding_to_pos(embedding, fully_triangulate=False) nx.draw(embedding, pos, node_size=30) plt.savefig("drawing_large_graph_internally_triangulated.png", format="PNG") plt.show()
def check_embedding_data(embedding_data): """Checks that the planar embedding of the input is correct""" embedding = nx.PlanarEmbedding() embedding.set_data(embedding_data) pos_fully = nx.combinatorial_embedding_to_pos(embedding, False) msg = "Planar drawing does not conform to the embedding (fully " \ "triangulation)" assert_true(planar_drawing_conforms_to_embedding(embedding, pos_fully), msg) check_edge_intersections(embedding, pos_fully) pos_internally = nx.combinatorial_embedding_to_pos(embedding, True) msg = "Planar drawing does not conform to the embedding (internal " \ "triangulation)" assert_true(planar_drawing_conforms_to_embedding(embedding, pos_internally), msg) check_edge_intersections(embedding, pos_internally)
def planar_layout(G, scale=1, center=None, dim=2): """Position nodes without edge intersections. Parameters ---------- G : NetworkX graph or list of nodes A position will be assigned to every node in G. If G is of type nx.PlanarEmbedding, the positions are selected accordingly. scale : number (default: 1) Scale factor for positions. center : array-like or None Coordinate pair around which to center the layout. dim : int Dimension of layout. Returns ------- pos : dict A dictionary of positions keyed by node Raises ------ NetworkXException If G is not planar Examples -------- >>> G = nx.path_graph(4) >>> pos = nx.planar_layout(G) """ import numpy as np if dim != 2: raise ValueError("can only handle 2 dimensions") G, center = _process_params(G, center, dim) if len(G) == 0: return {} if isinstance(G, nx.PlanarEmbedding): embedding = G else: is_planar, embedding = nx.check_planarity(G) if not is_planar: raise nx.NetworkXException("G is not planar.") pos = nx.combinatorial_embedding_to_pos(embedding) node_list = list(embedding) pos = np.row_stack([pos[x] for x in node_list]) pos = pos.astype(np.float64) pos = rescale_layout(pos, scale=scale) + center return dict(zip(node_list, pos))
def __init__(self, G, pos=None): if pos is None: is_planar, embedding = nx.check_planarity(G) pos = nx.combinatorial_embedding_to_pos(embedding) else: embedding = convert_pos_to_embedding(G, pos) self.G = G.copy() self.dcel = Dcel(G, embedding) self.dcel.ext_face = self.get_external_face(pos) self.dcel.ext_face.is_external = True
def __init__(self, G, pos=None): assert nx.number_of_selfloops(G) == 0 assert nx.is_connected(G) if pos is None: is_planar, self.embedding = nx.check_planarity(G) assert is_planar pos = nx.combinatorial_embedding_to_pos(self.embedding) else: assert number_of_cross(G, pos) == 0 self.embedding = convert_pos_to_embdeding(G, pos) self.G = G.copy() self.pos = pos # is only used to find the ext_face now. self.dcel = DCEL.Dcel(G, self.embedding) self.ext_face = self.get_external_face()
def test_random(): while True: n = 50 p = 1.0 is_planar = False while not is_planar: G = nx.fast_gnp_random_graph(n, p) is_planar, embedding = nx.check_planarity(G) p *= 0.9 pos = nx.combinatorial_embedding_to_pos(embedding, fully_triangulate=False) assert_true(planar_drawing_conforms_to_embedding(embedding, pos), "Planar drawing does not conform to the embedding") assert_true(is_planar_drawing_correct(G, pos), "Planar drawing is not correct") print("Graph correct")
def main(): while True: n = 50 p = 1.0 is_planar = False while not is_planar: G = nx.fast_gnp_random_graph(n, p) is_planar, embedding = nx.check_planarity(G) p *= 0.99 print("Embedding: ", embedding.get_data()) print("Displaying not fully triangulated drawing") plt.subplot(1, 2, 1) nx.draw_planar(embedding, node_size=2) pos = nx.combinatorial_embedding_to_pos(embedding, fully_triangulate=True) print("Displaying fully triangulated drawing") plt.subplot(1, 2, 2) nx.draw(G, pos, node_size=2) plt.show()
def plot(self, **kwargs): """Plots the graph. Parameters ---------- G: networkx.Graph """ G = None with_labels = False use_planar_drawer = False node_size = 100 if 'G' in kwargs: G = kwargs['G'] if 'with_labels' in kwargs: with_labels = kwargs['with_labels'] if 'use_planar_drawer' in kwargs: use_planar_drawer = kwargs['use_planar_drawer'] if 'node_size' in kwargs: node_size = kwargs['node_size'] if G is None: G = self.to_networkx_graph() # Generate planar embedding or use default algorithm. pos = None if use_planar_drawer: emb = self.to_planar_embedding() pos = nx.combinatorial_embedding_to_pos(emb, fully_triangulate=False) # Take color attributes on the nodes into account. colors = nx.get_node_attributes(G, 'color').values() if len(colors) == G.number_of_nodes(): nx.draw(G, pos=pos, with_labels=with_labels, node_color=list(colors), node_size=node_size) else: nx.draw(G, pos=pos, with_labels=with_labels, node_size=node_size)
def test_invalid_half_edge(): embedding_data = {1: [2, 3], 2: [1, 3], 3: [1, 2], 4: [1, 2, 3]} embedding = nx.PlanarEmbedding() embedding.set_data(embedding_data) nx.combinatorial_embedding_to_pos(embedding)
def test_invalid_half_edge(): embedding_data = {1: [2, 3, 4], 2: [1, 3, 4], 3: [1, 2, 4], 4: [1, 2, 3]} embedding = nx.PlanarEmbedding() embedding.set_data(embedding_data) nx.combinatorial_embedding_to_pos(embedding)
def convert_to_game_structure(graph: nx.Graph, embedding: nx.PlanarEmbedding, path_grouping): positions = scale_positions( nx.combinatorial_embedding_to_pos(embedding, True)) points = [GraphicsPoint] * len(graph.nodes) paths = [] # Initialize points for index, position in positions.items(): point = GraphicsPoint(*position, False) point.index = index points[index] = point # Initialize paths for path_start, path_end, mid_point in path_grouping: start_point = points[path_start[0]] end_point = points[path_end[1]] # The path was created from the same point to itself if start_point == end_point: end_point = points[path_start[1]] # Make small difference to width of the paths delta_pos = end_point - start_point mid_point = start_point + delta_pos.scalar(0.5) shift = delta_pos.rotate_anticlock().normalized().scalar(5) pos_control = mid_point + shift neg_control = mid_point - shift path_0 = Path([ GraphicsBezier(start_point, end_point, gc.LINE_COLOR, pos_control, pos_control) ], start_point, end_point) path_1 = Path([ GraphicsBezier(start_point, end_point, gc.LINE_COLOR, neg_control, neg_control) ], start_point, end_point) # Update paths of points start_point.add_to_path(path_0) start_point.add_to_path(path_1) end_point.add_to_path(path_0) end_point.add_to_path(path_1) paths.append((path_0, path_1, points[path_start[1]])) # Normal path else: middle_point = points[path_start[1]] path_0 = Path([GraphicsBezier(start_point, middle_point)], start_point, middle_point) path_1 = Path([GraphicsBezier(middle_point, end_point)], middle_point, end_point) # Update paths of points start_point.add_to_path(path_0) middle_point.add_to_path(path_0) middle_point.add_to_path(path_1) end_point.add_to_path(path_1) paths.append((path_0, path_1, middle_point)) # Test whether the points are still valid valid_point(start_point, start_point, end_point) valid_point(end_point, start_point, end_point) return points, paths