public static void quick_test_2() { DMesh3 target = TestUtil.LoadTestInputMesh("cylinder_orig.obj"); DMeshAABBTree3 targetSpatial = new DMeshAABBTree3(target, true); DMesh3 mesh = TestUtil.LoadTestInputMesh("cylinder_approx.obj"); DMeshAABBTree3 meshSpatial = new DMeshAABBTree3(mesh, true); double search_dist = 10.0; MeshTopology topo = new MeshTopology(target); topo.Compute(); RemesherPro r = new RemesherPro(mesh); r.SetTargetEdgeLength(2.0); r.SmoothSpeedT = 0.5; r.SetProjectionTarget(MeshProjectionTarget.Auto(target)); MeshConstraints cons = new MeshConstraints(); r.SetExternalConstraints(cons); int set_id = 1; foreach (var loop in topo.Loops) { DCurveProjectionTarget curveTarget = new DCurveProjectionTarget(loop.ToCurve(target)); set_id++; // pick a set of points we will find paths between. We will chain // up those paths and constrain them to target loops. // (this part is the hack!) List <int> target_verts = new List <int>(); List <int> mesh_verts = new List <int>(); for (int k = 0; k < loop.VertexCount; k += 5) { target_verts.Add(loop.Vertices[k]); Vector3d vCurve = target.GetVertex(loop.Vertices[k]); int mesh_vid = meshSpatial.FindNearestVertex(vCurve, search_dist); mesh_verts.Add(mesh_vid); } int NT = target_verts.Count; // find the paths to assemble the edge chain // [TODO] need to filter out junction vertices? or will they just handle themselves // because they can be collapsed away? List <int> vert_seq = new List <int>(); for (int k = 0; k < NT; k++) { EdgeSpan e = find_edge_path(mesh, mesh_verts[k], mesh_verts[(k + 1) % NT]); int n = e.Vertices.Length; for (int i = 0; i < n - 1; ++i) { vert_seq.Add(e.Vertices[i]); } } // now it's easy, just add the loop constraint EdgeLoop full_loop = EdgeLoop.FromVertices(mesh, vert_seq); MeshConstraintUtil.ConstrainVtxLoopTo(cons, mesh, full_loop.Vertices, curveTarget, set_id); } r.FastestRemesh(); TestUtil.WriteTestOutputMesh(mesh, "curves_test_out.obj"); }
protected override void SolveInstance(IGH_DataAccess DA) { DMesh3_goo dMsh_goo = null; List <Point3d> points = new List <Point3d>(); double targetL = 0; int numI = 0; int fixB = 0; bool projBack = false; double smooth = 0; DA.GetData(0, ref dMsh_goo); DA.GetDataList(2, points); DA.GetData(1, ref targetL); DA.GetData(6, ref numI); DA.GetData(3, ref fixB); DA.GetData(5, ref projBack); DA.GetData(7, ref smooth); List <EdgeConstraint_goo> edgeC = new List <EdgeConstraint_goo>(); DA.GetDataList(4, edgeC); DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value); Remesher r = new Remesher(dMsh_copy); r.PreventNormalFlips = true; r.SetTargetEdgeLength(targetL); r.SmoothSpeedT = smooth; if (fixB == 2) { MeshConstraintUtil.FixAllBoundaryEdges(r); } else if (fixB == 1) { MeshConstraintUtil.PreserveBoundaryLoops(r); } else { r.SetExternalConstraints(new MeshConstraints()); } if (edgeC.Count > 0) { for (int i = 0; i < edgeC.Count; i++) { var tempEC = edgeC[i]; IProjectionTarget target = new DCurveProjectionTarget(tempEC.crv); for (int j = 0; j < tempEC.edges.Length; j++) { tempEC.constraint.Target = target; r.Constraints.SetOrUpdateEdgeConstraint(tempEC.edges[j], tempEC.constraint); } for (int j = 0; j < tempEC.vertices.Length; j++) { if (tempEC.PinVerts) { r.Constraints.SetOrUpdateVertexConstraint(tempEC.vertices[j], VertexConstraint.Pinned); } else { r.Constraints.SetOrUpdateVertexConstraint(tempEC.vertices[j], new VertexConstraint(target)); } } } } if (points.Count > 0) { DMeshAABBTree3 mshAABB = new DMeshAABBTree3(dMsh_copy, true); var v3pts = points.Select(pt => pt.ToVec3d()); foreach (var p in v3pts) { int id = mshAABB.FindNearestVertex(p, 0.1); if (id != -1) { r.Constraints.SetOrUpdateVertexConstraint(id, VertexConstraint.Pinned); } } } if (projBack) { r.SetProjectionTarget(MeshProjectionTarget.Auto(dMsh_goo.Value)); } for (int k = 0; k < numI; ++k) { r.BasicRemeshPass(); } bool isValid = dMsh_copy.CheckValidity(); if (!isValid) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh seems to have been corrupted during remeshing. Please check..."); } DA.SetData(0, dMsh_copy); }