plotboilerplate 1.23.3 → 1.24.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 (159) hide show
  1. package/README.md +6 -0
  2. package/dist/index.esm.js +1390 -265
  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 +1264 -99
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +1 -1
  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.js +2 -9
  30. package/src/cjs/PlotBoilerplate.js.map +1 -1
  31. package/src/cjs/Polygon.d.ts +48 -4
  32. package/src/cjs/Polygon.js +91 -16
  33. package/src/cjs/Polygon.js.map +1 -1
  34. package/src/cjs/Triangle.d.ts +52 -3
  35. package/src/cjs/Triangle.js +80 -1
  36. package/src/cjs/Triangle.js.map +1 -1
  37. package/src/cjs/VEllipse.d.ts +62 -3
  38. package/src/cjs/VEllipse.js +181 -17
  39. package/src/cjs/VEllipse.js.map +1 -1
  40. package/src/cjs/VEllipseSector.d.ts +86 -2
  41. package/src/cjs/VEllipseSector.js +148 -4
  42. package/src/cjs/VEllipseSector.js.map +1 -1
  43. package/src/cjs/Vector.d.ts +12 -2
  44. package/src/cjs/Vector.js +15 -2
  45. package/src/cjs/Vector.js.map +1 -1
  46. package/src/cjs/VertTuple.d.ts +28 -4
  47. package/src/cjs/VertTuple.js +36 -3
  48. package/src/cjs/VertTuple.js.map +1 -1
  49. package/src/cjs/Vertex.d.ts +17 -2
  50. package/src/cjs/Vertex.js +18 -1
  51. package/src/cjs/Vertex.js.map +1 -1
  52. package/src/cjs/interfaces/core.d.ts +39 -0
  53. package/src/cjs/interfaces/core.js +2 -0
  54. package/src/cjs/interfaces/core.js.map +1 -1
  55. package/src/cjs/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
  56. package/src/cjs/utils/algorithms/convexPolygonIncircle.js +14 -6
  57. package/src/cjs/utils/algorithms/convexPolygonIncircle.js.map +1 -1
  58. package/src/cjs/utils/createRandomizedPolygon.d.ts +14 -0
  59. package/src/cjs/utils/createRandomizedPolygon.js +32 -0
  60. package/src/cjs/utils/createRandomizedPolygon.js.map +1 -0
  61. package/src/cjs/utils/helpers/BezierPathInteractionHelper.d.ts +9 -7
  62. package/src/cjs/utils/helpers/BezierPathInteractionHelper.js +37 -23
  63. package/src/cjs/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
  64. package/src/cjs/utils/helpers/CircleSectorHelper.d.ts +10 -1
  65. package/src/cjs/utils/helpers/CircleSectorHelper.js +19 -20
  66. package/src/cjs/utils/helpers/CircleSectorHelper.js.map +1 -1
  67. package/src/cjs/utils/helpers/VEllipseHelper.d.ts +30 -0
  68. package/src/cjs/utils/helpers/VEllipseHelper.js +86 -0
  69. package/src/cjs/utils/helpers/VEllipseHelper.js.map +1 -0
  70. package/src/cjs/utils/helpers/VEllipseSectorHelper.d.ts +42 -3
  71. package/src/cjs/utils/helpers/VEllipseSectorHelper.js +107 -25
  72. package/src/cjs/utils/helpers/VEllipseSectorHelper.js.map +1 -1
  73. package/src/createDemoDrawables.js +3 -1
  74. package/src/esm/BezierPath.d.ts +41 -5
  75. package/src/esm/BezierPath.js +50 -2
  76. package/src/esm/BezierPath.js.map +1 -1
  77. package/src/esm/Bounds.d.ts +67 -3
  78. package/src/esm/Bounds.js +101 -3
  79. package/src/esm/Bounds.js.map +1 -1
  80. package/src/esm/Circle.d.ts +46 -4
  81. package/src/esm/Circle.js +79 -3
  82. package/src/esm/Circle.js.map +1 -1
  83. package/src/esm/CircleSector.d.ts +51 -2
  84. package/src/esm/CircleSector.js +108 -3
  85. package/src/esm/CircleSector.js.map +1 -1
  86. package/src/esm/CubicBezierCurve.d.ts +113 -7
  87. package/src/esm/CubicBezierCurve.js +277 -33
  88. package/src/esm/CubicBezierCurve.js.map +1 -1
  89. package/src/esm/Line.d.ts +38 -3
  90. package/src/esm/Line.js +62 -1
  91. package/src/esm/Line.js.map +1 -1
  92. package/src/esm/PlotBoilerplate.js +2 -9
  93. package/src/esm/PlotBoilerplate.js.map +1 -1
  94. package/src/esm/Polygon.d.ts +48 -4
  95. package/src/esm/Polygon.js +89 -16
  96. package/src/esm/Polygon.js.map +1 -1
  97. package/src/esm/Triangle.d.ts +52 -3
  98. package/src/esm/Triangle.js +77 -1
  99. package/src/esm/Triangle.js.map +1 -1
  100. package/src/esm/VEllipse.d.ts +62 -3
  101. package/src/esm/VEllipse.js +178 -17
  102. package/src/esm/VEllipse.js.map +1 -1
  103. package/src/esm/VEllipseSector.d.ts +86 -2
  104. package/src/esm/VEllipseSector.js +146 -7
  105. package/src/esm/VEllipseSector.js.map +1 -1
  106. package/src/esm/Vector.d.ts +12 -2
  107. package/src/esm/Vector.js +15 -2
  108. package/src/esm/Vector.js.map +1 -1
  109. package/src/esm/VertTuple.d.ts +28 -4
  110. package/src/esm/VertTuple.js +36 -3
  111. package/src/esm/VertTuple.js.map +1 -1
  112. package/src/esm/Vertex.d.ts +17 -2
  113. package/src/esm/Vertex.js +18 -1
  114. package/src/esm/Vertex.js.map +1 -1
  115. package/src/esm/interfaces/core.d.ts +39 -0
  116. package/src/esm/interfaces/core.js +2 -0
  117. package/src/esm/interfaces/core.js.map +1 -1
  118. package/src/esm/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
  119. package/src/esm/utils/algorithms/convexPolygonIncircle.js +15 -7
  120. package/src/esm/utils/algorithms/convexPolygonIncircle.js.map +1 -1
  121. package/src/esm/utils/algorithms/createRandomizedPolygon.d.ts +14 -0
  122. package/src/esm/utils/algorithms/createRandomizedPolygon.js +28 -0
  123. package/src/esm/utils/algorithms/createRandomizedPolygon.js.map +1 -0
  124. package/src/esm/utils/createRandomizedPolygon.d.ts +14 -0
  125. package/src/esm/utils/createRandomizedPolygon.js +28 -0
  126. package/src/esm/utils/createRandomizedPolygon.js.map +1 -0
  127. package/src/esm/utils/helpers/BezierPathInteractionHelper.d.ts +9 -7
  128. package/src/esm/utils/helpers/BezierPathInteractionHelper.js +35 -22
  129. package/src/esm/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
  130. package/src/esm/utils/helpers/CircleSectorHelper.d.ts +10 -1
  131. package/src/esm/utils/helpers/CircleSectorHelper.js +19 -20
  132. package/src/esm/utils/helpers/CircleSectorHelper.js.map +1 -1
  133. package/src/esm/utils/helpers/VEllipseHelper.d.ts +30 -0
  134. package/src/esm/utils/helpers/VEllipseHelper.js +81 -0
  135. package/src/esm/utils/helpers/VEllipseHelper.js.map +1 -0
  136. package/src/esm/utils/helpers/VEllipseSectorHelper.d.ts +42 -3
  137. package/src/esm/utils/helpers/VEllipseSectorHelper.js +106 -24
  138. package/src/esm/utils/helpers/VEllipseSectorHelper.js.map +1 -1
  139. package/src/ts/BezierPath.ts +58 -5
  140. package/src/ts/Bounds.ts +110 -6
  141. package/src/ts/Circle.ts +87 -5
  142. package/src/ts/CircleSector.ts +115 -5
  143. package/src/ts/CubicBezierCurve.ts +332 -42
  144. package/src/ts/Line.ts +66 -3
  145. package/src/ts/PlotBoilerplate.ts +3 -9
  146. package/src/ts/Polygon.ts +103 -22
  147. package/src/ts/Triangle.ts +85 -3
  148. package/src/ts/VEllipse.ts +214 -19
  149. package/src/ts/VEllipseSector.ts +154 -8
  150. package/src/ts/Vector.ts +16 -2
  151. package/src/ts/VertTuple.ts +39 -4
  152. package/src/ts/Vertex.ts +20 -2
  153. package/src/ts/interfaces/core.ts +42 -0
  154. package/src/ts/utils/algorithms/convexPolygonIncircle.ts +82 -78
  155. package/src/ts/utils/createRandomizedPolygon.ts +31 -0
  156. package/src/ts/utils/helpers/BezierPathInteractionHelper.ts +45 -29
  157. package/src/ts/utils/helpers/CircleSectorHelper.ts +115 -125
  158. package/src/ts/utils/helpers/VEllipseHelper.ts +113 -0
  159. package/src/ts/utils/helpers/VEllipseSectorHelper.ts +142 -25
package/src/ts/Line.ts CHANGED
@@ -16,15 +16,19 @@
16
16
  * @modified 2022-10-09 Changed the actual return value of the `intersection` function to null (was undefined before).
17
17
  * @modified 2022-10-17 Adding these methods from the `PathSegment` interface: getStartPoint, getEndPoint, revert.
18
18
  * @modified 2023-09-25 Changed param type of `intersection()` from Line to VertTuple.
19
- * @version 2.3.0
19
+ * @modified 2025-04-15 Class `Line` now implements interface `Intersectable`.
20
+ * @modified 2025-04-16 Class `Line` now implements interface `IBounded`.
21
+ * @version 2.4.0
20
22
  *
21
23
  * @file Line
22
24
  * @public
23
25
  **/
24
26
 
27
+ import { Bounds } from "./Bounds";
28
+ import { Vector } from "./Vector";
25
29
  import { VertTuple } from "./VertTuple";
26
30
  import { Vertex } from "./Vertex";
27
- import { PathSegment, SVGSerializable } from "./interfaces";
31
+ import { IBounded, Intersectable, PathSegment, SVGSerializable } from "./interfaces";
28
32
 
29
33
  /**
30
34
  * @classdesc A line consists of two vertices a and b.<br>
@@ -34,7 +38,7 @@ import { PathSegment, SVGSerializable } from "./interfaces";
34
38
  *
35
39
  * @requires Vertex
36
40
  */
37
- export class Line extends VertTuple<Line> implements SVGSerializable, PathSegment {
41
+ export class Line extends VertTuple<Line> implements IBounded, Intersectable, PathSegment, SVGSerializable {
38
42
  /**
39
43
  * Required to generate proper CSS classes and other class related IDs.
40
44
  **/
@@ -87,6 +91,20 @@ export class Line extends VertTuple<Line> implements SVGSerializable, PathSegmen
87
91
  return new Vertex(x, y);
88
92
  }
89
93
 
94
+ //--- BEGIN --- Implement interface `IBounded`
95
+ /**
96
+ * Get the bounding box (bounds) of this Line.
97
+ *
98
+ * @method getBounds
99
+ * @instance
100
+ * @memberof Line
101
+ * @return {Bounds} The rectangular bounds of this Line.
102
+ **/
103
+ getBounds(): Bounds {
104
+ return Bounds.computeFromVertices([this.a, this.b]);
105
+ }
106
+ //--- END --- Implement interface `IBounded`
107
+
90
108
  //--- Implement PathSegment ---
91
109
  /**
92
110
  * Get the start point of this path segment.
@@ -146,4 +164,49 @@ export class Line extends VertTuple<Line> implements SVGSerializable, PathSegmen
146
164
  return this;
147
165
  }
148
166
  //--- END Implement PathSegment ---
167
+
168
+ //--- BEGIN --- Implement interface `Intersectable`
169
+ /**
170
+ * Get all line intersections with this polygon.
171
+ *
172
+ * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
173
+ *
174
+ * See demo `47-closest-vector-projection-on-polygon` for how it works.
175
+ *
176
+ * @param {VertTuple} line - The line to find intersections with.
177
+ * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).
178
+ * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.
179
+ */
180
+ lineIntersections(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vertex> {
181
+ // Find the intersections of all lines inside the edge bounds
182
+ const intersection: Vertex | null = this.intersection(line);
183
+ if (!intersection) {
184
+ return []; // Both lines parallel
185
+ }
186
+ if (this.hasPoint(intersection, true) && (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {
187
+ return [intersection];
188
+ } else {
189
+ return [];
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Get all line intersections of this polygon and their tangents along the shape.
195
+ *
196
+ * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
197
+ *
198
+ * @param line
199
+ * @param inVectorBoundsOnly
200
+ * @returns
201
+ */
202
+ lineIntersectionTangents(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vector> {
203
+ // Find the intersection tangents of all lines inside the edge bounds
204
+ const intersections: Vertex[] = this.lineIntersections(line, inVectorBoundsOnly);
205
+ if (intersections.length === 0) {
206
+ return [];
207
+ }
208
+ const intrsctn = intersections[0];
209
+ return [new Vector(this.a.clone(), this.b.clone()).moveTo(intrsctn) as Vector];
210
+ }
211
+ //--- END --- Implement interface `Intersectable`
149
212
  }
@@ -1302,16 +1302,16 @@ export class PlotBoilerplate {
1302
1302
  }
1303
1303
  } else if (d instanceof Triangle) {
1304
1304
  draw.polyline([d.a, d.b, d.c], false, this.drawConfig.triangle.color, this.drawConfig.triangle.lineWidth);
1305
- if (!this.drawConfig.drawHandlePoints) d.a.attr.renderTime = d.b.attr.renderTime = d.c.attr.renderTime = renderTime;
1305
+ if (!this.drawConfig.drawHandlePoints) {
1306
+ d.a.attr.renderTime = d.b.attr.renderTime = d.c.attr.renderTime = renderTime;
1307
+ }
1306
1308
  } else if (d instanceof VEllipse) {
1307
1309
  if (this.drawConfig.drawHandleLines) {
1308
1310
  draw.setCurrentId(`${d.uid}_e0`);
1309
1311
  draw.setCurrentClassName(`${d.className}-v-line`);
1310
- // draw.line( d.center.clone().add(0,d.axis.y-d.center.y), d.axis, '#c8c8c8' );
1311
1312
  draw.handleLine(d.center.clone().add(0, d.signedRadiusV()).rotate(d.rotation, d.center), d.axis); // , "#c8c8c8");
1312
1313
  draw.setCurrentId(`${d.uid}_e1`);
1313
1314
  draw.setCurrentClassName(`${d.className}-h-line`);
1314
- // draw.line( d.center.clone().add(d.axis.x-d.center.x,0), d.axis, '#c8c8c8' );
1315
1315
  draw.handleLine(d.center.clone().add(d.signedRadiusH(), 0).rotate(d.rotation, d.center), d.axis); // , "#c8c8c8");
1316
1316
  }
1317
1317
  draw.setCurrentId(d.uid);
@@ -1332,12 +1332,6 @@ export class PlotBoilerplate {
1332
1332
  } else if (d instanceof VEllipseSector) {
1333
1333
  draw.setCurrentId(d.uid);
1334
1334
  draw.setCurrentClassName(`${d.className}`);
1335
- /* draw.ellipse( d.center,
1336
- // Math.abs(d.axis.x-d.center.x), Math.abs(d.axis.y-d.center.y),
1337
- d.radiusH(), d.radiusV(),
1338
- this.drawConfig.ellipse.color,
1339
- this.drawConfig.ellipse.lineWidth,
1340
- d.rotation ); */
1341
1335
  const data: SVGPathParams = VEllipseSector.ellipseSectorUtils.describeSVGArc(
1342
1336
  d.ellipse.center.x,
1343
1337
  d.ellipse.center.y,
package/src/ts/Polygon.ts CHANGED
@@ -32,7 +32,11 @@
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
+ * @version 1.15.0
36
40
  *
37
41
  * @file Polygon
38
42
  * @public
@@ -43,10 +47,11 @@ import { Bounds } from "./Bounds";
43
47
  import { Line } from "./Line";
44
48
  import { Triangle } from "./Triangle";
45
49
  import { UIDGenerator } from "./UIDGenerator";
50
+ import { Vector } from "./Vector";
46
51
  import { VertTuple } from "./VertTuple";
47
52
  import { Vertex } from "./Vertex";
48
53
  import { geomutils } from "./geomutils";
49
- import { XYCoords, SVGSerializable, UID } from "./interfaces";
54
+ import { XYCoords, SVGSerializable, UID, Intersectable, IBounded } from "./interfaces";
50
55
 
51
56
  /**
52
57
  * @classdesc A polygon class. Any polygon consists of an array of vertices; polygons can be open or closed.
@@ -59,7 +64,7 @@ import { XYCoords, SVGSerializable, UID } from "./interfaces";
59
64
  * @requires Vertex
60
65
  * @requires XYCoords
61
66
  */
62
- export class Polygon implements SVGSerializable {
67
+ export class Polygon implements IBounded, Intersectable, SVGSerializable {
63
68
  /**
64
69
  * Required to generate proper CSS classes and other class related IDs.
65
70
  **/
@@ -459,11 +464,11 @@ export class Polygon implements SVGSerializable {
459
464
  * @memberof Polygon
460
465
  * @return {Vertex|null} `null` is no vertices are available.
461
466
  */
462
- getMeanCenter() {
467
+ getMeanCenter(): Vertex | null {
463
468
  if (this.vertices.length === 0) {
464
469
  return null;
465
470
  }
466
- const center = this.vertices[0].clone();
471
+ const center: Vertex = this.vertices[0].clone();
467
472
  for (var i = 1; i < this.vertices.length; i++) {
468
473
  center.add(this.vertices[i]);
469
474
  }
@@ -472,9 +477,45 @@ export class Polygon implements SVGSerializable {
472
477
  return center;
473
478
  }
474
479
 
480
+ /**
481
+ * Get centroid.
482
+ * Centroids define the barycenter of any non self-intersecting convex polygon.
483
+ *
484
+ * If the polygon is self intersecting or non konvex then the barycenter is not well defined.
485
+ *
486
+ * https://mathworld.wolfram.com/PolygonCentroid.html
487
+ *
488
+ * @method getCentroid
489
+ * @instance
490
+ * @memberof Polygon
491
+ * @returns {Vertex|null}
492
+ */
493
+ getCentroid(): Vertex | null {
494
+ if (this.vertices.length === 0) {
495
+ return null;
496
+ }
497
+ const center: Vertex = new Vertex(0.0, 0.0);
498
+ const n = this.vertices.length;
499
+ for (var i = 0; i < n; i++) {
500
+ // center.add(this.vertices[i]);
501
+ const cur: Vertex = this.vertices[i];
502
+ const next: Vertex = this.vertices[(i + 1) % n];
503
+ var factor: number = cur.x * next.y - next.x * cur.y;
504
+ center.x += (cur.x + next.x) * factor;
505
+ center.y += (cur.y + next.y) * factor;
506
+ }
507
+ const area = this.area();
508
+ center.x *= 1 / (6 * area);
509
+ center.y *= 1 / (6 * area);
510
+ return center;
511
+ }
512
+
513
+ //--- BEGIN --- Implement interface `Intersectable`
475
514
  /**
476
515
  * Get all line intersections with this polygon.
477
516
  *
517
+ * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
518
+ *
478
519
  * See demo `47-closest-vector-projection-on-polygon` for how it works.
479
520
  *
480
521
  * @param {VertTuple} line - The line to find intersections with.
@@ -483,23 +524,28 @@ export class Polygon implements SVGSerializable {
483
524
  */
484
525
  lineIntersections(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vertex> {
485
526
  // 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;
527
+ return Polygon.utils
528
+ .locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly)
529
+ .map(intersectionTuple => intersectionTuple.intersectionPoint);
530
+ }
531
+
532
+ /**
533
+ * Get all line intersections of this polygon and their tangents along the shape.
534
+ *
535
+ * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
536
+ *
537
+ * @param line
538
+ * @param inVectorBoundsOnly
539
+ * @returns
540
+ */
541
+ lineIntersectionTangents(line: VertTuple<any>, inVectorBoundsOnly: boolean = false): Array<Vector> {
542
+ // Find the intersection tangents of all lines inside the edge bounds
543
+ return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {
544
+ const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
545
+ return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersectionPoint) as Vector;
546
+ });
502
547
  }
548
+ //--- END --- Implement interface `Intersectable`
503
549
 
504
550
  /**
505
551
  * Get the closest line-polygon-intersection point (closest the line point A).
@@ -606,6 +652,7 @@ export class Polygon implements SVGSerializable {
606
652
  return result;
607
653
  }
608
654
 
655
+ //--- BEGIN --- Implement interface `IBounded`
609
656
  /**
610
657
  * Get the bounding box (bounds) of this polygon.
611
658
  *
@@ -617,6 +664,7 @@ export class Polygon implements SVGSerializable {
617
664
  getBounds(): Bounds {
618
665
  return Bounds.computeFromVertices(this.vertices);
619
666
  }
667
+ //--- END --- Implement interface `IBounded`
620
668
 
621
669
  /**
622
670
  * Create a deep copy of this polygon.
@@ -676,7 +724,6 @@ export class Polygon implements SVGSerializable {
676
724
  // -> delete all vertices in between
677
725
  if (j - i > 2) {
678
726
  // Means: there have been 'colinear vertices' in between
679
- // console.log("Splice", "i", i, "j", j, i + 1, j - i - 1);
680
727
  verts.splice(i + 1, j - i - 2);
681
728
  }
682
729
  i++;
@@ -886,6 +933,40 @@ export class Polygon implements SVGSerializable {
886
933
  sum += (vertices[j].x - vertices[i].x) * (vertices[i].y + vertices[j].y);
887
934
  }
888
935
  return sum;
936
+ },
937
+
938
+ /**
939
+ * Find intersections of a line with a polygon (vertices).
940
+ *
941
+ * @param {VertTuple<any>} line - The line to find intersections with.
942
+ * @param {Array<Vertex>} vertices - The polygon's vertices.
943
+ * @param {boolean} isOpen - True if the polygon is open, false otherwise.
944
+ * @param {boolean} inVectorBoundsOnly - If only intersections in strict vector bounds should be returned.
945
+ * @returns
946
+ */
947
+ locateLineIntersecion(
948
+ line: VertTuple<any>,
949
+ vertices: Array<Vertex>,
950
+ isOpen: boolean,
951
+ inVectorBoundsOnly: boolean
952
+ ): Array<{ edgeIndex: number; intersectionPoint: Vertex }> {
953
+ // Find the intersections of all lines inside the edge bounds
954
+ const intersectionPoints: Array<{ edgeIndex: number; intersectionPoint: Vertex }> = [];
955
+ var n = isOpen ? vertices.length - 1 : vertices.length;
956
+ for (var i = 0; i < n; i++) {
957
+ const polyLine = new Line(vertices[i % n], vertices[(i + 1) % n]);
958
+ const intersection = polyLine.intersection(line);
959
+ // true => only inside bounds
960
+ // ignore last edge if open
961
+ if (
962
+ intersection !== null &&
963
+ polyLine.hasPoint(intersection, true) &&
964
+ (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))
965
+ ) {
966
+ intersectionPoints.push({ edgeIndex: i, intersectionPoint: intersection });
967
+ }
968
+ }
969
+ return intersectionPoints;
889
970
  }
890
971
  };
891
972
  }
@@ -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.intersectionPoint);
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.intersectionPoint) 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
  *