plotboilerplate 1.28.1 → 1.29.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 (66) hide show
  1. package/README.md +8 -0
  2. package/dist/index.esm.js +335 -39
  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 +335 -37
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +1 -1
  11. package/src/cjs/Circle.d.ts +70 -3
  12. package/src/cjs/Circle.js +159 -4
  13. package/src/cjs/Circle.js.map +1 -1
  14. package/src/cjs/Triangle.d.ts +40 -4
  15. package/src/cjs/Triangle.js +127 -31
  16. package/src/cjs/Triangle.js.map +1 -1
  17. package/src/cjs/VertTuple.d.ts +4 -1
  18. package/src/cjs/VertTuple.js +6 -1
  19. package/src/cjs/VertTuple.js.map +1 -1
  20. package/src/cjs/Vertex.d.ts +25 -2
  21. package/src/cjs/Vertex.js +43 -1
  22. package/src/cjs/Vertex.js.map +1 -1
  23. package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.d.ts +21 -0
  24. package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.js +73 -0
  25. package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.js.map +1 -0
  26. package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.d.ts +21 -0
  27. package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.js +73 -0
  28. package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.js.map +1 -0
  29. package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.d.ts +21 -0
  30. package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.js +73 -0
  31. package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.js.map +1 -0
  32. package/src/cjs/utils/algorithms/solveApollonius3.d.ts +69 -0
  33. package/src/cjs/utils/algorithms/solveApollonius3.js +118 -0
  34. package/src/cjs/utils/algorithms/solveApollonius3.js.map +1 -0
  35. package/src/esm/Circle.d.ts +70 -3
  36. package/src/esm/Circle.js +159 -4
  37. package/src/esm/Circle.js.map +1 -1
  38. package/src/esm/Triangle.d.ts +40 -4
  39. package/src/esm/Triangle.js +128 -32
  40. package/src/esm/Triangle.js.map +1 -1
  41. package/src/esm/VertTuple.d.ts +4 -1
  42. package/src/esm/VertTuple.js +6 -1
  43. package/src/esm/VertTuple.js.map +1 -1
  44. package/src/esm/Vertex.d.ts +25 -2
  45. package/src/esm/Vertex.js +44 -2
  46. package/src/esm/Vertex.js.map +1 -1
  47. package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.d.ts +21 -0
  48. package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.js +69 -0
  49. package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.js.map +1 -0
  50. package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.d.ts +21 -0
  51. package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.js +69 -0
  52. package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.js.map +1 -0
  53. package/src/esm/utils/algorithms/pointsMinimalContainingCircle.d.ts +21 -0
  54. package/src/esm/utils/algorithms/pointsMinimalContainingCircle.js +69 -0
  55. package/src/esm/utils/algorithms/pointsMinimalContainingCircle.js.map +1 -0
  56. package/src/esm/utils/algorithms/solveApollonius3.d.ts +69 -0
  57. package/src/esm/utils/algorithms/solveApollonius3.js +114 -0
  58. package/src/esm/utils/algorithms/solveApollonius3.js.map +1 -0
  59. package/src/index-gl.js +5 -2
  60. package/src/index.js +25 -17
  61. package/src/ts/Circle.ts +178 -5
  62. package/src/ts/Triangle.ts +148 -41
  63. package/src/ts/VertTuple.ts +14 -1
  64. package/src/ts/Vertex.ts +44 -2
  65. package/src/ts/utils/algorithms/minimalEnclosingCircleFromPoints.ts +69 -0
  66. package/src/ts/utils/algorithms/solveApollonius3.ts +132 -0
@@ -1742,7 +1742,15 @@ exports.Bounds = Bounds;
1742
1742
  * @modified 2022-08-23 Added the `closestPoint` function.
1743
1743
  * @modified 2025-04-09 Added the `Circle.move(amount: XYCoords)` method.
1744
1744
  * @modified 2025-04-16 Class `Circle` now implements interface `Intersectable`.
1745
- * @version 1.5.0
1745
+ * @modified 2026-06-10 Adding the utility function `Circle.circleUtils.containsPoint`.
1746
+ * @modified 2026-06-10 Adding the `Circle.clone` method.
1747
+ * @modified 2026-01-13 Adding helper function `Circle.circleUtils.containsPoint` and refactored the member method `containsPoint`.
1748
+ * @modified 2026-07-03 Adding the optional `epsilon` parameter to the `Circle.containsCircle` method.
1749
+ * @modified 2026-07-03 Fixing the `Circle.clone` method; the center had not been cloned at all, this was fixed.
1750
+ * @modified 2026-07-08 Adding the `Circle.setRadius` method (for chaining).
1751
+ * @mofified 2026-07-31 Adding the `radicalAxis(Circle)` method. Added the `Circle.circleUtils.createRadicalAxisHelperCircle` and `.circleDistance` helper methods.
1752
+ * @modified 2026-08-03 Adding `Circle.tangentsFromPoint`.
1753
+ * @version 1.7.0
1746
1754
  **/
1747
1755
  Object.defineProperty(exports, "__esModule", ({ value: true }));
1748
1756
  exports.Circle = void 0;
@@ -1751,6 +1759,7 @@ var Line_1 = __webpack_require__(939);
1751
1759
  var UIDGenerator_1 = __webpack_require__(938);
1752
1760
  var Vector_1 = __webpack_require__(30);
1753
1761
  var Vertex_1 = __webpack_require__(787);
1762
+ var geomutils_1 = __webpack_require__(328);
1754
1763
  /**
1755
1764
  * @classdesc A simple circle: center point and radius.
1756
1765
  *
@@ -1780,6 +1789,20 @@ var Circle = /** @class */ (function () {
1780
1789
  this.center = center;
1781
1790
  this.radius = radius;
1782
1791
  }
1792
+ /**
1793
+ * Set the radius of this circle.
1794
+ * The method is meant for chaining, you may also alter the `radius` attribute directly.
1795
+ *
1796
+ * @method setRadius
1797
+ * @param {number} radius - The amount to move.
1798
+ * @instance
1799
+ * @memberof Circle
1800
+ * @return {Circle} this for chaining
1801
+ **/
1802
+ Circle.prototype.setRadius = function (radius) {
1803
+ this.radius = radius;
1804
+ return this;
1805
+ };
1783
1806
  /**
1784
1807
  * Move the circle by the given amount.
1785
1808
  *
@@ -1803,7 +1826,8 @@ var Circle = /** @class */ (function () {
1803
1826
  * @return {boolean} `true` if the given point is inside this circle.
1804
1827
  */
1805
1828
  Circle.prototype.containsPoint = function (point) {
1806
- return this.center.distance(point) < this.radius;
1829
+ // return this.center.distance(point) < this.radius;//
1830
+ return Circle.circleUtils.containsPoint(this.center, this.radius, point);
1807
1831
  };
1808
1832
  /**
1809
1833
  * Check if the given circle is fully contained inside this circle.
@@ -1814,8 +1838,13 @@ var Circle = /** @class */ (function () {
1814
1838
  * @memberof Circle
1815
1839
  * @return {boolean} `true` if any only if the given circle is completely inside this circle.
1816
1840
  */
1817
- Circle.prototype.containsCircle = function (circle) {
1818
- return this.center.distance(circle.center) + circle.radius < this.radius;
1841
+ Circle.prototype.containsCircle = function (circle, epsilon) {
1842
+ if (typeof epsilon === "undefined" || Number.isNaN(epsilon)) {
1843
+ return this.center.distance(circle.center) + circle.radius < this.radius;
1844
+ }
1845
+ else {
1846
+ return this.center.distance(circle.center) + circle.radius < this.radius + Math.abs(epsilon);
1847
+ }
1819
1848
  };
1820
1849
  /**
1821
1850
  * Calculate the distance from this circle to the given line.
@@ -2021,6 +2050,40 @@ var Circle = /** @class */ (function () {
2021
2050
  });
2022
2051
  };
2023
2052
  //--- END --- Implement interface `Intersectable`
2053
+ /**
2054
+ * Calculate the radical axis of this and a different circle.
2055
+ * The two circles must not be co-centric.
2056
+ *
2057
+ * See this article for details:
2058
+ * https://www.cut-the-knot.org/Curriculum/Geometry/GeoGebra/RadicalAxes.shtml
2059
+ *
2060
+ * @method radicalAxis
2061
+ * @instance
2062
+ * @memberof Circle
2063
+ * @param {Circle} circleB - The second circle to calculated the radical axis for.
2064
+ * @return {Line} A line defining the radical axis of the two circles.
2065
+ **/
2066
+ Circle.prototype.radicalAxis = function (circleB) {
2067
+ var helperCircle = Circle.circleUtils.createRadicalAxisHelperCircle(this, circleB);
2068
+ var intersectionLineA = this.circleIntersection(helperCircle);
2069
+ var intersectionLineB = circleB.circleIntersection(helperCircle);
2070
+ var intersection = this.circleIntersection(circleB);
2071
+ if (!intersectionLineA || !intersectionLineB) {
2072
+ console.error("Critical error: none of the two intersections must be null.");
2073
+ return intersection; // Fallback
2074
+ }
2075
+ var lineA = new Line_1.Line(intersectionLineA.a, intersectionLineA.b);
2076
+ var lineB = new Line_1.Line(intersectionLineB.a, intersectionLineB.b);
2077
+ var firstRadicalAxisPoint = lineA.intersection(lineB);
2078
+ var centerConnectLine = new Line_1.Line(this.center, circleB.center);
2079
+ var secondRadicalAxisPoint = centerConnectLine.getClosestPoint(firstRadicalAxisPoint);
2080
+ // Create a mirrored version of the second radical axis point so both are located
2081
+ // symmetrical from the circle connect point.
2082
+ // (currently the second point is located ON the connect line)
2083
+ var secondRadicalAxisPoint_mirrored = secondRadicalAxisPoint.clone().scale(2.0, firstRadicalAxisPoint);
2084
+ var radicalAxis = new Line_1.Line(firstRadicalAxisPoint, secondRadicalAxisPoint_mirrored);
2085
+ return intersection && intersection.length() > radicalAxis.length() ? intersection : radicalAxis;
2086
+ };
2024
2087
  /**
2025
2088
  * Calculate the closest point on the outline of this circle to the given point.
2026
2089
  *
@@ -2044,6 +2107,71 @@ var Circle = /** @class */ (function () {
2044
2107
  return lineIntersection.b;
2045
2108
  }
2046
2109
  };
2110
+ /**
2111
+ * Get the two tangent vectors for the given point.
2112
+ * If the point is on or in the circle then null is returned.
2113
+ *
2114
+ * @method tangentsFromPoint
2115
+ * @instance
2116
+ * @memberof Circle
2117
+ * @param {Vertex} vert - The point to find the two tangents for.
2118
+ * @return {[Vector,Vector]} The two tangent vector
2119
+ **/
2120
+ Circle.prototype.tangentsFromPoint = function (vert) {
2121
+ // Inspired by
2122
+ // https://www.omnicalculator.com/math/tangent-circle
2123
+ var centerDistance = this.center.distance(vert);
2124
+ var tangentLength = Math.sqrt(centerDistance * centerDistance - this.radius * this.radius);
2125
+ // console.log("this.radius ", this.radius, "centerDistance", centerDistance, "tangentLength", tangentLength);
2126
+ if (Number.isNaN(tangentLength)) {
2127
+ // vertex is inside circle
2128
+ console.log("tangentLength is NaN", tangentLength);
2129
+ return null;
2130
+ }
2131
+ var helperCircle = new Circle(vert, tangentLength);
2132
+ var intersection = this.circleIntersection(helperCircle);
2133
+ if (!intersection) {
2134
+ // No intersection (vertex is inside circle)
2135
+ return null;
2136
+ }
2137
+ return [new Vector_1.Vector(intersection.a, vert), new Vector_1.Vector(intersection.b, vert)];
2138
+ };
2139
+ /**
2140
+ * Create a deep copy of this circle.
2141
+ *
2142
+ * @method clone
2143
+ * @return {Circle} A new circle, an exact copy of this one.
2144
+ * @instance
2145
+ * @memberof Circle
2146
+ **/
2147
+ Circle.prototype.clone = function () {
2148
+ return new Circle(this.center.clone(), this.radius);
2149
+ };
2150
+ Circle.fromICircle = function (obj) {
2151
+ return new Circle(new Vertex_1.Vertex(obj.center), obj.radius);
2152
+ };
2153
+ // static fromObject(obj: object): Circle {
2154
+ // if (!obj) {
2155
+ // return null;
2156
+ // }
2157
+ // if (typeof obj !== "object") {
2158
+ // return null;
2159
+ // }
2160
+ // if (!obj.hasOwnProperty("center") || typeof (obj as any).center != "object") {
2161
+ // return null;
2162
+ // }
2163
+ // if (!obj.hasOwnProperty("radius") || typeof !(obj as any).radius != "number") {
2164
+ // return null;
2165
+ // }
2166
+ // var center = (obj as any).center;
2167
+ // if (!center.hasOwnProperty("x") || typeof (center as any).x != "number") {
2168
+ // return null;
2169
+ // }
2170
+ // if (!center.hasOwnProperty("y") || typeof (center as any).y != "number") {
2171
+ // return null;
2172
+ // }
2173
+ // return new Circle(new Vertex(center), (obj as any).radius);
2174
+ // }
2047
2175
  /**
2048
2176
  * This function should invalidate any installed listeners and invalidate this object.
2049
2177
  * After calling this function the object might not hold valid data any more and
@@ -2058,6 +2186,33 @@ var Circle = /** @class */ (function () {
2058
2186
  /* return new Vertex( Math.sin(angle) * radius,
2059
2187
  Math.cos(angle) * radius ); */
2060
2188
  return new Vertex_1.Vertex(Math.cos(angle) * radius, Math.sin(angle) * radius);
2189
+ },
2190
+ containsPoint: function (circleCenter, circleRadius, point) {
2191
+ // TODO: cleanup
2192
+ // return (
2193
+ // (circle.center.x - point.x) * (circle.center.x - point.x) + (circle.center.y - point.y) * (circle.center.y - point.y) <=
2194
+ // circle.radius * circle.radius
2195
+ // );
2196
+ return geomutils_1.geomutils.dist4(point.x, point.y, circleCenter.x, circleCenter.y) < circleRadius;
2197
+ },
2198
+ createRadicalAxisHelperCircle: function (circleA, circleB) {
2199
+ // We need to create a helper circle that intersects BOTH other circles,
2200
+ // each in TWO points.
2201
+ var circleConnectLine = new Vector_1.Vector(circleA.center.clone(), circleB.center);
2202
+ circleConnectLine.a.set(circleConnectLine.vertAt(0.5));
2203
+ // Get the perpendicular by half the circle distance.
2204
+ var bisector = circleConnectLine.perp();
2205
+ var bisectorLength = Math.max(circleA.radius, circleB.radius, bisector.length());
2206
+ bisector.setLength(bisectorLength);
2207
+ return new Circle(bisector.b, bisector.b.distance(circleA.center));
2208
+ },
2209
+ /**
2210
+ * Calculate the outer distance between two circles. If the circles touch then the
2211
+ * distance is 0.0.
2212
+ * If the circles intersect then the distance in negative.
2213
+ */
2214
+ circleDistance: function (circleA, circleB) {
2215
+ return circleA.center.distance(circleB.center) - circleA.radius - circleB.radius;
2061
2216
  }
2062
2217
  };
2063
2218
  return Circle;
@@ -8122,7 +8277,8 @@ exports["default"] = PlotBoilerplate;
8122
8277
  * @modified 2025-03-31 Added the `VertTuple.revert` method.
8123
8278
  * @modified 2025-04-15 Changed param of `VertTuple.moveTo` method from `Vertex` to `XYCoords`.
8124
8279
  * @modified 2025-04-15 Added method `VertTuple.move` method.
8125
- * @version 1.4.0
8280
+ * @modified 2026-06-10 Adding helper function `VertTuple.utils.calcCircumcircle`.
8281
+ * @version 1.5.0
8126
8282
  */
8127
8283
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8128
8284
  exports.VertTuple = void 0;
@@ -8445,6 +8601,10 @@ var VertTuple = /** @class */ (function () {
8445
8601
  VertTuple.vtutils = {
8446
8602
  dist2: function (v, w) {
8447
8603
  return (v.x - w.x) * (v.x - w.x) + (v.y - w.y) * (v.y - w.y);
8604
+ },
8605
+ calcCircumcircle: function (p1, p2) {
8606
+ var p1x = p1.x, p1y = p1.y, p2x = p2.x, p2y = p2.y, cx = 0.5 * (p1x + p2x), cy = 0.5 * (p1y + p2y);
8607
+ return { center: { x: cx, y: cy }, radius: Math.sqrt((p1x - cx) * (p1x - cx) + (p1y - cy) * (p1y - cy)) };
8448
8608
  }
8449
8609
  };
8450
8610
  return VertTuple;
@@ -11479,7 +11639,10 @@ exports.BezierPath = BezierPath;
11479
11639
  * @modified 2025-14-16 Class `Triangle` now implements interface `IBounded`.
11480
11640
  * @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.
11481
11641
  * @modified 2025-14-16 Added method `Triangle.move`.
11482
- * @version 2.10.0
11642
+ * @modified 2026-06-10 Refactoring the `Trianble.bounds` method and added a plain `Triangle.utils.bounds` method.
11643
+ * @modified 2026-06-10 Refactoring the `Trianble.calcCircumCircle` method and added a plain `Triangle.utils.calcCircumCircle` method.
11644
+ * @modified 2026-06-13 Adding `Triangle.getVertices()`.
11645
+ * @version 2.11.0
11483
11646
  *
11484
11647
  * @file Triangle
11485
11648
  * @fileoverview A simple triangle class: three vertices.
@@ -11493,6 +11656,7 @@ var Line_1 = __webpack_require__(939);
11493
11656
  var Polygon_1 = __webpack_require__(687);
11494
11657
  var UIDGenerator_1 = __webpack_require__(938);
11495
11658
  var Vector_1 = __webpack_require__(30);
11659
+ var VertTuple_1 = __webpack_require__(590);
11496
11660
  var Vertex_1 = __webpack_require__(787);
11497
11661
  var geomutils_1 = __webpack_require__(328);
11498
11662
  /**
@@ -11634,7 +11798,7 @@ var Triangle = /** @class */ (function () {
11634
11798
  * after triangle vertex changes.
11635
11799
  *
11636
11800
  * @method getCircumcircle
11637
- * @return {Object} - { center:Vertex, radius:float }
11801
+ * @return {Circle} - The circle touching exactly all three triangle vertices.
11638
11802
  * @instance
11639
11803
  * @memberof Triangle
11640
11804
  */
@@ -11643,6 +11807,33 @@ var Triangle = /** @class */ (function () {
11643
11807
  this.calcCircumcircle();
11644
11808
  return new Circle_1.Circle(this.center.clone(), this.radius);
11645
11809
  };
11810
+ /**
11811
+ * Calculates the minimun enclosing circle.
11812
+ *
11813
+ * @method getMinimumEnclosingCircle
11814
+ * @return {Object} - { center:Vertex, radius:float }
11815
+ * @instance
11816
+ * @memberof Triangle
11817
+ * @returns
11818
+ */
11819
+ Triangle.prototype.getMinimumEnclosingCircle = function () {
11820
+ // First option: two points construct a circle and the third point is contained.
11821
+ var circleAB = VertTuple_1.VertTuple.vtutils.calcCircumcircle(this.a, this.b);
11822
+ if (Circle_1.Circle.circleUtils.containsPoint(circleAB.center, circleAB.radius, this.c)) {
11823
+ return Circle_1.Circle.fromICircle(circleAB);
11824
+ }
11825
+ var circleBC = VertTuple_1.VertTuple.vtutils.calcCircumcircle(this.b, this.c);
11826
+ if (Circle_1.Circle.circleUtils.containsPoint(circleBC.center, circleBC.radius, this.c)) {
11827
+ return Circle_1.Circle.fromICircle(circleBC);
11828
+ }
11829
+ var circleCA = VertTuple_1.VertTuple.vtutils.calcCircumcircle(this.c, this.a);
11830
+ if (Circle_1.Circle.circleUtils.containsPoint(circleCA.center, circleCA.radius, this.c)) {
11831
+ return Circle_1.Circle.fromICircle(circleCA);
11832
+ }
11833
+ // If none of the three upper cases applies: return the circumcircle.
11834
+ var circumCircle = Triangle.utils.calcCircumcircle(this.a, this.b, this.c);
11835
+ return Circle_1.Circle.fromICircle(circumCircle);
11836
+ };
11646
11837
  /**
11647
11838
  * Check if this triangle and the passed triangle share an
11648
11839
  * adjacent edge.
@@ -11681,6 +11872,17 @@ var Triangle = /** @class */ (function () {
11681
11872
  //if( this.c.equals(vert1) && this.a.equals(vert2) || this.c.equals(vert2) && this.a.equals(vert1) )
11682
11873
  return this.b;
11683
11874
  };
11875
+ /**
11876
+ * Get the three triangele vertices in a 3-element array.
11877
+ *
11878
+ * @method getVertices
11879
+ * @returns {[Vertex, Vertex, Vertex]} - The three vertices – real instances, not copies.
11880
+ * @instance
11881
+ * @memberof Triangle
11882
+ */
11883
+ Triangle.prototype.getVertices = function () {
11884
+ return [this.a, this.b, this.c];
11885
+ };
11684
11886
  /**
11685
11887
  * Re-compute the circumcircle of this triangle (if the vertices
11686
11888
  * have changed).
@@ -11694,32 +11896,35 @@ var Triangle = /** @class */ (function () {
11694
11896
  * @memberof Triangle
11695
11897
  */
11696
11898
  Triangle.prototype.calcCircumcircle = function () {
11697
- // From
11698
- // http://www.exaflop.org/docs/cgafaq/cga1.html
11699
- var A = this.b.x - this.a.x;
11700
- var B = this.b.y - this.a.y;
11701
- var C = this.c.x - this.a.x;
11702
- var D = this.c.y - this.a.y;
11703
- var E = A * (this.a.x + this.b.x) + B * (this.a.y + this.b.y);
11704
- var F = C * (this.a.x + this.c.x) + D * (this.a.y + this.c.y);
11705
- var G = 2.0 * (A * (this.c.y - this.b.y) - B * (this.c.x - this.b.x));
11706
- var dx, dy;
11707
- if (Math.abs(G) < Triangle.EPSILON) {
11708
- // Collinear - find extremes and use the midpoint
11709
- var bounds = this.bounds();
11710
- this.center = new Vertex_1.Vertex((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2);
11711
- dx = this.center.x - bounds.min.x;
11712
- dy = this.center.y - bounds.min.y;
11713
- }
11714
- else {
11715
- var cx = (D * E - B * F) / G;
11716
- var cy = (A * F - C * E) / G;
11717
- this.center = new Vertex_1.Vertex(cx, cy);
11718
- dx = this.center.x - this.a.x;
11719
- dy = this.center.y - this.a.y;
11720
- }
11721
- this.radius_squared = dx * dx + dy * dy;
11722
- this.radius = Math.sqrt(this.radius_squared);
11899
+ // // From
11900
+ // // http://www.exaflop.org/docs/cgafaq/cga1.html
11901
+ // const A: number = this.b.x - this.a.x;
11902
+ // const B: number = this.b.y - this.a.y;
11903
+ // const C: number = this.c.x - this.a.x;
11904
+ // const D: number = this.c.y - this.a.y;
11905
+ // const E: number = A * (this.a.x + this.b.x) + B * (this.a.y + this.b.y);
11906
+ // const F: number = C * (this.a.x + this.c.x) + D * (this.a.y + this.c.y);
11907
+ // const G: number = 2.0 * (A * (this.c.y - this.b.y) - B * (this.c.x - this.b.x));
11908
+ // let dx: number, dy: number;
11909
+ // if (Math.abs(G) < Triangle.EPSILON) {
11910
+ // // Collinear - find extremes and use the midpoint
11911
+ // const bounds: Bounds = this.bounds();
11912
+ // this.center = new Vertex((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2);
11913
+ // dx = this.center.x - bounds.min.x;
11914
+ // dy = this.center.y - bounds.min.y;
11915
+ // } else {
11916
+ // const cx: number = (D * E - B * F) / G;
11917
+ // const cy: number = (A * F - C * E) / G;
11918
+ // this.center = new Vertex(cx, cy);
11919
+ // dx = this.center.x - this.a.x;
11920
+ // dy = this.center.y - this.a.y;
11921
+ // }
11922
+ // this.radius_squared = dx * dx + dy * dy;
11923
+ // this.radius = Math.sqrt(this.radius_squared);
11924
+ var tmpCircle = Triangle.utils.calcCircumcircle(this.a, this.b, this.c);
11925
+ this.center = new Vertex_1.Vertex(tmpCircle.center.x, tmpCircle.center.y);
11926
+ this.radius = tmpCircle.radius;
11927
+ this.radius_squared = tmpCircle.radius_squared;
11723
11928
  }; // END calcCircumcircle
11724
11929
  /**
11725
11930
  * Check if the passed vertex is inside this triangle's
@@ -11746,7 +11951,11 @@ var Triangle = /** @class */ (function () {
11746
11951
  * @memberof Triangle
11747
11952
  */
11748
11953
  Triangle.prototype.bounds = function () {
11749
- return new Bounds_1.Bounds(new Vertex_1.Vertex(Triangle.utils.min3(this.a.x, this.b.x, this.c.x), Triangle.utils.min3(this.a.y, this.b.y, this.c.y)), new Vertex_1.Vertex(Triangle.utils.max3(this.a.x, this.b.x, this.c.x), Triangle.utils.max3(this.a.y, this.b.y, this.c.y)));
11954
+ // return new Bounds(
11955
+ // new Vertex(Triangle.utils.min3(this.a.x, this.b.x, this.c.x), Triangle.utils.min3(this.a.y, this.b.y, this.c.y)),
11956
+ // new Vertex(Triangle.utils.max3(this.a.x, this.b.x, this.c.x), Triangle.utils.max3(this.a.y, this.b.y, this.c.y))
11957
+ // );
11958
+ return Triangle.utils.bounds(this.a, this.b, this.c);
11750
11959
  };
11751
11960
  //--- BEGIN --- Implement interface `Intersectable`
11752
11961
  /**
@@ -11872,8 +12081,9 @@ var Triangle = /** @class */ (function () {
11872
12081
  * @return Vertex The incenter of this triangle.
11873
12082
  **/
11874
12083
  Triangle.prototype.getIncenter = function () {
11875
- if (!this.center || !this.radius)
12084
+ if (!this.center || !this.radius) {
11876
12085
  this.calcCircumcircle();
12086
+ }
11877
12087
  return this.center.clone();
11878
12088
  };
11879
12089
  /**
@@ -11940,7 +12150,53 @@ var Triangle = /** @class */ (function () {
11940
12150
  */
11941
12151
  determinant: function (a, b, c) {
11942
12152
  return (b.y - a.y) * (c.x - b.x) - (c.y - b.y) * (b.x - a.x);
11943
- }
12153
+ },
12154
+ bounds: function (a, b, c) {
12155
+ return new Bounds_1.Bounds(new Vertex_1.Vertex(Triangle.utils.min3(a.x, b.x, c.x), Triangle.utils.min3(a.y, b.y, c.y)), new Vertex_1.Vertex(Triangle.utils.max3(a.x, b.x, c.x), Triangle.utils.max3(a.y, b.y, c.y)));
12156
+ },
12157
+ /**
12158
+ * Re-compute the circumcircle of this triangle (if the vertices
12159
+ * have changed).
12160
+ *
12161
+ * The circumcenter and radius are stored in this.center and
12162
+ * this.radius. There is a third result: radius_squared (for internal computations).
12163
+ *
12164
+ * @method calcCircumcircle
12165
+ * @return void
12166
+ * @instance
12167
+ * @memberof Triangle
12168
+ */
12169
+ calcCircumcircle: function (a, b, c) {
12170
+ // From
12171
+ // http://www.exaflop.org/docs/cgafaq/cga1.html
12172
+ var A = b.x - a.x;
12173
+ var B = b.y - a.y;
12174
+ var C = c.x - a.x;
12175
+ var D = c.y - a.y;
12176
+ var E = A * (a.x + b.x) + B * (a.y + b.y);
12177
+ var F = C * (a.x + c.x) + D * (a.y + c.y);
12178
+ var G = 2.0 * (A * (c.y - b.y) - B * (c.x - b.x));
12179
+ var dx, dy;
12180
+ var center;
12181
+ if (Math.abs(G) < Triangle.EPSILON) {
12182
+ // Collinear - find extremes and use the midpoint
12183
+ // const bounds: Bounds = this.bounds();
12184
+ var bounds = Triangle.utils.bounds(a, b, c);
12185
+ center = new Vertex_1.Vertex((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2);
12186
+ dx = center.x - bounds.min.x;
12187
+ dy = center.y - bounds.min.y;
12188
+ }
12189
+ else {
12190
+ var cx = (D * E - B * F) / G;
12191
+ var cy = (A * F - C * E) / G;
12192
+ center = new Vertex_1.Vertex(cx, cy);
12193
+ dx = center.x - a.x;
12194
+ dy = center.y - a.y;
12195
+ }
12196
+ var radius_squared = dx * dx + dy * dy;
12197
+ var radius = Math.sqrt(radius_squared);
12198
+ return { center: center, radius: radius, radius_squared: radius_squared };
12199
+ } // END calcCircumcircle
11944
12200
  };
11945
12201
  return Triangle;
11946
12202
  }());
@@ -11991,7 +12247,8 @@ exports.Triangle = Triangle;
11991
12247
  * @modified 2025-03-24 Making the second parameter `center` of the `Vertex.rotate` method optional.
11992
12248
  * @modified 2025-04-13 Adding the `Vertex.move(amount: XYCoords)` method (does the same as `add`, added by naming convention).
11993
12249
  * @modified 2025-05-07 Class `Vertex` is now implementing interface `IBounded` (to meet convention).
11994
- * @version 2.11.0
12250
+ * @modified 2026-06-10 Adding methods `Vertex.findClosestPoint` and `Vertex.findFarestPoint`.
12251
+ * @version 2.12.0
11995
12252
  *
11996
12253
  * @file Vertex
11997
12254
  * @public
@@ -12558,6 +12815,47 @@ var Vertex = /** @class */ (function () {
12558
12815
  return Bounds_1.Bounds.computeFromVertices([this]);
12559
12816
  };
12560
12817
  //--- END --- Implement interface `IBounded`
12818
+ /**
12819
+ * Find the one of two given points that's closest to this point.
12820
+ *
12821
+ * @method findClosestPoint
12822
+ * @instance
12823
+ * @memberof Vertex
12824
+ * @param {XYCoords | Vertex} pointA
12825
+ * @param {XYCoords | Vertex} pointB
12826
+ * @returns {XYCoords | Vertex}
12827
+ */
12828
+ Vertex.prototype.findClosestPoint = function (pointA, pointB) {
12829
+ // TODO: put this implementation to geomutils?
12830
+ var distA = this.distance(pointA);
12831
+ var distB = this.distance(pointB);
12832
+ if (distA < distB) {
12833
+ return pointA;
12834
+ }
12835
+ else {
12836
+ return pointB;
12837
+ }
12838
+ };
12839
+ /**
12840
+ * Find the one of two given points that's farest from this point.
12841
+ *
12842
+ * @method findFarestPoint
12843
+ * @instance
12844
+ * @memberof Vertex
12845
+ * @param {XYCoords | Vertex} pointA
12846
+ * @param {XYCoords | Vertex} pointB
12847
+ * @returns {XYCoords | Vertex}
12848
+ */
12849
+ Vertex.prototype.findFarestPoint = function (pointA, pointB) {
12850
+ var distA = this.distance(pointA);
12851
+ var distB = this.distance(pointB);
12852
+ if (distA > distB) {
12853
+ return pointA;
12854
+ }
12855
+ else {
12856
+ return pointB;
12857
+ }
12858
+ };
12561
12859
  /**
12562
12860
  * Get a string representation of this vertex.
12563
12861
  *