Source code for ddg.conversion.halfedge.nets

import ddg
from ddg.halfedge import Surface
from ddg.indexedfaceset import IndexedFaceSet


[docs]def discrete_net_to_halfedge(net, co_attr="co"): """Convert discrete net to halfedge. The vertices of the halfedge object will have an attribute co_attr containing the values of the net. The order/index of vertices in the returned surface will be the same as in net.traverser. Parameters ---------- net : DiscreteNet, EmptyNet, PointNet or NetCollection containing these co_attr : str (default='co') Name of coordinate attribute Returns ------- Surface """ def single_net_to_halfedge(net): # Special cases, in particular things that don't have traversers # These aren't even technically DiscreteNets. if isinstance(net, ddg.nets.EmptyNet): return Surface() if isinstance(net, ddg.nets.PointNet): s = Surface() v = s.verts() s.verts.add_attribute(co_attr) setattr(v, co_attr, net()) return s s = discrete_domain_to_halfedge(net.domain, co_attr=co_attr) # This requires that the order of vertices in s is the same as the # traverser order for v, c in zip(s.verts, net.domain.traverser): setattr(v, co_attr, net[c]) return s if isinstance(net, ddg.nets.NetCollection): output_list = [single_net_to_halfedge(n) for n in net] return ddg.halfedge.union(*output_list, verts_attr_list=[co_attr]) return single_net_to_halfedge(net)
[docs]def discrete_domain_to_halfedge(domain, co_attr="co"): """Convert a discrete domain to a halfedge object. The vertices of the halfedge object will have an attribute co_attr containing the values from domain.traverser. The order/index of vertices in the returned surface will be the same as in domain.traverser. Parameters ---------- domain : DiscreteDomain or EmptyDomain co_attr : str (default='co') Name of coordinate attribute Returns ------- Surface """ if isinstance(domain, ddg.nets.DiscreteRectangularDomain) and not domain.bounded: raise ValueError("Can not convert unbounded domain to halfedge.") # Determine the dimension of the domain. We can't just use domain.dimension # because it is more like ambient_dimension, for example [[0, 5], [0,0]] # has dimension 2, even though it is topologically an interval. if isinstance(domain, ddg.nets.EmptyDomain): # Does not have a traverser return Surface() else: num_pts = len(list(domain.traverser)) if num_pts == 0: dim = -1 elif num_pts == 1: dim = 0 elif len(domain.face_data) == 0 and len(domain.edge_data) != 0: dim = 1 elif isinstance( domain, (ddg.nets.DiscreteDiagonalDomain, ddg.nets.DiscreteTriangularDomain) ): dim = 2 else: dim = len([I for I in domain.intervals if I[1] - I[0] > 0]) if dim == -1: s = Surface() elif dim == 0: s = Surface() s.verts() elif dim == 1: s = Surface() # We need to remember the first and last vertex in case we need to # connect them because the domain is periodic v_first = s.verts() v_last = s.verts() s.add_edge(v_first, v_last) for _ in range(num_pts - 2): v_next = s.verts() s.add_edge(v_last, v_next) v_last = v_next if domain.periodic: s.add_edge(v_first, v_last) elif dim == 2: s = IndexedFaceSet(domain.face_data) s = ddg.indexedfaceset.indexed_face_set_to_surface( s, vertex_index_attribute=None, face_index_attribute=None ) else: raise ValueError( "Can only convert empty, points, intervals and 2D domains. This " f"domain was determined to have dimension {dim}." ) # This requires that the order of vertices in s is the same as the # traverser order s.verts.add_attribute(co_attr) for v, c in zip(s.verts, domain.traverser): setattr(v, co_attr, c) return s