diff --git a/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs b/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs index b0e97cd..0ae494b 100644 --- a/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs +++ b/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs @@ -13,23 +13,78 @@ namespace TriangleNet.Meshing.Iterators /// /// Iterates the region a given triangle belongs to and applies an action - /// to each connected trianlge in that region. Default action is to set the - /// region id. + /// to each connected trianlge in that region. /// + /// + /// The default action is to set the region id and area constraint. + /// public class RegionIterator { - List viri; + List region; public RegionIterator(Mesh mesh) { - this.viri = new List(); + 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 func) + /// + /// + void ProcessRegion(Action action, Func protector) { Otri testtri = default(Otri); Otri neighbor = default(Otri); @@ -38,20 +93,14 @@ namespace TriangleNet.Meshing.Iterators // 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 < viri.Count; i++) + for (int i = 0; i < region.Count; i++) { // WARNING: Don't use foreach, viri list gets modified. - testtri.tri = viri[i]; - // A triangle is marked as infected by messing with one of its pointers - // to subsegments, setting it to an illegal value. Hence, we have to - // temporarily uninfect this triangle so that we can examine its - // adjacent subsegments. - // TODO: Not true in the C# version (so we could skip this). - testtri.Uninfect(); + testtri.tri = region[i]; // Apply function. - func(testtri.tri); + action(testtri.tri); // Check each of the triangle's three neighbors. for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) @@ -63,64 +112,24 @@ namespace TriangleNet.Meshing.Iterators // Make sure the neighbor exists, is not already infected, and // isn't protected by a subsegment. if ((neighbor.tri.id != Mesh.DUMMY) && !neighbor.IsInfected() - && (neighborsubseg.seg.hash == Mesh.DUMMY)) + && protector(neighborsubseg.seg)) { // Infect the neighbor. neighbor.Infect(); // Ensure that the neighbor's neighbors will be infected. - viri.Add(neighbor.tri); + region.Add(neighbor.tri); } } - // Remark the triangle as infected, so it doesn't get added to the - // virus pool again. - testtri.Infect(); } // Uninfect all triangles. - foreach (var virus in viri) + foreach (var virus in region) { virus.infected = false; } // Empty the virus pool. - viri.Clear(); - } - - /// - /// Set the region attribute of all trianlges connected to given triangle. - /// - public void Process(Triangle triangle) - { - // Default action is to just set the region id for all trianlges. - this.Process(triangle, (tri) => - { - tri.label = triangle.label; - tri.area = triangle.area; - }); - } - - /// - /// Process all trianlges connected to given triangle and apply given action. - /// - public void Process(Triangle triangle, Action func) - { - if (triangle.id != Mesh.DUMMY) - { - // Make sure the triangle under consideration still exists. - // It may have been eaten by the virus. - if (!Otri.IsDead(triangle)) - { - // Put one triangle in the virus pool. - triangle.infected = true; - viri.Add(triangle); - // Apply one region's attribute and/or area constraint. - ProcessRegion(func); - // The virus pool should be empty now. - } - } - - // Free up memory (virus pool should be empty anyway). - viri.Clear(); + region.Clear(); } } }