geometry.test.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import type { GlobalPoint, LineSegment, Polygon, Radians } from "../../math";
  2. import {
  3. pointFrom,
  4. lineSegment,
  5. polygon,
  6. pointOnLineSegment,
  7. pointOnPolygon,
  8. polygonIncludesPoint,
  9. segmentsIntersectAt,
  10. } from "../../math";
  11. import { pointInEllipse, pointOnEllipse, type Ellipse } from "./shape";
  12. describe("point and line", () => {
  13. // const l: Line<GlobalPoint> = line(point(1, 0), point(1, 2));
  14. // it("point on left or right of line", () => {
  15. // expect(pointLeftofLine(point(0, 1), l)).toBe(true);
  16. // expect(pointLeftofLine(point(1, 1), l)).toBe(false);
  17. // expect(pointLeftofLine(point(2, 1), l)).toBe(false);
  18. // expect(pointRightofLine(point(0, 1), l)).toBe(false);
  19. // expect(pointRightofLine(point(1, 1), l)).toBe(false);
  20. // expect(pointRightofLine(point(2, 1), l)).toBe(true);
  21. // });
  22. const s: LineSegment<GlobalPoint> = lineSegment(
  23. pointFrom(1, 0),
  24. pointFrom(1, 2),
  25. );
  26. it("point on the line", () => {
  27. expect(pointOnLineSegment(pointFrom(0, 1), s)).toBe(false);
  28. expect(pointOnLineSegment(pointFrom(1, 1), s, 0)).toBe(true);
  29. expect(pointOnLineSegment(pointFrom(2, 1), s)).toBe(false);
  30. });
  31. });
  32. describe("point and polygon", () => {
  33. const poly: Polygon<GlobalPoint> = polygon(
  34. pointFrom(10, 10),
  35. pointFrom(50, 10),
  36. pointFrom(50, 50),
  37. pointFrom(10, 50),
  38. );
  39. it("point on polygon", () => {
  40. expect(pointOnPolygon(pointFrom(30, 10), poly)).toBe(true);
  41. expect(pointOnPolygon(pointFrom(50, 30), poly)).toBe(true);
  42. expect(pointOnPolygon(pointFrom(30, 50), poly)).toBe(true);
  43. expect(pointOnPolygon(pointFrom(10, 30), poly)).toBe(true);
  44. expect(pointOnPolygon(pointFrom(30, 30), poly)).toBe(false);
  45. expect(pointOnPolygon(pointFrom(30, 70), poly)).toBe(false);
  46. });
  47. it("point in polygon", () => {
  48. const poly: Polygon<GlobalPoint> = polygon(
  49. pointFrom(0, 0),
  50. pointFrom(2, 0),
  51. pointFrom(2, 2),
  52. pointFrom(0, 2),
  53. );
  54. expect(polygonIncludesPoint(pointFrom(1, 1), poly)).toBe(true);
  55. expect(polygonIncludesPoint(pointFrom(3, 3), poly)).toBe(false);
  56. });
  57. });
  58. describe("point and ellipse", () => {
  59. const ellipse: Ellipse<GlobalPoint> = {
  60. center: pointFrom(0, 0),
  61. angle: 0 as Radians,
  62. halfWidth: 2,
  63. halfHeight: 1,
  64. };
  65. it("point on ellipse", () => {
  66. [
  67. pointFrom(0, 1),
  68. pointFrom(0, -1),
  69. pointFrom(2, 0),
  70. pointFrom(-2, 0),
  71. ].forEach((p) => {
  72. expect(pointOnEllipse(p, ellipse)).toBe(true);
  73. });
  74. expect(pointOnEllipse(pointFrom(-1.4, 0.7), ellipse, 0.1)).toBe(true);
  75. expect(pointOnEllipse(pointFrom(-1.4, 0.71), ellipse, 0.01)).toBe(true);
  76. expect(pointOnEllipse(pointFrom(1.4, 0.7), ellipse, 0.1)).toBe(true);
  77. expect(pointOnEllipse(pointFrom(1.4, 0.71), ellipse, 0.01)).toBe(true);
  78. expect(pointOnEllipse(pointFrom(1, -0.86), ellipse, 0.1)).toBe(true);
  79. expect(pointOnEllipse(pointFrom(1, -0.86), ellipse, 0.01)).toBe(true);
  80. expect(pointOnEllipse(pointFrom(-1, -0.86), ellipse, 0.1)).toBe(true);
  81. expect(pointOnEllipse(pointFrom(-1, -0.86), ellipse, 0.01)).toBe(true);
  82. expect(pointOnEllipse(pointFrom(-1, 0.8), ellipse)).toBe(false);
  83. expect(pointOnEllipse(pointFrom(1, -0.8), ellipse)).toBe(false);
  84. });
  85. it("point in ellipse", () => {
  86. [
  87. pointFrom(0, 1),
  88. pointFrom(0, -1),
  89. pointFrom(2, 0),
  90. pointFrom(-2, 0),
  91. ].forEach((p) => {
  92. expect(pointInEllipse(p, ellipse)).toBe(true);
  93. });
  94. expect(pointInEllipse(pointFrom(-1, 0.8), ellipse)).toBe(true);
  95. expect(pointInEllipse(pointFrom(1, -0.8), ellipse)).toBe(true);
  96. expect(pointInEllipse(pointFrom(-1, 1), ellipse)).toBe(false);
  97. expect(pointInEllipse(pointFrom(-1.4, 0.8), ellipse)).toBe(false);
  98. });
  99. });
  100. describe("line and line", () => {
  101. const lineA: LineSegment<GlobalPoint> = lineSegment(
  102. pointFrom(1, 4),
  103. pointFrom(3, 4),
  104. );
  105. const lineB: LineSegment<GlobalPoint> = lineSegment(
  106. pointFrom(2, 1),
  107. pointFrom(2, 7),
  108. );
  109. const lineC: LineSegment<GlobalPoint> = lineSegment(
  110. pointFrom(1, 8),
  111. pointFrom(3, 8),
  112. );
  113. const lineD: LineSegment<GlobalPoint> = lineSegment(
  114. pointFrom(1, 8),
  115. pointFrom(3, 8),
  116. );
  117. const lineE: LineSegment<GlobalPoint> = lineSegment(
  118. pointFrom(1, 9),
  119. pointFrom(3, 9),
  120. );
  121. const lineF: LineSegment<GlobalPoint> = lineSegment(
  122. pointFrom(1, 2),
  123. pointFrom(3, 4),
  124. );
  125. const lineG: LineSegment<GlobalPoint> = lineSegment(
  126. pointFrom(0, 1),
  127. pointFrom(2, 3),
  128. );
  129. it("intersection", () => {
  130. expect(segmentsIntersectAt(lineA, lineB)).toEqual([2, 4]);
  131. expect(segmentsIntersectAt(lineA, lineC)).toBe(null);
  132. expect(segmentsIntersectAt(lineB, lineC)).toBe(null);
  133. expect(segmentsIntersectAt(lineC, lineD)).toBe(null); // Line overlapping line is not intersection!
  134. expect(segmentsIntersectAt(lineE, lineD)).toBe(null);
  135. expect(segmentsIntersectAt(lineF, lineG)).toBe(null);
  136. });
  137. });