// This function does local remeshing around a boundary loop within a fixed # of // rings, to try to 'massage' it into a cleaner shape/topology // [TODO] use geodesic distance instead of fixed # of rings? public static void cleanup_boundary(DMesh3 mesh, EdgeLoop loop, double target_edge_len, int nRings = 3) { Debug.Assert(loop.IsBoundaryLoop()); MeshFaceSelection roi = new MeshFaceSelection(mesh); roi.SelectVertexOneRings(loop.Vertices); for (int i = 0; i < nRings; ++i) { roi.ExpandToOneRingNeighbours(); } roi.LocalOptimize(true, true); RegionRemesher r = new RegionRemesher(mesh, roi.ToArray()); r.Precompute(); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = target_edge_len; r.MaxEdgeLength = 2 * target_edge_len; r.EnableSmoothing = true; r.SmoothSpeedT = 0.1f; for (int k = 0; k < nRings * 3; ++k) { r.BasicRemeshPass(); } Debug.Assert(mesh.CheckValidity()); r.BackPropropagate(); }
// This function does local remeshing around a boundary loop within a fixed # of // rings, to try to 'massage' it into a cleaner shape/topology. // The result_edges list is the mapped edges of loop on the resulting mesh, but it is *not* in-order // [TODO] use geodesic distance instead of fixed # of rings? public static void cleanup_boundary(DMesh3 mesh, EdgeLoop loop, double target_edge_len, out List <int> result_edges, int nRings = 3) { Debug.Assert(loop.IsBoundaryLoop()); var roi = new MeshFaceSelection(mesh); roi.SelectVertexOneRings(loop.Vertices); for (int i = 0; i < nRings; ++i) { roi.ExpandToOneRingNeighbours(); } roi.LocalOptimize(true, true); var r = new RegionRemesher(mesh, roi.ToArray()); // tag the input loop edges in the remesher, so that we can find this loop afterwards int[] init_loop_edges = new int[loop.EdgeCount]; Array.Copy(loop.Edges, init_loop_edges, loop.EdgeCount); r.Region.MapEdgesToSubmesh(init_loop_edges); MeshConstraintUtil.AddTrackedEdges(r.Constraints, init_loop_edges, 100); //foreach (int eid in init_loop_edges) // Debug.Assert(r.Region.SubMesh.IsBoundaryEdge(eid)); r.Precompute(); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = target_edge_len; r.MaxEdgeLength = 2 * target_edge_len; r.EnableSmoothing = true; r.SmoothSpeedT = 0.1f; for (int k = 0; k < nRings * 3; ++k) { r.BasicRemeshPass(); } Debug.Assert(mesh.CheckValidity()); // extract the edges we tagged (they are unordered) List <int> new_loop_edges = r.Constraints.FindConstrainedEdgesBySetID(100); //foreach (int eid in new_loop_edges) // Debug.Assert(r.Region.SubMesh.IsBoundaryEdge(eid)); r.BackPropropagate(); // map the extracted edges back to the backpropped input mesh result_edges = MeshIndexUtil.MapEdgesViaVertexMap(r.ReinsertSubToBaseMapV, r.Region.SubMesh, r.BaseMesh, new_loop_edges); //foreach (int eid in result_edges) // Debug.Assert(mesh.IsBoundaryEdge(eid)); }