// TODO: Euler operators from http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/HalfedgeDS_ref/Class_HalfedgeDS_decorator.html#Cross_link_anchor_573 /// <summary> /// Split the face across a diagonal between two vertices a and b. /// The returned edge has a pair of faces accessible through its /// Faces property. edge.Faces.First will always be the new face /// instance. edge.Faces.Second will always be the original reduced /// face instance that was supplied as a parameter. /// </summary> /// <param name="face">The face to be split</param> /// <param name="a">The start of the diagonal</param> /// <param name="b">The end of the diagonal</param> /// <returns></returns> public TEdge SplitFace(FaceBase face, VertexBase a, VertexBase b) { // Two vertices alone are not sufficient to determine a // unique face, so the face is also supplied. (The two // vertices may lie on the same boundary between two faces. Half p = a.FindHalfEdge(half => (half.Face == face)); Half q = b.FindHalfEdge(half => (half.Face == face)); Half h = p.previous; Half g = q.previous; return(SplitFace(h, g)); }
/// <summary> /// Creates a face that is a copy of the supplied face. The new face /// will have the same half edge as the original face, but the half-edge /// will not be connected to this face. After using this constructor, /// this faces half edge should be reassigned. /// </summary> /// <param name="other">The face to copy</param> private FaceBase(FaceBase other) : this() { half = other.half; }
/// <summary> /// Euler operator: Split the face incident to h and g into two faces with a new /// diagonal between the two vertices denoted by h and g respectively. /// The new face is to the right of the diagonal, the old face to the left. /// </summary> /// <param name="h">A half-edge indicent to a face to be split</param> /// <param name="g">A half-edge incident to a face to be split</param> /// <returns>The new diagonal</returns> public TEdge SplitFace(Half h, Half g) { #if DEBUG int euler = Euler; #endif if (h.Face != g.Face) { throw new ArgumentException(); } FaceBase originalFace = h.Face; TFace secondFace = (TFace)h.Face.Clone(); // Re-assign the half-edges to which both faces are connected originalFace.half = h; secondFace.half = g; // Re-assign half-edges after h upto g inclusive to the new face Half begin = h.next; Half current = begin; do { Debug.Assert(current != null); Debug.Assert(current.Face == originalFace); current.Face = secondFace; current = current.next; }while (current != g.next); // Insert a new edge and half-edge pair // Allocate data TEdge edge = new TEdge(); Half fromToHalf = new Half(); Half toFromHalf = new Half(); // Initialize data edge.half = fromToHalf; fromToHalf.next = h.next; fromToHalf.previous = g; fromToHalf.pair = toFromHalf; fromToHalf.Source = g.Target; fromToHalf.Edge = edge; fromToHalf.Face = secondFace; toFromHalf.next = g.next; toFromHalf.previous = h; toFromHalf.pair = fromToHalf; toFromHalf.Source = h.Target; toFromHalf.Edge = edge; toFromHalf.Face = originalFace; h.next.previous = fromToHalf; h.next = toFromHalf; g.next.previous = toFromHalf; g.next = fromToHalf; edges.Add(edge); faces.Add(secondFace); #if DEBUG // Assert the Euler invariant Debug.Assert(euler == Euler); #endif return(edge); }