示例#1
0
        DMesh3 GenerateRemesh(DMesh3 mesh)
        {
            DMesh3 remeshed = new DMesh3(mesh);

            DMeshAABBTree3 project = new DMeshAABBTree3(mesh);

            project.Build();
            MeshProjectionTarget Target = new MeshProjectionTarget(project.Mesh, project);

            double minlen, maxlen, avglen;

            MeshQueries.EdgeLengthStats(mesh, out minlen, out maxlen, out avglen);
            double edge_len = (TargetEdgeLength == 0) ? Loop.AverageEdgeLength : avglen;

            Remesher r = new Remesher(remeshed);

            r.SetTargetEdgeLength(edge_len);
            r.SetProjectionTarget(Target);
            MeshConstraintUtil.FixAllBoundaryEdges(r);

            for (int k = 0; k < 20; ++k)
            {
                r.BasicRemeshPass();
            }

            return(remeshed);
        }
示例#2
0
    void remove_old_vertices(int[] MapV, DMesh3 mesh)
    {
        HashSet <int> keepV = new HashSet <int>();

        for (int k = 0; k < MapV.Length; ++k)
        {
            if (MapV[k] != DMesh3.InvalidID)
            {
                keepV.Add(MapV[k]);
            }
        }

        Remesher r = new Remesher(mesh);

        //r.EnableCollapses = false;
        //r.EnableSplits = false;
        //r.EnableFlips = false;
        r.SmoothSpeedT = 1.0;
        //r.EnableSmoothing = false;
        r.PreventNormalFlips = true;
        r.SetTargetEdgeLength(1.0);
        //r.EnableSmoothing = false;
        MeshConstraints c = new MeshConstraints();

        foreach (int vid in keepV)
        {
            c.SetOrUpdateVertexConstraint(vid, VertexConstraint.Pinned);
        }
        r.SetExternalConstraints(c);

        double minE, maxE, avgE;

        MeshQueries.EdgeLengthStats(mesh, out minE, out maxE, out avgE);
        r.SetTargetEdgeLength(avgE * .3);

        for (int k = 0; k < 10; ++k)
        {
            r.BasicRemeshPass();
        }

        //int iter = 0;
        //while (iter++ < 10) {
        //    r.SetTargetEdgeLength(iter * 1.0);
        //    for (int k = 0; k < 10; ++k)
        //        r.BasicRemeshPass();
        //}
    }
示例#3
0
        public bool Compute()
        {
            PlanarMesh   = BuildPlanarMesh(false);
            InflatedMesh = ComputeInflation(PlanarMesh);

            DMesh3 remeshed = GenerateRemesh(InflatedMesh);

            Flatten(remeshed);

            ResultMesh = ComputeInflation(remeshed);

            MeshBoundaryLoops loops = new MeshBoundaryLoops(ResultMesh);

            DMesh3 otherSide = new DMesh3(ResultMesh);

            foreach (int vid in otherSide.VertexIndices())
            {
                Vector3d v = otherSide.GetVertex(vid);
                v.z = -v.z;
                otherSide.SetVertex(vid, v);
            }
            otherSide.ReverseOrientation();

            MeshEditor editor = new MeshEditor(ResultMesh);

            int[] mapVArray;
            editor.AppendMesh(otherSide, out mapVArray);
            IndexMap mapV = new IndexMap(mapVArray);

            foreach (EdgeLoop loop in loops)
            {
                int[] otherLoop = (int[])loop.Vertices.Clone();
                IndexUtil.Apply(otherLoop, mapV);
                editor.StitchLoop(loop.Vertices, otherLoop);
            }


            Remesher remesh = new Remesher(ResultMesh);

            remesh.SetTargetEdgeLength(TargetEdgeLength);
            remesh.SmoothSpeedT = 0.25f;
            for (int k = 0; k < 10; ++k)
            {
                remesh.BasicRemeshPass();
            }
            ResultMesh = new DMesh3(ResultMesh, true);


            LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(ResultMesh);

            foreach (int vid in ResultMesh.VertexIndices())
            {
                smoother.SetConstraint(vid, ResultMesh.GetVertex(vid), 0.5f, false);
            }
            smoother.SolveAndUpdateMesh();


            return(true);
        }
示例#4
0
        DMesh3 BuildPlanarMesh(bool bPreservePolygon)
        {
            DMesh3 planarMesh = new DMesh3();

            Vector2d center    = CurveUtils2.CentroidVtx(Loop.Vertices);
            int      center_id = planarMesh.AppendVertex(new Vector3d(center.x, center.y, 0));

            int prev_id  = -1;
            int first_id = -1;

            foreach (Vector2d v in Loop.Vertices)
            {
                int next_id = planarMesh.AppendVertex(new Vector3d(v.x, v.y, Thickness));
                if (prev_id > 0)
                {
                    planarMesh.AppendTriangle(center_id, prev_id, next_id);
                    prev_id = next_id;
                }
                else
                {
                    first_id = next_id;
                    prev_id  = next_id;
                }
            }
            planarMesh.AppendTriangle(center_id, prev_id, first_id);

            if (ReverseOrientation)
            {
                planarMesh.ReverseOrientation();
            }

            Debug.Assert(planarMesh.CheckValidity());


            double   edge_len = (TargetEdgeLength == 0) ? Loop.AverageEdgeLength : TargetEdgeLength;
            Remesher r        = new Remesher(planarMesh);

            r.SetTargetEdgeLength(edge_len);
            r.SmoothSpeedT = 1.0f;
            if (bPreservePolygon)
            {
                MeshConstraintUtil.FixAllBoundaryEdges(r);
            }
            else
            {
                MeshConstraintUtil.PreserveBoundaryLoops(r);
            }

            for (int k = 0; k < 20; ++k)
            {
                r.BasicRemeshPass();
            }

            return(planarMesh);
        }
        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);
        }
示例#6
0
        public static DMesh3 Remesh(DMesh3 mesh, double edgeLenght, int iteration)
        {
            Remesher r = new Remesher(mesh);

            r.PreventNormalFlips = true;
            r.SetTargetEdgeLength(edgeLenght);
            for (int k = 0; k < iteration; ++k)
            {
                r.BasicRemeshPass();
            }

            return(new g3.DMesh3(r.Mesh, true));
        }
示例#7
0
        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);
        }
示例#8
0
        /// <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;
        }
示例#9
0
        /// <summary>
        /// Class for normalising and refining a given mesh.
        /// </summary>
        /// <param name="mesh">The mesh that needs to be refined.</param>
        /// <param name="file">The file containing the shape to refine.</param>
        /// <exception cref="ArgumentNullException">If the given file is
        /// <see langword="null"/>.</exception>
        /// <exception cref="ArgumentException">If the given file does not exist.
        /// </exception>
        public void RefineMesh(Shapes.IMesh mesh, FileInfo file)
        {
            if (mesh == null)
            {
                throw new ArgumentNullException(nameof(mesh));
            }
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (!file.Exists)
            {
                throw new ArgumentException(Resources.EX_FileNotFound, file.FullName);
            }

            DMesh3 meshDMesh3 = mesh as GeometryMesh;

            Remesher remesher = new Remesher(meshDMesh3)
            {
                PreventNormalFlips = true
            };

            int i = 0;

            while (meshDMesh3.VertexCount < Settings.RefineVertexNumber && i < Settings.MaxRefineIterations)
            {
                remesher.SetTargetEdgeLength(0.0001F);
                remesher.BasicRemeshPass();
                i++;
            }

            Reducer reducer = new Reducer(meshDMesh3);

            reducer.ReduceToVertexCount(Settings.RefineVertexNumber);

            Settings.FileManager.Write(file.FullName, GeometryMesh.ToGeometryMesh(meshDMesh3));
        }
示例#10
0
        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);
        }
示例#11
0
        public static void performance_grinder()
        {
            LocalProfiler p = new LocalProfiler();

            DateTime start = DateTime.Now;

            //p.Start("Meshgen");
            //for (int k = 0; k < 100; ++k) {
            //    Sphere3Generator_NormalizedCube tmpgen = new Sphere3Generator_NormalizedCube();
            //    tmpgen.EdgeVertices = 100;
            //    tmpgen.Generate();
            //    DMesh3 tmp = tmpgen.MakeDMesh();
            //}
            //p.StopAndAccumulate("Meshgen");

            //System.Console.WriteLine("done meshgen");

            Sphere3Generator_NormalizedCube meshgen = new Sphere3Generator_NormalizedCube()
            {
                EdgeVertices = 100
            };

            meshgen.Generate();
            DMesh3 sphereMesh = meshgen.MakeDMesh();


            //p.Start("Spatial");
            //for (int k = 0; k < 100; ++k) {
            //    DMeshAABBTree3 tmpspatial = new DMeshAABBTree3(sphereMesh);
            //    tmpspatial.Build();
            //}
            //p.StopAndAccumulate("Spatial");

            //System.Console.WriteLine("done spatial");

            meshgen.EdgeVertices = 5;
            meshgen.Generate();
            sphereMesh = meshgen.MakeDMesh();
            double remesh_len = (2.0 / 5.0) * 0.025;   // takes ~220s
            //double remesh_len = (2.0 / 5.0) * 0.05;

            long     max_mem  = 0;
            Remesher remesher = new Remesher(sphereMesh);

            for (int k = 0; k < 10; ++k)
            {
                System.Console.WriteLine("{0}", k);
                p.Start("Remesh");
                remesher.SetTargetEdgeLength(remesh_len);
                remesher.SmoothSpeedT = 0.5f;
                for (int j = 0; j < 20; ++j)
                {
                    remesher.BasicRemeshPass();
                    foreach (int vid in sphereMesh.VertexIndices())
                    {
                        Vector3d v = sphereMesh.GetVertex(vid);
                        v.Normalize();
                        sphereMesh.SetVertex(vid, v);
                    }
                }
                p.StopAndAccumulate("Remesh");

                //System.Console.WriteLine(sphereMesh.MeshInfoString());

                System.Console.WriteLine(" {0}", k);

                p.Start("Reduce");
                remesher.SetTargetEdgeLength(remesh_len * 10);
                for (int j = 0; j < 20; ++j)
                {
                    remesher.BasicRemeshPass();
                    foreach (int vid in sphereMesh.VertexIndices())
                    {
                        Vector3d v = sphereMesh.GetVertex(vid);
                        v.Normalize();
                        sphereMesh.SetVertex(vid, v);
                    }
                }
                p.StopAndAccumulate("Reduce");
            }

            DateTime end = DateTime.Now;

            System.Console.WriteLine("done remesh");
            System.Console.WriteLine("Time {0} MaxMem {1}", (end - start).TotalSeconds, max_mem / (1024 * 1024));
            System.Console.WriteLine(p.AllAccumulatedTimes("Accumulated: "));
        }
示例#12
0
        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);
        }
示例#13
0
        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);
        }