/// <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; }