Update region iterator.

git-svn-id: https://triangle.svn.codeplex.com/svn@79514 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
SND\wo80_cp
2016-09-10 17:00:54 +00:00
parent e1c523299f
commit a05e67d7b3
@@ -13,23 +13,78 @@ namespace TriangleNet.Meshing.Iterators
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// The default action is to set the region id and area constraint.
/// </remarks>
public class RegionIterator
{
List<Triangle> viri;
List<Triangle> region;
public RegionIterator(Mesh mesh)
{
this.viri = new List<Triangle>();
this.region = new List<Triangle>();
}
/// <summary>
/// Set the region attribute of all trianlges connected to given triangle.
/// </summary>
/// <param name="triangle">The triangle seed.</param>
/// <param name="boundary">If non-zero, process all triangles of the
/// region that is enclosed by segments with given boundary label.</param>
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);
}
/// <summary>
/// Process all trianlges connected to given triangle and apply given action.
/// </summary>
/// <param name="triangle">The seeding triangle.</param>
/// <param name="action">The action to apply to each triangle.</param>
/// <param name="boundary">If non-zero, process all triangles of the
/// region that is enclosed by segments with given boundary label.</param>
public void Process(Triangle triangle, Action<Triangle> 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();
}
/// <summary>
/// Apply given action to each triangle of selected region.
/// </summary>
/// <param name="func"></param>
void ProcessRegion(Action<Triangle> func)
/// <param name="action"></param>
/// <param name="protector"></param>
void ProcessRegion(Action<Triangle> action, Func<SubSegment, bool> 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();
}
/// <summary>
/// Set the region attribute of all trianlges connected to given triangle.
/// </summary>
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;
});
}
/// <summary>
/// Process all trianlges connected to given triangle and apply given action.
/// </summary>
public void Process(Triangle triangle, Action<Triangle> 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();
}
}
}