Polygon.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. /// Changes from the Java version
  32. /// Polygon constructors sprused up, checks for 3+ polys
  33. /// Naming of everything
  34. /// getTriangulationMode() -> TriangulationMode { get; }
  35. /// Exceptions replaced
  36. /// Future possibilities
  37. /// We have a lot of Add/Clear methods -- we may prefer to just expose the container
  38. /// Some self-explanitory methods may deserve commenting anyways
  39. using System;
  40. using System.Collections.Generic;
  41. using System.Linq;
  42. using Veldrid.Common.Poly2Tri.Triangulation;
  43. using Veldrid.Common.Poly2Tri.Triangulation.Delaunay;
  44. namespace Veldrid.Common.Poly2Tri.Polygons
  45. {
  46. public class Polygon : Triangulatable {
  47. protected List<TriangulationPoint> _points = new List<TriangulationPoint>();
  48. protected List<TriangulationPoint> _steinerPoints;
  49. protected List<Polygon> _holes;
  50. protected List<DelaunayTriangle> _triangles;
  51. protected PolygonPoint _last;
  52. /// <summary>
  53. /// Create a polygon from a list of at least 3 points with no duplicates.
  54. /// </summary>
  55. /// <param name="points">A list of unique points</param>
  56. public Polygon( IList<PolygonPoint> points ) {
  57. if (points.Count < 3) throw new ArgumentException("List has fewer than 3 points", "points");
  58. // Lets do one sanity check that first and last point hasn't got same position
  59. // Its something that often happen when importing polygon data from other formats
  60. if (points[0].Equals(points[points.Count - 1])) points.RemoveAt(points.Count - 1);
  61. _points.AddRange(points.Cast<TriangulationPoint>());
  62. }
  63. /// <summary>
  64. /// Create a polygon from a list of at least 3 points with no duplicates.
  65. /// </summary>
  66. /// <param name="points">A list of unique points.</param>
  67. public Polygon( IEnumerable<PolygonPoint> points ): this( (points as IList<PolygonPoint>) ?? points.ToArray() ) {}
  68. /// <summary>
  69. /// Create a polygon from a list of at least 3 points with no duplicates.
  70. /// </summary>
  71. /// <param name="points">A list of unique points.</param>
  72. public Polygon( params PolygonPoint[] points ) : this((IList<PolygonPoint>)points) { }
  73. public TriangulationMode TriangulationMode { get { return TriangulationMode.Polygon; } }
  74. public void AddSteinerPoint( TriangulationPoint point ) {
  75. if (_steinerPoints == null) _steinerPoints = new List<TriangulationPoint>();
  76. _steinerPoints.Add(point);
  77. }
  78. public void AddSteinerPoints( List<TriangulationPoint> points ) {
  79. if (_steinerPoints == null) _steinerPoints = new List<TriangulationPoint>();
  80. _steinerPoints.AddRange(points);
  81. }
  82. public void ClearSteinerPoints() {
  83. if (_steinerPoints != null) _steinerPoints.Clear();
  84. }
  85. /// <summary>
  86. /// Add a hole to the polygon.
  87. /// </summary>
  88. /// <param name="poly">A subtraction polygon fully contained inside this polygon.</param>
  89. public void AddHole( Polygon poly ) {
  90. if (_holes == null) _holes = new List<Polygon>();
  91. _holes.Add(poly);
  92. // XXX: tests could be made here to be sure it is fully inside
  93. // addSubtraction( poly.getPoints() );
  94. }
  95. /// <summary>
  96. /// Inserts newPoint after point.
  97. /// </summary>
  98. /// <param name="point">The point to insert after in the polygon</param>
  99. /// <param name="newPoint">The point to insert into the polygon</param>
  100. public void InsertPointAfter( PolygonPoint point, PolygonPoint newPoint ) {
  101. // Validate that
  102. int index = _points.IndexOf(point);
  103. if (index == -1) throw new ArgumentException("Tried to insert a point into a Polygon after a point not belonging to the Polygon", "point");
  104. newPoint.Next = point.Next;
  105. newPoint.Previous = point;
  106. point.Next.Previous = newPoint;
  107. point.Next = newPoint;
  108. _points.Insert(index + 1, newPoint);
  109. }
  110. /// <summary>
  111. /// Inserts list (after last point in polygon?)
  112. /// </summary>
  113. /// <param name="list"></param>
  114. public void AddPoints( IEnumerable<PolygonPoint> list ) {
  115. PolygonPoint first;
  116. foreach (PolygonPoint p in list) {
  117. p.Previous = _last;
  118. if (_last != null) {
  119. p.Next = _last.Next;
  120. _last.Next = p;
  121. }
  122. _last = p;
  123. _points.Add(p);
  124. }
  125. first = (PolygonPoint)_points[0];
  126. _last.Next = first;
  127. first.Previous = _last;
  128. }
  129. /// <summary>
  130. /// Adds a point after the last in the polygon.
  131. /// </summary>
  132. /// <param name="p">The point to add</param>
  133. public void AddPoint( PolygonPoint p ) {
  134. p.Previous = _last;
  135. p.Next = _last.Next;
  136. _last.Next = p;
  137. _points.Add(p);
  138. }
  139. /// <summary>
  140. /// Removes a point from the polygon.
  141. /// </summary>
  142. /// <param name="p"></param>
  143. public void RemovePoint( PolygonPoint p ) {
  144. PolygonPoint next, prev;
  145. next = p.Next;
  146. prev = p.Previous;
  147. prev.Next = next;
  148. next.Previous = prev;
  149. _points.Remove(p);
  150. }
  151. public IList<TriangulationPoint> Points { get { return _points; } }
  152. public IList<DelaunayTriangle> Triangles { get { return _triangles; } }
  153. public IList<Polygon> Holes { get { return _holes; }}
  154. public void AddTriangle( DelaunayTriangle t ) {
  155. _triangles.Add(t);
  156. }
  157. public void AddTriangles( IEnumerable<DelaunayTriangle> list ) {
  158. _triangles.AddRange(list);
  159. }
  160. public void ClearTriangles() {
  161. if (_triangles != null) _triangles.Clear();
  162. }
  163. /// <summary>
  164. /// Creates constraints and populates the context with points
  165. /// </summary>
  166. /// <param name="tcx">The context</param>
  167. public void Prepare( TriangulationContext tcx ) {
  168. if (_triangles == null) {
  169. _triangles = new List<DelaunayTriangle>(_points.Count);
  170. } else {
  171. _triangles.Clear();
  172. }
  173. // Outer constraints
  174. for (int i = 0; i < _points.Count - 1; i++) tcx.NewConstraint(_points[i], _points[i + 1]);
  175. tcx.NewConstraint(_points[0], _points[_points.Count - 1]);
  176. tcx.Points.AddRange(_points);
  177. // Hole constraints
  178. if (_holes != null) {
  179. foreach (Polygon p in _holes) {
  180. for (int i = 0; i < p._points.Count - 1; i++) tcx.NewConstraint(p._points[i], p._points[i + 1]);
  181. tcx.NewConstraint(p._points[0], p._points[p._points.Count - 1]);
  182. tcx.Points.AddRange(p._points);
  183. }
  184. }
  185. if (_steinerPoints != null) {
  186. tcx.Points.AddRange(_steinerPoints);
  187. }
  188. }
  189. }
  190. }