136 lines
5.1 KiB
C#
136 lines
5.1 KiB
C#
// -----------------------------------------------------------------------
|
|
// <copyright file="RegionIterator.cs" company="">
|
|
// Original Matlab code by John Burkardt, Florida State University
|
|
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
|
// </copyright>
|
|
// -----------------------------------------------------------------------
|
|
|
|
namespace TriangleNet.Meshing.Iterators
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using TriangleNet.Topology;
|
|
|
|
/// <summary>
|
|
/// Iterates the region a given triangle belongs to and applies an action
|
|
/// 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> region;
|
|
|
|
public RegionIterator(Mesh mesh)
|
|
{
|
|
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="action"></param>
|
|
/// <param name="protector"></param>
|
|
void ProcessRegion(Action<Triangle> action, Func<SubSegment, bool> 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();
|
|
}
|
|
}
|
|
}
|