DTSweepContext.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* Poly2Tri
  2. * Copyright (c) 2009-2010, Poly2Tri Contributors
  3. * http://code.google.com/p/poly2tri/
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted provided that the following conditions are met:
  9. *
  10. * * Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright notice,
  13. * this list of conditions and the following disclaimer in the documentation
  14. * and/or other materials provided with the distribution.
  15. * * Neither the name of Poly2Tri nor the names of its contributors may be
  16. * used to endorse or promote products derived from this software without specific
  17. * prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. namespace Poly2Tri.Triangulation.Delaunay.Sweep
  32. {
  33. /**
  34. *
  35. * @author Thomas Åhlén, [email protected]
  36. *
  37. */
  38. public class DTSweepContext : TriangulationContext
  39. {
  40. // Inital triangle factor, seed triangle will extend 30% of
  41. // PointSet width to both left and right.
  42. private const float ALPHA = 0.3f;
  43. public DTSweepBasin Basin = new DTSweepBasin();
  44. public DTSweepEdgeEvent EdgeEvent = new DTSweepEdgeEvent();
  45. private DTSweepPointComparator _comparator = new DTSweepPointComparator();
  46. public AdvancingFront aFront;
  47. public DTSweepContext()
  48. {
  49. Clear();
  50. }
  51. public TriangulationPoint Head { get; set; }
  52. public TriangulationPoint Tail { get; set; }
  53. public void RemoveFromList(DelaunayTriangle triangle)
  54. {
  55. Triangles.Remove(triangle);
  56. // TODO: remove all neighbor pointers to this triangle
  57. // for( int i=0; i<3; i++ )
  58. // {
  59. // if( triangle.neighbors[i] != null )
  60. // {
  61. // triangle.neighbors[i].clearNeighbor( triangle );
  62. // }
  63. // }
  64. // triangle.clearNeighbors();
  65. }
  66. public void MeshClean(DelaunayTriangle triangle)
  67. {
  68. MeshCleanReq(triangle);
  69. }
  70. private void MeshCleanReq(DelaunayTriangle triangle)
  71. {
  72. if (triangle != null && !triangle.IsInterior)
  73. {
  74. triangle.IsInterior = true;
  75. Triangulatable.AddTriangle(triangle);
  76. for (int i = 0; i < 3; i++)
  77. {
  78. if (!triangle.EdgeIsConstrained[i])
  79. {
  80. MeshCleanReq(triangle.Neighbors[i]);
  81. }
  82. }
  83. }
  84. }
  85. public override void Clear()
  86. {
  87. base.Clear();
  88. Triangles.Clear();
  89. }
  90. public void AddNode(AdvancingFrontNode node)
  91. {
  92. // Console.WriteLine( "add:" + node.key + ":" + System.identityHashCode(node.key));
  93. // m_nodeTree.put( node.getKey(), node );
  94. aFront.AddNode(node);
  95. }
  96. public void RemoveNode(AdvancingFrontNode node)
  97. {
  98. // Console.WriteLine( "remove:" + node.key + ":" + System.identityHashCode(node.key));
  99. // m_nodeTree.delete( node.getKey() );
  100. aFront.RemoveNode(node);
  101. }
  102. public AdvancingFrontNode LocateNode(TriangulationPoint point)
  103. {
  104. return aFront.LocateNode(point);
  105. }
  106. public void CreateAdvancingFront()
  107. {
  108. AdvancingFrontNode head, tail, middle;
  109. // Initial triangle
  110. DelaunayTriangle iTriangle = new DelaunayTriangle(Points[0], Tail, Head);
  111. Triangles.Add(iTriangle);
  112. head = new AdvancingFrontNode(iTriangle.Points[1]);
  113. head.Triangle = iTriangle;
  114. middle = new AdvancingFrontNode(iTriangle.Points[0]);
  115. middle.Triangle = iTriangle;
  116. tail = new AdvancingFrontNode(iTriangle.Points[2]);
  117. aFront = new AdvancingFront(head, tail);
  118. aFront.AddNode(middle);
  119. // TODO: I think it would be more intuitive if head is middles next and not previous
  120. // so swap head and tail
  121. aFront.Head.Next = middle;
  122. middle.Next = aFront.Tail;
  123. middle.Prev = aFront.Head;
  124. aFront.Tail.Prev = middle;
  125. }
  126. /// <summary>
  127. /// Try to map a node to all sides of this triangle that don't have
  128. /// a neighbor.
  129. /// </summary>
  130. public void MapTriangleToNodes(DelaunayTriangle t)
  131. {
  132. AdvancingFrontNode n;
  133. for (int i = 0; i < 3; i++)
  134. {
  135. if (t.Neighbors[i] == null)
  136. {
  137. n = aFront.LocatePoint(t.PointCW(t.Points[i]));
  138. if (n != null)
  139. {
  140. n.Triangle = t;
  141. }
  142. }
  143. }
  144. }
  145. public override void PrepareTriangulation(Triangulatable t)
  146. {
  147. base.PrepareTriangulation(t);
  148. double xmax, xmin;
  149. double ymax, ymin;
  150. xmax = xmin = Points[0].X;
  151. ymax = ymin = Points[0].Y;
  152. // Calculate bounds. Should be combined with the sorting
  153. foreach (TriangulationPoint p in Points)
  154. {
  155. if (p.X > xmax)
  156. xmax = p.X;
  157. if (p.X < xmin)
  158. xmin = p.X;
  159. if (p.Y > ymax)
  160. ymax = p.Y;
  161. if (p.Y < ymin)
  162. ymin = p.Y;
  163. }
  164. double deltaX = ALPHA*(xmax - xmin);
  165. double deltaY = ALPHA*(ymax - ymin);
  166. TriangulationPoint p1 = new TriangulationPoint(xmax + deltaX, ymin - deltaY);
  167. TriangulationPoint p2 = new TriangulationPoint(xmin - deltaX, ymin - deltaY);
  168. Head = p1;
  169. Tail = p2;
  170. // long time = System.nanoTime();
  171. // Sort the points along y-axis
  172. Points.Sort(_comparator);
  173. // logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
  174. }
  175. public void FinalizeTriangulation()
  176. {
  177. Triangulatable.AddTriangles(Triangles);
  178. Triangles.Clear();
  179. }
  180. public override TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b)
  181. {
  182. return new DTSweepConstraint(a, b);
  183. }
  184. #region Nested type: DTSweepBasin
  185. public class DTSweepBasin
  186. {
  187. public AdvancingFrontNode bottomNode;
  188. public bool leftHighest;
  189. public AdvancingFrontNode leftNode;
  190. public AdvancingFrontNode rightNode;
  191. public double width;
  192. }
  193. #endregion
  194. #region Nested type: DTSweepEdgeEvent
  195. public class DTSweepEdgeEvent
  196. {
  197. public DTSweepConstraint ConstrainedEdge;
  198. public bool Right;
  199. }
  200. #endregion
  201. }
  202. }