plotboilerplate 1.29.0 → 1.31.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 +26 -13
- package/dist/index.esm.js +310 -57
- 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 +266 -36
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +1 -1
- package/src/cjs/Circle.d.ts +17 -1
- package/src/cjs/Circle.js +21 -1
- 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/Polygon.d.ts +18 -4
- package/src/cjs/Polygon.js +56 -18
- package/src/cjs/Polygon.js.map +1 -1
- package/src/cjs/VertTuple.d.ts +24 -2
- package/src/cjs/VertTuple.js +28 -2
- package/src/cjs/VertTuple.js.map +1 -1
- package/src/cjs/Vertex.d.ts +2 -2
- package/src/cjs/Vertex.js +2 -2
- package/src/cjs/utils/algorithms/delaunay2voronoi.d.ts +2 -1
- package/src/cjs/utils/algorithms/delaunay2voronoi.js +8 -10
- package/src/cjs/utils/algorithms/delaunay2voronoi.js.map +1 -1
- package/src/cjs/utils/datastructures/PointSet.d.ts +63 -0
- package/src/cjs/utils/datastructures/PointSet.js +126 -0
- package/src/cjs/utils/datastructures/PointSet.js.map +1 -0
- package/src/cjs/utils/datastructures/VoronoiCell.d.ts +19 -2
- package/src/cjs/utils/datastructures/VoronoiCell.js +39 -12
- package/src/cjs/utils/datastructures/VoronoiCell.js.map +1 -1
- package/src/cjs/utils/renderers/VoronoiRenderer.d.ts +99 -0
- package/src/cjs/utils/renderers/VoronoiRenderer.js +147 -0
- package/src/cjs/utils/renderers/VoronoiRenderer.js.map +1 -0
- package/src/esm/Circle.d.ts +17 -1
- package/src/esm/Circle.js +21 -1
- 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/Polygon.d.ts +18 -4
- package/src/esm/Polygon.js +56 -18
- package/src/esm/Polygon.js.map +1 -1
- package/src/esm/VertTuple.d.ts +24 -2
- package/src/esm/VertTuple.js +28 -2
- package/src/esm/VertTuple.js.map +1 -1
- package/src/esm/Vertex.d.ts +2 -2
- package/src/esm/Vertex.js +2 -2
- package/src/esm/utils/algorithms/delaunay2voronoi.d.ts +2 -1
- package/src/esm/utils/algorithms/delaunay2voronoi.js +8 -10
- package/src/esm/utils/algorithms/delaunay2voronoi.js.map +1 -1
- package/src/esm/utils/datastructures/PointSet.d.ts +63 -0
- package/src/esm/utils/datastructures/PointSet.js +115 -0
- package/src/esm/utils/datastructures/PointSet.js.map +1 -0
- package/src/esm/utils/datastructures/VoronoiCell.d.ts +19 -2
- package/src/esm/utils/datastructures/VoronoiCell.js +39 -12
- package/src/esm/utils/datastructures/VoronoiCell.js.map +1 -1
- package/src/esm/utils/renderers/VoronoiRenderer.d.ts +99 -0
- package/src/esm/utils/renderers/VoronoiRenderer.js +142 -0
- package/src/esm/utils/renderers/VoronoiRenderer.js.map +1 -0
- package/src/index-gl.js +1 -2
- package/src/ts/Circle.ts +23 -1
- package/src/ts/CubicBezierCurve.ts +133 -48
- package/src/ts/Line.ts +84 -1
- package/src/ts/Polygon.ts +58 -18
- package/src/ts/VertTuple.ts +30 -2
- package/src/ts/Vertex.ts +2 -2
- package/src/ts/utils/_AppContext.ts_ +22 -0
- package/src/ts/utils/algorithms/delaunay2voronoi.ts +81 -88
- package/src/ts/utils/datastructures/PointSet.ts +135 -0
- package/src/ts/utils/datastructures/VoronoiCell.ts +198 -169
- package/src/ts/utils/renderers/VoronoiRenderer.ts +200 -0
package/dist/index.esm.js
CHANGED
|
@@ -356,7 +356,8 @@ class VertexListeners {
|
|
|
356
356
|
* @modified 2026-07-08 Adding the `Circle.setRadius` method (for chaining).
|
|
357
357
|
* @mofified 2026-07-31 Adding the `radicalAxis(Circle)` method. Added the `Circle.circleUtils.createRadicalAxisHelperCircle` and `.circleDistance` helper methods.
|
|
358
358
|
* @modified 2026-08-03 Adding `Circle.tangentsFromPoint`.
|
|
359
|
-
* @
|
|
359
|
+
* @modified 2026-08-16 Adding the `Circle.sectorAngleByArcLength` method and the `Circle.circleUtils.sectorAngleByArcLength` helper method.
|
|
360
|
+
* @version 1.8.0
|
|
360
361
|
**/
|
|
361
362
|
/**
|
|
362
363
|
* @classdesc A simple circle: center point and radius.
|
|
@@ -731,6 +732,15 @@ class Circle {
|
|
|
731
732
|
}
|
|
732
733
|
return [new Vector(intersection.a, vert), new Vector(intersection.b, vert)];
|
|
733
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* Calculate inner sector angle for this circle and a given circle arc length.
|
|
737
|
+
*
|
|
738
|
+
* @param {number} sectorArcLength - The desired arc length (in units).
|
|
739
|
+
* @returns The sector's inner angle (in radians).
|
|
740
|
+
*/
|
|
741
|
+
sectorAngleByArcLength(sectorArcLength) {
|
|
742
|
+
return Circle.circleUtils.sectorAngleByArcLength(sectorArcLength, this.radius);
|
|
743
|
+
}
|
|
734
744
|
/**
|
|
735
745
|
* Create a deep copy of this circle.
|
|
736
746
|
*
|
|
@@ -809,6 +819,16 @@ Circle.circleUtils = {
|
|
|
809
819
|
*/
|
|
810
820
|
circleDistance: (circleA, circleB) => {
|
|
811
821
|
return circleA.center.distance(circleB.center) - circleA.radius - circleB.radius;
|
|
822
|
+
},
|
|
823
|
+
/**
|
|
824
|
+
* Calculate the inner sector angle for a given circle arc length and radius.
|
|
825
|
+
*
|
|
826
|
+
* @param {number} sectorArcLength - The desired arc length.
|
|
827
|
+
* @param {number} circleRadius - The circle's radius.
|
|
828
|
+
* @returns The sector angle in radians.
|
|
829
|
+
*/
|
|
830
|
+
sectorAngleByArcLength: (sectorArcLength, circleRadius) => {
|
|
831
|
+
return sectorArcLength / circleRadius;
|
|
812
832
|
}
|
|
813
833
|
};
|
|
814
834
|
|
|
@@ -1548,7 +1568,7 @@ const geomutils = {
|
|
|
1548
1568
|
* @modified 2025-04-13 Adding the `Vertex.move(amount: XYCoords)` method (does the same as `add`, added by naming convention).
|
|
1549
1569
|
* @modified 2025-05-07 Class `Vertex` is now implementing interface `IBounded` (to meet convention).
|
|
1550
1570
|
* @modified 2026-06-10 Adding methods `Vertex.findClosestPoint` and `Vertex.findFarestPoint`.
|
|
1551
|
-
* @version 2.12.
|
|
1571
|
+
* @version 2.12.1
|
|
1552
1572
|
*
|
|
1553
1573
|
* @file Vertex
|
|
1554
1574
|
* @public
|
|
@@ -2019,7 +2039,7 @@ class Vertex$1 {
|
|
|
2019
2039
|
* around given center.
|
|
2020
2040
|
*
|
|
2021
2041
|
* @method rotate
|
|
2022
|
-
* @param {number} angle - The angle to 'rotate' this vertex; 0.0 means no change.
|
|
2042
|
+
* @param {number} angle - The angle in radians to 'rotate' this vertex; 0.0 means no change.
|
|
2023
2043
|
* @param {XYCoords=} center - The center of rotation; default is (0,0).
|
|
2024
2044
|
* @return {Vertex} this
|
|
2025
2045
|
* @instance
|
|
@@ -2263,7 +2283,9 @@ Vertex$1.utils = {
|
|
|
2263
2283
|
* @modified 2025-04-15 Changed param of `VertTuple.moveTo` method from `Vertex` to `XYCoords`.
|
|
2264
2284
|
* @modified 2025-04-15 Added method `VertTuple.move` method.
|
|
2265
2285
|
* @modified 2026-06-10 Adding helper function `VertTuple.utils.calcCircumcircle`.
|
|
2266
|
-
* @
|
|
2286
|
+
* @modified 2026-06-17 Adding method `VertTuple.asLine` for converting TertTuples to Line instances.
|
|
2287
|
+
* @modified 2026-09-21 Adding method `VertTuple.asVector` for converting TertTuples to Vector instances.
|
|
2288
|
+
* @version 1.7.0
|
|
2267
2289
|
*/
|
|
2268
2290
|
/**
|
|
2269
2291
|
* @classdesc An abstract base classes for vertex tuple constructs, like Lines or Vectors.
|
|
@@ -2547,7 +2569,7 @@ class VertTuple {
|
|
|
2547
2569
|
/**
|
|
2548
2570
|
* Create a deep clone of this instance.
|
|
2549
2571
|
*
|
|
2550
|
-
* @method
|
|
2572
|
+
* @method clone
|
|
2551
2573
|
* @return {T} A type safe clone if this instance.
|
|
2552
2574
|
* @instance
|
|
2553
2575
|
* @memberof VertTuple
|
|
@@ -2555,6 +2577,28 @@ class VertTuple {
|
|
|
2555
2577
|
clone() {
|
|
2556
2578
|
return this.factory(this.a.clone(), this.b.clone());
|
|
2557
2579
|
}
|
|
2580
|
+
/**
|
|
2581
|
+
* Converts this `VertTuple` to a `Line` (segment).
|
|
2582
|
+
*
|
|
2583
|
+
* @method asLine
|
|
2584
|
+
* @return {Line} This tuple as `Line` instance.
|
|
2585
|
+
* @instance
|
|
2586
|
+
* @memberof VertTuple
|
|
2587
|
+
**/
|
|
2588
|
+
asLine() {
|
|
2589
|
+
return new Line(this.a, this.b);
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* Converts this `VertTuple` to a `Vector` (arrow).
|
|
2593
|
+
*
|
|
2594
|
+
* @method asVector
|
|
2595
|
+
* @return {Line} This tuple as `Vector` instance.
|
|
2596
|
+
* @instance
|
|
2597
|
+
* @memberof VertTuple
|
|
2598
|
+
**/
|
|
2599
|
+
asVector() {
|
|
2600
|
+
return new Vector(this.a, this.b);
|
|
2601
|
+
}
|
|
2558
2602
|
/**
|
|
2559
2603
|
* Create a string representation of this line.
|
|
2560
2604
|
*
|
|
@@ -2785,7 +2829,8 @@ Vector.utils = {
|
|
|
2785
2829
|
* @modified 2023-09-25 Changed param type of `intersection()` from Line to VertTuple.
|
|
2786
2830
|
* @modified 2025-04-15 Class `Line` now implements interface `Intersectable`.
|
|
2787
2831
|
* @modified 2025-04-16 Class `Line` now implements interface `IBounded`.
|
|
2788
|
-
* @
|
|
2832
|
+
* @modified 2026-08-16 Adding methods `Line.trimStart` and `Line.trimEnd`. Adding methods `Line.trimStartAt` and `Line.trimEndAt`.
|
|
2833
|
+
* @version 2.5.0
|
|
2789
2834
|
*
|
|
2790
2835
|
* @file Line
|
|
2791
2836
|
* @public
|
|
@@ -2912,6 +2957,84 @@ class Line extends VertTuple {
|
|
|
2912
2957
|
return this;
|
|
2913
2958
|
}
|
|
2914
2959
|
//--- END Implement PathSegment ---
|
|
2960
|
+
/**
|
|
2961
|
+
* Trim this line segment from the start point by the given amount.
|
|
2962
|
+
* The amount must be positive and should be withing the segment's length. If the amount exceeds the segment's length
|
|
2963
|
+
* then the length of the resulting line will be zero (0.0).
|
|
2964
|
+
*
|
|
2965
|
+
* @method trimStart
|
|
2966
|
+
* @memberof Line
|
|
2967
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
2968
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
2969
|
+
*/
|
|
2970
|
+
trimStart(amount) {
|
|
2971
|
+
// Calculate the relative position `t` on this line.
|
|
2972
|
+
var t = amount / this.length();
|
|
2973
|
+
// `t` should be inside 0..1 – otherwise the amount was too large or negative.
|
|
2974
|
+
if (t < 0.0) {
|
|
2975
|
+
return this;
|
|
2976
|
+
}
|
|
2977
|
+
if (t > 1.0) {
|
|
2978
|
+
// Set the line to length zero (endpoint only)
|
|
2979
|
+
this.a = this.b.clone();
|
|
2980
|
+
return this;
|
|
2981
|
+
}
|
|
2982
|
+
this.a = this.vertAt(t);
|
|
2983
|
+
return this;
|
|
2984
|
+
}
|
|
2985
|
+
/**
|
|
2986
|
+
* Trim this line segment from the start point by the given relative amount.
|
|
2987
|
+
* The amount must be positive and should be within 0.0 and 1.0. If the amount exceeds the segment's length
|
|
2988
|
+
* then the length of the resulting line will be zero (0.0).
|
|
2989
|
+
*
|
|
2990
|
+
* @method trimStartAt
|
|
2991
|
+
* @memberof Line
|
|
2992
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
2993
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
2994
|
+
*/
|
|
2995
|
+
trimStartAt(relativeAmount) {
|
|
2996
|
+
// Calculate the relative position `t` on this line.
|
|
2997
|
+
return this.trimStart(relativeAmount * this.length());
|
|
2998
|
+
}
|
|
2999
|
+
/**
|
|
3000
|
+
* Trim this line segment from the end point by the given amount.
|
|
3001
|
+
* The amount must be positive and should be withing the segment's length. If the amount exceeds the segment's length
|
|
3002
|
+
* then the length of the resulting line will be zero (0.0).
|
|
3003
|
+
*
|
|
3004
|
+
* @method trimEnd
|
|
3005
|
+
* @memberof Line
|
|
3006
|
+
* @param {number} amount - The positive amount to trim the line from the end point `b`.
|
|
3007
|
+
* @returns {Line} This for chaining, with updated point `b`.
|
|
3008
|
+
*/
|
|
3009
|
+
trimEnd(amount) {
|
|
3010
|
+
// Calculate the relative position `t` on this line.
|
|
3011
|
+
var t = 1.0 - amount / this.length();
|
|
3012
|
+
// `t` should be inside 0..1 – otherwise the amount was too large or negative.
|
|
3013
|
+
if (t < 0.0) {
|
|
3014
|
+
return this;
|
|
3015
|
+
}
|
|
3016
|
+
if (t > 1.0) {
|
|
3017
|
+
// Set the line to length zero (endpoint only)
|
|
3018
|
+
this.b = this.a.clone();
|
|
3019
|
+
return this;
|
|
3020
|
+
}
|
|
3021
|
+
this.b = this.vertAt(t);
|
|
3022
|
+
return this;
|
|
3023
|
+
}
|
|
3024
|
+
/**
|
|
3025
|
+
* Trim this line segment from the end point by the given relative amount.
|
|
3026
|
+
* The amount must be positive and should be within 0.0 and 1.0. If the amount exceeds the segment's length
|
|
3027
|
+
* then the length of the resulting line will be zero (0.0).
|
|
3028
|
+
*
|
|
3029
|
+
* @method trimEndAt
|
|
3030
|
+
* @memberof Line
|
|
3031
|
+
* @param {number} amount - The positive amount to trim the line from the start point `a`.
|
|
3032
|
+
* @returns {Line} This for chaining, with updated point `a`.
|
|
3033
|
+
*/
|
|
3034
|
+
trimEndAt(relativeAmount) {
|
|
3035
|
+
// Calculate the relative position `t` on this line.
|
|
3036
|
+
return this.trimEnd(relativeAmount * this.length());
|
|
3037
|
+
}
|
|
2915
3038
|
//--- BEGIN --- Implement interface `Intersectable`
|
|
2916
3039
|
/**
|
|
2917
3040
|
* Get all line intersections with this polygon.
|
|
@@ -2997,7 +3120,9 @@ class Line extends VertTuple {
|
|
|
2997
3120
|
* @modified 2025-05-16 Class `Polygon` now implements `IBounded`.
|
|
2998
3121
|
* @modified 2025-05-20 Tweaking `Polygon.getInnerAngleAt` and `Polygo.isAngleAcute` to handle indices out of array bounds as well.
|
|
2999
3122
|
* @modified 2025-06-07 Adding `Polygon.closestLineIntersectionIndex` to determine line intersections plus detected edge index.
|
|
3000
|
-
* @
|
|
3123
|
+
* @modified 2026-09-16 Adding a `forceClockwise` parameter to the `Polygon.getCentroid()` method.
|
|
3124
|
+
* @modified 2026-09-21 Adding `Polygon.revert` method to change the winding order.
|
|
3125
|
+
* @version 1.17.0
|
|
3001
3126
|
*
|
|
3002
3127
|
* @file Polygon
|
|
3003
3128
|
* @public
|
|
@@ -3291,6 +3416,20 @@ class Polygon {
|
|
|
3291
3416
|
// return Polygon.utils.signedArea(this.vertices) < 0;
|
|
3292
3417
|
return Polygon.utils.isClockwise(this.vertices);
|
|
3293
3418
|
}
|
|
3419
|
+
/**
|
|
3420
|
+
* Revert the order of this polygon's vertices to change the winding order.
|
|
3421
|
+
* This operation is in-place.
|
|
3422
|
+
*
|
|
3423
|
+
* @method revert
|
|
3424
|
+
* @instance
|
|
3425
|
+
* @memberof Polygon
|
|
3426
|
+
* @return {Polygon} This for chaining.
|
|
3427
|
+
*/
|
|
3428
|
+
revert() {
|
|
3429
|
+
// this.vertices.slice().reverse(); // Copy?
|
|
3430
|
+
this.vertices.reverse();
|
|
3431
|
+
return this;
|
|
3432
|
+
}
|
|
3294
3433
|
/**
|
|
3295
3434
|
* Get the perimeter of this polygon.
|
|
3296
3435
|
* The perimeter is the absolute length of the outline.
|
|
@@ -3372,35 +3511,37 @@ class Polygon {
|
|
|
3372
3511
|
}
|
|
3373
3512
|
/**
|
|
3374
3513
|
* Get centroid.
|
|
3375
|
-
* Centroids define the barycenter of any non self-intersecting convex polygon.
|
|
3514
|
+
* Centroids define the barycenter of any non self-intersecting convex clockwise polygon.
|
|
3376
3515
|
*
|
|
3377
|
-
* If the polygon is self intersecting or non
|
|
3516
|
+
* If the polygon is self intersecting or non convex or not clockwise then the barycenter is not well defined.
|
|
3378
3517
|
*
|
|
3379
3518
|
* https://mathworld.wolfram.com/PolygonCentroid.html
|
|
3380
3519
|
*
|
|
3381
3520
|
* @method getCentroid
|
|
3382
3521
|
* @instance
|
|
3522
|
+
* @param {boolean} forceClockwise - [optiona] If set to true then the centroid will be calculated for the clockwise polygon.
|
|
3383
3523
|
* @memberof Polygon
|
|
3384
3524
|
* @returns {Vertex|null}
|
|
3385
3525
|
*/
|
|
3386
|
-
getCentroid() {
|
|
3526
|
+
getCentroid(forceClockwise) {
|
|
3387
3527
|
if (this.vertices.length === 0) {
|
|
3388
3528
|
return null;
|
|
3389
3529
|
}
|
|
3390
|
-
const
|
|
3391
|
-
const n = this.vertices.length;
|
|
3392
|
-
for (var i = 0; i < n; i++) {
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
}
|
|
3400
|
-
const area = this.area();
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
return
|
|
3530
|
+
// const centroid: Vertex = new Vertex(0.0, 0.0);
|
|
3531
|
+
// const n = this.vertices.length;
|
|
3532
|
+
// for (var i = 0; i < n; i++) {
|
|
3533
|
+
// // center.add(this.vertices[i]);
|
|
3534
|
+
// const cur: Vertex = this.vertices[i];
|
|
3535
|
+
// const next: Vertex = this.vertices[(i + 1) % n];
|
|
3536
|
+
// var factor: number = cur.x * next.y - next.x * cur.y;
|
|
3537
|
+
// centroid.x += (cur.x + next.x) * factor;
|
|
3538
|
+
// centroid.y += (cur.y + next.y) * factor;
|
|
3539
|
+
// }
|
|
3540
|
+
// const area = this.area();
|
|
3541
|
+
// centroid.x *= 1 / (6 * area);
|
|
3542
|
+
// centroid.y *= 1 / (6 * area);
|
|
3543
|
+
// return centroid;
|
|
3544
|
+
return Polygon.utils.calculateCentroid(this.vertices, forceClockwise);
|
|
3404
3545
|
}
|
|
3405
3546
|
//--- BEGIN --- Implement interface `Intersectable`
|
|
3406
3547
|
/**
|
|
@@ -3825,6 +3966,26 @@ Polygon.utils = {
|
|
|
3825
3966
|
isClockwise(vertices) {
|
|
3826
3967
|
return Polygon.utils.signedArea(vertices) < 0;
|
|
3827
3968
|
},
|
|
3969
|
+
calculateCentroid(vertices, forceClockwise) {
|
|
3970
|
+
const centroid = new Vertex$1(0.0, 0.0);
|
|
3971
|
+
const n = vertices.length;
|
|
3972
|
+
if (forceClockwise && !Polygon.utils.isClockwise(vertices)) {
|
|
3973
|
+
return Polygon.utils.calculateCentroid(vertices.slice().reverse());
|
|
3974
|
+
}
|
|
3975
|
+
for (var i = 0; i < n; i++) {
|
|
3976
|
+
// center.add(this.vertices[i]);
|
|
3977
|
+
const cur = vertices[i];
|
|
3978
|
+
const next = vertices[(i + 1) % n];
|
|
3979
|
+
var factor = cur.x * next.y - next.x * cur.y;
|
|
3980
|
+
centroid.x += (cur.x + next.x) * factor;
|
|
3981
|
+
centroid.y += (cur.y + next.y) * factor;
|
|
3982
|
+
}
|
|
3983
|
+
// const area = this.area();
|
|
3984
|
+
const area = Polygon.utils.area(vertices);
|
|
3985
|
+
centroid.x *= 1 / (6 * area);
|
|
3986
|
+
centroid.y *= 1 / (6 * area);
|
|
3987
|
+
return centroid;
|
|
3988
|
+
},
|
|
3828
3989
|
/**
|
|
3829
3990
|
* Calulate the signed polyon area by interpreting the polygon as a matrix
|
|
3830
3991
|
* and calculating its determinant.
|
|
@@ -4214,8 +4375,9 @@ class Bounds {
|
|
|
4214
4375
|
* @modified 2025-04-18 Added evaluation method for cubic Bézier curves `CubicBezierCurve.utils.evaluateT`.
|
|
4215
4376
|
* @modified 2025-04-18 Refactored method `CubicBezierCurve.getPointAt` to use `evaluateT`.
|
|
4216
4377
|
* @modified 2025-04-18 Fixed the `CubicBezierCurve.getBounds` method: now returning the real bounding box. Before it was an approximated one.
|
|
4217
|
-
* @modified 2025
|
|
4218
|
-
* @
|
|
4378
|
+
* @modified 2025-04-18 Added helper methods for bounding box calculation `CubucBezierCurve.util.cubicPolyMinMax` and `cubicPoly`.
|
|
4379
|
+
* @modified 2026-09-09 Adding methods `CubicBezierCurve.trimStartEnd` and `CubicBezierCurve.trimStartEndAt`.
|
|
4380
|
+
* @version 2.10.0
|
|
4219
4381
|
*
|
|
4220
4382
|
* @file CubicBezierCurve
|
|
4221
4383
|
* @public
|
|
@@ -4664,6 +4826,7 @@ class CubicBezierCurve {
|
|
|
4664
4826
|
this.endControlPoint.set(subCurbePoints[3]);
|
|
4665
4827
|
this.updateArcLengths();
|
|
4666
4828
|
return this;
|
|
4829
|
+
// return this.trimStartEndAt(t, null);
|
|
4667
4830
|
}
|
|
4668
4831
|
/**
|
|
4669
4832
|
* Trim off the end of this curve. The position parameter `uValue` is the absolute position on the
|
|
@@ -4699,7 +4862,79 @@ class CubicBezierCurve {
|
|
|
4699
4862
|
this.endControlPoint.set(subCurbePoints[3]);
|
|
4700
4863
|
this.updateArcLengths();
|
|
4701
4864
|
return this;
|
|
4865
|
+
// return this.trimStartEndAt(null, t);
|
|
4702
4866
|
}
|
|
4867
|
+
/**
|
|
4868
|
+
* Trim off a start and end section of this curve. The position parameters `uStart` and `uEnd` are the absolute positions in [0..arcLength].
|
|
4869
|
+
* The remaining curve will be the one in the bounds `[uStart,uEnd]` (so `[0.0,uStart]` and `[uEnd,1.0]` are cut off).
|
|
4870
|
+
*
|
|
4871
|
+
* Parameters out of bounds (< 0.0 or > arcLength) are ignored.
|
|
4872
|
+
* If `uEnd` is smaller than `uStart` then a curve with length zero (0) at `uStart` is returned.
|
|
4873
|
+
*
|
|
4874
|
+
* @method trimStartEndAt
|
|
4875
|
+
* @instance
|
|
4876
|
+
* @memberof CubicBezierCurve
|
|
4877
|
+
* @param {number} tStart - The relative position parameter where to cut off the head curve.
|
|
4878
|
+
* @param {number} tEnd - The relative position parameter where to cut off the tail curve.
|
|
4879
|
+
* @returns {CubicBezierCurve} `this` for chanining.
|
|
4880
|
+
*/
|
|
4881
|
+
trimStartEnd(uStart, uEnd) {
|
|
4882
|
+
return this.trimStartEndAt(this.convertU2T(uStart), this.convertU2T(uEnd));
|
|
4883
|
+
}
|
|
4884
|
+
/**
|
|
4885
|
+
* Trim off a start and end section of this curve. The position parameters `tStart` and `tEnd` are the relative positions in [0..1].
|
|
4886
|
+
* The remaining curve will be the one in the bounds `[tStart,tEnd]` (so `[0.0,tStart]` and `[tEnd,1.0]` are cut off).
|
|
4887
|
+
*
|
|
4888
|
+
* Parameters out of bounds (< 0.0 or > 1.0) are ignored.
|
|
4889
|
+
* If `tEnd` is smaller than `tStart` then a curve with length zero (0) at `tStart` is returned.
|
|
4890
|
+
*
|
|
4891
|
+
* @method trimStartEndAt
|
|
4892
|
+
* @instance
|
|
4893
|
+
* @memberof CubicBezierCurve
|
|
4894
|
+
* @param {number} tStart - The relative position parameter where to cut off the head curve.
|
|
4895
|
+
* @param {number} tEnd - The relative position parameter where to cut off the tail curve.
|
|
4896
|
+
* @returns {CubicBezierCurve} `this` for chanining.
|
|
4897
|
+
*/
|
|
4898
|
+
trimStartEndAt(tStart, tEnd) {
|
|
4899
|
+
const cleanTrimStart = Math.min(Math.max(0.0, tStart), 1.0);
|
|
4900
|
+
const cleanTrimEnd = Math.min(Math.max(cleanTrimStart, tEnd), 1.0);
|
|
4901
|
+
this.trimStartAt(cleanTrimStart);
|
|
4902
|
+
const relativeTrimEnd = (cleanTrimEnd - cleanTrimStart) / (1.0 - cleanTrimStart);
|
|
4903
|
+
this.trimEndAt(relativeTrimEnd);
|
|
4904
|
+
return this;
|
|
4905
|
+
}
|
|
4906
|
+
// __trimStartEndAt(tStart: number, tEnd: number): CubicBezierCurve {
|
|
4907
|
+
// var finalCurvePoints = [
|
|
4908
|
+
// this.startPoint.clone(),
|
|
4909
|
+
// this.endPoint.clone(),
|
|
4910
|
+
// this.startControlPoint.clone(),
|
|
4911
|
+
// this.endControlPoint.clone()
|
|
4912
|
+
// ];
|
|
4913
|
+
// if (typeof tStart === "number" && !Number.isNaN(tStart)) {
|
|
4914
|
+
// const subCurvePointsStart = CubicBezierCurve.utils.getSubCurvePointsAt(this, tStart, 1.0);
|
|
4915
|
+
// finalCurvePoints[0].set(subCurvePointsStart[0]);
|
|
4916
|
+
// finalCurvePoints[2].set(subCurvePointsStart[2]);
|
|
4917
|
+
// // this.startPoint.set(subCurvePointsStart[0]);
|
|
4918
|
+
// // this.startControlPoint.set(subCurvePointsStart[2]);
|
|
4919
|
+
// // this.endPoint.set(subCurvePointsStart[1]);
|
|
4920
|
+
// // this.endControlPoint.set(subCurvePointsStart[3]);
|
|
4921
|
+
// }
|
|
4922
|
+
// if (typeof tEnd === "number" && !Number.isNaN(tEnd)) {
|
|
4923
|
+
// const subCurvePointsEnd = CubicBezierCurve.utils.getSubCurvePointsAt(this, 0.0, tEnd);
|
|
4924
|
+
// // this.startPoint.set(subCurvePointsEnd[0]);
|
|
4925
|
+
// // this.startControlPoint.set(subCurvePointsEnd[2]);
|
|
4926
|
+
// // this.endPoint.set(subCurvePointsEnd[1]);
|
|
4927
|
+
// // this.endControlPoint.set(subCurvePointsEnd[3]);
|
|
4928
|
+
// finalCurvePoints[1].set(subCurvePointsEnd[1]);
|
|
4929
|
+
// finalCurvePoints[3].set(subCurvePointsEnd[3]);
|
|
4930
|
+
// }
|
|
4931
|
+
// this.startPoint.set(finalCurvePoints[0]);
|
|
4932
|
+
// this.endPoint.set(finalCurvePoints[1]);
|
|
4933
|
+
// this.startControlPoint.set(finalCurvePoints[2]);
|
|
4934
|
+
// this.endControlPoint.set(finalCurvePoints[3]);
|
|
4935
|
+
// this.updateArcLengths();
|
|
4936
|
+
// return this;
|
|
4937
|
+
// }
|
|
4703
4938
|
/**
|
|
4704
4939
|
* Get a sub curve at the given start end end positions (values on the curve's length, between 0 and curve.arcLength).
|
|
4705
4940
|
*
|
|
@@ -5051,10 +5286,7 @@ CubicBezierCurve.END_POINT = 3;
|
|
|
5051
5286
|
*/
|
|
5052
5287
|
CubicBezierCurve.utils = {
|
|
5053
5288
|
evaluateT: (p0, p1, p2, p3, t) => {
|
|
5054
|
-
return p0 * Math.pow(1.0 - t, 3) +
|
|
5055
|
-
p1 * 3 * t * Math.pow(1.0 - t, 2) +
|
|
5056
|
-
p2 * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
5057
|
-
p3 * Math.pow(t, 3);
|
|
5289
|
+
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));
|
|
5058
5290
|
},
|
|
5059
5291
|
cubicPolyMinMax: (p0, p1, p2, p3) => {
|
|
5060
5292
|
// var polyX = CubicBezierCurve.utils.cubicPoly2(
|
|
@@ -5126,7 +5358,7 @@ CubicBezierCurve.utils = {
|
|
|
5126
5358
|
* @param {number} tEnd – The end offset if the desired cub curve (must be in [0..1]).
|
|
5127
5359
|
* @instance
|
|
5128
5360
|
* @memberof CubicBezierCurve
|
|
5129
|
-
* @return {
|
|
5361
|
+
* @return {[Vertex, Vertex, Vertex, Vertex]} The sub curve as curve vertices.
|
|
5130
5362
|
**/
|
|
5131
5363
|
getSubCurvePointsAt: (curve, tStart, tEnd) => {
|
|
5132
5364
|
const startVec = new Vector(curve.getPointAt(tStart), curve.getTangentAt(tStart));
|
|
@@ -5215,11 +5447,7 @@ CubicBezierCurve.utils = {
|
|
|
5215
5447
|
* @returns {[number,number,number]}
|
|
5216
5448
|
*/
|
|
5217
5449
|
cubicPoly: (p0, p1, p2, p3) => {
|
|
5218
|
-
return [
|
|
5219
|
-
3 * p3 - 9 * p2 + 9 * p1 - 3 * p0,
|
|
5220
|
-
6 * p0 - 12 * p1 + 6 * p2,
|
|
5221
|
-
3 * p1 - 3 * p0
|
|
5222
|
-
];
|
|
5450
|
+
return [3 * p3 - 9 * p2 + 9 * p1 - 3 * p0, 6 * p0 - 12 * p1 + 6 * p2, 3 * p1 - 3 * p0];
|
|
5223
5451
|
},
|
|
5224
5452
|
/**
|
|
5225
5453
|
* sign of number, but is division safe: no zero returned :)
|
|
@@ -19184,7 +19412,8 @@ class Delaunay {
|
|
|
19184
19412
|
* @modified 2020-08-12 Ported this class from vanilla JS to TypeScript.
|
|
19185
19413
|
* @modified 2020-08-17 Added some missing type declarations.
|
|
19186
19414
|
* @modified 2021-01-20 Members `triangles` and `sharedVertex` are now public.
|
|
19187
|
-
* @
|
|
19415
|
+
* @modified 2026-09-15 Added the `VoronoiCell.sharedVertexIndex` attribute.
|
|
19416
|
+
* @version 1.2.0
|
|
19188
19417
|
*
|
|
19189
19418
|
* @file VoronoiCell
|
|
19190
19419
|
* @public
|
|
@@ -19200,15 +19429,15 @@ class VoronoiCell {
|
|
|
19200
19429
|
* @param {Vertex} sharedVertex This is the 'center' of the voronoi cell; all triangles must share
|
|
19201
19430
|
* that vertex.
|
|
19202
19431
|
**/
|
|
19203
|
-
constructor(triangles, sharedVertex) {
|
|
19204
|
-
if (typeof triangles ===
|
|
19432
|
+
constructor(triangles, sharedVertex, sharedVertexIndex) {
|
|
19433
|
+
if (typeof triangles === "undefined")
|
|
19205
19434
|
triangles = [];
|
|
19206
|
-
if (typeof sharedVertex ===
|
|
19435
|
+
if (typeof sharedVertex === "undefined")
|
|
19207
19436
|
sharedVertex = new Vertex$1(0, 0);
|
|
19208
19437
|
this.triangles = triangles;
|
|
19209
19438
|
this.sharedVertex = sharedVertex;
|
|
19439
|
+
this.sharedVertexIndex = sharedVertexIndex;
|
|
19210
19440
|
}
|
|
19211
|
-
;
|
|
19212
19441
|
/**
|
|
19213
19442
|
* Check if the first and the last triangle in the path are NOT connected.
|
|
19214
19443
|
*
|
|
@@ -19221,7 +19450,6 @@ class VoronoiCell {
|
|
|
19221
19450
|
// There must be at least three triangles
|
|
19222
19451
|
return this.triangles.length < 3 || !this.triangles[0].isAdjacent(this.triangles[this.triangles.length - 1]);
|
|
19223
19452
|
}
|
|
19224
|
-
;
|
|
19225
19453
|
/**
|
|
19226
19454
|
* Convert this Voronoi cell to a path polygon, consisting of all Voronoi cell corner points.
|
|
19227
19455
|
*
|
|
@@ -19236,7 +19464,32 @@ class VoronoiCell {
|
|
|
19236
19464
|
toPolygon() {
|
|
19237
19465
|
return new Polygon(this.toPathArray(), this.isOpen());
|
|
19238
19466
|
}
|
|
19239
|
-
|
|
19467
|
+
/**
|
|
19468
|
+
* Get all 'umbrella' triangles for this Voronoi cell.
|
|
19469
|
+
*
|
|
19470
|
+
* The 'umbrella' is that sequence of triangles that covers the whole Voronoi cell and
|
|
19471
|
+
* meet in the cell's centroid.
|
|
19472
|
+
*
|
|
19473
|
+
* @method getUmbrellaTriangles
|
|
19474
|
+
* @instance
|
|
19475
|
+
* @memberof VoronoiCell
|
|
19476
|
+
* @return {Array<Triangle>}
|
|
19477
|
+
**/
|
|
19478
|
+
getUmbrellaTriangles() {
|
|
19479
|
+
var tris = [];
|
|
19480
|
+
// for (var i = 0; i < this.triangles.length; i++) {
|
|
19481
|
+
// var delaunayTri = this.triangles[i];
|
|
19482
|
+
// var tri = new Triangle(this.sharedVertex, delaunayTri.b, delaunayTri.c);
|
|
19483
|
+
// tris.push(tri);
|
|
19484
|
+
// }
|
|
19485
|
+
var vertices = this.toPathArray();
|
|
19486
|
+
var n = vertices.length;
|
|
19487
|
+
for (var i = 0; i < n; i++) {
|
|
19488
|
+
var tri = new Triangle(this.sharedVertex, vertices[i], vertices[(i + 1) % n]);
|
|
19489
|
+
tris.push(tri);
|
|
19490
|
+
}
|
|
19491
|
+
return tris;
|
|
19492
|
+
}
|
|
19240
19493
|
/**
|
|
19241
19494
|
* Convert the voronoi cell path data to an SVG polygon data string.
|
|
19242
19495
|
*
|
|
@@ -19251,9 +19504,12 @@ class VoronoiCell {
|
|
|
19251
19504
|
if (this.triangles.length == 0)
|
|
19252
19505
|
return "";
|
|
19253
19506
|
const arr = this.toPathArray();
|
|
19254
|
-
return arr
|
|
19507
|
+
return arr
|
|
19508
|
+
.map((vert) => {
|
|
19509
|
+
return "" + vert.x + "," + vert.y;
|
|
19510
|
+
})
|
|
19511
|
+
.join(" ");
|
|
19255
19512
|
}
|
|
19256
|
-
;
|
|
19257
19513
|
/**
|
|
19258
19514
|
* Convert the voronoi cell path data to an array.
|
|
19259
19515
|
*
|
|
@@ -19305,7 +19561,6 @@ class VoronoiCell {
|
|
|
19305
19561
|
const openEdgePoint = new Vertex$1(perpendicular.x + (center.x - perpendicular.x) * 1000, perpendicular.y + (center.y - perpendicular.y) * 1000);
|
|
19306
19562
|
return openEdgePoint;
|
|
19307
19563
|
}
|
|
19308
|
-
;
|
|
19309
19564
|
/**
|
|
19310
19565
|
* A helper function.
|
|
19311
19566
|
*
|
|
@@ -19329,13 +19584,12 @@ class VoronoiCell {
|
|
|
19329
19584
|
return tri.a;
|
|
19330
19585
|
}
|
|
19331
19586
|
// Here:
|
|
19332
|
-
// tri.c.equals(sharedVertex)
|
|
19587
|
+
// tri.c.equals(sharedVertex)
|
|
19333
19588
|
if (neighbour.a.equals(tri.a) || neighbour.b.equals(tri.a) || neighbour.c.equals(tri.a))
|
|
19334
19589
|
return tri.b;
|
|
19335
19590
|
else
|
|
19336
19591
|
return tri.a;
|
|
19337
19592
|
}
|
|
19338
|
-
;
|
|
19339
19593
|
}
|
|
19340
19594
|
|
|
19341
19595
|
/**
|
|
@@ -19343,7 +19597,8 @@ class VoronoiCell {
|
|
|
19343
19597
|
* @date 2018-04-07
|
|
19344
19598
|
* @modified 2018-04-11 Using VoronoiCells now (was array before).
|
|
19345
19599
|
* @modified 2020-08-15 Ported from vanilla JS to TypeScript.
|
|
19346
|
-
* @
|
|
19600
|
+
* @modified 2026-09-15 Added the `sharedVertexIndex` attribute to each Voronoi cell.
|
|
19601
|
+
* @version 1.1.0
|
|
19347
19602
|
**/
|
|
19348
19603
|
/**
|
|
19349
19604
|
* @classdesc Create the voronoi diagram from the given delaunay triangulation (they are dual graphs).
|
|
@@ -19358,13 +19613,12 @@ class delaunay2voronoi {
|
|
|
19358
19613
|
this.pointList = pointList;
|
|
19359
19614
|
this.triangles = triangles;
|
|
19360
19615
|
}
|
|
19361
|
-
;
|
|
19362
19616
|
// +---------------------------------------------------------------------------------
|
|
19363
19617
|
// | Convert the triangle set to the Voronoi diagram.
|
|
19364
19618
|
// +-------------------------------
|
|
19365
19619
|
build() {
|
|
19366
19620
|
const voronoiDiagram = [];
|
|
19367
|
-
for (var p
|
|
19621
|
+
for (var p = 0; p < this.pointList.length; p++) {
|
|
19368
19622
|
var point = this.pointList[p];
|
|
19369
19623
|
// Find adjacent triangles for first point
|
|
19370
19624
|
var adjacentSubset = [];
|
|
@@ -19373,12 +19627,12 @@ class delaunay2voronoi {
|
|
|
19373
19627
|
adjacentSubset.push(this.triangles[t]);
|
|
19374
19628
|
}
|
|
19375
19629
|
var path = this.subsetToPath(adjacentSubset);
|
|
19376
|
-
if (path)
|
|
19377
|
-
|
|
19630
|
+
if (path)
|
|
19631
|
+
// There may be errors
|
|
19632
|
+
voronoiDiagram.push(new VoronoiCell(path, point, p));
|
|
19378
19633
|
}
|
|
19379
19634
|
return voronoiDiagram;
|
|
19380
19635
|
}
|
|
19381
|
-
;
|
|
19382
19636
|
// +---------------------------------------------------------------------------------
|
|
19383
19637
|
// | Re-order a tiangle subset so the triangle define a single path.
|
|
19384
19638
|
// |
|
|
@@ -19391,7 +19645,7 @@ class delaunay2voronoi {
|
|
|
19391
19645
|
subsetToPath(triangleSet, startPosition, tryOnce) {
|
|
19392
19646
|
if (triangleSet.length == 0)
|
|
19393
19647
|
return [];
|
|
19394
|
-
if (typeof startPosition ===
|
|
19648
|
+
if (typeof startPosition === "undefined")
|
|
19395
19649
|
startPosition = 0;
|
|
19396
19650
|
let t = startPosition;
|
|
19397
19651
|
const result = [triangleSet[t]];
|
|
@@ -19432,8 +19686,7 @@ class delaunay2voronoi {
|
|
|
19432
19686
|
return result;
|
|
19433
19687
|
}
|
|
19434
19688
|
}
|
|
19435
|
-
|
|
19436
|
-
}
|
|
19689
|
+
} // END delaunay2voronoi
|
|
19437
19690
|
|
|
19438
19691
|
/**
|
|
19439
19692
|
* @requires Line
|