コード例 #1
0
ファイル: PlaneCutOp.cs プロジェクト: tomleetv/gsShapeModels
        DMesh3 compute_cut(Vector3d origin, Vector3d normal, double tol, bool fill_holes, double fill_len, out bool fill_errors)
        {
            fill_errors = false;
            DMesh3 cutMesh = new DMesh3(MeshSource.GetDMeshUnsafe());

            MeshPlaneCut cut = new MeshPlaneCut(cutMesh, origin, normal);

            cut.DegenerateEdgeTol = tol;

            if (cut.Cut() == false)
            {
                throw new Exception("[PlanarCutOp] cut.Cut() returned false");
            }

            if (fill_holes)
            {
                PlanarHoleFiller fill = new PlanarHoleFiller(cut)
                {
                    FillTargetEdgeLen = fill_len
                };
                if (fill.Fill() == false)
                {
                    fill_errors = true;
                }
            }

            return(cutMesh);
        }
コード例 #2
0
        public static void test_planar_fill()
        {
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_hollow.obj");
            DMesh3 mesh = TestUtil.LoadTestInputMesh("local\\__LAST_FAILED_CUT_MESH.obj");
            double mine, maxe, avge;

            MeshQueries.EdgeLengthStats(mesh, out mine, out maxe, out avge);

            AxisAlignedBox3d bounds    = mesh.CachedBounds;
            Vector3d         origin    = bounds.Center;
            Vector3d         axis      = Vector3d.AxisY;
            double           targetLen = avge;

            origin    = new Vector3d(-7.53203300, -39.50826000, -4.22260500);
            axis      = new Vector3d(0.00000007, 0.00000007, -0.99999960);
            targetLen = 3.0;

            MeshPlaneCut cut = new MeshPlaneCut(mesh, origin, axis);

            cut.Cut();

            PlanarHoleFiller fill = new PlanarHoleFiller(cut)
            {
                FillTargetEdgeLen = targetLen
            };

            if (fill.Fill() == false)
            {
                System.Console.WriteLine("test_meshEdits.test_planar_fill: Fill() failed!");
            }

            TestUtil.WriteTestOutputMesh(mesh, "planar_filled.obj");
        }
コード例 #3
0
        virtual public void CutMesh()
        {
            Frame3f frameL = SceneTransforms.SceneToObject(target, cut_plane);

            Action <DMesh3> editF = (mesh) => {
                MeshPlaneCut cut = new MeshPlaneCut(mesh, frameL.Origin, frameL.Y);
                cut.Cut();

                PlaneProjectionTarget planeTarget = new PlaneProjectionTarget()
                {
                    Origin = frameL.Origin, Normal = frameL.Y
                };

                if (GenerateFillSurface)
                {
                    double min, max, avg;
                    MeshQueries.EdgeLengthStats(mesh, out min, out max, out avg);

                    cut.FillHoles();

                    MeshFaceSelection selection = new MeshFaceSelection(mesh);
                    foreach (var tris in cut.LoopFillTriangles)
                    {
                        selection.Select(tris);
                    }
                    RegionRemesher.QuickRemesh(mesh, selection.ToArray(), 2 * avg, 1.0f, 25, planeTarget);

                    MeshNormals normals = new MeshNormals(mesh);
                    normals.Compute();
                    normals.CopyTo(mesh);
                }
            };

            target.EditAndUpdateMesh(editF, GeometryEditTypes.ArbitraryEdit);
        }
コード例 #4
0
        protected void ProcessPendingExtensionImplementation(ImplicitNaryDifference3d processedSide, List <BoundedImplicitFunction3d> pendingTools, AxisAlignedBox3d filterBox, Action <DMesh3> setProcessedMesh)
        {
            var bounds    = processedSide.Bounds();
            var indexList = new List <int>();

            for (int i = 0; i < pendingTools.Count; i++)
            {
                if (bounds.Intersects(pendingTools[i].Bounds()))
                {
                    indexList.Add(i);
                }
            }

            if (indexList.Count > 0)
            {
                foreach (var idx in indexList)
                {
                    processedSide.BSet.Add(pendingTools[idx]);
                }

                DMesh3 mesh = GenerateMeshBase(processedSide, filterBox);

                MeshPlaneCut cut = new MeshPlaneCut(mesh, Center.ToVector3d() + (Vector3d.AxisZ * SizeZ / 2.0), Vector3d.AxisZ);
                bool         bc  = cut.Cut();

                if (!mesh.IsCompact)
                {
                    mesh.CompactInPlace();
                }

                setProcessedMesh(mesh);
            }
        }
コード例 #5
0
ファイル: Mesh.cs プロジェクト: darager/GCodeViewer
 private void CloseCuttingSurfaceHoles(MeshPlaneCut cut)
 {
     foreach (var loop in cut.CutLoops)
     {
         var holeFill = new MinimalHoleFill(cut.Mesh, loop);
         holeFill.Apply();
     }
 }
コード例 #6
0
ファイル: Mesh.cs プロジェクト: darager/GCodeViewer
        private Mesh CutAndCloseMesh(Vector3d position, Vector3d normal)
        {
            // new Mesh has to be created since this method is not functional
            var cut = new MeshPlaneCut(new DMesh3(this), position, normal);

            cut.Cut();
            CloseCuttingSurfaceHoles(cut);

            return(new Mesh(cut.Mesh));
        }
コード例 #7
0
        }         // test_basic_fills

        public static void test_plane_cut()
        {
            List <int> tests = new List <int>()
            {
                2
            };

            bool DO_EXHAUSTIVE_TESTS = false;

            foreach (int num_test in tests)
            {
                string name;
                DMesh3 orig_mesh = MakeEditTestMesh(num_test, out name);

                DMesh3 mesh = new DMesh3(orig_mesh);

                AxisAlignedBox3d bounds = mesh.CachedBounds;

                MeshPlaneCut cut = new MeshPlaneCut(mesh, bounds.Center, Vector3d.AxisY);
                Debug.Assert(cut.Validate() == ValidationStatus.Ok);
                bool bCutOK  = cut.Cut();
                bool bFillOK = cut.FillHoles(-1);

                System.Console.WriteLine("cut: {0}  fill:D {1}",
                                         ((bCutOK) ? "Ok" : "Failed"), ((bFillOK) ? "Ok" : "Failed"));

                TestUtil.WriteTestOutputMesh(mesh, name + "_cut" + ".obj");


                if (DO_EXHAUSTIVE_TESTS == false)
                {
                    continue;
                }


                // grinder: cut through each vtx
                int VertexIncrement = 1;
                for (int vid = 0; vid < orig_mesh.MaxVertexID; vid += VertexIncrement)
                {
                    if (orig_mesh.IsVertex(vid) == false)
                    {
                        continue;
                    }
                    if (vid % 100 == 0)
                    {
                        System.Console.WriteLine("{0} / {1}", vid, orig_mesh.MaxVertexID);
                    }
                    Vector3d v = orig_mesh.GetVertex(vid);
                    mesh   = new DMesh3(orig_mesh);
                    cut    = new MeshPlaneCut(mesh, bounds.Center, Vector3d.AxisY);
                    bCutOK = cut.Cut();
                    Debug.Assert(bCutOK);
                }
            }             // test_plane_cut
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        public static DMesh3 Slice(this DMesh3 self, Plane plane)
        {
            var normal = plane.Normal;
            var origin = normal * -plane.D;
            var cutter = new MeshPlaneCut(self, origin.ToVector3D(), normal.ToVector3D());
            var result = cutter.Cut();

            Console.WriteLine($"Cutting result = {result}");
            Console.WriteLine($"Cut loops = {cutter.CutLoops.Count}");
            Console.WriteLine($"Cut spans = {cutter.CutSpans.Count}");
            Console.WriteLine($"Cut faces = {cutter.CutFaceSet?.Count ?? 0}");
            return(cutter.Mesh);
        }
コード例 #10
0
        protected void ProcessPendingRoutImplementation(ImplicitNaryDifference3d processedSide, AxisAlignedBox3d filterBox, Action <DMesh3> setProcessedMesh)
        {
            DMesh3 mesh = GenerateMeshBase(processedSide, filterBox);

            MeshPlaneCut cut = new MeshPlaneCut(mesh, Center.ToVector3d() + (Vector3d.AxisZ * SizeZ / 2.0), Vector3d.AxisZ);
            bool         bc  = cut.Cut();

            if (!mesh.IsCompact)
            {
                mesh.CompactInPlace();
            }

            setProcessedMesh(mesh);
        }
コード例 #11
0
        private void CutSectionSide(DMesh3 mesh, Vector3d origin, Vector3d direction, bool fill)
        {
            MeshPlaneCut cut = new MeshPlaneCut(mesh, origin, direction);
            bool         bc  = cut.Cut();

            if (fill)
            {
                PlanarHoleFiller filler = new PlanarHoleFiller(cut)
                {
                    FillTargetEdgeLen = _cubeSize
                };
                bool bf = filler.Fill();
            }
        }
コード例 #12
0
        public bool Compute()
        {
            DMesh3 copy = new DMesh3(Mesh);

            //Frame3f PlaneO = SceneTransforms.SceneToObject(TargetSO, PlaneS);
            Vector3f PlaneNormal = Plane.GetAxis(nPlaneAxis);

            MeshPlaneCut cut = new MeshPlaneCut(copy, Plane.Origin, PlaneNormal);

            cut.Cut();

            Loops = new DCurve3[cut.CutLoops.Count];
            for (int li = 0; li < cut.CutLoops.Count; ++li)
            {
                EdgeLoop edgeloop = cut.CutLoops[li];
                DCurve3  loop     = MeshUtil.ExtractLoopV(copy, edgeloop.Vertices);

                // [TODO] collapse degenerate points...

                if (NormalOffset > 0)
                {
                    for (int i = 0; i < loop.VertexCount; ++i)
                    {
                        Vector3f n = Vector3f.Zero;
                        if (copy.HasVertexNormals)
                        {
                            n = (Vector3f)copy.GetVertexNormal(edgeloop.Vertices[i]);
                        }
                        else
                        {
                            n = (Vector3f)MeshNormals.QuickCompute(Mesh, edgeloop.Vertices[i]);
                        }

                        n -= n.Dot(PlaneNormal) * PlaneNormal;
                        n.Normalize();
                        loop[i] += NormalOffset * (Vector3d)n;
                    }
                }

                Loops[li] = loop;
            }

            return(Loops.Length > 0);
        }
コード例 #13
0
        public static void test_arrangement_demo()
        {
            DMesh3 mesh = TestUtil.LoadTestInputMesh("spheres_and_planes.obj");

            MeshTransforms.Scale(mesh, 8);
            AxisAlignedBox3d meshBounds      = mesh.CachedBounds;
            Vector3d         origin          = meshBounds.Center;
            double           simplify_thresh = 5.0;

            Frame3f      plane = new Frame3f(origin, Vector3d.AxisY);
            MeshPlaneCut cut   = new MeshPlaneCut(mesh, plane.Origin, plane.Z);

            cut.Cut();

            Arrangement2d builder = new Arrangement2d(new AxisAlignedBox2d(1024.0));

            // insert all cut edges
            HashSet <Vector2d> srcpts = new HashSet <Vector2d>();

            foreach (EdgeLoop loop in cut.CutLoops)
            {
                Polygon2d poly = new Polygon2d();
                foreach (int vid in loop.Vertices)
                {
                    poly.AppendVertex(mesh.GetVertex(vid).xz);
                }

                poly.Simplify(simplify_thresh, 0.01, true);
                foreach (Vector2d v in poly.Vertices)
                {
                    srcpts.Add(v);
                }

                builder.Insert(poly);
            }
            foreach (EdgeSpan span in cut.CutSpans)
            {
                PolyLine2d pline = new PolyLine2d();
                foreach (int vid in span.Vertices)
                {
                    pline.AppendVertex(mesh.GetVertex(vid).xz);
                }
                pline.Simplify(simplify_thresh, 0.01, true);
                foreach (Vector2d v in pline)
                {
                    srcpts.Add(v);
                }
                builder.Insert(pline);
            }

            SVGWriter svg = new SVGWriter();

            svg.AddGraph(builder.Graph);

            var vtx_style = SVGWriter.Style.Outline("red", 1.0f);

            foreach (int vid in builder.Graph.VertexIndices())
            {
                Vector2d v = builder.Graph.GetVertex(vid);
                if (srcpts.Contains(v) == false)
                {
                    svg.AddCircle(new Circle2d(v, 2), vtx_style);
                }
            }

            svg.Write(TestUtil.GetTestOutputPath("arrangement.svg"));
        }
コード例 #14
0
        // appends connector to mesh. This one is messy
        bool compute_connector(DMesh3 mesh)
        {
            if (DebugStep <= 2)
            {
                return(true);
            }

            AxisAlignedBox3d socketBounds = mesh.CachedBounds;
            Vector3d         c            = socketBounds.Center;

            c.y = socketBounds.Min.y + ConnectorCutHeight;

            /*
             * first we select the outer shell triangles, and plane-cut them some ways up from the bottom.
             * This creates an open loop that we hang onto
             */

            MeshPlaneCut outer_cut = new MeshPlaneCut(mesh, c, CutPlaneNormal);

            outer_cut.CutFaceSet = new MeshFaceSelection(mesh, LastExtrudeOuterGroupID);
            outer_cut.Cut();

            MeshPlaneCut inner_cut = null;

            if (Connector.HasInner)
            {
                inner_cut            = new MeshPlaneCut(mesh, c, CutPlaneNormal);
                inner_cut.CutFaceSet = new MeshFaceSelection(mesh, LastInnerGroupID);
                inner_cut.Cut();
            }

            if (DebugStep <= 3)
            {
                return(true);
            }

            // save the loops we created
            EdgeLoop         outerCutLoop  = outer_cut.CutLoops[0];
            EdgeLoop         innerCutLoop  = (inner_cut != null) ? inner_cut.CutLoops[0] : null;
            AxisAlignedBox3d cutLoopBounds =
                BoundsUtil.Bounds(outerCutLoop.Vertices, (vid) => { return(mesh.GetVertex(vid)); });

            /*
             * Now we append the connector mesh and find its open loop
             */

            // figure out where we want to position connector (which will be centered below origin)
            double dy = 0; // socketBounds.Min.y;

            if (socketBounds.Min.y < 0)
            {
                dy = socketBounds.Min.y + 5.0;
            }
            Vector3d shiftxz  = Vector3d.Zero;// new Vector3d(cutLoopBounds.Center.x, 0, cutLoopBounds.Center.z);
            Vector3d shiftxyz = shiftxz + dy * Vector3d.AxisY;

            // append the connector
            // [TODO] do we need to hold the lock this entire time? I guess so since it would
            //   be a disaster if connector changes...
            bool bConnectorOK = true;

            lock (connector_lock) {
                SocketConnector.AppendInfo append_info =
                    Connector.AppendConnectorTo(mesh, shiftxyz);

                if (DebugStep <= 4)
                {
                    return(true);
                }

                // [TODO] push out of inner offset here...
                if (Connector.HasInner)
                {
                    merge_loops(mesh, innerCutLoop, append_info.InnerLoop, false);
                }
                // [TODO] in addition to pushing out of outer offset, we should also make sure
                //   we are far enough away from inner merge surface...
                merge_loops(mesh, outerCutLoop, append_info.OuterLoop, true);

                bConnectorOK = Connector.CutHoles(mesh, shiftxyz);
                if (bConnectorOK == false)
                {
                    f3.DebugUtil.Log("Connector.CutHoles failed!");
                }
            }

            return(bConnectorOK);
        }
コード例 #15
0
        // exports svg w/ different containments of point set (created by slicing mesh)
        public static void containment_demo_svg()
        {
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");

            MeshTransforms.Scale(mesh, 4);

            AxisAlignedBox3d meshBounds = mesh.CachedBounds;
            Vector3d         origin     = meshBounds.Center;

            origin -= 0.2 * meshBounds.Height * Vector3d.AxisY;
            Frame3f      plane = new Frame3f(origin, new Vector3d(1, 3, 0).Normalized);
            MeshPlaneCut cut   = new MeshPlaneCut(mesh, plane.Origin, plane.Z);

            cut.Cut();

            AxisAlignedBox2d polyBounds = AxisAlignedBox2d.Empty;
            List <Polygon2d> polys      = new List <Polygon2d>();

            foreach (EdgeLoop loop in cut.CutLoops)
            {
                Polygon2d poly = new Polygon2d();
                foreach (int vid in loop.Vertices)
                {
                    poly.AppendVertex(mesh.GetVertex(vid).xz);
                }
                poly.Rotate(new Matrix2d(90, true), Vector2d.Zero);
                polys.Add(poly);
                polyBounds.Contain(poly.Bounds);
            }

            SVGWriter svg       = new SVGWriter();
            var       polyStyle = SVGWriter.Style.Outline("red", 1.0f);
            var       contStyle = SVGWriter.Style.Outline("black", 1.0f);

            for (int k = 0; k < 3; ++k)
            {
                double          shift = (k == 2) ? 1.4f : 1.1f;
                Vector2d        tx    = (k - 1) * (polyBounds.Width * shift) * Vector2d.AxisX;
                List <Vector2d> pts   = new List <Vector2d>();
                foreach (Polygon2d poly in polys)
                {
                    var p2 = new Polygon2d(poly).Translate(tx);
                    pts.AddRange(p2.Vertices);
                    svg.AddPolygon(p2, polyStyle);
                }

                if (k == 0)
                {
                    ConvexHull2 hull = new ConvexHull2(pts, 0.001, QueryNumberType.QT_DOUBLE);
                    svg.AddPolygon(hull.GetHullPolygon(), contStyle);
                }
                else if (k == 1)
                {
                    ContMinBox2 contbox = new ContMinBox2(pts, 0.001, QueryNumberType.QT_DOUBLE, false);
                    svg.AddPolygon(new Polygon2d(contbox.MinBox.ComputeVertices()), contStyle);
                }
                else if (k == 2)
                {
                    ContMinCircle2 contcirc = new ContMinCircle2(pts);
                    svg.AddCircle(contcirc.Result, contStyle);
                }
            }


            svg.Write(TestUtil.GetTestOutputPath("contain_demos.svg"));
        }