예제 #1
0
        /// <summary>
        /// Inserts a pair of HalfEdges between two (non adjacent) vertices of a Face.
        /// </summary>
        /// <param name="geometry">The Geometry to insert a dignonal</param>
        /// <param name="p">First Vertex handle.</param>
        /// <param name="q">Second Vertex handle.</param>
        /// <exception cref="Exception"></exception>
        public static void InsertDiagonal(this Geometry geometry, int p, int q)
        {
            var pStartHe = new HalfEdge();
            var qStartHe = new HalfEdge();

            var face = geometry.GetFaceToInsertDiag(p, q, ref pStartHe, ref qStartHe);

            if (geometry.IsVertexAdjacentToVertex(p, q, pStartHe, qStartHe))
            {
                throw new ArgumentException("A diagonal can't be inserted between adjacent Vertices!");
            }

            var newFromP = new HalfEdge(geometry.CreateHalfEdgeHandleId());
            var newFromQ = new HalfEdge(geometry.CreateHalfEdgeHandleId());

            newFromP.OriginVertex = p;
            newFromP.NextHalfEdge = qStartHe.Handle;
            newFromP.PrevHalfEdge = pStartHe.PrevHalfEdge;
            newFromP.IncidentFace = face.Handle;

            newFromQ.OriginVertex = q;
            newFromQ.NextHalfEdge = pStartHe.Handle;
            newFromQ.PrevHalfEdge = qStartHe.PrevHalfEdge;
            newFromQ.IncidentFace = face.Handle;

            newFromP.TwinHalfEdge = newFromQ.Handle;
            newFromQ.TwinHalfEdge = newFromP.Handle;

            geometry.DictHalfEdges.Add(newFromP.Handle, newFromP);
            geometry.DictHalfEdges.Add(newFromQ.Handle, newFromQ);

            //Assign new sucessor to previous HalfEdges from p and q & assign new predecessor for qStartHe and pStartHe.
            var prevHeP = geometry.GetHalfEdgeByHandle(pStartHe.PrevHalfEdge);
            var prevHeQ = geometry.GetHalfEdgeByHandle(qStartHe.PrevHalfEdge);

            var prevHePUpdate = geometry.DictHalfEdges[prevHeP.Handle];

            prevHePUpdate.NextHalfEdge             = newFromP.Handle;
            geometry.DictHalfEdges[prevHeP.Handle] = prevHePUpdate;

            var prevHeQUpdate = geometry.DictHalfEdges[prevHeQ.Handle];

            prevHeQUpdate.NextHalfEdge             = newFromQ.Handle;
            geometry.DictHalfEdges[prevHeQ.Handle] = prevHeQUpdate;

            var nextHePUpdate = geometry.DictHalfEdges[pStartHe.Handle];

            nextHePUpdate.PrevHalfEdge = newFromQ.Handle;
            geometry.DictHalfEdges[pStartHe.Handle] = nextHePUpdate;

            var nextHeQUpdate = geometry.DictHalfEdges[qStartHe.Handle];

            nextHeQUpdate.PrevHalfEdge = newFromP.Handle;
            geometry.DictHalfEdges[qStartHe.Handle] = nextHeQUpdate;

            var holes = geometry.GetHoles(face);

            if (holes.Count != 0 && IsNewEdgeToHole(holes, p, q, face))
            {
                return;
            }

            var newFace = new Face(geometry.CreateFaceHandleId(), newFromQ.Handle);

            //The face normal of the newFace equals the normal of the original Face because adding a diagonal does not change the face vertices position.
            var newFaceData = newFace.FaceData;

            newFaceData.FaceNormal = face.FaceData.FaceNormal;
            newFace.FaceData       = newFaceData;

            geometry.DictFaces.Add(newFace.Handle, newFace);

            //Assign the handle of the new Face to its HalfEdges.
            geometry.AssignFaceHandle(newFace.OuterHalfEdge, newFace);

            //Set Face.OuterHalfEdge to newFromP - old OuterHalfEdge can be part of new Face now!
            var currentFace = face;

            currentFace.OuterHalfEdge = newFromP.Handle;
            face = currentFace;
            geometry.DictFaces[face.Handle] = face;
        }