RegionIterator.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // -----------------------------------------------------------------------
  2. // <copyright file="RegionIterator.cs" company="">
  3. // Original Matlab code by John Burkardt, Florida State University
  4. // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
  5. // </copyright>
  6. // -----------------------------------------------------------------------
  7. namespace UnityEngine.U2D.Animation.TriangleNet
  8. .Meshing.Iterators
  9. {
  10. using System;
  11. using System.Collections.Generic;
  12. using Animation.TriangleNet.Topology;
  13. /// <summary>
  14. /// Iterates the region a given triangle belongs to and applies an action
  15. /// to each connected trianlge in that region.
  16. /// </summary>
  17. /// <remarks>
  18. /// The default action is to set the region id and area constraint.
  19. /// </remarks>
  20. internal class RegionIterator
  21. {
  22. List<Triangle> region;
  23. public RegionIterator(Mesh mesh)
  24. {
  25. this.region = new List<Triangle>();
  26. }
  27. /// <summary>
  28. /// Set the region attribute of all trianlges connected to given triangle.
  29. /// </summary>
  30. /// <param name="triangle">The triangle seed.</param>
  31. /// <param name="boundary">If non-zero, process all triangles of the
  32. /// region that is enclosed by segments with given boundary label.</param>
  33. public void Process(Triangle triangle, int boundary = 0)
  34. {
  35. this.Process(triangle, (tri) =>
  36. {
  37. // Set the region id and area constraint.
  38. tri.label = triangle.label;
  39. tri.area = triangle.area;
  40. }, boundary);
  41. }
  42. /// <summary>
  43. /// Process all trianlges connected to given triangle and apply given action.
  44. /// </summary>
  45. /// <param name="triangle">The seeding triangle.</param>
  46. /// <param name="action">The action to apply to each triangle.</param>
  47. /// <param name="boundary">If non-zero, process all triangles of the
  48. /// region that is enclosed by segments with given boundary label.</param>
  49. public void Process(Triangle triangle, Action<Triangle> action, int boundary = 0)
  50. {
  51. // Make sure the triangle under consideration still exists.
  52. // It may have been eaten by the virus.
  53. if (triangle.id == Mesh.DUMMY || Otri.IsDead(triangle))
  54. {
  55. return;
  56. }
  57. // Add the seeding triangle to the region.
  58. region.Add(triangle);
  59. triangle.infected = true;
  60. if (boundary == 0)
  61. {
  62. // Stop at any subsegment.
  63. ProcessRegion(action, seg => seg.hash == Mesh.DUMMY);
  64. }
  65. else
  66. {
  67. // Stop at segments that have the given boundary label.
  68. ProcessRegion(action, seg => seg.boundary != boundary);
  69. }
  70. // Free up memory (virus pool should be empty anyway).
  71. region.Clear();
  72. }
  73. /// <summary>
  74. /// Apply given action to each triangle of selected region.
  75. /// </summary>
  76. /// <param name="action"></param>
  77. /// <param name="protector"></param>
  78. void ProcessRegion(Action<Triangle> action, Func<SubSegment, bool> protector)
  79. {
  80. Otri testtri = default(Otri);
  81. Otri neighbor = default(Otri);
  82. Osub neighborsubseg = default(Osub);
  83. // Loop through all the infected triangles, spreading the attribute
  84. // and/or area constraint to their neighbors, then to their neighbors'
  85. // neighbors.
  86. for (int i = 0; i < region.Count; i++)
  87. {
  88. // WARNING: Don't use foreach, viri list gets modified.
  89. testtri.tri = region[i];
  90. // Apply function.
  91. action(testtri.tri);
  92. // Check each of the triangle's three neighbors.
  93. for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
  94. {
  95. // Find the neighbor.
  96. testtri.Sym(ref neighbor);
  97. // Check for a subsegment between the triangle and its neighbor.
  98. testtri.Pivot(ref neighborsubseg);
  99. // Make sure the neighbor exists, is not already infected, and
  100. // isn't protected by a subsegment.
  101. if ((neighbor.tri.id != Mesh.DUMMY) && !neighbor.IsInfected()
  102. && protector(neighborsubseg.seg))
  103. {
  104. // Infect the neighbor.
  105. neighbor.Infect();
  106. // Ensure that the neighbor's neighbors will be infected.
  107. region.Add(neighbor.tri);
  108. }
  109. }
  110. }
  111. // Uninfect all triangles.
  112. foreach (var virus in region)
  113. {
  114. virus.infected = false;
  115. }
  116. // Empty the virus pool.
  117. region.Clear();
  118. }
  119. }
  120. }