/// <summary> /// Update a vertex as it can change from reflex to convex and convex vertices may /// become ears when other ears are removed. /// </summary> /// <param name="prev">Previous vertex.</param> /// <param name="curr">Current vertex.</param> /// <param name="next">Next vertex.</param> private void UpdateVertex(Vector3 prev, Vector3 curr, Vector3 next) { // Check if vertex became convex and update if so if (reflex.Contains(curr)) { if (Maths2D.IsConvex(prev, curr, next)) { reflex.Remove(curr); convex.AddLast(curr); } } // Check if the vertex is convex and if so, check if it is an ear. if (convex.Contains(curr)) { if (CheckIfEar(prev, curr, next)) { if (!ears.Contains(curr)) { ears.AddLast(curr); } } else if (ears.Contains(curr)) { ears.Remove(curr); } } }
/// <summary> /// Check if a vertex is an ear by iterating over reflex vertices and checking /// containment inside triangle formed by vertex and neighbours. /// </summary> /// <param name="prev">Previous vertex.</param> /// <param name="curr">Current vertex.</param> /// <param name="next">Next vertex.</param> /// <returns>Ear or not.</returns> private bool CheckIfEar(Vector3 prev, Vector3 curr, Vector3 next) { // If any reflex point is inside, it's not an ear. foreach (var vertex in reflex) { if (Maths2D.PointInTriangle(prev.ToXZ(), curr.ToXZ(), next.ToXZ(), vertex.ToXZ()) && vertex != prev && vertex != curr && vertex != next) { return(false); } } return(true); }
/// <summary> /// Construct the necessary lists for triangulation with ear clipping. /// </summary> private void PrepareLists() { // Get reflex/convex vertices var j = vertices.Count - 1; var i = j - 1; for (int k = 0; k < vertices.Count; k++) { if (!Maths2D.IsConvex(vertices[i], vertices[j], vertices[k])) { reflex.AddLast(vertices[j]); } else { convex.AddLast(vertices[j]); } i = j; j = k; } // Get ears var curr = convex.First; var prev = verts.Find(curr.Value).Previous ?? verts.Last; var next = verts.Find(curr.Value).Next ?? verts.First; while (curr != verts.First) { if (CheckIfEar(prev.Value, curr.Value, next.Value)) { ears.AddLast(curr.Value); } curr = curr.Next; if (curr == null) { break; } prev = verts.Find(curr.Value).Previous ?? verts.Last; next = verts.Find(curr.Value).Next ?? verts.First; } }