InteractiveRemesher make_remesher(DMesh3 mesh) { var m = new InteractiveRemesher(mesh); m.PreventNormalFlips = true; double mine, maxe, avge; MeshQueries.EdgeLengthStats(mesh, out mine, out avge, out maxe); m.SetTargetEdgeLength(avge * EdgeLengthMultiplier); m.SmoothSpeedT = SmoothSpeed; if (Reproject) { m.SetProjectionTarget(MeshProjectionTarget.Auto(mesh)); } if (RemeshBoundary) { MeshBoundaryLoops loops = new MeshBoundaryLoops(mesh); int k = 1; foreach (var loop in loops) { MeshConstraintUtil.ConstrainVtxLoopTo(m, loop.Vertices, new DCurveProjectionTarget(loop.ToCurve()), k++); } } else if (PreserveBoundary) { MeshConstraintUtil.FixAllBoundaryEdges(m); } return(m); }
void smooth_and_remesh(MeshFaceSelection tris) { if (EnableLaplacianSmooth) { LaplacianMeshSmoother.RegionSmooth(Mesh, tris, 2, 2, false); } if (RemeshAfterSmooth) { tris.ExpandToOneRingNeighbours(2); tris.LocalOptimize(true, true); MeshProjectionTarget target = MeshProjectionTarget.Auto(Mesh, tris, 5); RegionRemesher remesh2 = new RegionRemesher(Mesh, tris); remesh2.SetTargetEdgeLength(TargetEdgeLength); remesh2.SmoothSpeedT = 1.0; remesh2.SetProjectionTarget(target); if (ConfigureRemesherF != null) { ConfigureRemesherF(remesh2, false); } for (int k = 0; k < 10; ++k) { remesh2.BasicRemeshPass(); } remesh2.BackPropropagate(); FillTriangles = remesh2.CurrentBaseTriangles; } else { FillTriangles = tris.ToArray(); } }
void smooth_and_remesh_preserve(MeshFaceSelection tris, bool bFinal) { if (EnableLaplacianSmooth) { LaplacianMeshSmoother.RegionSmooth(Mesh, tris, 2, 2, true); } if (RemeshAfterSmooth) { MeshProjectionTarget target = (bFinal) ? MeshProjectionTarget.Auto(Mesh, tris, 5) : null; RegionRemesher remesh2 = new RegionRemesher(Mesh, tris); remesh2.SetTargetEdgeLength(TargetEdgeLength); remesh2.SmoothSpeedT = 1.0; remesh2.SetProjectionTarget(target); if (ConfigureRemesherF != null) { ConfigureRemesherF(remesh2, false); } for (int k = 0; k < 10; ++k) { remesh2.BasicRemeshPass(); } remesh2.BackPropropagate(); FillTriangles = remesh2.CurrentBaseTriangles; } else { FillTriangles = tris.ToArray(); } }
protected void generate(float fDiameter, float fHeight, float fWallThickness, float fBaseThickness) { base.reset_holes(); CappedCylinderGenerator outer_cylgen = new CappedCylinderGenerator() { BaseRadius = fDiameter / 2, TopRadius = fDiameter / 2, Height = fHeight + 10, Slices = 60, Clockwise = true }; DMesh3 outer_mesh = outer_cylgen.Generate().MakeDMesh(); float fInnerDiam = fDiameter - 2 * fWallThickness; CappedCylinderGenerator inner_cylgen = new CappedCylinderGenerator() { BaseRadius = fInnerDiam / 2, TopRadius = fInnerDiam / 2, Height = fHeight + 10, Slices = 60, Clockwise = false }; DMesh3 inner_mesh = inner_cylgen.Generate().MakeDMesh(); MeshTransforms.Translate(inner_mesh, fBaseThickness * Vector3d.AxisY); DMesh3[] meshes = new DMesh3[2] { outer_mesh, inner_mesh }; foreach (DMesh3 mesh in meshes) { Remesher r = new Remesher(mesh); r.SetTargetEdgeLength(TargetEdgeLength); r.SmoothSpeedT = 0.5f; r.SetExternalConstraints(new MeshConstraints()); MeshConstraintUtil.FixAllGroupBoundaryEdges(r.Constraints, mesh, true); r.SetProjectionTarget(MeshProjectionTarget.Auto(mesh)); for (int k = 0; k < 10; ++k) { r.BasicRemeshPass(); } } Vector3d vCutPos = new Vector3d(0, fHeight, 0); Vector3d vCutNormal = Vector3d.AxisY; foreach (DMesh3 mesh in meshes) { MeshPlaneCut cut = new MeshPlaneCut(mesh, new Vector3d(0, fHeight, 0), Vector3d.AxisY); cut.Cut(); } base.set_output_meshes(inner_mesh, outer_mesh); }
protected override void SolveInstance(IGH_DataAccess DA) { DMesh3_goo dMsh_goo = null; double targetL = 0; int numI = 0; bool fixB = false; bool projBack = false; DA.GetData(0, ref dMsh_goo); DA.GetData(1, ref targetL); DA.GetData(2, ref numI); DA.GetData(3, ref fixB); DA.GetData(4, ref projBack); DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value); Remesher r = new Remesher(dMsh_copy); r.PreventNormalFlips = true; r.SetTargetEdgeLength(targetL); r.SmoothSpeedT = 0.5; if (fixB) { MeshConstraintUtil.FixAllBoundaryEdges(r); } 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); }
/// <summary> /// uses marching cubes to help smooth the mesh after using the remesher /// experimental /// </summary> /// <param name="edgeLength"></param> /// <param name="smoothSpeed"></param> /// <param name="iterations"></param> /// <param name="cells"></param> public void Smooth(double edgeLength, double smoothSpeed, double iterations, double cells) { //Use the Remesher class to do a basic remeshing DMesh3 mesh = new DMesh3(_mesh); Remesher r = new Remesher(mesh); r.PreventNormalFlips = true; r.SetTargetEdgeLength(edgeLength); r.SmoothSpeedT = smoothSpeed; r.SetProjectionTarget(MeshProjectionTarget.Auto(mesh)); for (int k = 0; k < iterations; k++) { r.BasicRemeshPass(); } //marching cubes int num_cells = (int)cells; if (cells > 0) { double cell_size = mesh.CachedBounds.MaxDim / num_cells; MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(mesh, cell_size); sdf.Compute(); var iso = new DenseGridTrilinearImplicit(sdf.Grid, sdf.GridOrigin, sdf.CellSize); MarchingCubes c = new MarchingCubes(); c.Implicit = iso; c.Bounds = mesh.CachedBounds; c.CubeSize = c.Bounds.MaxDim / cells; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); _smoothMesh = c.Mesh; } else { _smoothMesh = mesh; } _displayMesh = DMeshToMeshGeometry(_smoothMesh); _moldMesh = null; }
protected override void SolveInstance(IGH_DataAccess DA) { DMesh3_goo dMsh_goo = null; double targetL = 0; bool fixB = false; bool projBack = false; bool run = false; bool reset = false; int maxIter = 0; DA.GetData(0, ref dMsh_goo); DA.GetData(1, ref targetL); DA.GetData(3, ref fixB); DA.GetData(4, ref projBack); DA.GetData(2, ref maxIter); DA.GetData(5, ref run); DA.GetData(6, ref reset); if (passes >= maxIter) { run = false; } if (r is null || reset) { dMsh_copy = new DMesh3(dMsh_goo.Value); r = new Remesher(dMsh_copy); r.PreventNormalFlips = true; r.SetTargetEdgeLength(targetL); r.SmoothSpeedT = 0.5; passes = 0; if (fixB) { MeshConstraintUtil.FixAllBoundaryEdges(r); } if (projBack) { r.SetProjectionTarget(MeshProjectionTarget.Auto(dMsh_goo.Value)); } } if (run && !reset) { r.BasicRemeshPass(); passes++; Update(); } bool isValid = dMsh_copy.CheckValidity(); if (!isValid) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh seems to have been corrupted during remeshing. Please check..."); } this.Message = "Pass: " + passes.ToString(); DA.SetData(0, dMsh_copy); }
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); }
protected void do_flatten(DMesh3 mesh) { double BAND_HEIGHT = flatten_band_height; Vector3d down_axis = -Vector3d.AxisY; double dot_thresh = 0.2; AxisAlignedBox3d bounds = mesh.CachedBounds; DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true); Ray3d ray = new Ray3d(bounds.Center - 2 * bounds.Height * Vector3d.AxisY, Vector3d.AxisY); int hit_tid = spatial.FindNearestHitTriangle(ray); Frame3f hitF; MeshQueries.RayHitPointFrame(mesh, spatial, ray, out hitF); Vector3d basePt = hitF.Origin; Frame3f basePlane = new Frame3f(basePt, Vector3f.AxisY); MeshConnectedComponents components = new MeshConnectedComponents(mesh) { FilterF = (tid) => { if (mesh.GetTriangleGroup(tid) != LastExtrudeOuterGroupID) { return(false); } Vector3d n, c; double a; mesh.GetTriInfo(tid, out n, out a, out c); double h = Math.Abs(c.y - basePt.y); if (h > BAND_HEIGHT) { return(false); } if (n.Dot(down_axis) < dot_thresh) { return(false); } return(true); }, SeedFilterF = (tid) => { return(tid == hit_tid); } }; components.FindConnectedT(); MeshFaceSelection all_faces = new MeshFaceSelection(mesh); foreach (var comp in components) { MeshVertexSelection vertices = new MeshVertexSelection(mesh); vertices.SelectTriangleVertices(comp.Indices); foreach (int vid in vertices) { Vector3d v = mesh.GetVertex(vid); v = basePlane.ProjectToPlane((Vector3f)v, 2); mesh.SetVertex(vid, v); } all_faces.SelectVertexOneRings(vertices); } all_faces.ExpandToOneRingNeighbours(3, (tid) => { return(mesh.GetTriangleGroup(tid) == LastExtrudeOuterGroupID); }); RegionRemesher r = new RegionRemesher(mesh, all_faces); r.SetProjectionTarget(MeshProjectionTarget.Auto(mesh)); r.SetTargetEdgeLength(2.0f); r.SmoothSpeedT = 1.0f; for (int k = 0; k < 10; ++k) { r.BasicRemeshPass(); } r.SetProjectionTarget(null); r.SmoothSpeedT = 1.0f; for (int k = 0; k < 10; ++k) { r.BasicRemeshPass(); } r.BackPropropagate(); }
protected override void SolveInstance(IGH_DataAccess DA) { Mesh m = DA.Fetch <Mesh>("Mesh"); bool fixEdges = DA.Fetch <bool>("FixEdges"); double l = DA.Fetch <double>("EdgeLength"); int iterations = DA.Fetch <int>("Iterations"); List <Point3d> fixPt = DA.FetchList <Point3d>("FixPt"); bool project = DA.Fetch <bool>("Project"); bool loops = DA.Fetch <bool>("Loops"); Mesh mesh = m.DuplicateMesh(); mesh.Faces.ConvertQuadsToTriangles(); double len = (l == 0) ? mesh.GetBoundingBox(false).Diagonal.Length * 0.1 : l; //r.PreventNormalFlips = true; List <int> ids = new List <int>(); Point3d[] pts = mesh.Vertices.ToPoint3dArray(); foreach (Point3d p in fixPt) { ids.Add(NGonsCore.PointUtil.ClosestPoint(p, pts)); } DMesh3 dmesh = mesh.ToDMesh3(); Remesher r = new Remesher(dmesh); r.Precompute(); r.SetTargetEdgeLength(len); r.SmoothSpeedT = 0.5; if (project) { r.SetProjectionTarget(MeshProjectionTarget.Auto(dmesh)); } r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.EnableSmoothing = true; MeshConstraints cons = new MeshConstraints(); if (ids.Count > 0) { foreach (int id in ids) { //cons.SetOrUpdateVertexConstraint(id, new VertexConstraint(true, 1)); cons.SetOrUpdateVertexConstraint(id, VertexConstraint.Pinned); } } r.SetExternalConstraints(cons); r.Precompute(); if (fixEdges) { //r.SetExternalConstraints(new MeshConstraints()); MeshConstraintUtil.FixAllBoundaryEdges(r); MeshConstraintUtil.FixAllBoundaryEdges_AllowSplit(cons, dmesh, 0); //MeshConstraintUtil.FixAllBoundaryEdges_AllowCollapse(cons, dmesh, 0); } if (loops) { MeshConstraintUtil.PreserveBoundaryLoops(r); //project to edge //MeshConstraintUtil.PreserveBoundaryLoops(cons,dmesh);//project to edge } r.SetExternalConstraints(cons); for (int k = 0; k < iterations; ++k) { r.BasicRemeshPass(); } //output if (ids.Count > 0 && !fixEdges) { this.Message = "Vertices"; } else if (ids.Count == 0 && fixEdges) { this.Message = "Edges"; } else if (ids.Count > 0 && fixEdges) { this.Message = "Vertices + Edges"; } else { this.Message = ""; } dmesh = new DMesh3(dmesh, true); Mesh rmesh = dmesh.ToRhinoMesh(); if (loops) { Mesh mesh_ = rmesh.DuplicateMesh(); Rhino.IndexPair[] closestEdges = new Rhino.IndexPair[fixPt.Count]; int counter = 0; foreach (Point3d p in fixPt) { double[] d = new double[rmesh.TopologyEdges.Count]; int[] eid = new int[rmesh.TopologyEdges.Count]; for (int i = 0; i < rmesh.TopologyEdges.Count; i++) { if (rmesh.TopologyEdges.GetConnectedFaces(i).Length == 1) { Line line = rmesh.TopologyEdges.EdgeLine(i); line.ClosestPoint(p, true); d[i] = line.ClosestPoint(p, true).DistanceToSquared(p); //line.From.DistanceToSquared(p) + line.To.DistanceToSquared(p); } else { d[i] = 99999; } eid[i] = i; } Array.Sort(d, eid); closestEdges[counter++] = rmesh.TopologyEdges.GetTopologyVertices(eid[0]); } for (int i = 0; i < fixPt.Count; i++) { mesh_.Vertices.Add(fixPt[i]); mesh_.Faces.AddFace(rmesh.Vertices.Count + i, closestEdges[i].I, closestEdges[i].J); } rmesh = mesh_; } rmesh.UnifyNormals(); rmesh.RebuildNormals(); // rmesh.UnifyNormals(); DA.SetData(0, rmesh); }