plotboilerplate 1.23.3 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +19 -1
  2. package/dist/index.esm.js +1684 -394
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.esm.min.js +1 -1
  5. package/dist/index.esm.min.js.map +1 -1
  6. package/dist/plotboilerplate.browser.min.js +1 -1
  7. package/dist/plotboilerplate.browser.min.js.map +1 -1
  8. package/dist/plotboilerplate.js +12450 -11120
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +9 -5
  11. package/src/cjs/BezierPath.d.ts +41 -5
  12. package/src/cjs/BezierPath.js +52 -2
  13. package/src/cjs/BezierPath.js.map +1 -1
  14. package/src/cjs/Bounds.d.ts +67 -3
  15. package/src/cjs/Bounds.js +101 -3
  16. package/src/cjs/Bounds.js.map +1 -1
  17. package/src/cjs/Circle.d.ts +46 -4
  18. package/src/cjs/Circle.js +82 -3
  19. package/src/cjs/Circle.js.map +1 -1
  20. package/src/cjs/CircleSector.d.ts +51 -2
  21. package/src/cjs/CircleSector.js +112 -3
  22. package/src/cjs/CircleSector.js.map +1 -1
  23. package/src/cjs/CubicBezierCurve.d.ts +113 -7
  24. package/src/cjs/CubicBezierCurve.js +281 -33
  25. package/src/cjs/CubicBezierCurve.js.map +1 -1
  26. package/src/cjs/Line.d.ts +38 -3
  27. package/src/cjs/Line.js +64 -1
  28. package/src/cjs/Line.js.map +1 -1
  29. package/src/cjs/PlotBoilerplate.d.ts +37 -6
  30. package/src/cjs/PlotBoilerplate.js +224 -125
  31. package/src/cjs/PlotBoilerplate.js.map +1 -1
  32. package/src/cjs/Polygon.d.ts +68 -5
  33. package/src/cjs/Polygon.js +143 -22
  34. package/src/cjs/Polygon.js.map +1 -1
  35. package/src/cjs/Triangle.d.ts +52 -3
  36. package/src/cjs/Triangle.js +80 -1
  37. package/src/cjs/Triangle.js.map +1 -1
  38. package/src/cjs/VEllipse.d.ts +62 -3
  39. package/src/cjs/VEllipse.js +181 -17
  40. package/src/cjs/VEllipse.js.map +1 -1
  41. package/src/cjs/VEllipseSector.d.ts +86 -2
  42. package/src/cjs/VEllipseSector.js +148 -4
  43. package/src/cjs/VEllipseSector.js.map +1 -1
  44. package/src/cjs/Vector.d.ts +12 -2
  45. package/src/cjs/Vector.js +15 -2
  46. package/src/cjs/Vector.js.map +1 -1
  47. package/src/cjs/VertTuple.d.ts +28 -4
  48. package/src/cjs/VertTuple.js +36 -3
  49. package/src/cjs/VertTuple.js.map +1 -1
  50. package/src/cjs/Vertex.d.ts +31 -4
  51. package/src/cjs/Vertex.js +35 -1
  52. package/src/cjs/Vertex.js.map +1 -1
  53. package/src/cjs/interfaces/core.d.ts +67 -0
  54. package/src/cjs/interfaces/core.js +4 -0
  55. package/src/cjs/interfaces/core.js.map +1 -1
  56. package/src/cjs/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
  57. package/src/cjs/utils/algorithms/convexPolygonIncircle.js +14 -6
  58. package/src/cjs/utils/algorithms/convexPolygonIncircle.js.map +1 -1
  59. package/src/cjs/utils/createRandomizedPolygon.d.ts +14 -0
  60. package/src/cjs/utils/createRandomizedPolygon.js +32 -0
  61. package/src/cjs/utils/createRandomizedPolygon.js.map +1 -0
  62. package/src/cjs/utils/datastructures/Color.d.ts +147 -1
  63. package/src/cjs/utils/datastructures/Color.js +385 -41
  64. package/src/cjs/utils/datastructures/Color.js.map +1 -1
  65. package/src/cjs/utils/datastructures/ColorGradient.d.ts +79 -0
  66. package/src/cjs/utils/datastructures/ColorGradient.js +171 -0
  67. package/src/cjs/utils/datastructures/ColorGradient.js.map +1 -0
  68. package/src/cjs/utils/dom/components/ColorGradientPicker.d.ts +245 -0
  69. package/src/cjs/utils/dom/components/ColorGradientPicker.js +667 -0
  70. package/src/cjs/utils/dom/components/ColorGradientPicker.js.map +1 -0
  71. package/src/cjs/utils/dom/components/ColorGradientPickerJSX.d.ts +129 -0
  72. package/src/cjs/utils/dom/components/ColorGradientPickerJSX.js +520 -0
  73. package/src/cjs/utils/dom/components/ColorGradientPickerJSX.js.map +1 -0
  74. package/src/cjs/utils/dom/components/ColorGradientSelector.d.ts +117 -0
  75. package/src/cjs/utils/dom/components/ColorGradientSelector.js +325 -0
  76. package/src/cjs/utils/dom/components/ColorGradientSelector.js.map +1 -0
  77. package/src/cjs/utils/dom/components/Test.d.ts +7 -0
  78. package/src/cjs/utils/dom/components/Test.js +30 -0
  79. package/src/cjs/utils/dom/components/Test.js.map +1 -0
  80. package/src/cjs/utils/dom/guiSizeToggler.js +1 -1
  81. package/src/cjs/utils/dom/guiSizeToggler.js.map +1 -1
  82. package/src/cjs/utils/helpers/BezierPathInteractionHelper.d.ts +16 -8
  83. package/src/cjs/utils/helpers/BezierPathInteractionHelper.js +49 -28
  84. package/src/cjs/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
  85. package/src/cjs/utils/helpers/CircleHelper.d.ts +10 -1
  86. package/src/cjs/utils/helpers/CircleHelper.js +13 -2
  87. package/src/cjs/utils/helpers/CircleHelper.js.map +1 -1
  88. package/src/cjs/utils/helpers/CircleSectorHelper.d.ts +11 -2
  89. package/src/cjs/utils/helpers/CircleSectorHelper.js +20 -20
  90. package/src/cjs/utils/helpers/CircleSectorHelper.js.map +1 -1
  91. package/src/cjs/utils/helpers/TriangleHelper.d.ts +57 -0
  92. package/src/cjs/utils/helpers/TriangleHelper.js +83 -0
  93. package/src/cjs/utils/helpers/TriangleHelper.js.map +1 -0
  94. package/src/cjs/utils/helpers/VEllipseHelper.d.ts +32 -0
  95. package/src/cjs/utils/helpers/VEllipseHelper.js +88 -0
  96. package/src/cjs/utils/helpers/VEllipseHelper.js.map +1 -0
  97. package/src/cjs/utils/helpers/VEllipseSectorHelper.d.ts +44 -4
  98. package/src/cjs/utils/helpers/VEllipseSectorHelper.js +108 -25
  99. package/src/cjs/utils/helpers/VEllipseSectorHelper.js.map +1 -1
  100. package/src/cjs/utils/parsers/LinearColorGradientParser.d.ts +78 -0
  101. package/src/cjs/utils/parsers/LinearColorGradientParser.js +224 -0
  102. package/src/cjs/utils/parsers/LinearColorGradientParser.js.map +1 -0
  103. package/src/createDemoDrawables.js +4 -1
  104. package/src/esm/BezierPath.d.ts +41 -5
  105. package/src/esm/BezierPath.js +50 -2
  106. package/src/esm/BezierPath.js.map +1 -1
  107. package/src/esm/Bounds.d.ts +67 -3
  108. package/src/esm/Bounds.js +101 -3
  109. package/src/esm/Bounds.js.map +1 -1
  110. package/src/esm/Circle.d.ts +46 -4
  111. package/src/esm/Circle.js +79 -3
  112. package/src/esm/Circle.js.map +1 -1
  113. package/src/esm/CircleSector.d.ts +51 -2
  114. package/src/esm/CircleSector.js +108 -3
  115. package/src/esm/CircleSector.js.map +1 -1
  116. package/src/esm/CubicBezierCurve.d.ts +113 -7
  117. package/src/esm/CubicBezierCurve.js +277 -33
  118. package/src/esm/CubicBezierCurve.js.map +1 -1
  119. package/src/esm/Line.d.ts +38 -3
  120. package/src/esm/Line.js +62 -1
  121. package/src/esm/Line.js.map +1 -1
  122. package/src/esm/PlotBoilerplate.d.ts +37 -6
  123. package/src/esm/PlotBoilerplate.js +224 -125
  124. package/src/esm/PlotBoilerplate.js.map +1 -1
  125. package/src/esm/Polygon.d.ts +68 -5
  126. package/src/esm/Polygon.js +138 -22
  127. package/src/esm/Polygon.js.map +1 -1
  128. package/src/esm/Triangle.d.ts +52 -3
  129. package/src/esm/Triangle.js +77 -1
  130. package/src/esm/Triangle.js.map +1 -1
  131. package/src/esm/VEllipse.d.ts +62 -3
  132. package/src/esm/VEllipse.js +178 -17
  133. package/src/esm/VEllipse.js.map +1 -1
  134. package/src/esm/VEllipseSector.d.ts +86 -2
  135. package/src/esm/VEllipseSector.js +146 -7
  136. package/src/esm/VEllipseSector.js.map +1 -1
  137. package/src/esm/Vector.d.ts +12 -2
  138. package/src/esm/Vector.js +15 -2
  139. package/src/esm/Vector.js.map +1 -1
  140. package/src/esm/VertTuple.d.ts +28 -4
  141. package/src/esm/VertTuple.js +36 -3
  142. package/src/esm/VertTuple.js.map +1 -1
  143. package/src/esm/Vertex.d.ts +31 -4
  144. package/src/esm/Vertex.js +35 -1
  145. package/src/esm/Vertex.js.map +1 -1
  146. package/src/esm/interfaces/core.d.ts +67 -0
  147. package/src/esm/interfaces/core.js +4 -0
  148. package/src/esm/interfaces/core.js.map +1 -1
  149. package/src/esm/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
  150. package/src/esm/utils/algorithms/convexPolygonIncircle.js +15 -7
  151. package/src/esm/utils/algorithms/convexPolygonIncircle.js.map +1 -1
  152. package/src/esm/utils/algorithms/createRandomizedPolygon.d.ts +14 -0
  153. package/src/esm/utils/algorithms/createRandomizedPolygon.js +28 -0
  154. package/src/esm/utils/algorithms/createRandomizedPolygon.js.map +1 -0
  155. package/src/esm/utils/createRandomizedPolygon.d.ts +14 -0
  156. package/src/esm/utils/createRandomizedPolygon.js +28 -0
  157. package/src/esm/utils/createRandomizedPolygon.js.map +1 -0
  158. package/src/esm/utils/datastructures/Color.d.ts +147 -1
  159. package/src/esm/utils/datastructures/Color.js +386 -42
  160. package/src/esm/utils/datastructures/Color.js.map +1 -1
  161. package/src/esm/utils/datastructures/ColorGradient.d.ts +79 -0
  162. package/src/esm/utils/datastructures/ColorGradient.js +166 -0
  163. package/src/esm/utils/datastructures/ColorGradient.js.map +1 -0
  164. package/src/esm/utils/dom/components/ColorGradientPicker.d.ts +245 -0
  165. package/src/esm/utils/dom/components/ColorGradientPicker.js +732 -0
  166. package/src/esm/utils/dom/components/ColorGradientPicker.js.map +1 -0
  167. package/src/esm/utils/dom/components/ColorGradientPickerJSX.d.ts +129 -0
  168. package/src/esm/utils/dom/components/ColorGradientPickerJSX.js +582 -0
  169. package/src/esm/utils/dom/components/ColorGradientPickerJSX.js.map +1 -0
  170. package/src/esm/utils/dom/components/ColorGradientSelector.d.ts +117 -0
  171. package/src/esm/utils/dom/components/ColorGradientSelector.js +332 -0
  172. package/src/esm/utils/dom/components/ColorGradientSelector.js.map +1 -0
  173. package/src/esm/utils/dom/components/Test.d.ts +7 -0
  174. package/src/esm/utils/dom/components/Test.js +26 -0
  175. package/src/esm/utils/dom/components/Test.js.map +1 -0
  176. package/src/esm/utils/dom/guiSizeToggler.js +1 -1
  177. package/src/esm/utils/dom/guiSizeToggler.js.map +1 -1
  178. package/src/esm/utils/helpers/BezierPathInteractionHelper.d.ts +16 -8
  179. package/src/esm/utils/helpers/BezierPathInteractionHelper.js +47 -27
  180. package/src/esm/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
  181. package/src/esm/utils/helpers/CircleHelper.d.ts +10 -1
  182. package/src/esm/utils/helpers/CircleHelper.js +13 -2
  183. package/src/esm/utils/helpers/CircleHelper.js.map +1 -1
  184. package/src/esm/utils/helpers/CircleSectorHelper.d.ts +11 -2
  185. package/src/esm/utils/helpers/CircleSectorHelper.js +20 -20
  186. package/src/esm/utils/helpers/CircleSectorHelper.js.map +1 -1
  187. package/src/esm/utils/helpers/TriangleHelper.d.ts +57 -0
  188. package/src/esm/utils/helpers/TriangleHelper.js +78 -0
  189. package/src/esm/utils/helpers/TriangleHelper.js.map +1 -0
  190. package/src/esm/utils/helpers/VEllipseHelper.d.ts +32 -0
  191. package/src/esm/utils/helpers/VEllipseHelper.js +83 -0
  192. package/src/esm/utils/helpers/VEllipseHelper.js.map +1 -0
  193. package/src/esm/utils/helpers/VEllipseSectorHelper.d.ts +44 -4
  194. package/src/esm/utils/helpers/VEllipseSectorHelper.js +107 -24
  195. package/src/esm/utils/helpers/VEllipseSectorHelper.js.map +1 -1
  196. package/src/esm/utils/parsers/LinearColorGradientParser.d.ts +78 -0
  197. package/src/esm/utils/parsers/LinearColorGradientParser.js +217 -0
  198. package/src/esm/utils/parsers/LinearColorGradientParser.js.map +1 -0
  199. package/src/external.d.ts +9 -0
  200. package/src/ts/BezierPath.ts +58 -5
  201. package/src/ts/Bounds.ts +110 -6
  202. package/src/ts/Circle.ts +87 -5
  203. package/src/ts/CircleSector.ts +115 -5
  204. package/src/ts/CubicBezierCurve.ts +332 -42
  205. package/src/ts/Line.ts +66 -3
  206. package/src/ts/PlotBoilerplate.ts +236 -114
  207. package/src/ts/Polygon.ts +164 -29
  208. package/src/ts/Triangle.ts +85 -3
  209. package/src/ts/VEllipse.ts +214 -19
  210. package/src/ts/VEllipseSector.ts +154 -8
  211. package/src/ts/Vector.ts +16 -2
  212. package/src/ts/VertTuple.ts +39 -4
  213. package/src/ts/Vertex.ts +40 -4
  214. package/src/ts/interfaces/core.ts +73 -0
  215. package/src/ts/utils/algorithms/convexPolygonIncircle.ts +82 -78
  216. package/src/ts/utils/createRandomizedPolygon.ts +31 -0
  217. package/src/ts/utils/datastructures/Color.ts +423 -44
  218. package/src/ts/utils/datastructures/ColorGradient.ts +196 -0
  219. package/src/ts/utils/dom/components/ColorGradientPicker.tsx +877 -0
  220. package/src/ts/utils/dom/components/ColorGradientSelector.tsx +445 -0
  221. package/src/ts/utils/dom/components/Test.tsx +44 -0
  222. package/src/ts/utils/dom/components/_ColorGradientPicker_raw.ts_ +392 -0
  223. package/src/ts/utils/dom/guiSizeToggler.ts +1 -1
  224. package/src/ts/utils/helpers/BezierPathInteractionHelper.ts +61 -35
  225. package/src/ts/utils/helpers/CircleHelper.ts +17 -3
  226. package/src/ts/utils/helpers/CircleSectorHelper.ts +118 -126
  227. package/src/ts/utils/helpers/TriangleHelper.ts +102 -0
  228. package/src/ts/utils/helpers/VEllipseHelper.ts +115 -0
  229. package/src/ts/utils/helpers/VEllipseSectorHelper.ts +144 -26
  230. package/src/ts/utils/parsers/LinearColorGradientParser.ts +297 -0
package/src/ts/Polygon.ts CHANGED
@@ -32,7 +32,13 @@
32
32
  * @modified 2024-10-30 Added the `getEdges` method.
33
33
  * @modified 2024-12-02 Added the `elimitateColinearEdges` method.
34
34
  * @modified 2025-02-12 Added the `containsVerts` method to test multiple vertices for containment.
35
- * @version 1.14.0
35
+ * @modified 2025-03-28 Added the `Polygon.utils.locateLineIntersecion` static helper method.
36
+ * @modified 2025-03-28 Added the `Polygon.lineIntersectionTangents` method.
37
+ * @modified 2025-04-09 Added the `Polygon.getCentroid` method.
38
+ * @modified 2025-05-16 Class `Polygon` now implements `IBounded`.
39
+ * @modified 2025-05-20 Tweaking `Polygon.getInnerAngleAt` and `Polygo.isAngleAcute` to handle indices out of array bounds as well.
40
+ * @modified 2025-06-07 Adding `Polygon.closestLineIntersectionIndex` to determine line intersections plus detected edge index.
41
+ * @version 1.16.0
36
42
  *
37
43
  * @file Polygon
38
44
  * @public
@@ -43,10 +49,11 @@ import { Bounds } from "./Bounds";
43
49
  import { Line } from "./Line";
44
50
  import { Triangle } from "./Triangle";
45
51
  import { UIDGenerator } from "./UIDGenerator";
52
+ import { Vector } from "./Vector";
46
53
  import { VertTuple } from "./VertTuple";
47
54
  import { Vertex } from "./Vertex";
48
55
  import { geomutils } from "./geomutils";
49
- import { XYCoords, SVGSerializable, UID } from "./interfaces";
56
+ import { XYCoords, SVGSerializable, UID, Intersectable, IBounded, PolygonIntersectionTuple } from "./interfaces";
50
57
 
51
58
  /**
52
59
  * @classdesc A polygon class. Any polygon consists of an array of vertices; polygons can be open or closed.
@@ -59,7 +66,7 @@ import { XYCoords, SVGSerializable, UID } from "./interfaces";
59
66
  * @requires Vertex
60
67
  * @requires XYCoords
61
68
  */
62
- export class Polygon implements SVGSerializable {
69
+ export class Polygon implements IBounded, Intersectable, SVGSerializable {
63
70
  /**
64
71
  * Required to generate proper CSS classes and other class related IDs.
65
72
  **/
@@ -190,7 +197,7 @@ export class Polygon implements SVGSerializable {
190
197
  * @returns {boolean} `true` is angle is acute, `false` is obtuse.
191
198
  */
192
199
  getInnerAngleAt(vertIndex: number): number {
193
- const p2: Vertex = this.vertices[vertIndex];
200
+ const p2: Vertex = this.vertices[vertIndex % this.vertices.length];
194
201
  const p1: Vertex = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();
195
202
  const p3: Vertex = this.vertices[(vertIndex + 1) % this.vertices.length].clone();
196
203
 
@@ -230,7 +237,7 @@ export class Polygon implements SVGSerializable {
230
237
  */
231
238
  isAngleAcute(vertIndex: number): boolean {
232
239
  const A: Vertex = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();
233
- const B: Vertex = this.vertices[vertIndex];
240
+ const B: Vertex = this.vertices[vertIndex % this.vertices.length];
234
241
  const C: Vertex = this.vertices[(vertIndex + 1) % this.vertices.length].clone();
235
242
 
236
243
  // Find local winding number for triangle A B C
@@ -302,7 +309,9 @@ export class Polygon implements SVGSerializable {
302
309
  yj: number = this.vertices[j].y;
303
310
 
304
311
  var intersect: boolean = yi > vert.y != yj > vert.y && vert.x < ((xj - xi) * (vert.y - yi)) / (yj - yi) + xi;
305
- if (intersect) inside = !inside;
312
+ if (intersect) {
313
+ inside = !inside;
314
+ }
306
315
  }
307
316
  return inside;
308
317
  }
@@ -459,11 +468,11 @@ export class Polygon implements SVGSerializable {
459
468
  * @memberof Polygon
460
469
  * @return {Vertex|null} `null` is no vertices are available.
461
470
  */
462
- getMeanCenter() {
471
+ getMeanCenter(): Vertex | null {
463
472
  if (this.vertices.length === 0) {
464
473
  return null;
465
474
  }
466
- const center = this.vertices[0].clone();
475
+ const center: Vertex = this.vertices[0].clone();
467
476
  for (var i = 1; i < this.vertices.length; i++) {
468
477
  center.add(this.vertices[i]);
469
478
  }
@@ -472,9 +481,45 @@ export class Polygon implements SVGSerializable {
472
481
  return center;
473
482
  }
474
483
 
484
+ /**
485
+ * Get centroid.
486
+ * Centroids define the barycenter of any non self-intersecting convex polygon.
487
+ *
488
+ * If the polygon is self intersecting or non konvex then the barycenter is not well defined.
489
+ *
490
+ * https://mathworld.wolfram.com/PolygonCentroid.html
491
+ *
492
+ * @method getCentroid
493
+ * @instance
494
+ * @memberof Polygon
495
+ * @returns {Vertex|null}
496
+ */
497
+ getCentroid(): Vertex | null {
498
+ if (this.vertices.length === 0) {
499
+ return null;
500
+ }
501
+ const center: Vertex = new Vertex(0.0, 0.0);
502
+ const n = this.vertices.length;
503
+ for (var i = 0; i < n; i++) {
504
+ // center.add(this.vertices[i]);
505
+ const cur: Vertex = this.vertices[i];
506
+ const next: Vertex = this.vertices[(i + 1) % n];
507
+ var factor: number = cur.x * next.y - next.x * cur.y;
508
+ center.x += (cur.x + next.x) * factor;
509
+ center.y += (cur.y + next.y) * factor;
510
+ }
511
+ const area = this.area();
512
+ center.x *= 1 / (6 * area);
513
+ center.y *= 1 / (6 * area);
514
+ return center;
515
+ }
516
+
517
+ //--- BEGIN --- Implement interface `Intersectable`
475
518
  /**
476
519
  * Get all line intersections with this polygon.
477
520
  *
521
+ * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
522
+ *
478
523
  * See demo `47-closest-vector-projection-on-polygon` for how it works.
479
524
  *
480
525
  * @param {VertTuple} line - The line to find intersections with.
@@ -483,22 +528,50 @@ export class Polygon implements SVGSerializable {
483
528
  */
484
529
  lineIntersections(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vertex> {
485
530
  // Find the intersections of all lines inside the edge bounds
486
- const intersectionPoints: Array<Vertex> = [];
487
- for (var i = 0; i < this.vertices.length; i++) {
488
- const polyLine = new Line(this.vertices[i], this.vertices[(i + 1) % this.vertices.length]);
489
- const intersection = polyLine.intersection(line);
490
- // true => only inside bounds
491
- // ignore last edge if open
492
- if (
493
- (!this.isOpen || i + 1 !== this.vertices.length) &&
494
- intersection !== null &&
495
- polyLine.hasPoint(intersection, true) &&
496
- (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))
497
- ) {
498
- intersectionPoints.push(intersection);
499
- }
500
- }
501
- return intersectionPoints;
531
+ return Polygon.utils
532
+ .locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly)
533
+ .map(intersectionTuple => intersectionTuple.intersection);
534
+ }
535
+
536
+ /**
537
+ * Get all line intersections of this polygon and their tangents along the shape.
538
+ *
539
+ * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
540
+ *
541
+ * @param line
542
+ * @param inVectorBoundsOnly
543
+ * @returns
544
+ */
545
+ lineIntersectionTangents(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vector> {
546
+ // Find the intersection tangents of all lines inside the edge bounds
547
+ return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {
548
+ const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
549
+ return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection) as Vector;
550
+ });
551
+ }
552
+ //--- END --- Implement interface `Intersectable`
553
+
554
+ /**
555
+ * Get all line intersections of this polygon and their tangents along the shape.
556
+ *
557
+ * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
558
+ *
559
+ * @param line
560
+ * @param inVectorBoundsOnly
561
+ * @returns
562
+ */
563
+ lineIntersectionTangentsIndices(
564
+ line: VertTuple<any>,
565
+ inVectorBoundsOnly: boolean = false
566
+ ): Array<PolygonIntersectionTuple<Vector>> {
567
+ // Find the intersection tangents of all lines inside the edge bounds
568
+ return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {
569
+ const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
570
+ return {
571
+ intersection: new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection) as Vector,
572
+ edgeIndex: intersectionTuple.edgeIndex
573
+ };
574
+ });
502
575
  }
503
576
 
504
577
  /**
@@ -508,27 +581,54 @@ export class Polygon implements SVGSerializable {
508
581
  *
509
582
  * @param {VertTuple} line - The line to find intersections with.
510
583
  * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).
511
- * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.
584
+ * @returns {Vertex | null} - The intersection point within the polygon bounds.
512
585
  */
513
586
  closestLineIntersection(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Vertex | null {
587
+ var closestInterSectionIndex: PolygonIntersectionTuple<Vertex> | null = this.closestLineIntersectionIndex(
588
+ line,
589
+ inVectorBoundsOnly
590
+ );
591
+ if (closestInterSectionIndex) {
592
+ return closestInterSectionIndex.intersection;
593
+ } else {
594
+ return null;
595
+ }
596
+ }
597
+
598
+ /**
599
+ * Get the closest line-polygon-intersection point (closest the line point A) plus the edge index..
600
+ *
601
+ * See demo `63-measure-angles-on-polygon` for how it works.
602
+ *
603
+ * @param {VertTuple} line - The line to find intersections with.
604
+ * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).
605
+ * @returns {PolygonIntersectionTuple| null} - A pair containing the intersection point and the affected polygon edge index.
606
+ */
607
+ closestLineIntersectionIndex(
608
+ line: VertTuple<any>,
609
+ inVectorBoundsOnly: boolean = false
610
+ ): PolygonIntersectionTuple<Vertex> | null {
514
611
  const allIntersections = this.lineIntersections(line, inVectorBoundsOnly);
515
612
  if (allIntersections.length <= 0) {
516
613
  // Empty polygon -> no intersections
517
614
  return null;
518
615
  }
519
616
  // Find the closest intersection
520
- let closestIntersection = new Vertex(Number.MAX_VALUE, Number.MAX_VALUE);
617
+ let closestIntersection: Vertex = new Vertex(Number.MAX_VALUE, Number.MAX_VALUE);
618
+ let closestInterSectionIndex: number = -1;
521
619
  let curDist = Number.MAX_VALUE;
522
- for (var i in allIntersections) {
620
+ for (var i = 0; i < allIntersections.length; i++) {
523
621
  const curVert = allIntersections[i];
524
622
  const dist = curVert.distance(line.a);
525
623
  if (dist < curDist) {
526
624
  // && line.hasPoint(curVert)) {
527
625
  curDist = dist;
528
626
  closestIntersection = curVert;
627
+ closestInterSectionIndex = i;
529
628
  }
530
629
  }
531
- return closestIntersection;
630
+ // return [closestIntersection, closestInterSectionIndex];
631
+ return { edgeIndex: closestInterSectionIndex, intersection: closestIntersection };
532
632
  }
533
633
 
534
634
  /**
@@ -606,6 +706,7 @@ export class Polygon implements SVGSerializable {
606
706
  return result;
607
707
  }
608
708
 
709
+ //--- BEGIN --- Implement interface `IBounded`
609
710
  /**
610
711
  * Get the bounding box (bounds) of this polygon.
611
712
  *
@@ -617,6 +718,7 @@ export class Polygon implements SVGSerializable {
617
718
  getBounds(): Bounds {
618
719
  return Bounds.computeFromVertices(this.vertices);
619
720
  }
721
+ //--- END --- Implement interface `IBounded`
620
722
 
621
723
  /**
622
724
  * Create a deep copy of this polygon.
@@ -676,7 +778,6 @@ export class Polygon implements SVGSerializable {
676
778
  // -> delete all vertices in between
677
779
  if (j - i > 2) {
678
780
  // Means: there have been 'colinear vertices' in between
679
- // console.log("Splice", "i", i, "j", j, i + 1, j - i - 1);
680
781
  verts.splice(i + 1, j - i - 2);
681
782
  }
682
783
  i++;
@@ -886,6 +987,40 @@ export class Polygon implements SVGSerializable {
886
987
  sum += (vertices[j].x - vertices[i].x) * (vertices[i].y + vertices[j].y);
887
988
  }
888
989
  return sum;
990
+ },
991
+
992
+ /**
993
+ * Find intersections of a line with a polygon (vertices).
994
+ *
995
+ * @param {VertTuple<any>} line - The line to find intersections with.
996
+ * @param {Array<Vertex>} vertices - The polygon's vertices.
997
+ * @param {boolean} isOpen - True if the polygon is open, false otherwise.
998
+ * @param {boolean} inVectorBoundsOnly - If only intersections in strict vector bounds should be returned.
999
+ * @returns
1000
+ */
1001
+ locateLineIntersecion(
1002
+ line: VertTuple<any>,
1003
+ vertices: Array<Vertex>,
1004
+ isOpen: boolean,
1005
+ inVectorBoundsOnly: boolean
1006
+ ): Array<PolygonIntersectionTuple<Vertex>> {
1007
+ // Find the intersections of all lines inside the edge bounds
1008
+ const intersectionPoints: Array<PolygonIntersectionTuple<Vertex>> = [];
1009
+ var n = isOpen ? vertices.length - 1 : vertices.length;
1010
+ for (var i = 0; i < n; i++) {
1011
+ const polyLine = new Line(vertices[i % n], vertices[(i + 1) % n]);
1012
+ const intersection = polyLine.intersection(line);
1013
+ // true => only inside bounds
1014
+ // ignore last edge if open
1015
+ if (
1016
+ intersection !== null &&
1017
+ polyLine.hasPoint(intersection, true) &&
1018
+ (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))
1019
+ ) {
1020
+ intersectionPoints.push({ edgeIndex: i, intersection: intersection });
1021
+ }
1022
+ }
1023
+ return intersectionPoints;
889
1024
  }
890
1025
  };
891
1026
  }
@@ -23,7 +23,11 @@
23
23
  * @modified 2022-02-02 Cleared the `Triangle.toSVGString` function (deprecated). Use `drawutilssvg` instead.
24
24
  * @modified 2024-11-22 Added static utility function Triangle.utils.determinant; adapted method `determinant`.
25
25
  * @modified 2024-11-22 Changing visibility of `Triangle.utils` from `private` to `public`.
26
- * @version 2.8.0
26
+ * @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.
27
+ * @modified 2025-14-16 Class `Triangle` now implements interface `IBounded`.
28
+ * @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.
29
+ * @modified 2025-14-16 Added method `Triangle.move`.
30
+ * @version 2.10.0
27
31
  *
28
32
  * @file Triangle
29
33
  * @fileoverview A simple triangle class: three vertices.
@@ -35,9 +39,11 @@ import { Circle } from "./Circle";
35
39
  import { Line } from "./Line";
36
40
  import { Polygon } from "./Polygon";
37
41
  import { UIDGenerator } from "./UIDGenerator";
42
+ import { Vector } from "./Vector";
43
+ import { VertTuple } from "./VertTuple";
38
44
  import { Vertex } from "./Vertex";
39
45
  import { geomutils } from "./geomutils";
40
- import { SVGSerializable, UID, XYCoords } from "./interfaces";
46
+ import { IBounded, Intersectable, SVGSerializable, UID, XYCoords } from "./interfaces";
41
47
 
42
48
  /**
43
49
  * @classdesc A triangle class for triangulations.
@@ -56,7 +62,7 @@ import { SVGSerializable, UID, XYCoords } from "./interfaces";
56
62
  * @requires geomutils
57
63
  *
58
64
  */
59
- export class Triangle implements SVGSerializable {
65
+ export class Triangle implements IBounded, SVGSerializable, Intersectable {
60
66
  /**
61
67
  * Required to generate proper CSS classes and other class related IDs.
62
68
  **/
@@ -215,6 +221,37 @@ export class Triangle implements SVGSerializable {
215
221
  return this;
216
222
  }
217
223
 
224
+ //--- BEGIN --- Implement interface `IBounded`
225
+ /**
226
+ * Get the bounding box (bounds) of this Triangle.
227
+ *
228
+ * @method getBounds
229
+ * @instance
230
+ * @memberof Triangle
231
+ * @return {Bounds} The rectangular bounds of this Triangle.
232
+ **/
233
+ getBounds(): Bounds {
234
+ // return Bounds.computeFromVertices([this.a, this.b, this.c]);
235
+ return this.bounds();
236
+ }
237
+ //--- END --- Implement interface `IBounded`
238
+
239
+ /**
240
+ * Move the Triangle's vertices by the given amount.
241
+ *
242
+ * @method move
243
+ * @param {XYCoords} amount - The amount to move.
244
+ * @instance
245
+ * @memberof Triangle
246
+ * @return {Triangle} this for chaining
247
+ **/
248
+ move(amount: XYCoords): Triangle {
249
+ this.a.add(amount);
250
+ this.b.add(amount);
251
+ this.c.add(amount);
252
+ return this;
253
+ }
254
+
218
255
  /**
219
256
  * Get the circumcircle of this triangle.
220
257
  *
@@ -352,6 +389,51 @@ export class Triangle implements SVGSerializable {
352
389
  );
353
390
  }
354
391
 
392
+ //--- BEGIN --- Implement interface `Intersectable`
393
+ /**
394
+ * Get all line intersections with this polygon.
395
+ *
396
+ * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
397
+ *
398
+ * See demo `47-closest-vector-projection-on-polygon` for how it works.
399
+ *
400
+ * @param {VertTuple} line - The line to find intersections with.
401
+ * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).
402
+ * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.
403
+ */
404
+ lineIntersections(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vertex> {
405
+ // Find the intersections of all lines inside the edge bounds
406
+ return Polygon.utils
407
+ .locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)
408
+ .map(intersectionTuple => intersectionTuple.intersection);
409
+ }
410
+
411
+ /**
412
+ * Get all line intersections of this polygon and their tangents along the shape.
413
+ *
414
+ * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
415
+ *
416
+ * @param line
417
+ * @param inVectorBoundsOnly
418
+ * @returns
419
+ */
420
+ lineIntersectionTangents(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vector> {
421
+ // Find the intersection tangents of all lines inside the edge bounds
422
+ return Polygon.utils
423
+ .locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)
424
+ .map(intersectionTuple => {
425
+ // const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
426
+ const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
427
+ return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection) as Vector;
428
+ });
429
+ }
430
+ //--- END --- Implement interface `Intersectable`
431
+
432
+ getEdgeAt(edgeIndex: number): Line {
433
+ var modIndex = edgeIndex % 3;
434
+ return modIndex === 0 ? new Line(this.a, this.b) : modIndex === 1 ? new Line(this.b, this.c) : new Line(this.c, this.a);
435
+ }
436
+
355
437
  /**
356
438
  * Convert this triangle to a polygon instance.
357
439
  *