geometry.test.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import {
  2. lineIntersectsLine,
  3. lineRotate,
  4. pointInEllipse,
  5. pointInPolygon,
  6. pointLeftofLine,
  7. pointOnCurve,
  8. pointOnEllipse,
  9. pointOnLine,
  10. pointOnPolygon,
  11. pointOnPolyline,
  12. pointRightofLine,
  13. pointRotate,
  14. } from "./geometry";
  15. import { Curve, Ellipse, Line, Point, Polygon, Polyline } from "./shape";
  16. describe("point and line", () => {
  17. const line: Line = [
  18. [1, 0],
  19. [1, 2],
  20. ];
  21. it("point on left or right of line", () => {
  22. expect(pointLeftofLine([0, 1], line)).toBe(true);
  23. expect(pointLeftofLine([1, 1], line)).toBe(false);
  24. expect(pointLeftofLine([2, 1], line)).toBe(false);
  25. expect(pointRightofLine([0, 1], line)).toBe(false);
  26. expect(pointRightofLine([1, 1], line)).toBe(false);
  27. expect(pointRightofLine([2, 1], line)).toBe(true);
  28. });
  29. it("point on the line", () => {
  30. expect(pointOnLine([0, 1], line)).toBe(false);
  31. expect(pointOnLine([1, 1], line, 0)).toBe(true);
  32. expect(pointOnLine([2, 1], line)).toBe(false);
  33. });
  34. });
  35. describe("point and polylines", () => {
  36. const polyline: Polyline = [
  37. [
  38. [1, 0],
  39. [1, 2],
  40. ],
  41. [
  42. [1, 2],
  43. [2, 2],
  44. ],
  45. [
  46. [2, 2],
  47. [2, 1],
  48. ],
  49. [
  50. [2, 1],
  51. [3, 1],
  52. ],
  53. ];
  54. it("point on the line", () => {
  55. expect(pointOnPolyline([1, 0], polyline)).toBe(true);
  56. expect(pointOnPolyline([1, 2], polyline)).toBe(true);
  57. expect(pointOnPolyline([2, 2], polyline)).toBe(true);
  58. expect(pointOnPolyline([2, 1], polyline)).toBe(true);
  59. expect(pointOnPolyline([3, 1], polyline)).toBe(true);
  60. expect(pointOnPolyline([1, 1], polyline)).toBe(true);
  61. expect(pointOnPolyline([2, 1.5], polyline)).toBe(true);
  62. expect(pointOnPolyline([2.5, 1], polyline)).toBe(true);
  63. expect(pointOnPolyline([0, 1], polyline)).toBe(false);
  64. expect(pointOnPolyline([2.1, 1.5], polyline)).toBe(false);
  65. });
  66. it("point on the line with rotation", () => {
  67. const truePoints = [
  68. [1, 0],
  69. [1, 2],
  70. [2, 2],
  71. [2, 1],
  72. [3, 1],
  73. ] as Point[];
  74. truePoints.forEach((point) => {
  75. const rotation = Math.random() * 360;
  76. const rotatedPoint = pointRotate(point, rotation);
  77. const rotatedPolyline: Polyline = polyline.map((line) =>
  78. lineRotate(line, rotation, [0, 0]),
  79. );
  80. expect(pointOnPolyline(rotatedPoint, rotatedPolyline)).toBe(true);
  81. });
  82. const falsePoints = [
  83. [0, 1],
  84. [2.1, 1.5],
  85. ] as Point[];
  86. falsePoints.forEach((point) => {
  87. const rotation = Math.random() * 360;
  88. const rotatedPoint = pointRotate(point, rotation);
  89. const rotatedPolyline: Polyline = polyline.map((line) =>
  90. lineRotate(line, rotation, [0, 0]),
  91. );
  92. expect(pointOnPolyline(rotatedPoint, rotatedPolyline)).toBe(false);
  93. });
  94. });
  95. });
  96. describe("point and polygon", () => {
  97. const polygon: Polygon = [
  98. [10, 10],
  99. [50, 10],
  100. [50, 50],
  101. [10, 50],
  102. ];
  103. it("point on polygon", () => {
  104. expect(pointOnPolygon([30, 10], polygon)).toBe(true);
  105. expect(pointOnPolygon([50, 30], polygon)).toBe(true);
  106. expect(pointOnPolygon([30, 50], polygon)).toBe(true);
  107. expect(pointOnPolygon([10, 30], polygon)).toBe(true);
  108. expect(pointOnPolygon([30, 30], polygon)).toBe(false);
  109. expect(pointOnPolygon([30, 70], polygon)).toBe(false);
  110. });
  111. it("point in polygon", () => {
  112. const polygon: Polygon = [
  113. [0, 0],
  114. [2, 0],
  115. [2, 2],
  116. [0, 2],
  117. ];
  118. expect(pointInPolygon([1, 1], polygon)).toBe(true);
  119. expect(pointInPolygon([3, 3], polygon)).toBe(false);
  120. });
  121. });
  122. describe("point and curve", () => {
  123. const curve: Curve = [
  124. [1.4, 1.65],
  125. [1.9, 7.9],
  126. [5.9, 1.65],
  127. [6.44, 4.84],
  128. ];
  129. it("point on curve", () => {
  130. expect(pointOnCurve(curve[0], curve)).toBe(true);
  131. expect(pointOnCurve(curve[3], curve)).toBe(true);
  132. expect(pointOnCurve([2, 4], curve, 0.1)).toBe(true);
  133. expect(pointOnCurve([4, 4.4], curve, 0.1)).toBe(true);
  134. expect(pointOnCurve([5.6, 3.85], curve, 0.1)).toBe(true);
  135. expect(pointOnCurve([5.6, 4], curve, 0.1)).toBe(false);
  136. expect(pointOnCurve(curve[1], curve, 0.1)).toBe(false);
  137. expect(pointOnCurve(curve[2], curve, 0.1)).toBe(false);
  138. });
  139. });
  140. describe("point and ellipse", () => {
  141. const ellipse: Ellipse = {
  142. center: [0, 0],
  143. angle: 0,
  144. halfWidth: 2,
  145. halfHeight: 1,
  146. };
  147. it("point on ellipse", () => {
  148. [
  149. [0, 1],
  150. [0, -1],
  151. [2, 0],
  152. [-2, 0],
  153. ].forEach((point) => {
  154. expect(pointOnEllipse(point as Point, ellipse)).toBe(true);
  155. });
  156. expect(pointOnEllipse([-1.4, 0.7], ellipse, 0.1)).toBe(true);
  157. expect(pointOnEllipse([-1.4, 0.71], ellipse, 0.01)).toBe(true);
  158. expect(pointOnEllipse([1.4, 0.7], ellipse, 0.1)).toBe(true);
  159. expect(pointOnEllipse([1.4, 0.71], ellipse, 0.01)).toBe(true);
  160. expect(pointOnEllipse([1, -0.86], ellipse, 0.1)).toBe(true);
  161. expect(pointOnEllipse([1, -0.86], ellipse, 0.01)).toBe(true);
  162. expect(pointOnEllipse([-1, -0.86], ellipse, 0.1)).toBe(true);
  163. expect(pointOnEllipse([-1, -0.86], ellipse, 0.01)).toBe(true);
  164. expect(pointOnEllipse([-1, 0.8], ellipse)).toBe(false);
  165. expect(pointOnEllipse([1, -0.8], ellipse)).toBe(false);
  166. });
  167. it("point in ellipse", () => {
  168. [
  169. [0, 1],
  170. [0, -1],
  171. [2, 0],
  172. [-2, 0],
  173. ].forEach((point) => {
  174. expect(pointInEllipse(point as Point, ellipse)).toBe(true);
  175. });
  176. expect(pointInEllipse([-1, 0.8], ellipse)).toBe(true);
  177. expect(pointInEllipse([1, -0.8], ellipse)).toBe(true);
  178. expect(pointInEllipse([-1, 1], ellipse)).toBe(false);
  179. expect(pointInEllipse([-1.4, 0.8], ellipse)).toBe(false);
  180. });
  181. });
  182. describe("line and line", () => {
  183. const lineA: Line = [
  184. [1, 4],
  185. [3, 4],
  186. ];
  187. const lineB: Line = [
  188. [2, 1],
  189. [2, 7],
  190. ];
  191. const lineC: Line = [
  192. [1, 8],
  193. [3, 8],
  194. ];
  195. const lineD: Line = [
  196. [1, 8],
  197. [3, 8],
  198. ];
  199. const lineE: Line = [
  200. [1, 9],
  201. [3, 9],
  202. ];
  203. const lineF: Line = [
  204. [1, 2],
  205. [3, 4],
  206. ];
  207. const lineG: Line = [
  208. [0, 1],
  209. [2, 3],
  210. ];
  211. it("intersection", () => {
  212. expect(lineIntersectsLine(lineA, lineB)).toBe(true);
  213. expect(lineIntersectsLine(lineA, lineC)).toBe(false);
  214. expect(lineIntersectsLine(lineB, lineC)).toBe(false);
  215. expect(lineIntersectsLine(lineC, lineD)).toBe(true);
  216. expect(lineIntersectsLine(lineE, lineD)).toBe(false);
  217. expect(lineIntersectsLine(lineF, lineG)).toBe(true);
  218. });
  219. });