DtStrictDtPolygonByCircleConstraint.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using System;
  2. using DotRecast.Core;
  3. namespace DotRecast.Detour
  4. {
  5. /**
  6. * Calculate the intersection between a polygon and a circle. A dodecagon is used as an approximation of the circle.
  7. */
  8. public class DtStrictDtPolygonByCircleConstraint : IDtPolygonByCircleConstraint
  9. {
  10. private const int CIRCLE_SEGMENTS = 12;
  11. private static readonly float[] UnitCircle = MakeUnitCircle();
  12. public static readonly IDtPolygonByCircleConstraint Shared = new DtStrictDtPolygonByCircleConstraint();
  13. private DtStrictDtPolygonByCircleConstraint()
  14. {
  15. }
  16. private static float[] MakeUnitCircle()
  17. {
  18. var temp = new float[CIRCLE_SEGMENTS * 3];
  19. for (int i = 0; i < CIRCLE_SEGMENTS; i++)
  20. {
  21. double a = i * Math.PI * 2 / CIRCLE_SEGMENTS;
  22. temp[3 * i] = (float)Math.Cos(a);
  23. temp[3 * i + 1] = 0;
  24. temp[3 * i + 2] = (float)-Math.Sin(a);
  25. }
  26. return temp;
  27. }
  28. public float[] Apply(float[] verts, RcVec3f center, float radius)
  29. {
  30. float radiusSqr = radius * radius;
  31. int outsideVertex = -1;
  32. for (int pv = 0; pv < verts.Length; pv += 3)
  33. {
  34. if (RcVec3f.Dist2DSqr(center, verts, pv) > radiusSqr)
  35. {
  36. outsideVertex = pv;
  37. break;
  38. }
  39. }
  40. if (outsideVertex == -1)
  41. {
  42. // polygon inside circle
  43. return verts;
  44. }
  45. float[] qCircle = Circle(center, radius);
  46. float[] intersection = ConvexConvexIntersection.Intersect(verts, qCircle);
  47. if (intersection == null && DtUtils.PointInPolygon(center, verts, verts.Length / 3))
  48. {
  49. // circle inside polygon
  50. return qCircle;
  51. }
  52. return intersection;
  53. }
  54. private float[] Circle(RcVec3f center, float radius)
  55. {
  56. float[] circle = new float[12 * 3];
  57. for (int i = 0; i < CIRCLE_SEGMENTS * 3; i += 3)
  58. {
  59. circle[i] = UnitCircle[i] * radius + center.x;
  60. circle[i + 1] = center.y;
  61. circle[i + 2] = UnitCircle[i + 2] * radius + center.z;
  62. }
  63. return circle;
  64. }
  65. }
  66. }