Triangulator.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /// <summary>
  2. /// Credit - ryanslikesocool
  3. /// Sourced from - https://github.com/ryanslikesocool/Unity-Card-UI
  4. /// </summary>
  5. using UnityEngine;
  6. using System.Collections.Generic;
  7. namespace UnityEngine.UI.Extensions
  8. {
  9. ///Credit where credit is due
  10. ///https://wiki.unity3d.com/index.php?title=Triangulator
  11. [ExecuteInEditMode]
  12. public class Triangulator
  13. {
  14. private List<Vector2> m_points = new List<Vector2>();
  15. public Triangulator(Vector2[] points)
  16. {
  17. m_points = new List<Vector2>(points);
  18. }
  19. public int[] Triangulate()
  20. {
  21. List<int> indices = new List<int>();
  22. int n = m_points.Count;
  23. if (n < 3)
  24. return indices.ToArray();
  25. int[] V = new int[n];
  26. if (Area() > 0)
  27. {
  28. for (int v = 0; v < n; v++)
  29. V[v] = v;
  30. }
  31. else
  32. {
  33. for (int v = 0; v < n; v++)
  34. V[v] = (n - 1) - v;
  35. }
  36. int nv = n;
  37. int count = 2 * nv;
  38. for (int m = 0, v = nv - 1; nv > 2;)
  39. {
  40. if ((count--) <= 0)
  41. return indices.ToArray();
  42. int u = v;
  43. if (nv <= u)
  44. u = 0;
  45. v = u + 1;
  46. if (nv <= v)
  47. v = 0;
  48. int w = v + 1;
  49. if (nv <= w)
  50. w = 0;
  51. if (Snip(u, v, w, nv, V))
  52. {
  53. int a, b, c, s, t;
  54. a = V[u];
  55. b = V[v];
  56. c = V[w];
  57. indices.Add(a);
  58. indices.Add(b);
  59. indices.Add(c);
  60. m++;
  61. for (s = v, t = v + 1; t < nv; s++, t++)
  62. V[s] = V[t];
  63. nv--;
  64. count = 2 * nv;
  65. }
  66. }
  67. indices.Reverse();
  68. return indices.ToArray();
  69. }
  70. private float Area()
  71. {
  72. int n = m_points.Count;
  73. float A = 0.0f;
  74. for (int p = n - 1, q = 0; q < n; p = q++)
  75. {
  76. Vector2 pval = m_points[p];
  77. Vector2 qval = m_points[q];
  78. A += pval.x * qval.y - qval.x * pval.y;
  79. }
  80. return (A * 0.5f);
  81. }
  82. private bool Snip(int u, int v, int w, int n, int[] V)
  83. {
  84. int p;
  85. Vector2 A = m_points[V[u]];
  86. Vector2 B = m_points[V[v]];
  87. Vector2 C = m_points[V[w]];
  88. if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
  89. return false;
  90. for (p = 0; p < n; p++)
  91. {
  92. if ((p == u) || (p == v) || (p == w))
  93. continue;
  94. Vector2 P = m_points[V[p]];
  95. if (InsideTriangle(A, B, C, P))
  96. return false;
  97. }
  98. return true;
  99. }
  100. private bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P)
  101. {
  102. float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
  103. float cCROSSap, bCROSScp, aCROSSbp;
  104. ax = C.x - B.x; ay = C.y - B.y;
  105. bx = A.x - C.x; by = A.y - C.y;
  106. cx = B.x - A.x; cy = B.y - A.y;
  107. apx = P.x - A.x; apy = P.y - A.y;
  108. bpx = P.x - B.x; bpy = P.y - B.y;
  109. cpx = P.x - C.x; cpy = P.y - C.y;
  110. aCROSSbp = ax * bpy - ay * bpx;
  111. cCROSSap = cx * apy - cy * apx;
  112. bCROSScp = bx * cpy - by * cpx;
  113. return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
  114. }
  115. }
  116. }