Ejemplo n.º 1
0
        DMesh3 compute_through_hole(Vector3d start, Vector3d end, double tol)
        {
            DMesh3         origMesh    = MeshSource.GetDMeshUnsafe();
            DMeshAABBTree3 origSpatial = MeshSource.GetSpatial() as DMeshAABBTree3;

            DMesh3 cutMesh = new DMesh3(origMesh);

            Polygon2d polygon = Polygon2d.MakeCircle(hole_size / 2, hole_subdivisions);

            Vector3f axis = (Vector3f)(start - end).Normalized;

            int     start_tid   = origSpatial.FindNearestTriangle(start);
            Frame3f start_frame = origMesh.GetTriFrame(start_tid);

            start_frame.Origin = (Vector3f)start;
            start_frame.AlignAxis(2, axis);

            int end_tid = origSpatial.FindNearestTriangle(end);
            //Frame3f end_frame = origMesh.GetTriFrame(end_tid); end_frame.Origin = (Vector3f)end;
            Frame3f end_frame = start_frame; end_frame.Origin = (Vector3f)end;

            MeshInsertProjectedPolygon start_insert = new MeshInsertProjectedPolygon(cutMesh, polygon, start_frame, start_tid);
            bool start_ok = start_insert.Insert();

            MeshInsertProjectedPolygon end_insert = new MeshInsertProjectedPolygon(cutMesh, polygon, end_frame, end_tid);
            bool end_ok = end_insert.Insert();

            if (start_ok == false || end_ok == false)
            {
                throw new Exception("CutPolygonHoleOp.compute_through_hole: start or end insertion failed!");
            }

            MeshEditor editor = new MeshEditor(cutMesh);
            EdgeLoop   l0     = start_insert.InsertedLoop;
            EdgeLoop   l1     = end_insert.InsertedLoop;

            l1.Reverse();
            editor.StitchLoop(l0.Vertices, l1.Vertices);

            return(cutMesh);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Cut through-hole either vertically or horizontally.
        ///
        /// One current failure mode is if we get more than two ray-hits, which
        /// can happen due pathological cases or unexpected mesh shape. Currently
        /// trying to handle the pathological cases (ie ray hits adjacent triangles cases)
        /// via sorting, not sure if this works spectacularly well.
        ///
        /// </summary>
        protected bool CutThroughHole(DMesh3 mesh, HoleInfo hi, Vector3d translate)
        {
            Vector3d basePoint = CombinedBounds.Center - CombinedBounds.Extents.y * Vector3d.AxisY + translate;

            // do we need to compute spatial DS for each hole? not super efficient...
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            Vector3d origin    = Vector3d.Zero;
            Vector3d direction = Vector3d.One;

            if (hi.IsVertical)
            {
                direction = Vector3d.AxisY;
                origin    = basePoint + new Vector3d(hi.XZOffset.x, 0, hi.XZOffset.y) - 100 * direction;
            }
            else
            {
                origin    = basePoint + hi.Height * Vector3d.AxisY;
                direction = Quaterniond.AxisAngleD(Vector3d.AxisY, hi.AroundAngle) * Vector3d.AxisX;
            }

            // Find upper and lower triangles that contain center-points of
            // holes we want to cut. This is the most error-prone part
            // because we depend on ray-hits, which is not very reliable...

            Ray3d ray1 = new Ray3d(origin, direction);
            Ray3d ray2 = new Ray3d(origin + 10000 * direction, -direction);

            if (hi.GroupIDFilters.a > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.a);
                };
            }
            int hit_1 = spatial.FindNearestHitTriangle(ray1);

            spatial.TriangleFilterF = null;

            if (hi.GroupIDFilters.b > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.b);
                };
            }
            int hit_2 = spatial.FindNearestHitTriangle(ray2);

            spatial.TriangleFilterF = null;

            if (hit_1 == DMesh3.InvalidID || hit_2 == DMesh3.InvalidID)
            {
                return(false);
            }
            if (hit_1 == hit_2)
            {
                return(false);
            }

            List <int> hitTris = new List <int>()
            {
                hit_1, hit_2
            };


            Frame3f projectFrame = new Frame3f(ray1.Origin, ray1.Direction);

            int nVerts = 32;

            if (hi.Vertices != 0)
            {
                nVerts = hi.Vertices;
            }
            double    angleShiftRad = hi.AxisAngleD * MathUtil.Deg2Rad;
            Polygon2d circle        = Polygon2d.MakeCircle(hi.Radius, nVerts, angleShiftRad);


            List <EdgeLoop> edgeLoops = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                try {
                    MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid)
                    {
                        SimplifyInsertion = true
                    };
                    if (insert.Insert())
                    {
                        // if we have extra edges just randomly collapse
                        EdgeLoop loop = insert.InsertedLoop;

                        if (loop.VertexCount > circle.VertexCount)
                        {
                            loop = simplify_loop(mesh, loop, circle.VertexCount);
                        }

                        edgeLoops.Add(loop);
                    }
                    else
                    {
                        f3.DebugUtil.Log("insert.Insert() failed!!");
                        return(false);
                    }
                } catch (Exception e) {
                    // ignore this loop but we might already be in trouble...
                    f3.DebugUtil.Log("insert.Insert() threw exception for hole {0}!!", hi.nHole);
                    f3.DebugUtil.Log(e.Message);
                }
            }
            if (edgeLoops.Count != 2)
            {
                return(false);
            }

            try {
                MeshEditor editor = new MeshEditor(mesh);
                EdgeLoop   l0     = edgeLoops[0];
                EdgeLoop   l1     = edgeLoops[1];
                l1.Reverse();
                editor.StitchVertexLoops_NearestV(l0.Vertices, l1.Vertices);

                // split edges around the holes we cut. This is helpful
                // if we are going to do additional operations in these areas,
                // as it gives us extra rings to work with
                //MeshEdgeSelection edges = new MeshEdgeSelection(mesh);
                //edges.SelectVertexEdges(l0.Vertices);
                //edges.SelectVertexEdges(l1.Vertices);
                //DMesh3.EdgeSplitInfo splitInfo;
                //foreach ( int eid in edges )
                //    mesh.SplitEdge(eid, out splitInfo);

                return(true);
            } catch {
                f3.DebugUtil.Log("stitch threw exception!");
                return(false);
            }
        }
Ejemplo n.º 3
0
        public static void testInsertPolygon_PlanarProj()
        {
            double dscale = 1.0;
            DMesh3 mesh   = TestUtil.LoadTestInputMesh("bunny_solid.obj");  dscale = 0.3;
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("cylinder.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("cube.obj");
            double   size = mesh.CachedBounds.MaxDim;
            Vector3d c    = mesh.CachedBounds.Center;
            Vector3d fw   = c + mesh.CachedBounds.DiagonalLength * 2 * Vector3d.AxisZ;
            Ray3d    ray  = new Ray3d(fw, (c - fw).Normalized);

            // projection frame and polygon that lives in this frame
            Frame3f   projectFrame = new Frame3f(ray.Origin, ray.Direction);
            Polygon2d circle       = Polygon2d.MakeCircle(dscale * size * 0.1, 6);


            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);
            List <int>     hitTris = new List <int>();

            spatial.FindAllHitTriangles(ray, hitTris);
            while (hitTris.Count != 2)
            {
                ray.Origin += 100 * MathUtil.Epsilon * Vector3d.One;
                hitTris.Clear();
                spatial.FindAllHitTriangles(ray, hitTris);
            }

            // insert polygons but don't simplify the result

            DMesh3          noTrimMesh      = new DMesh3(mesh);
            List <int[]>    noTrimPolyVerts = new List <int[]>();
            List <EdgeLoop> noTrimLoops     = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(noTrimMesh, circle, projectFrame, hit_tid);
                insert.SimplifyInsertion = false;
                if (insert.Insert())
                {
                    noTrimPolyVerts.Add(insert.InsertedPolygonVerts);
                    noTrimLoops.Add(insert.InsertedLoop);
                }
                else
                {
                    System.Console.WriteLine("testInsertPolygon_PlanarProj: no-trim Insert() failed");
                }
            }
            TestUtil.WriteTestOutputMesh(noTrimMesh, "insert_polygon_notrim.obj");

            // do different-vtx-count stitch
            if (noTrimLoops.Count == 2)
            {
                noTrimLoops[1].Reverse();
                MeshStitchLoops stitcher = new MeshStitchLoops(noTrimMesh, noTrimLoops[0], noTrimLoops[1]);
                stitcher.TrustLoopOrientations = false;
                stitcher.AddKnownCorrespondences(noTrimPolyVerts[0], noTrimPolyVerts[1]);
                stitcher.Stitch();
            }
            TestUtil.WriteTestOutputMesh(noTrimMesh, "insert_polygon_notrim_joined.obj");


            // now do simplified version, which we can trivially stitch

            List <EdgeLoop> edgeLoops = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid);
                if (insert.Insert())
                {
                    edgeLoops.Add(insert.InsertedLoop);
                }
                else
                {
                    System.Console.WriteLine("testInsertPolygon_PlanarProj: Insert() failed");
                }
            }

            //TestUtil.WriteTestOutputMesh(mesh, "insert_polygon_before_stitch.obj");

            // do stitch
            if (edgeLoops.Count == 2)
            {
                MeshEditor editor = new MeshEditor(mesh);
                EdgeLoop   l0     = edgeLoops[0];
                EdgeLoop   l1     = edgeLoops[1];
                l1.Reverse();
                editor.StitchLoop(l0.Vertices, l1.Vertices);
            }

            TestUtil.WriteTestOutputMesh(mesh, "insert_polygon_joined.obj");
        }