Source code for ddg.halfedge._get

import ddg

##############################
# utilities acting on vertices
##############################


[docs]def in_edges(v): """ Get the incoming edges of a vertex, Parameters ---------- v : vertex Yields ------ edge All edges pointing to the vertex `v` (i.e., `edge.head` = `v`). """ if v.edge is None: return first_edge = v.edge yield first_edge next_edge = first_edge.nex.opp while next_edge != first_edge: yield next_edge next_edge = next_edge.nex.opp
[docs]def out_edges(v): """ Get the outgoing edges of a vertex. Parameters ---------- v : vertex Yields ------ edge All edges pointing away from the vertex `v` (i.e., `edge.tail` == `v`). """ if v.edge is None: return first_edge = v.edge.opp yield first_edge next_edge = first_edge.opp.nex while next_edge != first_edge: yield next_edge next_edge = next_edge.opp.nex
########################### # utilities acting on edges ###########################
[docs]def edge_loop(e): """ Get all consecutive edges of a given edge, forming a loop. Parameters ---------- e : edge Starting edge of the edge loop. Yields ------ edge The consecutive edges in a loop starting with argument edge `e`. """ first_edge = e yield first_edge next_edge = first_edge.nex while next_edge is not first_edge: yield next_edge next_edge = next_edge.nex
[docs]def count_edges_in_loop(e): """ Counts the number of consecutive half-edges in a loop along a given one. Parameters ---------- e : edge The edge whose number of consecutive half-edges in a loop is counted. Returns ------- int The number of half-edges belonging to the edge loop along `e`. """ i = 0 for _ in edge_loop(e): i += 1 return i
[docs]def opposite_edge_in_face(e): n = len(list(edge_loop_from_face(e.face))) opp_edge = e if n % 2 != 0: raise ValueError("non even face") else: for i in range(n // 2): opp_edge = opp_edge.nex return opp_edge.opp
[docs]def opposite_edge_at_head(e): n = len(list(in_edges(e.head))) opp_edge = e if n % 2 != 0: raise ValueError("non even vertex degree") else: for i in range(n // 2): opp_edge = opp_edge.nex.opp return opp_edge.opp
[docs]def length_from_co(e, co_attr="co"): """ Calculates the euclidean length of an edge, provided its vertices have coordinates. Parameters ---------- e : edge The edge whose length will be calculated. co_attr : string (default='co') Name of the vertex attribute storing the coordinates. Returns ------- f : float The length of the edge 'e'. Raises ------ AttributeError If head or tail of the edge has no coordinate attribute 'co'. """ if not hasattr(e.head, co_attr): raise AttributeError(f"The vertex {e.head} has no coordinate attribute.") if not hasattr(e.tail, co_attr): raise AttributeError(f"The vertex {e.tail} has no coordinate attribute.") a = e.head.co b = e.tail.co return ddg.math.euclidean.distance(a, b)
########################### # utilities acting on faces ###########################
[docs]def face_vertices(f): """ Get the boundary vertices of a face in cyclic order. Parameters ---------- f : face Yields ------ vertex The boundary vertices of the face `f` in cyclic order. """ first_edge = f.edge yield first_edge.head next_edge = first_edge.nex while next_edge != first_edge: yield next_edge.head next_edge = next_edge.nex
[docs]def edge_loop_from_face(f): """ Get the edges of a face in cyclic order. Parameters ---------- f : face Yields ------ edge The edges of the face `f` in cyclic order. """ return edge_loop(f.edge)
[docs]def number_of_edges(f): """ Counts the number of half-edges associated with the given face. Parameters ---------- f : face The face whose number of half-edges is counted. Returns ------- int The number of half-edges belonging to face f. """ return count_edges_in_loop(f.edge)
########################### # utilities acting on cells ###########################
[docs]def complement(cells, type, surface): """ Parameters ---------- cells: iterable Iterable of cells of a surface to find the complement from. type: str Type of the cells, "verts", "edges" or "faces" surface: ddg.halfedge.Surface Surface that the cells belong to. Returns ------- set set of complement cells """ res = set() for cell in getattr(surface, type): if cell not in cells: res.add(cell) return res
############################## # utilities acting on surfaces ##############################
[docs]def some_vertex(s): """ Get one vertex of the given surface. Parameters ---------- s : ddg.halfedge.Surface Returns ------- v : vertex One of the vertices of the given surface. """ for v in s.verts: return v
[docs]def some_edge(s): """ Get one edge of the given surface. Parameters ---------- s : ddg.halfedge.Surface Returns ------- e : edge One of the edges of the given surface. """ for e in s.edges: return e
[docs]def some_face(s): """ Get one face of the given surface. Parameters ---------- s : ddg.halfedge.Surface Returns ------- f : face One of the faces of the given surface. """ for f in s.faces: return f
[docs]def is_triangulation(surf): """ Checks if a surface is a triangulation. Parameters ---------- surf : ddg.halfedge.Surface The surface that is checked for being a triangulation. Returns ------- bool """ surf.validate() for f in surf.faces: if number_of_edges(f) != 3: return False return True
[docs]def is_connected(s): """Whether a half-edge object is connected. The empty set counts as connected. Parameters ---------- s : ddg.halfedge.Surface Returns ------- bool """ # The empty set is connected if not s.verts: return True # dfs r = some_vertex(s) visited_vertices = [r] Q = [r] while Q: v = Q[-1] for e in out_edges(v): w = e.head if w not in visited_vertices: visited_vertices.append(w) Q.append(w) break # else triggers if no break was encountered else: Q.pop() return len(visited_vertices) == len(s.verts)
[docs]def single_edges(surf): """ Yields a generator that iterates through half of the half-edges of a surface Parameters ---------- surf: surface The half-edge data through which must be iterated Yields ------ edge: half of the half-edges """ visited_edges = set() for edge in surf.edges: if edge.opp in visited_edges: continue visited_edges.add(edge) yield edge
############################# # boundary and interior cells #############################
[docs]def boundary_vertices(surf): """ Get all boundary vertices of a surface. Parameters ---------- surf : surface Yields ------ vertex All boundary vertices of a surface. """ for v in surf.verts: if is_boundary_vertex(v): yield v
[docs]def boundary_edges(surf): """ Get a list of all boundary half-edges of a surface. Parameters ---------- surf : ddg.halfedge.Surface Yields ------ edge All boundary half-edges of a surface. """ for e in surf.edges: if is_boundary_edge(e): yield e
[docs]def interior_vertices(surf): """ Get all interior vertices of a surface. Parameters ---------- surf : ddg.halfedge.Surface Yields ------ vertex All interior vertices of a surface. """ for v in surf.verts: if not is_boundary_vertex(v): yield v
[docs]def interior_edges(surf): """ Get all interior half-edges of a surface. Parameters ---------- surf : ddg.halfedge.Surface Yields ------ edge All interior half-edges of a surface. """ for e in surf.edges: if not is_boundary_edge(e): yield e
[docs]def is_boundary_vertex(v): """ Checks whether a vertex lies on the boundary of the surface.. Parameters ---------- v : vertex The vertex that is checked for being a boundary vertex. Returns ------- bool True if `v` is a boundary vertex, False if not. """ if v.edge is None: return True for e in in_edges(v): if not e.face: return True return False
[docs]def is_boundary_edge(e): """ Checks whether a half-edge lies on the boundary of the surface. Parameters ---------- e : edge The edge that is checked for being a boundary edge. Returns ------- bool True if `e` is a boundary edge, False if not. """ return not e.face