PolygonHelper.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. namespace VLB
  4. {
  5. public class PolygonHelper : MonoBehaviour
  6. {
  7. public struct Plane2D
  8. {
  9. public Vector2 normal;
  10. public float distance;
  11. public float Distance(Vector2 point) { return Vector2.Dot(normal, point) + distance; }
  12. public Vector2 ClosestPoint(Vector2 pt) { return pt - normal * Distance(pt); }
  13. public Vector2 Intersect(Vector2 p1, Vector2 p2)
  14. {
  15. float denominator = Vector2.Dot(normal, p1 - p2);
  16. if (Utils.IsAlmostZero(denominator))
  17. return (p1 + p2) * 0.5f;
  18. float u = (normal.x * p1.x + normal.y * p1.y + distance) / denominator;
  19. return (p1 + u * (p2 - p1));
  20. }
  21. public bool GetSide(Vector2 point) { return Distance(point) > 0.0f; }
  22. public static Plane2D FromPoints(Vector3 p1, Vector3 p2)
  23. {
  24. var v = (p2 - p1).normalized;
  25. return new Plane2D
  26. {
  27. normal = new Vector2(v.y, -v.x),
  28. distance = (-v.y * p1.x + v.x * p1.y)
  29. };
  30. }
  31. public static Plane2D FromNormalAndPoint(Vector3 normalizedNormal, Vector3 p1)
  32. {
  33. return new Plane2D
  34. {
  35. normal = normalizedNormal,
  36. distance = (-normalizedNormal.x * p1.x - normalizedNormal.y * p1.y)
  37. };
  38. }
  39. public void Flip() { normal = -normal; distance = -distance; }
  40. public Vector2[] CutConvex(Vector2[] poly)
  41. {
  42. Debug.Assert(poly.Length >= 3);
  43. var polyOut = new List<Vector2>(poly.Length);
  44. Vector2 startingPoint = poly[poly.Length - 1];
  45. foreach (var endPoint in poly)
  46. {
  47. var startingSide = GetSide(startingPoint);
  48. var endSide = GetSide(endPoint);
  49. if (startingSide && endSide)
  50. {
  51. polyOut.Add(endPoint);
  52. }
  53. else if (startingSide && !endSide)
  54. {
  55. polyOut.Add(Intersect(startingPoint, endPoint));
  56. }
  57. else if (!startingSide && endSide)
  58. {
  59. polyOut.Add(Intersect(startingPoint, endPoint));
  60. polyOut.Add(endPoint);
  61. }
  62. startingPoint = endPoint;
  63. }
  64. return polyOut.ToArray();
  65. }
  66. public override string ToString() { return string.Format("{0} x {1} + {2}", normal.x, normal.y, distance); }
  67. }
  68. }
  69. }