4444}
4545
4646
47- def map_mesh (target_mesh , pattern_mesh , clip_boundaries = True , simplify_borders = True , fixed_vertices = None , tolerance = 1e-6 ):
47+ def map_mesh (target_mesh , pattern_mesh , clip_boundaries = True , simplify_borders = True , fixed_vertices = None , tolerance = 1e-6 , unify_cycles = True ):
4848 """
4949 Map a 2D pattern mesh onto a 3D target.
5050
@@ -66,17 +66,20 @@ def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, simplify_borders=T
6666 tolerance : float, optional
6767 The tolerance for point comparison, to remove duplicates.
6868 Default is 1e-6.
69+ unify_cycles : bool, optional
70+ Whether to unify cycles of the pattern mesh.
71+ Default is True.
6972
7073 Returns
7174 -------
72- tuple[ndarray, VectorVectorInt, ndarray, VectorBool, VectorInt ]
75+ tuple[np.array, list[list[int]], np.array, list[bool], list[int] ]
7376 A tuple containing:
7477
75- * vertices: ndarray - The 3D coordinates of the mapped mesh vertices
76- * faces: VectorVectorInt - The faces of the mapped mesh
77- * normals: ndarray - The normal vectors at each vertex
78- * boundary_flags: VectorBool - Boolean flags indicating if vertices are on the boundary
79- * polygon_groups: VectorInt - Grouping indices for polygons (to form holes)
78+ * vertices: np.array - The 3D coordinates of the mapped mesh vertices
79+ * faces: list[list[int]] - The faces of the mapped mesh
80+ * normals: np.array - The normal vectors at each vertex
81+ * boundary_flags: list[bool] - Boolean flags indicating if vertices are on the boundary
82+ * polygon_groups: list[int] - Grouping indices for polygons (to form holes)
8083 """
8184 # Unpack mesh tuples
8285 v , f = target_mesh
@@ -106,11 +109,17 @@ def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, simplify_borders=T
106109 v_numpy , f_numpy , pattern_v_numpy , pattern_f_vec , clip_boundaries , simplify_borders , fixed_vertices_vectorint , tolerance
107110 )
108111
112+ # LIBIGL has no BFS orienting for polygons, only triangles, so we copy here data several times:
113+ if unify_cycles :
114+ mesh = Mesh .from_vertices_and_faces (pv_numpy_copy , pf_numpy_cleaned )
115+ mesh .unify_cycles ()
116+ pv_numpy_copy , pf_numpy_cleaned = mesh .to_vertices_and_faces ()
117+
109118 # Return the result as a tuple
110119 return pv_numpy_copy , pf_numpy_cleaned , p_normals , pattern_is_boundary , pattern_groups
111120
112121
113- def map_pattern_to_mesh (name , mesh , clip_boundaries = True , tolerance = 1e-6 , pattern_u = 16 , pattern_v = 16 , simplify_borders = True , fixed_vertices = None ):
122+ def map_pattern_to_mesh (name , mesh , clip_boundaries = True , tolerance = 1e-6 , pattern_u = 16 , pattern_v = 16 , simplify_borders = True , fixed_vertices = None , unify_cycles = True ):
114123 """
115124 Map a 2D pattern mesh onto a 3D target.
116125
@@ -158,7 +167,9 @@ def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, patter
158167 fixed_vertices : list[list[float]], optional
159168 A list of fixed points on the target mesh.
160169 Default is None.
161-
170+ unify_cycles : bool, optional
171+ Whether to unify cycles of the pattern mesh.
172+ Default is True.
162173 Returns
163174 -------
164175 compas.datastructures.Mesh
@@ -195,7 +206,7 @@ def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, patter
195206
196207 v , f = mesh .to_vertices_and_faces ()
197208 mapped_vertices , mapped_faces , mapped_normals , mapped_is_boundary , mapped_groups = map_mesh (
198- (v , f ), (pv , pf ), clip_boundaries = clip_boundaries , simplify_borders = simplify_borders , fixed_vertices = fixed_vertices , tolerance = tolerance
209+ (v , f ), (pv , pf ), clip_boundaries = clip_boundaries , simplify_borders = simplify_borders , fixed_vertices = fixed_vertices , tolerance = tolerance , unify_cycles = unify_cycles
199210 )
200211
201212 return Mesh .from_vertices_and_faces (mapped_vertices , mapped_faces )
0 commit comments