def _sort_vertex_neighbors(key, nbrs, xyz, ccw=True): if len(nbrs) == 1: return nbrs ordered = nbrs[0:1] a = xyz[key] for i, nbr in enumerate(nbrs[1:]): c = xyz[nbr] pos = 0 b = xyz[ordered[pos]] while not is_ccw_xy(a, b, c): pos += 1 if pos > i: break b = xyz[ordered[pos]] if pos == 0: pos = -1 b = xyz[ordered[pos]] while is_ccw_xy(a, b, c): pos -= 1 if pos < -len(ordered): break b = xyz[ordered[pos]] pos += 1 ordered.insert(pos, nbr) if not ccw: return ordered[::-1] return ordered
def _sort_neighbours(network, ccw=True): sorted_neighbours = {} xyz = {key: network.vertex_coordinates(key) for key in network.vertices()} for key in network.vertices(): nbrs = network.vertex_neighbours(key) if len(nbrs) == 1: sorted_neighbours[key] = nbrs continue ordered = [nbrs[0]] a = xyz[key] for i, nbr in enumerate(nbrs[1:]): c = xyz[nbr] pos = 0 b = xyz[ordered[pos]] while not is_ccw_xy(a, b, c): pos += 1 if pos > i: break b = xyz[ordered[pos]] if pos == 0: pos = -1 b = xyz[ordered[pos]] while is_ccw_xy(a, b, c): pos -= 1 if pos < -len(ordered): break b = xyz[ordered[pos]] pos += 1 ordered.insert(pos, nbr) if not ccw: sorted_neighbours[key] = ordered[::-1] sorted_neighbours[key] = ordered for key, nbrs in sorted_neighbours.items(): network.vertex[key]['sorted_neighbours'] = nbrs[::-1] return sorted_neighbours
def _find_first_neighbor(key, network): nbrs = list(network.halfedge[key].keys()) if len(nbrs) == 1: return nbrs[0] ab = [-1.0, -1.0, 0.0] a = network.vertex_coordinates(key, 'xyz') b = [a[0] + ab[0], a[1] + ab[1], 0] angles = [] for nbr in nbrs: c = network.vertex_coordinates(nbr, 'xyz') ac = [c[0] - a[0], c[1] - a[1], 0] alpha = angle_vectors(ab, ac) if is_ccw_xy(a, b, c, True): alpha = PI2 - alpha angles.append(alpha) return nbrs[angles.index(min(angles))]
def network_node_find_first_neighbor(network, key): nbrs = network.neighbors(key) if len(nbrs) == 1: return nbrs[0] ab = [-1.0, -1.0, 0.0] a = network.node_coordinates(key, 'xyz') b = [a[0] + ab[0], a[1] + ab[1], 0] angles = [] for nbr in nbrs: c = network.node_coordinates(nbr, 'xyz') ac = [c[0] - a[0], c[1] - a[1], 0] alpha = angle_vectors(ab, ac) if is_ccw_xy(a, b, c, True): alpha = PI2 - alpha angles.append(alpha) return nbrs[angles.index(min(angles))]
def _find_first_neighbour(key, network): nbrs = list(network.halfedge[key].keys()) if len(nbrs) == 1: return nbrs[0] vu = [-1.0, -1.0, 0.0] a = network.vertex_coordinates(key, 'xyz') b = [a[0] + vu[0], a[1] + vu[1], 0] cw = [] for nbr in nbrs: c = network.vertex_coordinates(nbr, 'xyz') if not is_ccw_xy(a, b, c, True): cw.append(nbr) if cw: nbrs = cw angles = [] v = [network.vertex[key][_] for _ in 'xyz'] for nbr in nbrs: w = [network.vertex[nbr][_] for _ in 'xyz'] vw = [w[0] - v[0], w[1] - v[1], 0] angles.append(angle_vectors(vu, vw)) if cw: return nbrs[angles.index(min(angles))] return nbrs[angles.index(max(angles))]
def _is_point_in_edgezone(p, p0, p1): n = cross_vectors(p1 - p0, [0, 0, 1.]) return (is_ccw_xy(p0 - p0, n, p - p0) and not is_ccw_xy(p0 - p0, p1 - p0, p - p0) and not is_ccw_xy(p1 - p1, n, p - p1))
def network_embed_in_plane(network, fix=None, straightline=True): """Embed the network in the plane. Parameters ---------- network : Network A network object. fix : list (None) Two fixed points. straightline : bool (True) Embed using straight lines. Returns ------- bool True if the embedding was successful. False otherwise. Raises ------ ImportError If NetworkX is not installed. Warning ------- This function uses the Python package NetworkX. NetworkX can be *pip installed*. Examples -------- .. plot:: :include-source: import compas from compas.datastructures import Network from compas.topology import network_embed_in_plane from compas.plotters import NetworkPlotter network = Network.from_obj(compas.get('fink.obj')) embedding = network.copy() fix = (1, 12) if network_embed_in_plane(embedding, fix=fix): plotter = NetworkPlotter(embedding) plotter.draw_lines([{'start': network.vertex_coordinates(u, 'xy'), 'end': network.vertex_coordinates(v, 'xy'), 'color': '#cccccc'} for u, v in network.edges()]) plotter.draw_vertices(radius=0.3, text={key: key for key in embedding.vertices()}, facecolor={key: '#ff0000' for key in fix}) plotter.draw_edges() plotter.show() """ try: import networkx as nx except ImportError: print( "NetworkX is not installed. Get NetworkX at https://networkx.github.io/." ) raise x = network.get_vertices_attribute('x') y = network.get_vertices_attribute('y') xmin, xmax = min(x), max(x) ymin, ymax = min(y), max(y) xspan = xmax - xmin yspan = ymax - ymin edges = [(u, v) for u, v in network.edges() if not network.is_vertex_leaf(u) and not network.is_vertex_leaf(v) ] is_embedded = False count = 100 while count: graph = nx.Graph(edges) pos = nx.spring_layout(graph, 2, iterations=100, scale=max(xspan, yspan)) if not _network_are_edges_crossed(edges, pos): is_embedded = True break count -= 1 if not is_embedded: return False if fix: a, b = fix p0 = network.vertex_coordinates(a, 'xy') p1 = network.vertex_coordinates(b, 'xy') p2 = pos[b] vec0 = [ network.vertex[b][axis] - network.vertex[a][axis] for axis in 'xy' ] vec1 = [pos[b][axis] - pos[a][axis] for axis in (0, 1)] # rotate a = angle_vectors_xy(vec0, vec1) if is_ccw_xy(p0, p1, p2): a = 2 * pi - a cosa = cos(a) sina = sin(a) for key in pos: x, y = pos[key] pos[key][0] = cosa * x - sina * y pos[key][1] = sina * x + cosa * y # scale l0 = (vec0[0]**2 + vec0[1]**2)**0.5 l1 = (vec1[0]**2 + vec1[1]**2)**0.5 scale = l0 / l1 for key in pos: pos[key][0] *= scale pos[key][1] *= scale # translate t = network.vertex[fix[0]]['x'] - pos[fix[0]][0], network.vertex[ fix[0]]['y'] - pos[fix[0]][1] for key in pos: pos[key][0] += t[0] pos[key][1] += t[1] # update network vertex coordinates for key in network.vertices(): if key in pos: network.vertex[key]['x'] = pos[key][0] network.vertex[key]['y'] = pos[key][1] return True
def network_embed_in_plane(network, fixed=None, straightline=True): """Embed the network in the plane. Parameters ---------- network : Network A network object. fixed : list (None) Two fixed points. straightline : bool (True) Embed using straight lines. Returns ------- bool True if the embedding was successful. False otherwise. Raises ------ ImportError If NetworkX is not installed. Examples -------- >>> """ try: import networkx as nx except ImportError: print( "NetworkX is not installed. Get NetworkX at https://networkx.github.io/." ) raise x = network.nodes_attribute('x') y = network.nodes_attribute('y') xmin, xmax = min(x), max(x) ymin, ymax = min(y), max(y) xspan = xmax - xmin yspan = ymax - ymin edges = [(u, v) for u, v in network.edges() if not network.is_leaf(u) and not network.is_leaf(v)] is_embedded = False count = 100 while count: graph = nx.Graph(edges) pos = nx.spring_layout(graph, iterations=100, scale=max(xspan, yspan)) if not _are_edges_crossed(edges, pos): is_embedded = True break count -= 1 if not is_embedded: return False if fixed: a, b = fixed p0 = network.node_attributes(a, 'xy') p1 = network.node_attributes(b, 'xy') p2 = pos[b] vec0 = subtract_vectors_xy(p1, p0) vec1 = subtract_vectors_xy(pos[b], pos[a]) # rotate angle = angle_vectors_xy(vec0, vec1) if is_ccw_xy(p0, p1, p2): angle = 2 * pi - angle cosa = cos(angle) sina = sin(angle) for key in pos: x, y = pos[key] pos[key][0] = cosa * x - sina * y pos[key][1] = sina * x + cosa * y # scale l0 = (vec0[0]**2 + vec0[1]**2)**0.5 l1 = (vec1[0]**2 + vec1[1]**2)**0.5 scale = l0 / l1 for key in pos: pos[key][0] *= scale pos[key][1] *= scale # translate t = subtract_vectors_xy(p0, pos[a]) for key in pos: pos[key][0] += t[0] pos[key][1] += t[1] # update network node coordinates for key in network.nodes(): if key in pos: network.node_attributes(key, 'xy', pos[key]) return True
def network_embed_in_plane(network, fix=None, straightline=True): """Embed the network in the plane. Parameters: network (compas.datastructures.network.Network): The network object. fix (list): Optional. Two fixed points. Default is ``None``. straightline (bool): Optional. Embed using straight lines. Default is ``True``. Returns: bool: ``True`` if the embedding was successful. ``False`` otherwise. Raises: ImportError: If NetworkX is not installed. Example: .. plot:: :include-source: import compas from compas.datastructures.network import Network from compas.visualization.plotters import NetworkPlotter from compas.datastructures.network.algorithms import network_embed_in_plane network = Network.from_obj(compas.get_data('fink.obj')) embedding = network.copy() fix = (1, 12) if network_embed_in_plane(embedding, fix=fix): plotter = NetworkPlotter(embedding) points = [] for key in network: points.append({ 'pos': network.vertex_coordinates(key, 'xy'), 'radius': 0.1 }) lines = [] for u, v in network.edges(): lines.append({ 'start': network.vertex_coordinates(u, 'xy'), 'end' : network.vertex_coordinates(v, 'xy'), 'color': '#cccccc', }) plotter.draw_xlines(lines) plotter.draw_xpoints(points) plotter.draw_edges() plotter.draw_vertices(facecolor={key: ('#ff0000' if key in fix else '#ffffff') for key in embedding.vertices()}, text={key: key for key in fix}) plotter.show() """ try: import networkx as nx except ImportError: print( "NetworkX is not installed. Get NetworkX at https://networkx.github.io/." ) raise x = network.get_vertices_attribute('x') y = network.get_vertices_attribute('y') xmin, xmax = min(x), max(x) ymin, ymax = min(y), max(y) xspan = xmax - xmin yspan = ymax - ymin edges = [(u, v) for u, v in network.edges() if not network.is_vertex_leaf(u) and not network.is_vertex_leaf(v) ] is_embedded = False count = 100 while count: graph = nx.Graph(edges) pos = nx.spring_layout(graph, 2, iterations=100, scale=max(xspan, yspan)) if not _network_are_edges_crossed(edges, pos): is_embedded = True break count -= 1 if not is_embedded: return False if fix: a, b = fix p0 = network.vertex_coordinates(a, 'xy') p1 = network.vertex_coordinates(b, 'xy') p2 = pos[b] vec0 = [network[b][axis] - network[a][axis] for axis in 'xy'] vec1 = [pos[b][axis] - pos[a][axis] for axis in (0, 1)] # rotate a = angle_smallest_vectors_xy(vec0, vec1) if is_ccw_xy(p0, p1, p2): a = 2 * pi - a cosa = cos(a) sina = sin(a) for key in pos: x, y = pos[key] pos[key][0] = cosa * x - sina * y pos[key][1] = sina * x + cosa * y # scale l0 = (vec0[0]**2 + vec0[1]**2)**0.5 l1 = (vec1[0]**2 + vec1[1]**2)**0.5 scale = l0 / l1 for key in pos: pos[key][0] *= scale pos[key][1] *= scale # translate t = network[fix[0]]['x'] - pos[fix[0]][0], network[fix[0]]['y'] - pos[ fix[0]][1] for key in pos: pos[key][0] += t[0] pos[key][1] += t[1] # update network vertex coordinates for key in network: if key in pos: network[key]['x'] = pos[key][0] network[key]['y'] = pos[key][1] return True