// ----------------------------------------------------------------------- // // Original Matlab code by John Burkardt, Florida State University // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/ // // ----------------------------------------------------------------------- namespace UnityEngine.U2D.Animation.TriangleNet .Meshing.Iterators { using System; using System.Collections.Generic; using Animation.TriangleNet.Topology; /// /// Iterates the region a given triangle belongs to and applies an action /// to each connected trianlge in that region. /// /// /// The default action is to set the region id and area constraint. /// internal class RegionIterator { List region; public RegionIterator(Mesh mesh) { this.region = new List(); } /// /// Set the region attribute of all trianlges connected to given triangle. /// /// The triangle seed. /// If non-zero, process all triangles of the /// region that is enclosed by segments with given boundary label. public void Process(Triangle triangle, int boundary = 0) { this.Process(triangle, (tri) => { // Set the region id and area constraint. tri.label = triangle.label; tri.area = triangle.area; }, boundary); } /// /// Process all trianlges connected to given triangle and apply given action. /// /// The seeding triangle. /// The action to apply to each triangle. /// If non-zero, process all triangles of the /// region that is enclosed by segments with given boundary label. public void Process(Triangle triangle, Action action, int boundary = 0) { // Make sure the triangle under consideration still exists. // It may have been eaten by the virus. if (triangle.id == Mesh.DUMMY || Otri.IsDead(triangle)) { return; } // Add the seeding triangle to the region. region.Add(triangle); triangle.infected = true; if (boundary == 0) { // Stop at any subsegment. ProcessRegion(action, seg => seg.hash == Mesh.DUMMY); } else { // Stop at segments that have the given boundary label. ProcessRegion(action, seg => seg.boundary != boundary); } // Free up memory (virus pool should be empty anyway). region.Clear(); } /// /// Apply given action to each triangle of selected region. /// /// /// void ProcessRegion(Action action, Func protector) { Otri testtri = default(Otri); Otri neighbor = default(Otri); Osub neighborsubseg = default(Osub); // Loop through all the infected triangles, spreading the attribute // and/or area constraint to their neighbors, then to their neighbors' // neighbors. for (int i = 0; i < region.Count; i++) { // WARNING: Don't use foreach, viri list gets modified. testtri.tri = region[i]; // Apply function. action(testtri.tri); // Check each of the triangle's three neighbors. for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { // Find the neighbor. testtri.Sym(ref neighbor); // Check for a subsegment between the triangle and its neighbor. testtri.Pivot(ref neighborsubseg); // Make sure the neighbor exists, is not already infected, and // isn't protected by a subsegment. if ((neighbor.tri.id != Mesh.DUMMY) && !neighbor.IsInfected() && protector(neighborsubseg.seg)) { // Infect the neighbor. neighbor.Infect(); // Ensure that the neighbor's neighbors will be infected. region.Add(neighbor.tri); } } } // Uninfect all triangles. foreach (var virus in region) { virus.infected = false; } // Empty the virus pool. region.Clear(); } } }