// v1 and v2 successive vertices must be along a boundary, with the Halfedge from v1 to v2 having no face (on the left). // Then we create a new vertex 'outside' the boundary, create new edges and a face // \ / / // \/ old e / old edge // v2 o <-----o v1 // \ new / // new \ f / new edge // edge \ / no face here... // o v3 public Face CreateTriangle(Vertex v1, Vertex v2, TVertexTraits vt3 = default(TVertexTraits), TFaceTraits ft = default(TFaceTraits)) { Halfedge e12 = v1.HalfedgeTo(v2); Halfedge e21 = e12.Opposite; // Checks adjacency condition if (e12 == null) { throw new InvalidOperationException("v1 and v2 must be neighbors - but no Halfedge found!"); } if (e12.Face != null) { throw new InvalidOperationException("Halfedge from v1 to v2 must be a boundary - but a face was found for the Halfedge!"); } var v3 = CreateVertex(vt3); var e23 = CreateEdgeInvalid(v2, v3); var e32 = e23.Opposite; var e31 = CreateEdgeInvalid(v3, v1); var e13 = e31.Opposite; // New vertex won't have an Outgoing yet - e32 is good - it will be a boundary Halfedge v3.Outgoing = e32; // Fix v1 Outgoing to maintain Vertex boundary condition v1.Outgoing = e13; // This is the tricky part - updating the Halfedge adjacencies e32.Next = e12.Next; e13.Previous = e12.Previous; e12.Previous.Next = e13; e12.Next.Previous = e32; e12.Next = e23; e12.Previous = e31; e32.Previous = e13; e13.Next = e32; e23.Previous = e12; e23.Next = e31; e31.Previous = e23; e31.Next = e12; // This will go around fixing up the faces along the ring of halfedges. var f = CreateFace(e12, ft); e12.AssertValid(); e21.AssertValid(); e23.AssertValid(); e32.AssertValid(); e31.AssertValid(); e13.AssertValid(); AssertValid(); return(f); }