Source code for ddg.halfedge._layout

from collections import deque

import numpy as np

import ddg


[docs]def integrate_one_form( hds, start_vertex, start_vertex_co, co_attr, edge_attr, boundary_attr=None ): """ Lays out a surface using edge directions and lengths via breadth-first traversal. I.e. integrates a discrete one-form with values stored on hds.edges. Parameters ---------- hds : ddg.halfedge.Surface Halfedge object with combinatorics and edge attributes. start_vertex : hds.verts Initial vertex to start from. start_vertex_co : np.ndarray, shape (3,) 3D position of the start_vertex. co_attr : str Name of the vertex attribute to store the new coordinates. edge_attr : str Name of the edge attribute storing new edge vectors (shape (3,)). The edge vectors must be scaled to desired length. boundary_attr : str (default = None) Vertex attribute with values True/False. If a string is given, the BFS stops further traversal from that vertex. Useful for example for vertices close to infinity. Returns ------- hds : ddg.halfedge.Surface Same halfedge object with new vertex coordinates stored under co_attr. """ # Initialize BFS queue queue = deque([start_vertex]) # Create a visited attribute to track traversed vertices visited_attr = "visited_in_layout_fct" visited = hds.verts.add_attribute(visited_attr, False) visited[start_vertex] = True # Initialize coordinate attribute if it doesn't exist if not hasattr(hds.verts, co_attr): hds.verts.add_attribute(co_attr) setattr(start_vertex, co_attr, start_vertex_co) # BFS traversal to lay out the surface while queue: current = queue.popleft() for edge in ddg.halfedge.out_edges(current): head = edge.head if visited[head]: continue # Compute and assign head vertex coordinate new_edge = getattr(edge, edge_attr) new_coord = getattr(current, co_attr) + new_edge setattr(head, co_attr, new_coord) visited[head] = True # Add to queue unless it's a boundary if boundary_attr is None or not getattr(head, boundary_attr): queue.append(head) # Remove temporary visited attribute delattr(hds.verts, visited_attr) return hds
[docs]def verify_closure_one_form(hds, edge_attr, tol=1e-6): """ Verifies closure of a discrete one-form with edge lenths and directions stored in an attribute called edge_attr. Parameters ---------- hds : ddg.halfedge.Surface Halfedge object. edge_attr: str Name of the edge attribute storing the new scaled edge vectors. tol : float(default: 1e-6) Tolerance for the error considered acceptable. Returns ------- int Number of faces with large closure errors. """ broken_faces = 0 for f in hds.faces: error = np.zeros(3) for e in ddg.halfedge.edge_loop(f.edge): error += getattr(e, edge_attr) norm = np.linalg.norm(error) if norm > tol: print(f"❌ Face {f.index} error: {norm}") broken_faces += 1 if broken_faces == 0: print("✅ All faces pass the closure test within tolerance.") else: print(f"⚠️ {broken_faces} faces failed closure test (tol = {tol}).") return broken_faces