Beispiel #1
0
        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();
            }
        }
Beispiel #2
0
    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);
    }
Beispiel #3
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);
        }
Beispiel #4
0
        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();
            }
        }
Beispiel #5
0
        public DMesh3 remesh_constraints_fixedverts(int iterations, DMesh3 mesh, double min, double max, double angle)
        {
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh = meshCopy, Spatial = tree
            };

            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > angle)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
                    Index2i ev      = mesh.GetEdgeV(eid);
                    int     nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2;
                    int     nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }
            }

            Remesher r = new Remesher(mesh);

            r.Precompute();
            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);
            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = min;
            r.MaxEdgeLength   = max;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 1;


            for (int k = 0; k < iterations; ++k)
            {
                r.BasicRemeshPass();
                mesh.CheckValidity();
            }


            return(mesh);
        }
        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);
        }
Beispiel #7
0
        public static DMesh3 MakeRemeshedCappedCylinder(double fResFactor = 1.0)
        {
            DMesh3 mesh = MakeCappedCylinder(false, 128);

            MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new g3.Vector3f(1, 2, 1));

            // construct mesh projection target
            DMesh3         meshCopy = new DMesh3(mesh);
            DMeshAABBTree3 tree     = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh    = meshCopy,
                Spatial = tree
            };
            MeshConstraints cons     = new MeshConstraints();
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
                    Index2i ev      = mesh.GetEdgeV(eid);
                    int     nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2;
                    int     nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }
            }
            Remesher r = new Remesher(mesh);

            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);
            r.Precompute();
            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = 0.1f * fResFactor;
            r.MaxEdgeLength   = 0.2f * fResFactor;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 0.5f;
            for (int k = 0; k < 20; ++k)
            {
                r.BasicRemeshPass();
            }
            return(mesh);
        }
Beispiel #8
0
        protected virtual DMesh3 update_standard()
        {
            DMesh3 sourceMesh = MeshSource.GetDMeshUnsafe();

            ISpatial sourceSpatial = (ReprojectToInput) ? MeshSource.GetSpatial() : null;

            DMesh3 meshIn = new DMesh3(sourceMesh);

            Reducer reduce = new Reducer(meshIn);

            if (ReprojectToInput)
            {
                reduce.ProjectionMode = Reducer.TargetProjectionMode.AfterRefinement;
                MeshProjectionTarget target = new MeshProjectionTarget(sourceMesh, sourceSpatial);
                reduce.SetProjectionTarget(target);
            }
            else
            {
                reduce.ProjectionMode = Reducer.TargetProjectionMode.NoProjection;
            }

            switch (TargetMode)
            {
            case TargetModes.TriangleCount:
                int tc = MathUtil.Clamp(TriangleCount, 1, meshIn.TriangleCount);
                reduce.ReduceToTriangleCount(tc);
                break;

            case TargetModes.VertexCount:
                int tv = MathUtil.Clamp(VertexCount, 1, meshIn.VertexCount);
                reduce.ReduceToVertexCount(tv);
                break;

            case TargetModes.MinEdgeLength:
                reduce.ReduceToEdgeLength(MinEdgeLength);
                break;
            }

            reduce.Progress = new ProgressCancel(is_invalidated);

            if (is_invalidated())
            {
                return(null);
            }

            return(meshIn);
        }
Beispiel #9
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);
        }
Beispiel #10
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;
        }
Beispiel #11
0
        public Mesh Reduce(Mesh inMesh, int targetCount)
        {
            var mesh    = inMesh.ToDMesh3();
            var reducer = new Reducer(mesh);

            if (MaintainSurface)
            {
                var tree = new DMeshAABBTree3(new DMesh3(mesh));
                tree.Build();
                var target = new MeshProjectionTarget(tree.Mesh, tree);
                reducer.SetProjectionTarget(target);
                reducer.ProjectionMode = Reducer.TargetProjectionMode.Inline;
            }

            reducer.ReduceToTriangleCount(Math.Max(4, targetCount));

            return(reducer.Mesh.ToMesh());
        }
Beispiel #12
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DMesh3_goo dMsh_goo = null;
            int        numF     = 0;
            bool       fixB     = false;
            bool       projBack = false;

            DA.GetData(0, ref dMsh_goo);
            DA.GetData(1, ref numF);
            DA.GetData(2, ref fixB);
            DA.GetData(3, ref projBack);

            DMesh3  dMsh_copy = new DMesh3(dMsh_goo.Value);
            Reducer r         = new Reducer(dMsh_copy);

            if (fixB)
            {
                r.SetExternalConstraints(new MeshConstraints());
                MeshConstraintUtil.PreserveBoundaryLoops(r.Constraints, dMsh_copy);
            }
            if (projBack)
            {
                DMeshAABBTree3 tree = new DMeshAABBTree3(new DMesh3(dMsh_copy));
                tree.Build();
                MeshProjectionTarget target = new MeshProjectionTarget(tree.Mesh, tree);
                r.SetProjectionTarget(target);
            }

            r.ReduceToTriangleCount(numF);
            bool isValid = dMsh_copy.CheckValidity();

            if (!isValid)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh seems to have been corrupted during reduction. Please check...");
            }

            DA.SetData(0, dMsh_copy);
        }
Beispiel #13
0
        public static void basic_test()
        {
            DMesh3 target = TestUtil.LoadTestInputMesh("twocylinder_orig.obj");
            DMesh3 mesh   = TestUtil.LoadTestInputMesh("twocylinder_approx.obj");

            DMeshAABBTree3 targetSpatial = new DMeshAABBTree3(target, true);

            ConstantMeshSourceOp sourceOp = new ConstantMeshSourceOp(mesh, true, true);
            ConstantMeshSourceOp targetOp = new ConstantMeshSourceOp(target, true, true);

            RemesherPro remesher = new RemesherPro(mesh);

            remesher.SetTargetEdgeLength(0.5f);
            //remesher.MinEdgeLength = 0.25;
            remesher.SmoothSpeedT = 0.5f;
            var ProjTarget = new MeshProjectionTarget(target, targetSpatial);

            remesher.SetProjectionTarget(ProjTarget);

            remesher.SharpEdgeReprojectionRemesh(20, 40);

            TestUtil.WriteTestOutputMesh(mesh, "reproject_cylinder.obj");
        }
Beispiel #14
0
        protected virtual DMesh3 compute_standard()
        {
            DMesh3   sourceMesh    = MeshSource.GetDMeshUnsafe();
            ISpatial sourceSpatial = MeshSource.GetSpatial();
            DMesh3   meshIn        = new DMesh3(sourceMesh);

            RemesherPro remesh = new RemesherPro(meshIn);

            //Remesher remesh = new Remesher(meshIn);

            remesh.SetTargetEdgeLength(TargetEdgeLength);
            remesh.PreventNormalFlips = this.PreventNormalFlips;
            remesh.EnableFlips        = this.EnableFlips;
            remesh.EnableSplits       = this.EnableSplits;
            remesh.EnableCollapses    = this.EnableCollapses;
            remesh.EnableSmoothing    = this.EnableSmoothing;
            remesh.SmoothSpeedT       = this.SmoothingSpeed;

            if (ReprojectToInput)
            {
                MeshProjectionTarget target = new MeshProjectionTarget(sourceMesh, sourceSpatial);
                remesh.SetProjectionTarget(target);
            }


            // if we are preserving creases, this will also automatically constrain boundary
            // edges boundary loops/spans.
            if (preserve_creases)
            {
                if (remesh.Constraints == null)
                {
                    remesh.SetExternalConstraints(new MeshConstraints());
                }

                MeshTopology topo = new MeshTopology(meshIn);
                topo.CreaseAngle = this.CreaseAngle;
                topo.AddRemeshConstraints(remesh.Constraints);

                // replace boundary edge constraints if we want other behaviors
                if (BoundaryMode == BoundaryModes.FixedBoundaries)
                {
                    MeshConstraintUtil.FixEdges(remesh.Constraints, meshIn, topo.BoundaryEdges);
                }
            }
            else if (sourceMesh.CachedIsClosed == false)
            {
                if (remesh.Constraints == null)
                {
                    remesh.SetExternalConstraints(new MeshConstraints());
                }

                if (BoundaryMode == BoundaryModes.FreeBoundaries)
                {
                    MeshConstraintUtil.PreserveBoundaryLoops(remesh.Constraints, meshIn);
                }
                else if (BoundaryMode == BoundaryModes.FixedBoundaries)
                {
                    MeshConstraintUtil.FixAllBoundaryEdges(remesh.Constraints, meshIn);
                }
                else if (BoundaryMode == BoundaryModes.ConstrainedBoundaries)
                {
                    MeshConstraintUtil.FixAllBoundaryEdges_AllowSplit(remesh.Constraints, meshIn, 0);
                }
            }

            remesh.Progress = new ProgressCancel(is_invalidated);

            remesh.FastestRemesh(RemeshRounds, true);
            //for (int k = 0; k < RemeshRounds; ++k)
            //    remesh.BasicRemeshPass();

            // free boundary remesh can leave sliver triangles around the border. clean that up.
            if (sourceMesh.CachedIsClosed == false && BoundaryMode == BoundaryModes.FreeBoundaries)
            {
                MeshEditor.RemoveFinTriangles(meshIn, (mesh, tid) => {
                    Index3i tv = mesh.GetTriangle(tid);
                    return(MathUtil.AspectRatio(mesh.GetVertex(tv.a), mesh.GetVertex(tv.b), mesh.GetVertex(tv.c)) > 2);
                });
            }

            if (is_invalidated())
            {
                return(null);
            }
            return(meshIn);
        }
        public static void test_remesh_constraints_fixedverts()
        {
            int    Slices = 128;
            DMesh3 mesh   = TestUtil.MakeCappedCylinder(false, Slices);

            MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1));
            mesh.CheckValidity();
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh = meshCopy, Spatial = tree
            };

            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_fixed_constraints_test_before.obj");
            }

            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
                    Index2i ev      = mesh.GetEdgeV(eid);
                    int     nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2;
                    int     nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }
            }

            Remesher r = new Remesher(mesh);

            r.Precompute();
            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);

            var stopwatch = Stopwatch.StartNew();

            //double fResScale = 1.0f;
            double fResScale = 0.5f;

            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = 0.1f * fResScale;
            r.MaxEdgeLength   = 0.2f * fResScale;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 0.5f;

            try {
                for (int k = 0; k < 20; ++k)
                {
                    r.BasicRemeshPass();
                    mesh.CheckValidity();
                }
            } catch {
                // ignore
            }

            stopwatch.Stop();
            System.Console.WriteLine("Second Pass Timing: " + stopwatch.Elapsed);

            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_fixed_constraints_test_after.obj");
            }
        }
Beispiel #16
0
        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();
        }
Beispiel #17
0
        public DMesh3 remesh_constraints_vertcurves(int iterations, DMesh3 mesh, double min, double max, double angle)
        {
            mesh.CheckValidity();
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget mesh_target = new MeshProjectionTarget()
            {
                Mesh    = meshCopy,
                Spatial = tree
            };

            // cylinder projection target
            CylinderProjectionTarget cyl_target = new CylinderProjectionTarget()
            {
                Cylinder = new Cylinder3d(new Vector3D(0, 1, 0), Vector3D.AxisY, 1, 2)
            };

            //IProjectionTarget target = mesh_target;
            IProjectionTarget target = cyl_target;

            // construct projection target circles
            CircleProjectionTarget bottomCons = new CircleProjectionTarget()
            {
                Circle = new Circle3d(bounds.Center, 1.0)
            };

            bottomCons.Circle.Center.y = bounds.Min.y;
            CircleProjectionTarget topCons = new CircleProjectionTarget()
            {
                Circle = new Circle3d(bounds.Center, 1.0)
            };

            topCons.Circle.Center.y = bounds.Max.y;


            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            bool bConstrainVertices = true;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    Index2i  ev  = mesh.GetEdgeV(eid);
                    Vector3D ev0 = mesh.GetVertex(ev[0]);
                    Vector3D ev1 = mesh.GetVertex(ev[1]);
                    CircleProjectionTarget loopTarget = null;
                    if (ev0.y > bounds.Center.y && ev1.y > bounds.Center.y)
                    {
                        loopTarget = topCons;
                    }
                    else if (ev0.y < bounds.Center.y && ev1.y < bounds.Center.y)
                    {
                        loopTarget = bottomCons;
                    }

                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags, loopTarget));
                    if (bConstrainVertices && loopTarget != null)
                    {
                        cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(loopTarget));
                        cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(loopTarget));
                    }
                }
            }


            Remesher r = new Remesher(mesh);

            //r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);
            r.Precompute();
            r.ENABLE_PROFILING = true;
            r.EnableFlips      = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength    = min;
            r.MaxEdgeLength    = max;
            r.EnableSmoothing  = true;
            r.SmoothSpeedT     = 1.0f;

            for (int k = 0; k < iterations; ++k)
            {
                r.BasicRemeshPass();
                mesh.CheckValidity();
            }

            return(mesh);
        }
Beispiel #18
0
        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");
        }
        public static void test_remesh_constraints_vertcurves()
        {
            int    Slices = 16;
            DMesh3 mesh   = TestUtil.MakeCappedCylinder(false, Slices);

            MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1));
            //DMesh3 mesh = TestUtil.MakeRemeshedCappedCylinder(0.25);
            //DMesh3 mesh = TestUtil.MakeRemeshedCappedCylinder(1.0);
            mesh.CheckValidity();
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget mesh_target = new MeshProjectionTarget()
            {
                Mesh = meshCopy, Spatial = tree
            };

            // cylinder projection target
            CylinderProjectionTarget cyl_target = new CylinderProjectionTarget()
            {
                Cylinder = new Cylinder3d(new Vector3d(0, 1, 0), Vector3d.AxisY, 1, 2)
            };

            //IProjectionTarget target = mesh_target;
            IProjectionTarget target = cyl_target;

            // construct projection target circles
            CircleProjectionTarget bottomCons = new CircleProjectionTarget()
            {
                Circle = new Circle3d(bounds.Center, 1.0)
            };

            bottomCons.Circle.Center.y = bounds.Min.y;
            CircleProjectionTarget topCons = new CircleProjectionTarget()
            {
                Circle = new Circle3d(bounds.Center, 1.0)
            };

            topCons.Circle.Center.y = bounds.Max.y;


            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_analytic_constraints_test_before.obj");
            }

            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            bool bConstrainVertices = true;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    Index2i  ev  = mesh.GetEdgeV(eid);
                    Vector3d ev0 = mesh.GetVertex(ev[0]);
                    Vector3d ev1 = mesh.GetVertex(ev[1]);
                    CircleProjectionTarget loopTarget = null;
                    if (ev0.y > bounds.Center.y && ev1.y > bounds.Center.y)
                    {
                        loopTarget = topCons;
                    }
                    else if (ev0.y < bounds.Center.y && ev1.y < bounds.Center.y)
                    {
                        loopTarget = bottomCons;
                    }

                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags, loopTarget));
                    if (bConstrainVertices && loopTarget != null)
                    {
                        cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(loopTarget));
                        cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(loopTarget));
                    }
                }
            }


            Remesher r = new Remesher(mesh);

            //r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);
            r.Precompute();
            r.ENABLE_PROFILING = true;

            var stopwatch = Stopwatch.StartNew();

            //double fResScale = 1.0f;
            double fResScale = 0.5f;

            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = 0.1f * fResScale;
            r.MaxEdgeLength   = 0.2f * fResScale;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 1.0f;

            try {
                for (int k = 0; k < 20; ++k)
                {
                    r.BasicRemeshPass();
                    mesh.CheckValidity();
                }
            } catch {
                // continue;
            }
            stopwatch.Stop();
            System.Console.WriteLine("Second Pass Timing: " + stopwatch.Elapsed);

            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_analytic_constraints_test_after.obj");
            }
        }
Beispiel #20
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);
        }
Beispiel #21
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);
        }
        public static DMesh3 RemeshMesh(g3.DMesh3 mesh, float minEdgeLength, float maxEdgeLength, float contraintAngle, float smoothSpeed, int smoothPasses, List <Line3d> constrainedLines)
        {
            // construct mesh projection target
            DMesh3         meshCopy = new DMesh3(mesh);
            DMeshAABBTree3 tree     = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh    = meshCopy,
                Spatial = tree
            };

            MeshConstraints cons     = new MeshConstraints();
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);

                Index2i ev = mesh.GetEdgeV(eid);

                if (fAngle > contraintAngle)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));


                    // TODO Ids based off of ?? What?
                    int nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2;
                    int nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }

                Vector3d p1 = mesh.GetVertex(ev.a);
                Vector3d p2 = mesh.GetVertex(ev.b);


                foreach (var v in constrainedLines)
                {
                    if (p1.CompareTo(v.Origin) == 0)
                    {
                        Vector3d p = v.PointAt(1.0);

                        if (p2.CompareTo(p) == 0)
                        {
                            cons.SetOrUpdateEdgeConstraint(eid, EdgeConstraint.FullyConstrained);
                            break;
                        }
                    }
                }

                foreach (var v in constrainedLines)
                {
                    if (p2.CompareTo(v.Origin) == 0)
                    {
                        Vector3d p = v.PointAt(1.0);

                        if (p1.CompareTo(p) == 0)
                        {
                            cons.SetOrUpdateEdgeConstraint(eid, EdgeConstraint.FullyConstrained);
                            break;
                        }
                    }
                }
            }

            Remesher r = new Remesher(mesh);

            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);
            r.Precompute();
            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = minEdgeLength;     //0.1f;
            r.MaxEdgeLength   = maxEdgeLength;     // 0.2f;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = smoothSpeed;       // .5;
            for (int k = 0; k < smoothPasses; ++k) // smoothPasses = 20
            {
                r.BasicRemeshPass();
            }
            return(mesh);
        }
        public static DMesh3 RemeshMesh(g3.DMesh3 mesh, float minEdgeLength, float maxEdgeLength, float contraintAngle, float smoothSpeed, int smoothPasses, g3.DMesh3 projectMeshInput = null, float projectAmount = 1.0f, float projectedDistance = float.MaxValue, List <Line3d> constrainedLines = null)
        {
            g3.DMesh3 projectMesh = projectMeshInput;

            if (projectMesh == null)
            {
                projectMesh = mesh;
            }

            DMesh3         projectMeshCopy = new DMesh3(projectMesh);
            DMeshAABBTree3 treeProject     = new DMeshAABBTree3(projectMeshCopy);

            treeProject.Build();
            MeshProjectionTarget targetProject = new MeshProjectionTarget()
            {
                Mesh    = projectMeshCopy,
                Spatial = treeProject
            };

            MeshConstraints cons     = new MeshConstraints();
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > contraintAngle)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
                    Index2i ev = mesh.GetEdgeV(eid);
                    //int nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2;
                    //int nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true));
                }

                if (constrainedLines != null)
                {
                    Index2i ev = mesh.GetEdgeV(eid);

                    Vector3d p1 = mesh.GetVertex(ev.a);
                    Vector3d p2 = mesh.GetVertex(ev.b);

                    foreach (var v in constrainedLines)
                    {
                        if (p1.CompareTo(v.Origin) == 0)
                        {
                            Vector3d p = v.PointAt(1.0);

                            if (p2.CompareTo(p) == 0)
                            {
                                cons.SetOrUpdateEdgeConstraint(eid, EdgeConstraint.FullyConstrained);
                                break;
                            }
                        }
                    }

                    foreach (var v in constrainedLines)
                    {
                        if (p2.CompareTo(v.Origin) == 0)
                        {
                            Vector3d p = v.PointAt(1.0);

                            if (p1.CompareTo(p) == 0)
                            {
                                cons.SetOrUpdateEdgeConstraint(eid, EdgeConstraint.FullyConstrained);
                                break;
                            }
                        }
                    }
                }
            }

            // TODO Constrain Vertices too far away
            foreach (int vid in mesh.VertexIndices())
            {
                var v = mesh.GetVertex(vid);

                //v.Distance()
                //targetProject.Project()
            }

            Remesher rProjected = new Remesher(mesh);

            rProjected.SetExternalConstraints(cons);
            rProjected.SetProjectionTarget(targetProject);
            rProjected.Precompute();
            rProjected.EnableFlips     = rProjected.EnableSplits = rProjected.EnableCollapses = true;
            rProjected.MinEdgeLength   = minEdgeLength; //0.1f;
            rProjected.MaxEdgeLength   = maxEdgeLength; // 0.2f;
            rProjected.EnableSmoothing = true;
            rProjected.SmoothSpeedT    = smoothSpeed;   // .5;

            if (projectMeshInput != null)
            {
                float bestSmoothPassProjectAmount     = projectAmount / smoothPasses;
                float testbestSmoothPassProjectAmount = float.MaxValue;
                for (float smoothPassProjectAmount = -.1f; smoothPassProjectAmount < 1.1f; smoothPassProjectAmount += 0.005f)
                {
                    double test = 0;

                    for (int i = 0; i < smoothPasses; i++)
                    {
                        test = 1.0 * smoothPassProjectAmount + test * (1 - smoothPassProjectAmount);
                    }

                    if (Math.Abs(test - projectAmount) < Math.Abs(testbestSmoothPassProjectAmount - projectAmount))
                    {
                        bestSmoothPassProjectAmount     = (float)smoothPassProjectAmount;
                        testbestSmoothPassProjectAmount = (float)test;
                    }
                }

                for (int k = 0; k < smoothPasses; ++k) // smoothPasses = 20
                {
                    rProjected.FullProjectionPass(bestSmoothPassProjectAmount, projectedDistance);
                }
            }
            else
            {
                for (int k = 0; k < smoothPasses; ++k) // smoothPasses = 20
                {
                    rProjected.BasicRemeshPass();
                }
            }


            return(mesh);
        }
Beispiel #24
0
        public static Mesh RemeshTest(Mesh inMesh, double fResScale = 1.0, int iterations = 50)
        {
            inMesh.Faces.ConvertQuadsToTriangles();
            DMesh3 mesh = inMesh.ToDMesh3();

            mesh.CheckValidity();
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh    = meshCopy,
                Spatial = tree
            };

            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
                    Index2i ev      = mesh.GetEdgeV(eid);
                    int     nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2;
                    int     nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }
            }

            Remesher r = new Remesher(mesh);

            r.Precompute();
            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);

            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = 0.5 * fResScale;
            r.MaxEdgeLength   = 1.0 * fResScale;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 0.5;

            try
            {
                for (int k = 0; k < iterations; ++k)
                {
                    r.BasicRemeshPass();
                    // mesh.CheckValidity();
                }
            }
            catch
            {
                // ignore
            }

            return(mesh.ToRhinoMesh());
        }
        public static void test_reduce_constraints_fixedverts()
        {
            int    Slices = 128;
            DMesh3 mesh   = TestUtil.MakeCappedCylinder(false, Slices);

            MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1));
            mesh.CheckValidity();
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh = meshCopy, Spatial = tree
            };

            if (WriteDebugMeshes)
            {
                TestUtil.WriteTestOutputMesh(mesh, "reduce_fixed_constraints_test_before.obj");
            }

            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.PreserveTopology;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)
                    {
                        TrackingSetID = 1
                    });
                    Index2i ev      = mesh.GetEdgeV(eid);
                    int     nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2;
                    int     nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }
            }

            Reducer r = new Reducer(mesh);

            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);

            r.ReduceToTriangleCount(50);
            mesh.CheckValidity();

            if (WriteDebugMeshes)
            {
                TestUtil.WriteTestOutputMesh(mesh, "reduce_fixed_constraints_test_after.obj");
            }
        }
Beispiel #26
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);
        }
Beispiel #27
0
        public void Close_Flat()
        {
            double minlen, maxlen, avglen;

            MeshQueries.EdgeLengthStats(Mesh, out minlen, out maxlen, out avglen, 1000);
            double target_edge_len = (TargetEdgeLen <= 0) ? avglen : TargetEdgeLen;

            // massage around boundary loop
            cleanup_boundary(Mesh, InitialBorderLoop, avglen, 3);

            // find new border loop
            // [TODO] this just assumes there is only one!!
            MeshBoundaryLoops loops     = new MeshBoundaryLoops(Mesh);
            EdgeLoop          fill_loop = loops.Loops[0];

            int extrude_group = (ExtrudeGroup == -1) ? Mesh.AllocateTriangleGroup() : ExtrudeGroup;
            int fill_group    = (FillGroup == -1) ? Mesh.AllocateTriangleGroup() : FillGroup;

            // decide on projection plane
            //AxisAlignedBox3d loopbox = fill_loop.GetBounds();
            //Vector3d topPt = loopbox.Center;
            //if ( bIsUpper ) {
            //    topPt.y = loopbox.Max.y + 0.25 * dims.y;
            //} else {
            //    topPt.y = loopbox.Min.y - 0.25 * dims.y;
            //}
            //Frame3f plane = new Frame3f((Vector3f)topPt);

            // extrude loop to this plane
            MeshExtrusion extrude = new MeshExtrusion(Mesh, fill_loop);

            extrude.PositionF = (v, n, i) => {
                return(FlatClosePlane.ProjectToPlane((Vector3F)v, 1));
            };
            extrude.Extrude(extrude_group);
            MeshValidation.IsBoundaryLoop(Mesh, extrude.NewLoop);

            Debug.Assert(Mesh.CheckValidity());

            // smooth the extrude loop
            MeshLoopSmooth loop_smooth = new MeshLoopSmooth(Mesh, extrude.NewLoop);

            loop_smooth.ProjectF = (v, i) => {
                return(FlatClosePlane.ProjectToPlane((Vector3F)v, 1));
            };
            loop_smooth.Alpha  = 0.5f;
            loop_smooth.Rounds = 100;
            loop_smooth.Smooth();

            Debug.Assert(Mesh.CheckValidity());

            // fill result
            SimpleHoleFiller filler = new SimpleHoleFiller(Mesh, extrude.NewLoop);

            filler.Fill(fill_group);

            Debug.Assert(Mesh.CheckValidity());

            // make selection for remesh region
            MeshFaceSelection remesh_roi = new MeshFaceSelection(Mesh);

            remesh_roi.Select(extrude.NewTriangles);
            remesh_roi.Select(filler.NewTriangles);
            remesh_roi.ExpandToOneRingNeighbours();
            remesh_roi.ExpandToOneRingNeighbours();
            remesh_roi.LocalOptimize(true, true);
            int[] new_roi = remesh_roi.ToArray();

            // get rid of extrude group
            FaceGroupUtil.SetGroupToGroup(Mesh, extrude_group, 0);

            /*  clean up via remesh
             *     - constrain loop we filled to itself
             */

            RegionRemesher r = new RegionRemesher(Mesh, new_roi);

            DCurve3 top_curve = mesh.MeshUtil.ExtractLoopV(Mesh, extrude.NewLoop.Vertices);
            DCurveProjectionTarget curve_target = new DCurveProjectionTarget(top_curve);

            int[] top_loop = (int[])extrude.NewLoop.Vertices.Clone();
            r.Region.MapVerticesToSubmesh(top_loop);
            MeshConstraintUtil.ConstrainVtxLoopTo(r.Constraints, r.Mesh, top_loop, curve_target);

            DMeshAABBTree3 spatial = new DMeshAABBTree3(Mesh);

            spatial.Build();
            MeshProjectionTarget target = new MeshProjectionTarget(Mesh, spatial);

            r.SetProjectionTarget(target);

            bool bRemesh = true;

            if (bRemesh)
            {
                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    = 1.0f;
                for (int k = 0; k < 40; ++k)
                {
                    r.BasicRemeshPass();
                }
                r.SetProjectionTarget(null);
                r.SmoothSpeedT = 0.25f;
                for (int k = 0; k < 10; ++k)
                {
                    r.BasicRemeshPass();
                }
                Debug.Assert(Mesh.CheckValidity());

                r.BackPropropagate();
            }

            // smooth around the join region to clean up ugliness
            smooth_region(Mesh, r.Region.BaseBorderV, 3);
        }