Example #1
0
        public virtual bool Fill(int group_id = -1)
        {
            if (Loop.Vertices.Length < 3)
            {
                return(false);
            }

            // this just needs one triangle
            if (Loop.Vertices.Length == 3)
            {
                Index3i tri     = new Index3i(Loop.Vertices[0], Loop.Vertices[2], Loop.Vertices[1]);
                int     new_tid = Mesh.AppendTriangle(tri, group_id);
                if (new_tid == NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID)
                {
                    return(false);
                }
                NewTriangles = new int[1] {
                    new_tid
                };
                NewVertex = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID;
                return(true);
            }

            // [TODO] 4-case? could check nbr normals to figure out best internal edge...


            // compute centroid
            Vector3D c = Vector3D.Zero;

            for (int i = 0; i < Loop.Vertices.Length; ++i)
            {
                c += Mesh.GetVertex(Loop.Vertices[i]);
            }
            c *= 1.0 / Loop.Vertices.Length;

            // add centroid vtx
            NewVertex = Mesh.AppendVertex(c);

            // stitch triangles
            MeshEditor editor = new MeshEditor(Mesh);

            try {
                NewTriangles = editor.AddTriangleFan_OrderedVertexLoop(NewVertex, Loop.Vertices, group_id);
            } catch {
                NewTriangles = null;
            }

            // if fill failed, back out vertex-add
            if (NewTriangles == null)
            {
                Mesh.RemoveVertex(NewVertex);
                NewVertex = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID;
            }

            return(true);
        }
Example #2
0
        public virtual bool Cut()
        {
            double invalidDist = double.MinValue;

            // compute signs
            int MaxVID = Mesh.MaxVertexID;

            double[] signs = new double[MaxVID];
            gParallel.ForEach(Interval1i.Range(MaxVID), (vid) => {
                if (Mesh.IsVertex(vid))
                {
                    Vector3D v = Mesh.GetVertex(vid);
                    signs[vid] = (v - PlaneOrigin).Dot(PlaneNormal);
                }
                else
                {
                    signs[vid] = invalidDist;
                }
            });

            HashSet <int> ZeroEdges    = new HashSet <int>();
            HashSet <int> ZeroVertices = new HashSet <int>();
            HashSet <int> OnCutEdges   = new HashSet <int>();

            // have to skip processing of new edges. If edge id
            // is > max at start, is new. Otherwise if in NewEdges list, also new.
            int           MaxEID   = Mesh.MaxEdgeID;
            HashSet <int> NewEdges = new HashSet <int>();

            // cut existing edges with plane, using edge split
            for (int eid = 0; eid < MaxEID; ++eid)
            {
                if (Mesh.IsEdge(eid) == false)
                {
                    continue;
                }
                if (eid >= MaxEID || NewEdges.Contains(eid))
                {
                    continue;
                }

                Index2i ev = Mesh.GetEdgeV(eid);
                double  f0 = signs[ev.a];
                double  f1 = signs[ev.b];

                // If both signs are 0, this edge is on-contour
                // If one sign is 0, that vertex is on-contour
                int n0 = (Math.Abs(f0) < math.MathUtil.Epsilon) ? 1 : 0;
                int n1 = (Math.Abs(f1) < math.MathUtil.Epsilon) ? 1 : 0;
                if (n0 + n1 > 0)
                {
                    if (n0 + n1 == 2)
                    {
                        ZeroEdges.Add(eid);
                    }
                    else
                    {
                        ZeroVertices.Add((n0 == 1) ? ev[0] : ev[1]);
                    }
                    continue;
                }

                // no crossing
                if (f0 * f1 > 0)
                {
                    continue;
                }

                NGonsCore.geometry3Sharp.mesh.DMesh3.EdgeSplitInfo splitInfo;
                MeshResult result = Mesh.SplitEdge(eid, out splitInfo);
                if (result != MeshResult.Ok)
                {
                    throw new Exception("MeshPlaneCut.Cut: failed in SplitEdge");
                    //return false;
                }

                // SplitEdge just bisects edge - use plane intersection instead
                double   t      = f0 / (f0 - f1);
                Vector3D newPos = (1 - t) * Mesh.GetVertex(ev.a) + (t) * Mesh.GetVertex(ev.b);
                Mesh.SetVertex(splitInfo.vNew, newPos);

                NewEdges.Add(splitInfo.eNewBN);
                NewEdges.Add(splitInfo.eNewCN);  OnCutEdges.Add(splitInfo.eNewCN);
                if (splitInfo.eNewDN != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID)
                {
                    NewEdges.Add(splitInfo.eNewDN);
                    OnCutEdges.Add(splitInfo.eNewDN);
                }
            }

            // remove one-rings of all positive-side vertices.
            for (int i = 0; i < signs.Length; ++i)
            {
                if (signs[i] > 0 && Mesh.IsVertex(i))
                {
                    Mesh.RemoveVertex(i, true, false);
                }
            }

            // ok now we extract boundary loops, but restricted
            // to either the zero-edges we found, or the edges we created! bang!!
            Func <int, bool> CutEdgeFilterF = (eid) => {
                if (OnCutEdges.Contains(eid) || ZeroEdges.Contains(eid))
                {
                    return(true);
                }
                return(false);
            };

            try {
                MeshBoundaryLoops loops = new MeshBoundaryLoops(Mesh, false);
                loops.EdgeFilterF = CutEdgeFilterF;
                loops.Compute();

                CutLoops       = loops.Loops;
                CutLoopsFailed = false;
            } catch {
                CutLoops       = new List <EdgeLoop>();
                CutLoopsFailed = true;
            }

            return(true);
        }         // Cut()