plotboilerplate 1.28.1 → 1.30.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.
- package/README.md +8 -0
- package/dist/index.esm.js +527 -53
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/plotboilerplate.browser.min.js +1 -1
- package/dist/plotboilerplate.browser.min.js.map +1 -1
- package/dist/plotboilerplate.js +528 -51
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +1 -1
- package/src/cjs/Circle.d.ts +86 -3
- package/src/cjs/Circle.js +179 -4
- package/src/cjs/Circle.js.map +1 -1
- package/src/cjs/CubicBezierCurve.d.ts +34 -3
- package/src/cjs/CubicBezierCurve.js +79 -12
- package/src/cjs/CubicBezierCurve.js.map +1 -1
- package/src/cjs/Line.d.ts +46 -1
- package/src/cjs/Line.js +80 -1
- package/src/cjs/Line.js.map +1 -1
- package/src/cjs/Triangle.d.ts +40 -4
- package/src/cjs/Triangle.js +127 -31
- package/src/cjs/Triangle.js.map +1 -1
- package/src/cjs/VertTuple.d.ts +16 -2
- package/src/cjs/VertTuple.js +20 -2
- package/src/cjs/VertTuple.js.map +1 -1
- package/src/cjs/Vertex.d.ts +25 -2
- package/src/cjs/Vertex.js +43 -1
- package/src/cjs/Vertex.js.map +1 -1
- package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.d.ts +21 -0
- package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.js +73 -0
- package/src/cjs/utils/algorithms/minimalContainingCircleFromPoints.js.map +1 -0
- package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.d.ts +21 -0
- package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.js +73 -0
- package/src/cjs/utils/algorithms/minimalEnclosingCircleFromPoints.js.map +1 -0
- package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.d.ts +21 -0
- package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.js +73 -0
- package/src/cjs/utils/algorithms/pointsMinimalContainingCircle.js.map +1 -0
- package/src/cjs/utils/algorithms/solveApollonius3.d.ts +69 -0
- package/src/cjs/utils/algorithms/solveApollonius3.js +118 -0
- package/src/cjs/utils/algorithms/solveApollonius3.js.map +1 -0
- package/src/esm/Circle.d.ts +86 -3
- package/src/esm/Circle.js +179 -4
- package/src/esm/Circle.js.map +1 -1
- package/src/esm/CubicBezierCurve.d.ts +34 -3
- package/src/esm/CubicBezierCurve.js +79 -12
- package/src/esm/CubicBezierCurve.js.map +1 -1
- package/src/esm/Line.d.ts +46 -1
- package/src/esm/Line.js +80 -1
- package/src/esm/Line.js.map +1 -1
- package/src/esm/Triangle.d.ts +40 -4
- package/src/esm/Triangle.js +128 -32
- package/src/esm/Triangle.js.map +1 -1
- package/src/esm/VertTuple.d.ts +16 -2
- package/src/esm/VertTuple.js +20 -2
- package/src/esm/VertTuple.js.map +1 -1
- package/src/esm/Vertex.d.ts +25 -2
- package/src/esm/Vertex.js +44 -2
- package/src/esm/Vertex.js.map +1 -1
- package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.d.ts +21 -0
- package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.js +69 -0
- package/src/esm/utils/algorithms/minimalContainingCircleFromPoints.js.map +1 -0
- package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.d.ts +21 -0
- package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.js +69 -0
- package/src/esm/utils/algorithms/minimalEnclosingCircleFromPoints.js.map +1 -0
- package/src/esm/utils/algorithms/pointsMinimalContainingCircle.d.ts +21 -0
- package/src/esm/utils/algorithms/pointsMinimalContainingCircle.js +69 -0
- package/src/esm/utils/algorithms/pointsMinimalContainingCircle.js.map +1 -0
- package/src/esm/utils/algorithms/solveApollonius3.d.ts +69 -0
- package/src/esm/utils/algorithms/solveApollonius3.js +114 -0
- package/src/esm/utils/algorithms/solveApollonius3.js.map +1 -0
- package/src/index-gl.js +6 -4
- package/src/index.js +25 -17
- package/src/ts/Circle.ts +200 -5
- package/src/ts/CubicBezierCurve.ts +133 -48
- package/src/ts/Line.ts +84 -1
- package/src/ts/Triangle.ts +148 -41
- package/src/ts/VertTuple.ts +29 -2
- package/src/ts/Vertex.ts +44 -2
- package/src/ts/utils/algorithms/minimalEnclosingCircleFromPoints.ts +69 -0
- package/src/ts/utils/algorithms/solveApollonius3.ts +132 -0
package/dist/plotboilerplate.js
CHANGED
|
@@ -1742,7 +1742,16 @@ 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
|
-
* @
|
|
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
|
+
* @modified 2026-08-16 Adding the `Circle.sectorAngleByArcLength` method and the `Circle.circleUtils.sectorAngleByArcLength` helper method.
|
|
1754
|
+
* @version 1.8.0
|
|
1746
1755
|
**/
|
|
1747
1756
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1748
1757
|
exports.Circle = void 0;
|
|
@@ -1751,6 +1760,7 @@ var Line_1 = __webpack_require__(939);
|
|
|
1751
1760
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
1752
1761
|
var Vector_1 = __webpack_require__(30);
|
|
1753
1762
|
var Vertex_1 = __webpack_require__(787);
|
|
1763
|
+
var geomutils_1 = __webpack_require__(328);
|
|
1754
1764
|
/**
|
|
1755
1765
|
* @classdesc A simple circle: center point and radius.
|
|
1756
1766
|
*
|
|
@@ -1780,6 +1790,20 @@ var Circle = /** @class */ (function () {
|
|
|
1780
1790
|
this.center = center;
|
|
1781
1791
|
this.radius = radius;
|
|
1782
1792
|
}
|
|
1793
|
+
/**
|
|
1794
|
+
* Set the radius of this circle.
|
|
1795
|
+
* The method is meant for chaining, you may also alter the `radius` attribute directly.
|
|
1796
|
+
*
|
|
1797
|
+
* @method setRadius
|
|
1798
|
+
* @param {number} radius - The amount to move.
|
|
1799
|
+
* @instance
|
|
1800
|
+
* @memberof Circle
|
|
1801
|
+
* @return {Circle} this for chaining
|
|
1802
|
+
**/
|
|
1803
|
+
Circle.prototype.setRadius = function (radius) {
|
|
1804
|
+
this.radius = radius;
|
|
1805
|
+
return this;
|
|
1806
|
+
};
|
|
1783
1807
|
/**
|
|
1784
1808
|
* Move the circle by the given amount.
|
|
1785
1809
|
*
|
|
@@ -1803,7 +1827,8 @@ var Circle = /** @class */ (function () {
|
|
|
1803
1827
|
* @return {boolean} `true` if the given point is inside this circle.
|
|
1804
1828
|
*/
|
|
1805
1829
|
Circle.prototype.containsPoint = function (point) {
|
|
1806
|
-
return this.center.distance(point) < this.radius
|
|
1830
|
+
// return this.center.distance(point) < this.radius;//
|
|
1831
|
+
return Circle.circleUtils.containsPoint(this.center, this.radius, point);
|
|
1807
1832
|
};
|
|
1808
1833
|
/**
|
|
1809
1834
|
* Check if the given circle is fully contained inside this circle.
|
|
@@ -1814,8 +1839,13 @@ var Circle = /** @class */ (function () {
|
|
|
1814
1839
|
* @memberof Circle
|
|
1815
1840
|
* @return {boolean} `true` if any only if the given circle is completely inside this circle.
|
|
1816
1841
|
*/
|
|
1817
|
-
Circle.prototype.containsCircle = function (circle) {
|
|
1818
|
-
|
|
1842
|
+
Circle.prototype.containsCircle = function (circle, epsilon) {
|
|
1843
|
+
if (typeof epsilon === "undefined" || Number.isNaN(epsilon)) {
|
|
1844
|
+
return this.center.distance(circle.center) + circle.radius < this.radius;
|
|
1845
|
+
}
|
|
1846
|
+
else {
|
|
1847
|
+
return this.center.distance(circle.center) + circle.radius < this.radius + Math.abs(epsilon);
|
|
1848
|
+
}
|
|
1819
1849
|
};
|
|
1820
1850
|
/**
|
|
1821
1851
|
* Calculate the distance from this circle to the given line.
|
|
@@ -2021,6 +2051,40 @@ var Circle = /** @class */ (function () {
|
|
|
2021
2051
|
});
|
|
2022
2052
|
};
|
|
2023
2053
|
//--- END --- Implement interface `Intersectable`
|
|
2054
|
+
/**
|
|
2055
|
+
* Calculate the radical axis of this and a different circle.
|
|
2056
|
+
* The two circles must not be co-centric.
|
|
2057
|
+
*
|
|
2058
|
+
* See this article for details:
|
|
2059
|
+
* https://www.cut-the-knot.org/Curriculum/Geometry/GeoGebra/RadicalAxes.shtml
|
|
2060
|
+
*
|
|
2061
|
+
* @method radicalAxis
|
|
2062
|
+
* @instance
|
|
2063
|
+
* @memberof Circle
|
|
2064
|
+
* @param {Circle} circleB - The second circle to calculated the radical axis for.
|
|
2065
|
+
* @return {Line} A line defining the radical axis of the two circles.
|
|
2066
|
+
**/
|
|
2067
|
+
Circle.prototype.radicalAxis = function (circleB) {
|
|
2068
|
+
var helperCircle = Circle.circleUtils.createRadicalAxisHelperCircle(this, circleB);
|
|
2069
|
+
var intersectionLineA = this.circleIntersection(helperCircle);
|
|
2070
|
+
var intersectionLineB = circleB.circleIntersection(helperCircle);
|
|
2071
|
+
var intersection = this.circleIntersection(circleB);
|
|
2072
|
+
if (!intersectionLineA || !intersectionLineB) {
|
|
2073
|
+
console.error("Critical error: none of the two intersections must be null.");
|
|
2074
|
+
return intersection; // Fallback
|
|
2075
|
+
}
|
|
2076
|
+
var lineA = new Line_1.Line(intersectionLineA.a, intersectionLineA.b);
|
|
2077
|
+
var lineB = new Line_1.Line(intersectionLineB.a, intersectionLineB.b);
|
|
2078
|
+
var firstRadicalAxisPoint = lineA.intersection(lineB);
|
|
2079
|
+
var centerConnectLine = new Line_1.Line(this.center, circleB.center);
|
|
2080
|
+
var secondRadicalAxisPoint = centerConnectLine.getClosestPoint(firstRadicalAxisPoint);
|
|
2081
|
+
// Create a mirrored version of the second radical axis point so both are located
|
|
2082
|
+
// symmetrical from the circle connect point.
|
|
2083
|
+
// (currently the second point is located ON the connect line)
|
|
2084
|
+
var secondRadicalAxisPoint_mirrored = secondRadicalAxisPoint.clone().scale(2.0, firstRadicalAxisPoint);
|
|
2085
|
+
var radicalAxis = new Line_1.Line(firstRadicalAxisPoint, secondRadicalAxisPoint_mirrored);
|
|
2086
|
+
return intersection && intersection.length() > radicalAxis.length() ? intersection : radicalAxis;
|
|
2087
|
+
};
|
|
2024
2088
|
/**
|
|
2025
2089
|
* Calculate the closest point on the outline of this circle to the given point.
|
|
2026
2090
|
*
|
|
@@ -2044,6 +2108,80 @@ var Circle = /** @class */ (function () {
|
|
|
2044
2108
|
return lineIntersection.b;
|
|
2045
2109
|
}
|
|
2046
2110
|
};
|
|
2111
|
+
/**
|
|
2112
|
+
* Get the two tangent vectors for the given point.
|
|
2113
|
+
* If the point is on or in the circle then null is returned.
|
|
2114
|
+
*
|
|
2115
|
+
* @method tangentsFromPoint
|
|
2116
|
+
* @instance
|
|
2117
|
+
* @memberof Circle
|
|
2118
|
+
* @param {Vertex} vert - The point to find the two tangents for.
|
|
2119
|
+
* @return {[Vector,Vector]} The two tangent vector
|
|
2120
|
+
**/
|
|
2121
|
+
Circle.prototype.tangentsFromPoint = function (vert) {
|
|
2122
|
+
// Inspired by
|
|
2123
|
+
// https://www.omnicalculator.com/math/tangent-circle
|
|
2124
|
+
var centerDistance = this.center.distance(vert);
|
|
2125
|
+
var tangentLength = Math.sqrt(centerDistance * centerDistance - this.radius * this.radius);
|
|
2126
|
+
// console.log("this.radius ", this.radius, "centerDistance", centerDistance, "tangentLength", tangentLength);
|
|
2127
|
+
if (Number.isNaN(tangentLength)) {
|
|
2128
|
+
// vertex is inside circle
|
|
2129
|
+
console.log("tangentLength is NaN", tangentLength);
|
|
2130
|
+
return null;
|
|
2131
|
+
}
|
|
2132
|
+
var helperCircle = new Circle(vert, tangentLength);
|
|
2133
|
+
var intersection = this.circleIntersection(helperCircle);
|
|
2134
|
+
if (!intersection) {
|
|
2135
|
+
// No intersection (vertex is inside circle)
|
|
2136
|
+
return null;
|
|
2137
|
+
}
|
|
2138
|
+
return [new Vector_1.Vector(intersection.a, vert), new Vector_1.Vector(intersection.b, vert)];
|
|
2139
|
+
};
|
|
2140
|
+
/**
|
|
2141
|
+
* Calculate inner sector angle for this circle and a given circle arc length.
|
|
2142
|
+
*
|
|
2143
|
+
* @param {number} sectorArcLength - The desired arc length (in units).
|
|
2144
|
+
* @returns The sector's inner angle (in radians).
|
|
2145
|
+
*/
|
|
2146
|
+
Circle.prototype.sectorAngleByArcLength = function (sectorArcLength) {
|
|
2147
|
+
return Circle.circleUtils.sectorAngleByArcLength(sectorArcLength, this.radius);
|
|
2148
|
+
};
|
|
2149
|
+
/**
|
|
2150
|
+
* Create a deep copy of this circle.
|
|
2151
|
+
*
|
|
2152
|
+
* @method clone
|
|
2153
|
+
* @return {Circle} A new circle, an exact copy of this one.
|
|
2154
|
+
* @instance
|
|
2155
|
+
* @memberof Circle
|
|
2156
|
+
**/
|
|
2157
|
+
Circle.prototype.clone = function () {
|
|
2158
|
+
return new Circle(this.center.clone(), this.radius);
|
|
2159
|
+
};
|
|
2160
|
+
Circle.fromICircle = function (obj) {
|
|
2161
|
+
return new Circle(new Vertex_1.Vertex(obj.center), obj.radius);
|
|
2162
|
+
};
|
|
2163
|
+
// static fromObject(obj: object): Circle {
|
|
2164
|
+
// if (!obj) {
|
|
2165
|
+
// return null;
|
|
2166
|
+
// }
|
|
2167
|
+
// if (typeof obj !== "object") {
|
|
2168
|
+
// return null;
|
|
2169
|
+
// }
|
|
2170
|
+
// if (!obj.hasOwnProperty("center") || typeof (obj as any).center != "object") {
|
|
2171
|
+
// return null;
|
|
2172
|
+
// }
|
|
2173
|
+
// if (!obj.hasOwnProperty("radius") || typeof !(obj as any).radius != "number") {
|
|
2174
|
+
// return null;
|
|
2175
|
+
// }
|
|
2176
|
+
// var center = (obj as any).center;
|
|
2177
|
+
// if (!center.hasOwnProperty("x") || typeof (center as any).x != "number") {
|
|
2178
|
+
// return null;
|
|
2179
|
+
// }
|
|
2180
|
+
// if (!center.hasOwnProperty("y") || typeof (center as any).y != "number") {
|
|
2181
|
+
// return null;
|
|
2182
|
+
// }
|
|
2183
|
+
// return new Circle(new Vertex(center), (obj as any).radius);
|
|
2184
|
+
// }
|
|
2047
2185
|
/**
|
|
2048
2186
|
* This function should invalidate any installed listeners and invalidate this object.
|
|
2049
2187
|
* After calling this function the object might not hold valid data any more and
|
|
@@ -2058,6 +2196,43 @@ var Circle = /** @class */ (function () {
|
|
|
2058
2196
|
/* return new Vertex( Math.sin(angle) * radius,
|
|
2059
2197
|
Math.cos(angle) * radius ); */
|
|
2060
2198
|
return new Vertex_1.Vertex(Math.cos(angle) * radius, Math.sin(angle) * radius);
|
|
2199
|
+
},
|
|
2200
|
+
containsPoint: function (circleCenter, circleRadius, point) {
|
|
2201
|
+
// TODO: cleanup
|
|
2202
|
+
// return (
|
|
2203
|
+
// (circle.center.x - point.x) * (circle.center.x - point.x) + (circle.center.y - point.y) * (circle.center.y - point.y) <=
|
|
2204
|
+
// circle.radius * circle.radius
|
|
2205
|
+
// );
|
|
2206
|
+
return geomutils_1.geomutils.dist4(point.x, point.y, circleCenter.x, circleCenter.y) < circleRadius;
|
|
2207
|
+
},
|
|
2208
|
+
createRadicalAxisHelperCircle: function (circleA, circleB) {
|
|
2209
|
+
// We need to create a helper circle that intersects BOTH other circles,
|
|
2210
|
+
// each in TWO points.
|
|
2211
|
+
var circleConnectLine = new Vector_1.Vector(circleA.center.clone(), circleB.center);
|
|
2212
|
+
circleConnectLine.a.set(circleConnectLine.vertAt(0.5));
|
|
2213
|
+
// Get the perpendicular by half the circle distance.
|
|
2214
|
+
var bisector = circleConnectLine.perp();
|
|
2215
|
+
var bisectorLength = Math.max(circleA.radius, circleB.radius, bisector.length());
|
|
2216
|
+
bisector.setLength(bisectorLength);
|
|
2217
|
+
return new Circle(bisector.b, bisector.b.distance(circleA.center));
|
|
2218
|
+
},
|
|
2219
|
+
/**
|
|
2220
|
+
* Calculate the outer distance between two circles. If the circles touch then the
|
|
2221
|
+
* distance is 0.0.
|
|
2222
|
+
* If the circles intersect then the distance in negative.
|
|
2223
|
+
*/
|
|
2224
|
+
circleDistance: function (circleA, circleB) {
|
|
2225
|
+
return circleA.center.distance(circleB.center) - circleA.radius - circleB.radius;
|
|
2226
|
+
},
|
|
2227
|
+
/**
|
|
2228
|
+
* Calculate the inner sector angle for a given circle arc length and radius.
|
|
2229
|
+
*
|
|
2230
|
+
* @param {number} sectorArcLength - The desired arc length.
|
|
2231
|
+
* @param {number} circleRadius - The circle's radius.
|
|
2232
|
+
* @returns The sector angle in radians.
|
|
2233
|
+
*/
|
|
2234
|
+
sectorAngleByArcLength: function (sectorArcLength, circleRadius) {
|
|
2235
|
+
return sectorArcLength / circleRadius;
|
|
2061
2236
|
}
|
|
2062
2237
|
};
|
|
2063
2238
|
return Circle;
|
|
@@ -8122,12 +8297,15 @@ exports["default"] = PlotBoilerplate;
|
|
|
8122
8297
|
* @modified 2025-03-31 Added the `VertTuple.revert` method.
|
|
8123
8298
|
* @modified 2025-04-15 Changed param of `VertTuple.moveTo` method from `Vertex` to `XYCoords`.
|
|
8124
8299
|
* @modified 2025-04-15 Added method `VertTuple.move` method.
|
|
8125
|
-
* @
|
|
8300
|
+
* @modified 2026-06-10 Adding helper function `VertTuple.utils.calcCircumcircle`.
|
|
8301
|
+
* @modified 2026-06-17 Adding method `VertTuple.asLine` for converting Vector to Line instances.
|
|
8302
|
+
* @version 1.6.0
|
|
8126
8303
|
*/
|
|
8127
8304
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
8128
8305
|
exports.VertTuple = void 0;
|
|
8129
8306
|
var Vertex_1 = __webpack_require__(787);
|
|
8130
8307
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
8308
|
+
var Line_1 = __webpack_require__(939);
|
|
8131
8309
|
/**
|
|
8132
8310
|
* @classdesc An abstract base classes for vertex tuple constructs, like Lines or Vectors.
|
|
8133
8311
|
* @abstract
|
|
@@ -8410,7 +8588,7 @@ var VertTuple = /** @class */ (function () {
|
|
|
8410
8588
|
/**
|
|
8411
8589
|
* Create a deep clone of this instance.
|
|
8412
8590
|
*
|
|
8413
|
-
* @method
|
|
8591
|
+
* @method clone
|
|
8414
8592
|
* @return {T} A type safe clone if this instance.
|
|
8415
8593
|
* @instance
|
|
8416
8594
|
* @memberof VertTuple
|
|
@@ -8418,6 +8596,17 @@ var VertTuple = /** @class */ (function () {
|
|
|
8418
8596
|
VertTuple.prototype.clone = function () {
|
|
8419
8597
|
return this.factory(this.a.clone(), this.b.clone());
|
|
8420
8598
|
};
|
|
8599
|
+
/**
|
|
8600
|
+
* Converts this `Vector` to a `Line` (segment).
|
|
8601
|
+
*
|
|
8602
|
+
* @method asLine
|
|
8603
|
+
* @return {T} A type safe clone if this instance.
|
|
8604
|
+
* @instance
|
|
8605
|
+
* @memberof VertTuple
|
|
8606
|
+
**/
|
|
8607
|
+
VertTuple.prototype.asLine = function () {
|
|
8608
|
+
return new Line_1.Line(this.a, this.b);
|
|
8609
|
+
};
|
|
8421
8610
|
/**
|
|
8422
8611
|
* Create a string representation of this line.
|
|
8423
8612
|
*
|
|
@@ -8445,6 +8634,10 @@ var VertTuple = /** @class */ (function () {
|
|
|
8445
8634
|
VertTuple.vtutils = {
|
|
8446
8635
|
dist2: function (v, w) {
|
|
8447
8636
|
return (v.x - w.x) * (v.x - w.x) + (v.y - w.y) * (v.y - w.y);
|
|
8637
|
+
},
|
|
8638
|
+
calcCircumcircle: function (p1, p2) {
|
|
8639
|
+
var p1x = p1.x, p1y = p1.y, p2x = p2.x, p2y = p2.y, cx = 0.5 * (p1x + p2x), cy = 0.5 * (p1y + p2y);
|
|
8640
|
+
return { center: { x: cx, y: cy }, radius: Math.sqrt((p1x - cx) * (p1x - cx) + (p1y - cy) * (p1y - cy)) };
|
|
8448
8641
|
}
|
|
8449
8642
|
};
|
|
8450
8643
|
return VertTuple;
|
|
@@ -11479,7 +11672,10 @@ exports.BezierPath = BezierPath;
|
|
|
11479
11672
|
* @modified 2025-14-16 Class `Triangle` now implements interface `IBounded`.
|
|
11480
11673
|
* @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.
|
|
11481
11674
|
* @modified 2025-14-16 Added method `Triangle.move`.
|
|
11482
|
-
* @
|
|
11675
|
+
* @modified 2026-06-10 Refactoring the `Trianble.bounds` method and added a plain `Triangle.utils.bounds` method.
|
|
11676
|
+
* @modified 2026-06-10 Refactoring the `Trianble.calcCircumCircle` method and added a plain `Triangle.utils.calcCircumCircle` method.
|
|
11677
|
+
* @modified 2026-06-13 Adding `Triangle.getVertices()`.
|
|
11678
|
+
* @version 2.11.0
|
|
11483
11679
|
*
|
|
11484
11680
|
* @file Triangle
|
|
11485
11681
|
* @fileoverview A simple triangle class: three vertices.
|
|
@@ -11493,6 +11689,7 @@ var Line_1 = __webpack_require__(939);
|
|
|
11493
11689
|
var Polygon_1 = __webpack_require__(687);
|
|
11494
11690
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
11495
11691
|
var Vector_1 = __webpack_require__(30);
|
|
11692
|
+
var VertTuple_1 = __webpack_require__(590);
|
|
11496
11693
|
var Vertex_1 = __webpack_require__(787);
|
|
11497
11694
|
var geomutils_1 = __webpack_require__(328);
|
|
11498
11695
|
/**
|
|
@@ -11634,7 +11831,7 @@ var Triangle = /** @class */ (function () {
|
|
|
11634
11831
|
* after triangle vertex changes.
|
|
11635
11832
|
*
|
|
11636
11833
|
* @method getCircumcircle
|
|
11637
|
-
* @return {
|
|
11834
|
+
* @return {Circle} - The circle touching exactly all three triangle vertices.
|
|
11638
11835
|
* @instance
|
|
11639
11836
|
* @memberof Triangle
|
|
11640
11837
|
*/
|
|
@@ -11643,6 +11840,33 @@ var Triangle = /** @class */ (function () {
|
|
|
11643
11840
|
this.calcCircumcircle();
|
|
11644
11841
|
return new Circle_1.Circle(this.center.clone(), this.radius);
|
|
11645
11842
|
};
|
|
11843
|
+
/**
|
|
11844
|
+
* Calculates the minimun enclosing circle.
|
|
11845
|
+
*
|
|
11846
|
+
* @method getMinimumEnclosingCircle
|
|
11847
|
+
* @return {Object} - { center:Vertex, radius:float }
|
|
11848
|
+
* @instance
|
|
11849
|
+
* @memberof Triangle
|
|
11850
|
+
* @returns
|
|
11851
|
+
*/
|
|
11852
|
+
Triangle.prototype.getMinimumEnclosingCircle = function () {
|
|
11853
|
+
// First option: two points construct a circle and the third point is contained.
|
|
11854
|
+
var circleAB = VertTuple_1.VertTuple.vtutils.calcCircumcircle(this.a, this.b);
|
|
11855
|
+
if (Circle_1.Circle.circleUtils.containsPoint(circleAB.center, circleAB.radius, this.c)) {
|
|
11856
|
+
return Circle_1.Circle.fromICircle(circleAB);
|
|
11857
|
+
}
|
|
11858
|
+
var circleBC = VertTuple_1.VertTuple.vtutils.calcCircumcircle(this.b, this.c);
|
|
11859
|
+
if (Circle_1.Circle.circleUtils.containsPoint(circleBC.center, circleBC.radius, this.c)) {
|
|
11860
|
+
return Circle_1.Circle.fromICircle(circleBC);
|
|
11861
|
+
}
|
|
11862
|
+
var circleCA = VertTuple_1.VertTuple.vtutils.calcCircumcircle(this.c, this.a);
|
|
11863
|
+
if (Circle_1.Circle.circleUtils.containsPoint(circleCA.center, circleCA.radius, this.c)) {
|
|
11864
|
+
return Circle_1.Circle.fromICircle(circleCA);
|
|
11865
|
+
}
|
|
11866
|
+
// If none of the three upper cases applies: return the circumcircle.
|
|
11867
|
+
var circumCircle = Triangle.utils.calcCircumcircle(this.a, this.b, this.c);
|
|
11868
|
+
return Circle_1.Circle.fromICircle(circumCircle);
|
|
11869
|
+
};
|
|
11646
11870
|
/**
|
|
11647
11871
|
* Check if this triangle and the passed triangle share an
|
|
11648
11872
|
* adjacent edge.
|
|
@@ -11681,6 +11905,17 @@ var Triangle = /** @class */ (function () {
|
|
|
11681
11905
|
//if( this.c.equals(vert1) && this.a.equals(vert2) || this.c.equals(vert2) && this.a.equals(vert1) )
|
|
11682
11906
|
return this.b;
|
|
11683
11907
|
};
|
|
11908
|
+
/**
|
|
11909
|
+
* Get the three triangele vertices in a 3-element array.
|
|
11910
|
+
*
|
|
11911
|
+
* @method getVertices
|
|
11912
|
+
* @returns {[Vertex, Vertex, Vertex]} - The three vertices – real instances, not copies.
|
|
11913
|
+
* @instance
|
|
11914
|
+
* @memberof Triangle
|
|
11915
|
+
*/
|
|
11916
|
+
Triangle.prototype.getVertices = function () {
|
|
11917
|
+
return [this.a, this.b, this.c];
|
|
11918
|
+
};
|
|
11684
11919
|
/**
|
|
11685
11920
|
* Re-compute the circumcircle of this triangle (if the vertices
|
|
11686
11921
|
* have changed).
|
|
@@ -11694,32 +11929,35 @@ var Triangle = /** @class */ (function () {
|
|
|
11694
11929
|
* @memberof Triangle
|
|
11695
11930
|
*/
|
|
11696
11931
|
Triangle.prototype.calcCircumcircle = function () {
|
|
11697
|
-
// From
|
|
11698
|
-
// http://www.exaflop.org/docs/cgafaq/cga1.html
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
if (Math.abs(G) < Triangle.EPSILON) {
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
}
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
this.
|
|
11722
|
-
|
|
11932
|
+
// // From
|
|
11933
|
+
// // http://www.exaflop.org/docs/cgafaq/cga1.html
|
|
11934
|
+
// const A: number = this.b.x - this.a.x;
|
|
11935
|
+
// const B: number = this.b.y - this.a.y;
|
|
11936
|
+
// const C: number = this.c.x - this.a.x;
|
|
11937
|
+
// const D: number = this.c.y - this.a.y;
|
|
11938
|
+
// const E: number = A * (this.a.x + this.b.x) + B * (this.a.y + this.b.y);
|
|
11939
|
+
// const F: number = C * (this.a.x + this.c.x) + D * (this.a.y + this.c.y);
|
|
11940
|
+
// const G: number = 2.0 * (A * (this.c.y - this.b.y) - B * (this.c.x - this.b.x));
|
|
11941
|
+
// let dx: number, dy: number;
|
|
11942
|
+
// if (Math.abs(G) < Triangle.EPSILON) {
|
|
11943
|
+
// // Collinear - find extremes and use the midpoint
|
|
11944
|
+
// const bounds: Bounds = this.bounds();
|
|
11945
|
+
// this.center = new Vertex((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2);
|
|
11946
|
+
// dx = this.center.x - bounds.min.x;
|
|
11947
|
+
// dy = this.center.y - bounds.min.y;
|
|
11948
|
+
// } else {
|
|
11949
|
+
// const cx: number = (D * E - B * F) / G;
|
|
11950
|
+
// const cy: number = (A * F - C * E) / G;
|
|
11951
|
+
// this.center = new Vertex(cx, cy);
|
|
11952
|
+
// dx = this.center.x - this.a.x;
|
|
11953
|
+
// dy = this.center.y - this.a.y;
|
|
11954
|
+
// }
|
|
11955
|
+
// this.radius_squared = dx * dx + dy * dy;
|
|
11956
|
+
// this.radius = Math.sqrt(this.radius_squared);
|
|
11957
|
+
var tmpCircle = Triangle.utils.calcCircumcircle(this.a, this.b, this.c);
|
|
11958
|
+
this.center = new Vertex_1.Vertex(tmpCircle.center.x, tmpCircle.center.y);
|
|
11959
|
+
this.radius = tmpCircle.radius;
|
|
11960
|
+
this.radius_squared = tmpCircle.radius_squared;
|
|
11723
11961
|
}; // END calcCircumcircle
|
|
11724
11962
|
/**
|
|
11725
11963
|
* Check if the passed vertex is inside this triangle's
|
|
@@ -11746,7 +11984,11 @@ var Triangle = /** @class */ (function () {
|
|
|
11746
11984
|
* @memberof Triangle
|
|
11747
11985
|
*/
|
|
11748
11986
|
Triangle.prototype.bounds = function () {
|
|
11749
|
-
return new
|
|
11987
|
+
// return new Bounds(
|
|
11988
|
+
// 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)),
|
|
11989
|
+
// 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))
|
|
11990
|
+
// );
|
|
11991
|
+
return Triangle.utils.bounds(this.a, this.b, this.c);
|
|
11750
11992
|
};
|
|
11751
11993
|
//--- BEGIN --- Implement interface `Intersectable`
|
|
11752
11994
|
/**
|
|
@@ -11872,8 +12114,9 @@ var Triangle = /** @class */ (function () {
|
|
|
11872
12114
|
* @return Vertex The incenter of this triangle.
|
|
11873
12115
|
**/
|
|
11874
12116
|
Triangle.prototype.getIncenter = function () {
|
|
11875
|
-
if (!this.center || !this.radius)
|
|
12117
|
+
if (!this.center || !this.radius) {
|
|
11876
12118
|
this.calcCircumcircle();
|
|
12119
|
+
}
|
|
11877
12120
|
return this.center.clone();
|
|
11878
12121
|
};
|
|
11879
12122
|
/**
|
|
@@ -11940,7 +12183,53 @@ var Triangle = /** @class */ (function () {
|
|
|
11940
12183
|
*/
|
|
11941
12184
|
determinant: function (a, b, c) {
|
|
11942
12185
|
return (b.y - a.y) * (c.x - b.x) - (c.y - b.y) * (b.x - a.x);
|
|
11943
|
-
}
|
|
12186
|
+
},
|
|
12187
|
+
bounds: function (a, b, c) {
|
|
12188
|
+
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)));
|
|
12189
|
+
},
|
|
12190
|
+
/**
|
|
12191
|
+
* Re-compute the circumcircle of this triangle (if the vertices
|
|
12192
|
+
* have changed).
|
|
12193
|
+
*
|
|
12194
|
+
* The circumcenter and radius are stored in this.center and
|
|
12195
|
+
* this.radius. There is a third result: radius_squared (for internal computations).
|
|
12196
|
+
*
|
|
12197
|
+
* @method calcCircumcircle
|
|
12198
|
+
* @return void
|
|
12199
|
+
* @instance
|
|
12200
|
+
* @memberof Triangle
|
|
12201
|
+
*/
|
|
12202
|
+
calcCircumcircle: function (a, b, c) {
|
|
12203
|
+
// From
|
|
12204
|
+
// http://www.exaflop.org/docs/cgafaq/cga1.html
|
|
12205
|
+
var A = b.x - a.x;
|
|
12206
|
+
var B = b.y - a.y;
|
|
12207
|
+
var C = c.x - a.x;
|
|
12208
|
+
var D = c.y - a.y;
|
|
12209
|
+
var E = A * (a.x + b.x) + B * (a.y + b.y);
|
|
12210
|
+
var F = C * (a.x + c.x) + D * (a.y + c.y);
|
|
12211
|
+
var G = 2.0 * (A * (c.y - b.y) - B * (c.x - b.x));
|
|
12212
|
+
var dx, dy;
|
|
12213
|
+
var center;
|
|
12214
|
+
if (Math.abs(G) < Triangle.EPSILON) {
|
|
12215
|
+
// Collinear - find extremes and use the midpoint
|
|
12216
|
+
// const bounds: Bounds = this.bounds();
|
|
12217
|
+
var bounds = Triangle.utils.bounds(a, b, c);
|
|
12218
|
+
center = new Vertex_1.Vertex((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2);
|
|
12219
|
+
dx = center.x - bounds.min.x;
|
|
12220
|
+
dy = center.y - bounds.min.y;
|
|
12221
|
+
}
|
|
12222
|
+
else {
|
|
12223
|
+
var cx = (D * E - B * F) / G;
|
|
12224
|
+
var cy = (A * F - C * E) / G;
|
|
12225
|
+
center = new Vertex_1.Vertex(cx, cy);
|
|
12226
|
+
dx = center.x - a.x;
|
|
12227
|
+
dy = center.y - a.y;
|
|
12228
|
+
}
|
|
12229
|
+
var radius_squared = dx * dx + dy * dy;
|
|
12230
|
+
var radius = Math.sqrt(radius_squared);
|
|
12231
|
+
return { center: center, radius: radius, radius_squared: radius_squared };
|
|
12232
|
+
} // END calcCircumcircle
|
|
11944
12233
|
};
|
|
11945
12234
|
return Triangle;
|
|
11946
12235
|
}());
|
|
@@ -11991,7 +12280,8 @@ exports.Triangle = Triangle;
|
|
|
11991
12280
|
* @modified 2025-03-24 Making the second parameter `center` of the `Vertex.rotate` method optional.
|
|
11992
12281
|
* @modified 2025-04-13 Adding the `Vertex.move(amount: XYCoords)` method (does the same as `add`, added by naming convention).
|
|
11993
12282
|
* @modified 2025-05-07 Class `Vertex` is now implementing interface `IBounded` (to meet convention).
|
|
11994
|
-
* @
|
|
12283
|
+
* @modified 2026-06-10 Adding methods `Vertex.findClosestPoint` and `Vertex.findFarestPoint`.
|
|
12284
|
+
* @version 2.12.0
|
|
11995
12285
|
*
|
|
11996
12286
|
* @file Vertex
|
|
11997
12287
|
* @public
|
|
@@ -12558,6 +12848,47 @@ var Vertex = /** @class */ (function () {
|
|
|
12558
12848
|
return Bounds_1.Bounds.computeFromVertices([this]);
|
|
12559
12849
|
};
|
|
12560
12850
|
//--- END --- Implement interface `IBounded`
|
|
12851
|
+
/**
|
|
12852
|
+
* Find the one of two given points that's closest to this point.
|
|
12853
|
+
*
|
|
12854
|
+
* @method findClosestPoint
|
|
12855
|
+
* @instance
|
|
12856
|
+
* @memberof Vertex
|
|
12857
|
+
* @param {XYCoords | Vertex} pointA
|
|
12858
|
+
* @param {XYCoords | Vertex} pointB
|
|
12859
|
+
* @returns {XYCoords | Vertex}
|
|
12860
|
+
*/
|
|
12861
|
+
Vertex.prototype.findClosestPoint = function (pointA, pointB) {
|
|
12862
|
+
// TODO: put this implementation to geomutils?
|
|
12863
|
+
var distA = this.distance(pointA);
|
|
12864
|
+
var distB = this.distance(pointB);
|
|
12865
|
+
if (distA < distB) {
|
|
12866
|
+
return pointA;
|
|
12867
|
+
}
|
|
12868
|
+
else {
|
|
12869
|
+
return pointB;
|
|
12870
|
+
}
|
|
12871
|
+
};
|
|
12872
|
+
/**
|
|
12873
|
+
* Find the one of two given points that's farest from this point.
|
|
12874
|
+
*
|
|
12875
|
+
* @method findFarestPoint
|
|
12876
|
+
* @instance
|
|
12877
|
+
* @memberof Vertex
|
|
12878
|
+
* @param {XYCoords | Vertex} pointA
|
|
12879
|
+
* @param {XYCoords | Vertex} pointB
|
|
12880
|
+
* @returns {XYCoords | Vertex}
|
|
12881
|
+
*/
|
|
12882
|
+
Vertex.prototype.findFarestPoint = function (pointA, pointB) {
|
|
12883
|
+
var distA = this.distance(pointA);
|
|
12884
|
+
var distB = this.distance(pointB);
|
|
12885
|
+
if (distA > distB) {
|
|
12886
|
+
return pointA;
|
|
12887
|
+
}
|
|
12888
|
+
else {
|
|
12889
|
+
return pointB;
|
|
12890
|
+
}
|
|
12891
|
+
};
|
|
12561
12892
|
/**
|
|
12562
12893
|
* Get a string representation of this vertex.
|
|
12563
12894
|
*
|
|
@@ -14066,7 +14397,8 @@ exports.UIDGenerator = UIDGenerator;
|
|
|
14066
14397
|
* @modified 2023-09-25 Changed param type of `intersection()` from Line to VertTuple.
|
|
14067
14398
|
* @modified 2025-04-15 Class `Line` now implements interface `Intersectable`.
|
|
14068
14399
|
* @modified 2025-04-16 Class `Line` now implements interface `IBounded`.
|
|
14069
|
-
* @
|
|
14400
|
+
* @modified 2026-08-16 Adding methods `Line.trimStart` and `Line.trimEnd`. Adding methods `Line.trimStartAt` and `Line.trimEndAt`.
|
|
14401
|
+
* @version 2.5.0
|
|
14070
14402
|
*
|
|
14071
14403
|
* @file Line
|
|
14072
14404
|
* @public
|
|
@@ -14216,6 +14548,84 @@ var Line = /** @class */ (function (_super) {
|
|
|
14216
14548
|
return this;
|
|
14217
14549
|
};
|
|
14218
14550
|
//--- END Implement PathSegment ---
|
|
14551
|
+
/**
|
|
14552
|
+
* Trim this line segment from the start point by the given amount.
|
|
14553
|
+
* The amount must be positive and should be withing the segment's length. If the amount exceeds the segment's length
|
|
14554
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14555
|
+
*
|
|
14556
|
+
* @method trimStart
|
|
14557
|
+
* @memberof Line
|
|
14558
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
14559
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
14560
|
+
*/
|
|
14561
|
+
Line.prototype.trimStart = function (amount) {
|
|
14562
|
+
// Calculate the relative position `t` on this line.
|
|
14563
|
+
var t = amount / this.length();
|
|
14564
|
+
// `t` should be inside 0..1 – otherwise the amount was too large or negative.
|
|
14565
|
+
if (t < 0.0) {
|
|
14566
|
+
return this;
|
|
14567
|
+
}
|
|
14568
|
+
if (t > 1.0) {
|
|
14569
|
+
// Set the line to length zero (endpoint only)
|
|
14570
|
+
this.a = this.b.clone();
|
|
14571
|
+
return this;
|
|
14572
|
+
}
|
|
14573
|
+
this.a = this.vertAt(t);
|
|
14574
|
+
return this;
|
|
14575
|
+
};
|
|
14576
|
+
/**
|
|
14577
|
+
* Trim this line segment from the start point by the given relative amount.
|
|
14578
|
+
* The amount must be positive and should be within 0.0 and 1.0. If the amount exceeds the segment's length
|
|
14579
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14580
|
+
*
|
|
14581
|
+
* @method trimStartAt
|
|
14582
|
+
* @memberof Line
|
|
14583
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
14584
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
14585
|
+
*/
|
|
14586
|
+
Line.prototype.trimStartAt = function (relativeAmount) {
|
|
14587
|
+
// Calculate the relative position `t` on this line.
|
|
14588
|
+
return this.trimStart(relativeAmount * this.length());
|
|
14589
|
+
};
|
|
14590
|
+
/**
|
|
14591
|
+
* Trim this line segment from the end point by the given amount.
|
|
14592
|
+
* The amount must be positive and should be withing the segment's length. If the amount exceeds the segment's length
|
|
14593
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14594
|
+
*
|
|
14595
|
+
* @method trimEnd
|
|
14596
|
+
* @memberof Line
|
|
14597
|
+
* @param {number} amount - The positive amount to trim the line from the end point `b`.
|
|
14598
|
+
* @returns {Line} This for chaining, with updated point `b`.
|
|
14599
|
+
*/
|
|
14600
|
+
Line.prototype.trimEnd = function (amount) {
|
|
14601
|
+
// Calculate the relative position `t` on this line.
|
|
14602
|
+
var t = 1.0 - amount / this.length();
|
|
14603
|
+
// `t` should be inside 0..1 – otherwise the amount was too large or negative.
|
|
14604
|
+
if (t < 0.0) {
|
|
14605
|
+
return this;
|
|
14606
|
+
}
|
|
14607
|
+
if (t > 1.0) {
|
|
14608
|
+
// Set the line to length zero (endpoint only)
|
|
14609
|
+
this.b = this.a.clone();
|
|
14610
|
+
return this;
|
|
14611
|
+
}
|
|
14612
|
+
this.b = this.vertAt(t);
|
|
14613
|
+
return this;
|
|
14614
|
+
};
|
|
14615
|
+
/**
|
|
14616
|
+
* Trim this line segment from the end point by the given relative amount.
|
|
14617
|
+
* The amount must be positive and should be within 0.0 and 1.0. If the amount exceeds the segment's length
|
|
14618
|
+
* then the length of the resulting line will be zero (0.0).
|
|
14619
|
+
*
|
|
14620
|
+
* @method trimEndAt
|
|
14621
|
+
* @memberof Line
|
|
14622
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
14623
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
14624
|
+
*/
|
|
14625
|
+
Line.prototype.trimEndAt = function (relativeAmount) {
|
|
14626
|
+
// Calculate the relative position `t` on this line.
|
|
14627
|
+
return this.trimEnd(relativeAmount * this.length());
|
|
14628
|
+
};
|
|
14219
14629
|
//--- BEGIN --- Implement interface `Intersectable`
|
|
14220
14630
|
/**
|
|
14221
14631
|
* Get all line intersections with this polygon.
|
|
@@ -14306,8 +14716,9 @@ exports.Line = Line;
|
|
|
14306
14716
|
* @modified 2025-04-18 Added evaluation method for cubic Bézier curves `CubicBezierCurve.utils.evaluateT`.
|
|
14307
14717
|
* @modified 2025-04-18 Refactored method `CubicBezierCurve.getPointAt` to use `evaluateT`.
|
|
14308
14718
|
* @modified 2025-04-18 Fixed the `CubicBezierCurve.getBounds` method: now returning the real bounding box. Before it was an approximated one.
|
|
14309
|
-
* @modified 2025
|
|
14310
|
-
* @
|
|
14719
|
+
* @modified 2025-04-18 Added helper methods for bounding box calculation `CubucBezierCurve.util.cubicPolyMinMax` and `cubicPoly`.
|
|
14720
|
+
* @modified 2026-09-09 Adding methods `CubicBezierCurve.trimStartEnd` and `CubicBezierCurve.trimStartEndAt`.
|
|
14721
|
+
* @version 2.10.0
|
|
14311
14722
|
*
|
|
14312
14723
|
* @file CubicBezierCurve
|
|
14313
14724
|
* @public
|
|
@@ -14762,6 +15173,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
14762
15173
|
this.endControlPoint.set(subCurbePoints[3]);
|
|
14763
15174
|
this.updateArcLengths();
|
|
14764
15175
|
return this;
|
|
15176
|
+
// return this.trimStartEndAt(t, null);
|
|
14765
15177
|
};
|
|
14766
15178
|
/**
|
|
14767
15179
|
* Trim off the end of this curve. The position parameter `uValue` is the absolute position on the
|
|
@@ -14797,7 +15209,79 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
14797
15209
|
this.endControlPoint.set(subCurbePoints[3]);
|
|
14798
15210
|
this.updateArcLengths();
|
|
14799
15211
|
return this;
|
|
15212
|
+
// return this.trimStartEndAt(null, t);
|
|
14800
15213
|
};
|
|
15214
|
+
/**
|
|
15215
|
+
* Trim off a start and end section of this curve. The position parameters `uStart` and `uEnd` are the absolute positions in [0..arcLength].
|
|
15216
|
+
* The remaining curve will be the one in the bounds `[uStart,uEnd]` (so `[0.0,uStart]` and `[uEnd,1.0]` are cut off).
|
|
15217
|
+
*
|
|
15218
|
+
* Parameters out of bounds (< 0.0 or > arcLength) are ignored.
|
|
15219
|
+
* If `uEnd` is smaller than `uStart` then a curve with length zero (0) at `uStart` is returned.
|
|
15220
|
+
*
|
|
15221
|
+
* @method trimStartEndAt
|
|
15222
|
+
* @instance
|
|
15223
|
+
* @memberof CubicBezierCurve
|
|
15224
|
+
* @param {number} tStart - The relative position parameter where to cut off the head curve.
|
|
15225
|
+
* @param {number} tEnd - The relative position parameter where to cut off the tail curve.
|
|
15226
|
+
* @returns {CubicBezierCurve} `this` for chanining.
|
|
15227
|
+
*/
|
|
15228
|
+
CubicBezierCurve.prototype.trimStartEnd = function (uStart, uEnd) {
|
|
15229
|
+
return this.trimStartEndAt(this.convertU2T(uStart), this.convertU2T(uEnd));
|
|
15230
|
+
};
|
|
15231
|
+
/**
|
|
15232
|
+
* Trim off a start and end section of this curve. The position parameters `tStart` and `tEnd` are the relative positions in [0..1].
|
|
15233
|
+
* The remaining curve will be the one in the bounds `[tStart,tEnd]` (so `[0.0,tStart]` and `[tEnd,1.0]` are cut off).
|
|
15234
|
+
*
|
|
15235
|
+
* Parameters out of bounds (< 0.0 or > 1.0) are ignored.
|
|
15236
|
+
* If `tEnd` is smaller than `tStart` then a curve with length zero (0) at `tStart` is returned.
|
|
15237
|
+
*
|
|
15238
|
+
* @method trimStartEndAt
|
|
15239
|
+
* @instance
|
|
15240
|
+
* @memberof CubicBezierCurve
|
|
15241
|
+
* @param {number} tStart - The relative position parameter where to cut off the head curve.
|
|
15242
|
+
* @param {number} tEnd - The relative position parameter where to cut off the tail curve.
|
|
15243
|
+
* @returns {CubicBezierCurve} `this` for chanining.
|
|
15244
|
+
*/
|
|
15245
|
+
CubicBezierCurve.prototype.trimStartEndAt = function (tStart, tEnd) {
|
|
15246
|
+
var cleanTrimStart = Math.min(Math.max(0.0, tStart), 1.0);
|
|
15247
|
+
var cleanTrimEnd = Math.min(Math.max(cleanTrimStart, tEnd), 1.0);
|
|
15248
|
+
this.trimStartAt(cleanTrimStart);
|
|
15249
|
+
var relativeTrimEnd = (cleanTrimEnd - cleanTrimStart) / (1.0 - cleanTrimStart);
|
|
15250
|
+
this.trimEndAt(relativeTrimEnd);
|
|
15251
|
+
return this;
|
|
15252
|
+
};
|
|
15253
|
+
// __trimStartEndAt(tStart: number, tEnd: number): CubicBezierCurve {
|
|
15254
|
+
// var finalCurvePoints = [
|
|
15255
|
+
// this.startPoint.clone(),
|
|
15256
|
+
// this.endPoint.clone(),
|
|
15257
|
+
// this.startControlPoint.clone(),
|
|
15258
|
+
// this.endControlPoint.clone()
|
|
15259
|
+
// ];
|
|
15260
|
+
// if (typeof tStart === "number" && !Number.isNaN(tStart)) {
|
|
15261
|
+
// const subCurvePointsStart = CubicBezierCurve.utils.getSubCurvePointsAt(this, tStart, 1.0);
|
|
15262
|
+
// finalCurvePoints[0].set(subCurvePointsStart[0]);
|
|
15263
|
+
// finalCurvePoints[2].set(subCurvePointsStart[2]);
|
|
15264
|
+
// // this.startPoint.set(subCurvePointsStart[0]);
|
|
15265
|
+
// // this.startControlPoint.set(subCurvePointsStart[2]);
|
|
15266
|
+
// // this.endPoint.set(subCurvePointsStart[1]);
|
|
15267
|
+
// // this.endControlPoint.set(subCurvePointsStart[3]);
|
|
15268
|
+
// }
|
|
15269
|
+
// if (typeof tEnd === "number" && !Number.isNaN(tEnd)) {
|
|
15270
|
+
// const subCurvePointsEnd = CubicBezierCurve.utils.getSubCurvePointsAt(this, 0.0, tEnd);
|
|
15271
|
+
// // this.startPoint.set(subCurvePointsEnd[0]);
|
|
15272
|
+
// // this.startControlPoint.set(subCurvePointsEnd[2]);
|
|
15273
|
+
// // this.endPoint.set(subCurvePointsEnd[1]);
|
|
15274
|
+
// // this.endControlPoint.set(subCurvePointsEnd[3]);
|
|
15275
|
+
// finalCurvePoints[1].set(subCurvePointsEnd[1]);
|
|
15276
|
+
// finalCurvePoints[3].set(subCurvePointsEnd[3]);
|
|
15277
|
+
// }
|
|
15278
|
+
// this.startPoint.set(finalCurvePoints[0]);
|
|
15279
|
+
// this.endPoint.set(finalCurvePoints[1]);
|
|
15280
|
+
// this.startControlPoint.set(finalCurvePoints[2]);
|
|
15281
|
+
// this.endControlPoint.set(finalCurvePoints[3]);
|
|
15282
|
+
// this.updateArcLengths();
|
|
15283
|
+
// return this;
|
|
15284
|
+
// }
|
|
14801
15285
|
/**
|
|
14802
15286
|
* Get a sub curve at the given start end end positions (values on the curve's length, between 0 and curve.arcLength).
|
|
14803
15287
|
*
|
|
@@ -15152,10 +15636,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15152
15636
|
*/
|
|
15153
15637
|
CubicBezierCurve.utils = {
|
|
15154
15638
|
evaluateT: function (p0, p1, p2, p3, t) {
|
|
15155
|
-
return p0 * Math.pow(1.0 - t, 3) +
|
|
15156
|
-
p1 * 3 * t * Math.pow(1.0 - t, 2) +
|
|
15157
|
-
p2 * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
15158
|
-
p3 * Math.pow(t, 3);
|
|
15639
|
+
return (p0 * Math.pow(1.0 - t, 3) + p1 * 3 * t * Math.pow(1.0 - t, 2) + p2 * 3 * Math.pow(t, 2) * (1.0 - t) + p3 * Math.pow(t, 3));
|
|
15159
15640
|
},
|
|
15160
15641
|
cubicPolyMinMax: function (p0, p1, p2, p3) {
|
|
15161
15642
|
// var polyX = CubicBezierCurve.utils.cubicPoly2(
|
|
@@ -15227,7 +15708,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15227
15708
|
* @param {number} tEnd – The end offset if the desired cub curve (must be in [0..1]).
|
|
15228
15709
|
* @instance
|
|
15229
15710
|
* @memberof CubicBezierCurve
|
|
15230
|
-
* @return {
|
|
15711
|
+
* @return {[Vertex, Vertex, Vertex, Vertex]} The sub curve as curve vertices.
|
|
15231
15712
|
**/
|
|
15232
15713
|
getSubCurvePointsAt: function (curve, tStart, tEnd) {
|
|
15233
15714
|
var startVec = new Vector_1.Vector(curve.getPointAt(tStart), curve.getTangentAt(tStart));
|
|
@@ -15316,11 +15797,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
15316
15797
|
* @returns {[number,number,number]}
|
|
15317
15798
|
*/
|
|
15318
15799
|
cubicPoly: function (p0, p1, p2, p3) {
|
|
15319
|
-
return [
|
|
15320
|
-
3 * p3 - 9 * p2 + 9 * p1 - 3 * p0,
|
|
15321
|
-
6 * p0 - 12 * p1 + 6 * p2,
|
|
15322
|
-
3 * p1 - 3 * p0
|
|
15323
|
-
];
|
|
15800
|
+
return [3 * p3 - 9 * p2 + 9 * p1 - 3 * p0, 6 * p0 - 12 * p1 + 6 * p2, 3 * p1 - 3 * p0];
|
|
15324
15801
|
},
|
|
15325
15802
|
/**
|
|
15326
15803
|
* sign of number, but is division safe: no zero returned :)
|