plotboilerplate 1.23.2 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/index.esm.js +8351 -6928
- 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 +1590 -123
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +4 -2
- package/src/cjs/BezierPath.d.ts +41 -5
- package/src/cjs/BezierPath.js +52 -2
- package/src/cjs/BezierPath.js.map +1 -1
- package/src/cjs/Bounds.d.ts +67 -3
- package/src/cjs/Bounds.js +101 -3
- package/src/cjs/Bounds.js.map +1 -1
- package/src/cjs/Circle.d.ts +46 -4
- package/src/cjs/Circle.js +82 -3
- package/src/cjs/Circle.js.map +1 -1
- package/src/cjs/CircleSector.d.ts +51 -2
- package/src/cjs/CircleSector.js +112 -3
- package/src/cjs/CircleSector.js.map +1 -1
- package/src/cjs/CubicBezierCurve.d.ts +113 -7
- package/src/cjs/CubicBezierCurve.js +281 -33
- package/src/cjs/CubicBezierCurve.js.map +1 -1
- package/src/cjs/Line.d.ts +38 -3
- package/src/cjs/Line.js +64 -1
- package/src/cjs/Line.js.map +1 -1
- package/src/cjs/PlotBoilerplate.d.ts +4 -2
- package/src/cjs/PlotBoilerplate.js +9 -12
- package/src/cjs/PlotBoilerplate.js.map +1 -1
- package/src/cjs/Polygon.d.ts +153 -6
- package/src/cjs/Polygon.js +304 -23
- package/src/cjs/Polygon.js.map +1 -1
- package/src/cjs/Triangle.d.ts +73 -4
- package/src/cjs/Triangle.js +94 -2
- package/src/cjs/Triangle.js.map +1 -1
- package/src/cjs/VEllipse.d.ts +62 -3
- package/src/cjs/VEllipse.js +181 -17
- package/src/cjs/VEllipse.js.map +1 -1
- package/src/cjs/VEllipseSector.d.ts +86 -2
- package/src/cjs/VEllipseSector.js +148 -4
- package/src/cjs/VEllipseSector.js.map +1 -1
- package/src/cjs/Vector.d.ts +12 -2
- package/src/cjs/Vector.js +15 -2
- package/src/cjs/Vector.js.map +1 -1
- package/src/cjs/VertTuple.d.ts +39 -10
- package/src/cjs/VertTuple.js +49 -11
- package/src/cjs/VertTuple.js.map +1 -1
- package/src/cjs/Vertex.d.ts +18 -2
- package/src/cjs/Vertex.js +22 -2
- package/src/cjs/Vertex.js.map +1 -1
- package/src/cjs/draw.d.ts +1 -0
- package/src/cjs/draw.js +2 -1
- package/src/cjs/draw.js.map +1 -1
- package/src/cjs/drawutilssvg.js +24 -0
- package/src/cjs/drawutilssvg.js.map +1 -1
- package/src/cjs/geomutils.d.ts +32 -1
- package/src/cjs/geomutils.js +47 -1
- package/src/cjs/geomutils.js.map +1 -1
- package/src/cjs/interfaces/core.d.ts +39 -0
- package/src/cjs/interfaces/core.js +2 -0
- package/src/cjs/interfaces/core.js.map +1 -1
- package/src/cjs/utils/algorithms/PolygonInset.d.ts +184 -0
- package/src/cjs/utils/algorithms/PolygonInset.js +431 -0
- package/src/cjs/utils/algorithms/PolygonInset.js.map +1 -0
- package/src/cjs/utils/algorithms/clearDuplicateVertices.d.ts +5 -4
- package/src/cjs/utils/algorithms/clearDuplicateVertices.js +6 -3
- package/src/cjs/utils/algorithms/clearDuplicateVertices.js.map +1 -1
- package/src/cjs/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
- package/src/cjs/utils/algorithms/convexPolygonIncircle.js +14 -6
- package/src/cjs/utils/algorithms/convexPolygonIncircle.js.map +1 -1
- package/src/cjs/utils/algorithms/findPolygonSelfIntersections.d.ts +2 -1
- package/src/cjs/utils/algorithms/findPolygonSelfIntersections.js +3 -3
- package/src/cjs/utils/algorithms/findPolygonSelfIntersections.js.map +1 -1
- package/src/cjs/utils/algorithms/splitPolygonToNonIntersecting.d.ts +3 -2
- package/src/cjs/utils/algorithms/splitPolygonToNonIntersecting.js +11 -9
- package/src/cjs/utils/algorithms/splitPolygonToNonIntersecting.js.map +1 -1
- package/src/cjs/utils/createRandomizedPolygon.d.ts +14 -0
- package/src/cjs/utils/createRandomizedPolygon.js +32 -0
- package/src/cjs/utils/createRandomizedPolygon.js.map +1 -0
- package/src/cjs/utils/detectDarkMode.js.map +1 -1
- package/src/cjs/utils/dom/guiSizeToggler.d.ts +2 -1
- package/src/cjs/utils/dom/guiSizeToggler.js +5 -3
- package/src/cjs/utils/dom/guiSizeToggler.js.map +1 -1
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.d.ts +9 -7
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js +37 -23
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/cjs/utils/helpers/CircleSectorHelper.d.ts +10 -1
- package/src/cjs/utils/helpers/CircleSectorHelper.js +19 -20
- package/src/cjs/utils/helpers/CircleSectorHelper.js.map +1 -1
- package/src/cjs/utils/helpers/VEllipseHelper.d.ts +30 -0
- package/src/cjs/utils/helpers/VEllipseHelper.js +86 -0
- package/src/cjs/utils/helpers/VEllipseHelper.js.map +1 -0
- package/src/cjs/utils/helpers/VEllipseSectorHelper.d.ts +42 -3
- package/src/cjs/utils/helpers/VEllipseSectorHelper.js +107 -25
- package/src/cjs/utils/helpers/VEllipseSectorHelper.js.map +1 -1
- package/src/createDemoDrawables.js +3 -1
- package/src/esm/BezierPath.d.ts +41 -5
- package/src/esm/BezierPath.js +50 -2
- package/src/esm/BezierPath.js.map +1 -1
- package/src/esm/Bounds.d.ts +67 -3
- package/src/esm/Bounds.js +101 -3
- package/src/esm/Bounds.js.map +1 -1
- package/src/esm/Circle.d.ts +46 -4
- package/src/esm/Circle.js +79 -3
- package/src/esm/Circle.js.map +1 -1
- package/src/esm/CircleSector.d.ts +51 -2
- package/src/esm/CircleSector.js +108 -3
- package/src/esm/CircleSector.js.map +1 -1
- package/src/esm/CubicBezierCurve.d.ts +113 -7
- package/src/esm/CubicBezierCurve.js +277 -33
- package/src/esm/CubicBezierCurve.js.map +1 -1
- package/src/esm/Line.d.ts +38 -3
- package/src/esm/Line.js +62 -1
- package/src/esm/Line.js.map +1 -1
- package/src/esm/PlotBoilerplate.d.ts +4 -2
- package/src/esm/PlotBoilerplate.js +9 -12
- package/src/esm/PlotBoilerplate.js.map +1 -1
- package/src/esm/Polygon.d.ts +153 -6
- package/src/esm/Polygon.js +301 -23
- package/src/esm/Polygon.js.map +1 -1
- package/src/esm/Triangle.d.ts +73 -4
- package/src/esm/Triangle.js +91 -2
- package/src/esm/Triangle.js.map +1 -1
- package/src/esm/VEllipse.d.ts +62 -3
- package/src/esm/VEllipse.js +178 -17
- package/src/esm/VEllipse.js.map +1 -1
- package/src/esm/VEllipseSector.d.ts +86 -2
- package/src/esm/VEllipseSector.js +146 -7
- package/src/esm/VEllipseSector.js.map +1 -1
- package/src/esm/Vector.d.ts +12 -2
- package/src/esm/Vector.js +15 -2
- package/src/esm/Vector.js.map +1 -1
- package/src/esm/VertTuple.d.ts +39 -10
- package/src/esm/VertTuple.js +49 -11
- package/src/esm/VertTuple.js.map +1 -1
- package/src/esm/Vertex.d.ts +18 -2
- package/src/esm/Vertex.js +22 -2
- package/src/esm/Vertex.js.map +1 -1
- package/src/esm/draw.d.ts +1 -0
- package/src/esm/draw.js +2 -1
- package/src/esm/draw.js.map +1 -1
- package/src/esm/drawutilssvg.js +24 -0
- package/src/esm/drawutilssvg.js.map +1 -1
- package/src/esm/geomutils.d.ts +32 -1
- package/src/esm/geomutils.js +47 -1
- package/src/esm/geomutils.js.map +1 -1
- package/src/esm/interfaces/core.d.ts +39 -0
- package/src/esm/interfaces/core.js +2 -0
- package/src/esm/interfaces/core.js.map +1 -1
- package/src/esm/utils/algorithms/PolygonInset.d.ts +184 -0
- package/src/esm/utils/algorithms/PolygonInset.js +424 -0
- package/src/esm/utils/algorithms/PolygonInset.js.map +1 -0
- package/src/esm/utils/algorithms/clearDuplicateVertices.d.ts +5 -4
- package/src/esm/utils/algorithms/clearDuplicateVertices.js +6 -3
- package/src/esm/utils/algorithms/clearDuplicateVertices.js.map +1 -1
- package/src/esm/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
- package/src/esm/utils/algorithms/convexPolygonIncircle.js +15 -7
- package/src/esm/utils/algorithms/convexPolygonIncircle.js.map +1 -1
- package/src/esm/utils/algorithms/createRandomizedPolygon.d.ts +14 -0
- package/src/esm/utils/algorithms/createRandomizedPolygon.js +28 -0
- package/src/esm/utils/algorithms/createRandomizedPolygon.js.map +1 -0
- package/src/esm/utils/algorithms/findPolygonSelfIntersections.d.ts +2 -1
- package/src/esm/utils/algorithms/findPolygonSelfIntersections.js +3 -3
- package/src/esm/utils/algorithms/findPolygonSelfIntersections.js.map +1 -1
- package/src/esm/utils/algorithms/splitPolygonToNonIntersecting.d.ts +3 -2
- package/src/esm/utils/algorithms/splitPolygonToNonIntersecting.js +11 -9
- package/src/esm/utils/algorithms/splitPolygonToNonIntersecting.js.map +1 -1
- package/src/esm/utils/createRandomizedPolygon.d.ts +14 -0
- package/src/esm/utils/createRandomizedPolygon.js +28 -0
- package/src/esm/utils/createRandomizedPolygon.js.map +1 -0
- package/src/esm/utils/detectDarkMode.js.map +1 -1
- package/src/esm/utils/dom/guiSizeToggler.d.ts +2 -1
- package/src/esm/utils/dom/guiSizeToggler.js +4 -2
- package/src/esm/utils/dom/guiSizeToggler.js.map +1 -1
- package/src/esm/utils/helpers/BezierPathInteractionHelper.d.ts +9 -7
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js +35 -22
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/esm/utils/helpers/CircleSectorHelper.d.ts +10 -1
- package/src/esm/utils/helpers/CircleSectorHelper.js +19 -20
- package/src/esm/utils/helpers/CircleSectorHelper.js.map +1 -1
- package/src/esm/utils/helpers/VEllipseHelper.d.ts +30 -0
- package/src/esm/utils/helpers/VEllipseHelper.js +81 -0
- package/src/esm/utils/helpers/VEllipseHelper.js.map +1 -0
- package/src/esm/utils/helpers/VEllipseSectorHelper.d.ts +42 -3
- package/src/esm/utils/helpers/VEllipseSectorHelper.js +106 -24
- package/src/esm/utils/helpers/VEllipseSectorHelper.js.map +1 -1
- package/src/ts/BezierPath.ts +58 -5
- package/src/ts/Bounds.ts +110 -6
- package/src/ts/Circle.ts +87 -5
- package/src/ts/CircleSector.ts +115 -5
- package/src/ts/CubicBezierCurve.ts +332 -42
- package/src/ts/Line.ts +66 -3
- package/src/ts/PlotBoilerplate.ts +10 -12
- package/src/ts/Polygon.ts +329 -27
- package/src/ts/Triangle.ts +101 -5
- package/src/ts/VEllipse.ts +214 -19
- package/src/ts/VEllipseSector.ts +154 -8
- package/src/ts/Vector.ts +16 -2
- package/src/ts/VertTuple.ts +53 -13
- package/src/ts/Vertex.ts +24 -3
- package/src/ts/draw.ts +2 -1
- package/src/ts/drawutilssvg.ts +29 -0
- package/src/ts/geomutils.ts +49 -1
- package/src/ts/interfaces/core.ts +42 -0
- package/src/ts/utils/algorithms/PolygonInset.ts +529 -0
- package/src/ts/utils/algorithms/clearDuplicateVertices.ts +11 -8
- package/src/ts/utils/algorithms/convexPolygonIncircle.ts +82 -78
- package/src/ts/utils/algorithms/findPolygonSelfIntersections.ts +25 -26
- package/src/ts/utils/algorithms/splitPolygonToNonIntersecting.ts +92 -99
- package/src/ts/utils/createRandomizedPolygon.ts +31 -0
- package/src/ts/utils/detectDarkMode.ts +1 -3
- package/src/ts/utils/dom/guiSizeToggler.ts +4 -2
- package/src/ts/utils/helpers/BezierPathInteractionHelper.ts +45 -29
- package/src/ts/utils/helpers/CircleSectorHelper.ts +115 -125
- package/src/ts/utils/helpers/VEllipseHelper.ts +113 -0
- package/src/ts/utils/helpers/VEllipseSectorHelper.ts +142 -25
package/dist/plotboilerplate.js
CHANGED
|
@@ -450,7 +450,10 @@ class AlloyFinger {
|
|
|
450
450
|
* @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
451
451
|
* @modified 2023-10-06 Adding the `BezierPath.toPathPoints()` method.
|
|
452
452
|
* @modified 2023-10-07 Adding the `BezierPath.fromCurve(CubicBezierCurve)` static function.
|
|
453
|
-
* @
|
|
453
|
+
* @modified 2025-04-09 Added the `BezierPath.move` method to match the convention – which just calls `translate`.
|
|
454
|
+
* @modified 2025-04-09 Modified the `BezierPath.translate` method: chaning parameter `Vertex` to more generalized `XYCoords`.
|
|
455
|
+
* @modified 2025-04-14 Class `BezierPath` is now implementing interface `Intersectable`.
|
|
456
|
+
* @version 2.7.0
|
|
454
457
|
*
|
|
455
458
|
* @file BezierPath
|
|
456
459
|
* @public
|
|
@@ -661,7 +664,7 @@ var BezierPath = /** @class */ (function () {
|
|
|
661
664
|
* Move the whole bezier path by the given (x,y)-amount.
|
|
662
665
|
*
|
|
663
666
|
* @method translate
|
|
664
|
-
* @param {
|
|
667
|
+
* @param {XYCoords} amount - The amount to be added (amount.x and amount.y)
|
|
665
668
|
* to each vertex of the curve.
|
|
666
669
|
* @instance
|
|
667
670
|
* @memberof BezierPath
|
|
@@ -680,6 +683,19 @@ var BezierPath = /** @class */ (function () {
|
|
|
680
683
|
this.updateArcLengths();
|
|
681
684
|
return this;
|
|
682
685
|
};
|
|
686
|
+
/**
|
|
687
|
+
* Move the whole bezier path by the given (x,y)-amount.
|
|
688
|
+
*
|
|
689
|
+
* @method move
|
|
690
|
+
* @param {XYCoords} amount - The amount to be added (amount.x and amount.y)
|
|
691
|
+
* to each vertex of the curve.
|
|
692
|
+
* @instance
|
|
693
|
+
* @memberof BezierPath
|
|
694
|
+
* @return {BezierPath} this for chaining
|
|
695
|
+
**/
|
|
696
|
+
BezierPath.prototype.move = function (amount) {
|
|
697
|
+
return this.translate(amount);
|
|
698
|
+
};
|
|
683
699
|
/**
|
|
684
700
|
* Scale the whole bezier path by the given uniform factor.
|
|
685
701
|
*
|
|
@@ -890,6 +906,38 @@ var BezierPath = /** @class */ (function () {
|
|
|
890
906
|
var relativeU = u - uResult.uPart;
|
|
891
907
|
return bCurve.getPerpendicular(relativeU);
|
|
892
908
|
};
|
|
909
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
910
|
+
/**
|
|
911
|
+
* Get all line intersections with this shape.
|
|
912
|
+
*
|
|
913
|
+
* This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
|
|
914
|
+
*
|
|
915
|
+
* @param {VertTuple} line - The line to find intersections with.
|
|
916
|
+
* @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).
|
|
917
|
+
* @returns {Array<Vertex>} - An array of all intersections with the shape's outline.
|
|
918
|
+
*/
|
|
919
|
+
BezierPath.prototype.lineIntersections = function (line, inVectorBoundsOnly) {
|
|
920
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
921
|
+
return this.bezierCurves.reduce(function (accu, curCurve) {
|
|
922
|
+
return accu.concat(curCurve.lineIntersections(line, inVectorBoundsOnly));
|
|
923
|
+
}, []);
|
|
924
|
+
};
|
|
925
|
+
/**
|
|
926
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
927
|
+
*
|
|
928
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
929
|
+
*
|
|
930
|
+
* @param line
|
|
931
|
+
* @param lineIntersectionTangents
|
|
932
|
+
* @returns
|
|
933
|
+
*/
|
|
934
|
+
BezierPath.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
935
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
936
|
+
return this.bezierCurves.reduce(function (accu, curCurve) {
|
|
937
|
+
return accu.concat(curCurve.lineIntersectionTangents(line, inVectorBoundsOnly));
|
|
938
|
+
}, []);
|
|
939
|
+
};
|
|
940
|
+
//--- END --- Implement interface `Intersectable`
|
|
893
941
|
/**
|
|
894
942
|
* This is a helper function to locate the curve index for a given
|
|
895
943
|
* absolute path position u.
|
|
@@ -1103,6 +1151,7 @@ var BezierPath = /** @class */ (function () {
|
|
|
1103
1151
|
}
|
|
1104
1152
|
neighbourCurve.updateArcLengths();
|
|
1105
1153
|
};
|
|
1154
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
1106
1155
|
/**
|
|
1107
1156
|
* Get the bounds of this Bézier path.
|
|
1108
1157
|
*
|
|
@@ -1124,6 +1173,7 @@ var BezierPath = /** @class */ (function () {
|
|
|
1124
1173
|
}
|
|
1125
1174
|
return new Bounds_1.Bounds(min, max);
|
|
1126
1175
|
};
|
|
1176
|
+
//--- END --- Implement interface `IBounded`
|
|
1127
1177
|
/**
|
|
1128
1178
|
* Get n 'equally' distributed vertices along this Bézier path.
|
|
1129
1179
|
*
|
|
@@ -1517,7 +1567,11 @@ exports.BezierPath = BezierPath;
|
|
|
1517
1567
|
* @modified 2022-10-09 Added the `fromDimension` function.
|
|
1518
1568
|
* @modified 2022-11-28 Added the `clone` method.
|
|
1519
1569
|
* @modified 2023-09-29 Added the `randomPoint` method.
|
|
1520
|
-
* @
|
|
1570
|
+
* @modified 2025-03-23 Added the `getMinDimension` and `getMaxDimension` methods.
|
|
1571
|
+
* @modified 2025-04-18 Change parameter type in `Bounds.computeFromVertices` from `Vertex` to more general `XYCoords`.
|
|
1572
|
+
* @modified 2025-04-19 Added methods to `Bounds` class: `getNorthPoint`, `getSouthPoint`, `getEastPoint` and `getWestPoint`.
|
|
1573
|
+
* @modified 2025-04-26 Added static method `Bounds.computeFromBoundsSet` to calculate containing bounds for a set of bounding boxes.
|
|
1574
|
+
* @version 1.8.0
|
|
1521
1575
|
**/
|
|
1522
1576
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1523
1577
|
exports.Bounds = void 0;
|
|
@@ -1545,6 +1599,54 @@ var Bounds = /** @class */ (function () {
|
|
|
1545
1599
|
this.width = max.x - min.x;
|
|
1546
1600
|
this.height = max.y - min.y;
|
|
1547
1601
|
}
|
|
1602
|
+
/**
|
|
1603
|
+
* Get the center point of the north bound.
|
|
1604
|
+
*
|
|
1605
|
+
* @method getNorthPoint
|
|
1606
|
+
* @instance
|
|
1607
|
+
* @memberof Bounds
|
|
1608
|
+
* @return {Vertex} The "northmost" centered point of this bounding box.
|
|
1609
|
+
*/
|
|
1610
|
+
Bounds.prototype.getNorthPoint = function () {
|
|
1611
|
+
return new Vertex_1.Vertex(this.min.x + this.width / 2.0, this.min.y);
|
|
1612
|
+
};
|
|
1613
|
+
;
|
|
1614
|
+
/**
|
|
1615
|
+
* Get the center point of the south bound.
|
|
1616
|
+
*
|
|
1617
|
+
* @method getNorthPoint
|
|
1618
|
+
* @instance
|
|
1619
|
+
* @memberof Bounds
|
|
1620
|
+
* @return {Vertex} The "southhmost" centered point of this bounding box.
|
|
1621
|
+
*/
|
|
1622
|
+
Bounds.prototype.getSouthPoint = function () {
|
|
1623
|
+
return new Vertex_1.Vertex(this.min.x + this.width / 2.0, this.max.y);
|
|
1624
|
+
};
|
|
1625
|
+
;
|
|
1626
|
+
/**
|
|
1627
|
+
* Get the center point of the west bound.
|
|
1628
|
+
*
|
|
1629
|
+
* @method getWestPoint
|
|
1630
|
+
* @instance
|
|
1631
|
+
* @memberof Bounds
|
|
1632
|
+
* @return {Vertex} The "westhmost" centered point of this bounding box.
|
|
1633
|
+
*/
|
|
1634
|
+
Bounds.prototype.getWestPoint = function () {
|
|
1635
|
+
return new Vertex_1.Vertex(this.min.x, this.min.y + this.height / 2.0);
|
|
1636
|
+
};
|
|
1637
|
+
;
|
|
1638
|
+
/**
|
|
1639
|
+
* Get the center point of the east bound.
|
|
1640
|
+
*
|
|
1641
|
+
* @method getEastPoint
|
|
1642
|
+
* @instance
|
|
1643
|
+
* @memberof Bounds
|
|
1644
|
+
* @return {Vertex} The "easthmost" centered point of this bounding box.
|
|
1645
|
+
*/
|
|
1646
|
+
Bounds.prototype.getEastPoint = function () {
|
|
1647
|
+
return new Vertex_1.Vertex(this.max.x, this.min.y + this.height / 2.0);
|
|
1648
|
+
};
|
|
1649
|
+
;
|
|
1548
1650
|
/**
|
|
1549
1651
|
* Convert this rectangular bounding box to a polygon with four vertices.
|
|
1550
1652
|
*
|
|
@@ -1567,6 +1669,22 @@ var Bounds = /** @class */ (function () {
|
|
|
1567
1669
|
Bounds.prototype.getCenter = function () {
|
|
1568
1670
|
return new Vertex_1.Vertex(this.min.x + (this.max.x - this.min.x) / 2.0, this.min.y + (this.max.y - this.min.y) / 2);
|
|
1569
1671
|
};
|
|
1672
|
+
/**
|
|
1673
|
+
* Get the minimum of `width` and `height`.
|
|
1674
|
+
*
|
|
1675
|
+
* @returns {number} The value of Math.min( this.width, this.height )
|
|
1676
|
+
*/
|
|
1677
|
+
Bounds.prototype.getMinDimension = function () {
|
|
1678
|
+
return Math.min(this.width, this.height);
|
|
1679
|
+
};
|
|
1680
|
+
/**
|
|
1681
|
+
* Get the minimum of `width` and `height`.
|
|
1682
|
+
*
|
|
1683
|
+
* @returns {number} The value of Math.min( this.width, this.height )
|
|
1684
|
+
*/
|
|
1685
|
+
Bounds.prototype.getMaxDimension = function () {
|
|
1686
|
+
return Math.max(this.width, this.height);
|
|
1687
|
+
};
|
|
1570
1688
|
/**
|
|
1571
1689
|
* Generate a random point inside this bounds object. Safe areas at the border to avoid
|
|
1572
1690
|
* included.
|
|
@@ -1619,12 +1737,13 @@ var Bounds = /** @class */ (function () {
|
|
|
1619
1737
|
* @static
|
|
1620
1738
|
* @method computeFromVertices
|
|
1621
1739
|
* @memberof Bounds
|
|
1622
|
-
* @param {Array<
|
|
1740
|
+
* @param {Array<XYCoords>} vertices - The set of vertices you want to get the bounding box for.
|
|
1623
1741
|
* @return The minimal Bounds for the given vertices.
|
|
1624
1742
|
**/
|
|
1625
1743
|
Bounds.computeFromVertices = function (vertices) {
|
|
1626
|
-
if (vertices.length == 0)
|
|
1744
|
+
if (vertices.length == 0) {
|
|
1627
1745
|
return new Bounds(new Vertex_1.Vertex(0, 0), new Vertex_1.Vertex(0, 0));
|
|
1746
|
+
}
|
|
1628
1747
|
var xMin = vertices[0].x;
|
|
1629
1748
|
var xMax = vertices[0].x;
|
|
1630
1749
|
var yMin = vertices[0].y;
|
|
@@ -1639,6 +1758,35 @@ var Bounds = /** @class */ (function () {
|
|
|
1639
1758
|
}
|
|
1640
1759
|
return new Bounds(new Vertex_1.Vertex(xMin, yMin), new Vertex_1.Vertex(xMax, yMax));
|
|
1641
1760
|
};
|
|
1761
|
+
/**
|
|
1762
|
+
* Compute the minimal bounding box for a given set of existing bounding boxes.
|
|
1763
|
+
*
|
|
1764
|
+
* An empty vertex array will return an empty bounding box located at (0,0).
|
|
1765
|
+
*
|
|
1766
|
+
* @static
|
|
1767
|
+
* @method computeFromBoundsSet
|
|
1768
|
+
* @memberof Bounds
|
|
1769
|
+
* @param {Array<IBounds>} boundingBoxes - The set of existing bounding boxes to get the containing bounding box for.
|
|
1770
|
+
* @return The minimal Bounds for the given bounds instances.
|
|
1771
|
+
**/
|
|
1772
|
+
Bounds.computeFromBoundsSet = function (boundingBoxes) {
|
|
1773
|
+
if (boundingBoxes.length == 0) {
|
|
1774
|
+
return new Bounds(new Vertex_1.Vertex(0, 0), new Vertex_1.Vertex(0, 0));
|
|
1775
|
+
}
|
|
1776
|
+
var xMin = boundingBoxes[0].min.x;
|
|
1777
|
+
var xMax = boundingBoxes[0].max.x;
|
|
1778
|
+
var yMin = boundingBoxes[0].min.y;
|
|
1779
|
+
var yMax = boundingBoxes[0].min.y;
|
|
1780
|
+
var bounds;
|
|
1781
|
+
for (var i in boundingBoxes) {
|
|
1782
|
+
bounds = boundingBoxes[i];
|
|
1783
|
+
xMin = Math.min(xMin, bounds.min.x);
|
|
1784
|
+
xMax = Math.max(xMax, bounds.max.x);
|
|
1785
|
+
yMin = Math.min(yMin, bounds.min.y);
|
|
1786
|
+
yMax = Math.max(yMax, bounds.min.y);
|
|
1787
|
+
}
|
|
1788
|
+
return new Bounds(new Vertex_1.Vertex(xMin, yMin), new Vertex_1.Vertex(xMax, yMax));
|
|
1789
|
+
};
|
|
1642
1790
|
/**
|
|
1643
1791
|
* Create a new `Bounds` instance just from `width` and `height`, located at (0,0) or the optionally given origin.
|
|
1644
1792
|
*
|
|
@@ -1675,10 +1823,13 @@ exports.Bounds = Bounds;
|
|
|
1675
1823
|
* @modified 2022-08-15 Added the `containsPoint` function.
|
|
1676
1824
|
* @modified 2022-08-23 Added the `lineIntersection` function.
|
|
1677
1825
|
* @modified 2022-08-23 Added the `closestPoint` function.
|
|
1678
|
-
* @
|
|
1826
|
+
* @modified 2025-04-09 Added the `Circle.move(amount: XYCoords)` method.
|
|
1827
|
+
* @modified 2025-04-16 Class `Circle` now implements interface `Intersectable`.
|
|
1828
|
+
* @version 1.5.0
|
|
1679
1829
|
**/
|
|
1680
1830
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1681
1831
|
exports.Circle = void 0;
|
|
1832
|
+
var Bounds_1 = __webpack_require__(76);
|
|
1682
1833
|
var Line_1 = __webpack_require__(939);
|
|
1683
1834
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
1684
1835
|
var Vector_1 = __webpack_require__(30);
|
|
@@ -1712,6 +1863,19 @@ var Circle = /** @class */ (function () {
|
|
|
1712
1863
|
this.center = center;
|
|
1713
1864
|
this.radius = radius;
|
|
1714
1865
|
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Move the circle by the given amount.
|
|
1868
|
+
*
|
|
1869
|
+
* @method move
|
|
1870
|
+
* @param {XYCoords} amount - The amount to move.
|
|
1871
|
+
* @instance
|
|
1872
|
+
* @memberof Circle
|
|
1873
|
+
* @return {Circle} this for chaining
|
|
1874
|
+
**/
|
|
1875
|
+
Circle.prototype.move = function (amount) {
|
|
1876
|
+
this.center.add(amount);
|
|
1877
|
+
return this;
|
|
1878
|
+
};
|
|
1715
1879
|
/**
|
|
1716
1880
|
* Check if the given circle is fully contained inside this circle.
|
|
1717
1881
|
*
|
|
@@ -1782,7 +1946,21 @@ var Circle = /** @class */ (function () {
|
|
|
1782
1946
|
var pointA = Circle.circleUtils.vertAt(angle, this.radius);
|
|
1783
1947
|
// Construct the perpendicular of the line in point a. Then move relative to center.
|
|
1784
1948
|
return new Vector_1.Vector(pointA, new Vertex_1.Vertex(0, 0)).add(this.center).perp();
|
|
1949
|
+
// return (new Vector(this.center.clone(), pointA).add(pointA) as Vector).perp() as Vector;
|
|
1785
1950
|
};
|
|
1951
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
1952
|
+
/**
|
|
1953
|
+
* Get the bounding box (bounds) of this Circle.
|
|
1954
|
+
*
|
|
1955
|
+
* @method getBounds
|
|
1956
|
+
* @instance
|
|
1957
|
+
* @memberof Circle
|
|
1958
|
+
* @return {Bounds} The rectangular bounds of this Circle.
|
|
1959
|
+
**/
|
|
1960
|
+
Circle.prototype.getBounds = function () {
|
|
1961
|
+
return new Bounds_1.Bounds(this.center.clone().subXY(Math.abs(this.radius), Math.abs(this.radius)), this.center.clone().addXY(Math.abs(this.radius), Math.abs(this.radius)));
|
|
1962
|
+
};
|
|
1963
|
+
//--- END --- Implement interface `Intersectable`
|
|
1786
1964
|
/**
|
|
1787
1965
|
* Calculate the intersection points (if exists) with the given circle.
|
|
1788
1966
|
*
|
|
@@ -1842,7 +2020,7 @@ var Circle = /** @class */ (function () {
|
|
|
1842
2020
|
* @instance
|
|
1843
2021
|
* @memberof Circle
|
|
1844
2022
|
* @param {Vertex} a- The first of the two points defining the line.
|
|
1845
|
-
* @param {
|
|
2023
|
+
* @param {XYCoords} b - The second of the two points defining the line.
|
|
1846
2024
|
* @return {Line|null} The intersection points (as a line) or null if this circle does not intersect the line given.
|
|
1847
2025
|
**/
|
|
1848
2026
|
Circle.prototype.lineIntersection = function (a, b) {
|
|
@@ -1875,8 +2053,57 @@ var Circle = /** @class */ (function () {
|
|
|
1875
2053
|
interA.y = (-det * diff.x + Math.abs(diff.y) * sqrt) / distSquared;
|
|
1876
2054
|
interB.y = (-det * diff.x - Math.abs(diff.y) * sqrt) / distSquared;
|
|
1877
2055
|
return new Line_1.Line(interA.add(this.center), interB.add(this.center));
|
|
1878
|
-
// return new Line(interA, interB);
|
|
1879
2056
|
};
|
|
2057
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
2058
|
+
/**
|
|
2059
|
+
* Get all line intersections with this circle.
|
|
2060
|
+
*
|
|
2061
|
+
* This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
|
|
2062
|
+
*
|
|
2063
|
+
* @param {VertTuple} line - The line to find intersections with.
|
|
2064
|
+
* @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).
|
|
2065
|
+
* @returns {Array<Vertex>} - An array of all intersections with the circle outline.
|
|
2066
|
+
*/
|
|
2067
|
+
Circle.prototype.lineIntersections = function (line, inVectorBoundsOnly) {
|
|
2068
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
2069
|
+
// Find the intersections of all lines inside the edge bounds
|
|
2070
|
+
var intersectioLine = this.lineIntersection(line.a, line.b);
|
|
2071
|
+
if (!intersectioLine) {
|
|
2072
|
+
return [];
|
|
2073
|
+
}
|
|
2074
|
+
if (inVectorBoundsOnly) {
|
|
2075
|
+
// const maxDist = line.length();
|
|
2076
|
+
return [intersectioLine.a, intersectioLine.b].filter(function (vert) { return line.hasPoint(vert, true); });
|
|
2077
|
+
}
|
|
2078
|
+
else {
|
|
2079
|
+
return [intersectioLine.a, intersectioLine.b];
|
|
2080
|
+
}
|
|
2081
|
+
};
|
|
2082
|
+
/**
|
|
2083
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
2084
|
+
*
|
|
2085
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
2086
|
+
*
|
|
2087
|
+
* @param line
|
|
2088
|
+
* @param lineIntersectionTangents
|
|
2089
|
+
* @returns
|
|
2090
|
+
*/
|
|
2091
|
+
Circle.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
2092
|
+
var _this = this;
|
|
2093
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
2094
|
+
// Find the intersections of all lines plus their tangents inside the circle bounds
|
|
2095
|
+
var interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);
|
|
2096
|
+
return interSectionPoints.map(function (vert) {
|
|
2097
|
+
// Calculate angle
|
|
2098
|
+
var lineFromCenter = new Line_1.Line(_this.center, vert);
|
|
2099
|
+
var angle = lineFromCenter.angle();
|
|
2100
|
+
// console.log("angle", (angle / Math.PI) * 180.0);
|
|
2101
|
+
// const angle = Math.random() * Math.PI * 2; // TODO
|
|
2102
|
+
// Calculate tangent at angle
|
|
2103
|
+
return _this.tangentAt(angle);
|
|
2104
|
+
});
|
|
2105
|
+
};
|
|
2106
|
+
//--- END --- Implement interface `Intersectable`
|
|
1880
2107
|
/**
|
|
1881
2108
|
* Calculate the closest point on the outline of this circle to the given point.
|
|
1882
2109
|
*
|
|
@@ -1937,12 +2164,20 @@ exports.Circle = Circle;
|
|
|
1937
2164
|
* @modified 2024-03-08 Added the `containsAngle` method.
|
|
1938
2165
|
* @modified 2024-03-09 Added the `circleSectorIntersection` method to find coherent sector intersections..
|
|
1939
2166
|
* @modified 2024-03-09 Added the `angleAt` method to determine any angle at some ratio.
|
|
2167
|
+
* @modified 2025-04-02 Adding the `CircleSector.lineIntersections` and `CircleSector.lineIntersectionTangents` and implementing `Intersectable`.
|
|
2168
|
+
* @modified 2025-04-09 Adding the `CircleSector.move()` method.
|
|
2169
|
+
* @modified 2025-04-19 Tweaking the `CircleSector.containsAngle` method: all values (input angle, start- and end- angle) are wrapped into [0,2*PI) now.
|
|
2170
|
+
* @modified 2025-04-19 Class `CircleSector` implements interface `Bounded` now (method `getBounds` added).
|
|
1940
2171
|
* @version 1.2.0
|
|
1941
2172
|
**/
|
|
1942
2173
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1943
2174
|
exports.CircleSector = void 0;
|
|
2175
|
+
var Bounds_1 = __webpack_require__(76);
|
|
1944
2176
|
var Circle_1 = __webpack_require__(118);
|
|
2177
|
+
var Line_1 = __webpack_require__(939);
|
|
1945
2178
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
2179
|
+
var Vertex_1 = __webpack_require__(787);
|
|
2180
|
+
var geomutils_1 = __webpack_require__(328);
|
|
1946
2181
|
/**
|
|
1947
2182
|
* @classdesc A simple circle sector: circle, start- and end-angle.
|
|
1948
2183
|
*
|
|
@@ -1972,6 +2207,49 @@ var CircleSector = /** @class */ (function () {
|
|
|
1972
2207
|
this.startAngle = startAngle;
|
|
1973
2208
|
this.endAngle = endAngle;
|
|
1974
2209
|
}
|
|
2210
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
2211
|
+
/**
|
|
2212
|
+
* Get the bounds of this ellipse.
|
|
2213
|
+
*
|
|
2214
|
+
* The bounds are approximated by the underlying segment buffer; the more segment there are,
|
|
2215
|
+
* the more accurate will be the returned bounds.
|
|
2216
|
+
*
|
|
2217
|
+
* @method getBounds
|
|
2218
|
+
* @instance
|
|
2219
|
+
* @memberof VEllipse
|
|
2220
|
+
* @return {Bounds} The bounds of this curve.
|
|
2221
|
+
**/
|
|
2222
|
+
CircleSector.prototype.getBounds = function () {
|
|
2223
|
+
var _self = this;
|
|
2224
|
+
var circleBounds = this.circle.getBounds();
|
|
2225
|
+
// Calculage angles from east, west, north and south box points and check if they are inside
|
|
2226
|
+
var candidates = [
|
|
2227
|
+
circleBounds.getNorthPoint(),
|
|
2228
|
+
circleBounds.getSouthPoint(),
|
|
2229
|
+
circleBounds.getWestPoint(),
|
|
2230
|
+
circleBounds.getEastPoint()
|
|
2231
|
+
].filter(function (point) {
|
|
2232
|
+
// Check for each candidate points if they are contained in this sector. Drop if not.
|
|
2233
|
+
var angle = new Line_1.Line(_self.circle.center, point).angle();
|
|
2234
|
+
return _self.containsAngle(angle);
|
|
2235
|
+
});
|
|
2236
|
+
// Compute bounds and inlcude start end end point (they are definitely part of the bounds)
|
|
2237
|
+
return Bounds_1.Bounds.computeFromVertices(candidates.concat([this.getStartPoint(), this.getEndPoint()]));
|
|
2238
|
+
};
|
|
2239
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
2240
|
+
/**
|
|
2241
|
+
* Move the circle sector by the given amount.
|
|
2242
|
+
*
|
|
2243
|
+
* @method move
|
|
2244
|
+
* @param {XYCoords} amount - The amount to move.
|
|
2245
|
+
* @instance
|
|
2246
|
+
* @memberof CircleSector
|
|
2247
|
+
* @return {CircleSector} this for chaining
|
|
2248
|
+
**/
|
|
2249
|
+
CircleSector.prototype.move = function (amount) {
|
|
2250
|
+
this.circle.move(amount);
|
|
2251
|
+
return this;
|
|
2252
|
+
};
|
|
1975
2253
|
/**
|
|
1976
2254
|
* Checks wether the given angle (must be inside 0 and PI*2) is contained inside this sector.
|
|
1977
2255
|
*
|
|
@@ -1982,12 +2260,22 @@ var CircleSector = /** @class */ (function () {
|
|
|
1982
2260
|
* @return {boolean} True if (and only if) this sector contains the given angle.
|
|
1983
2261
|
*/
|
|
1984
2262
|
CircleSector.prototype.containsAngle = function (angle) {
|
|
1985
|
-
|
|
1986
|
-
|
|
2263
|
+
var wrappedAngle = geomutils_1.geomutils.mapAngleTo2PI(angle);
|
|
2264
|
+
var wrappedStart = geomutils_1.geomutils.mapAngleTo2PI(this.startAngle);
|
|
2265
|
+
var wrappedEnd = geomutils_1.geomutils.mapAngleTo2PI(this.endAngle);
|
|
2266
|
+
// TODO: cleanup
|
|
2267
|
+
// if (this.startAngle <= this.endAngle) {
|
|
2268
|
+
// return angle >= this.startAngle && angle < this.endAngle;
|
|
2269
|
+
// } else {
|
|
2270
|
+
// // startAngle > endAngle
|
|
2271
|
+
// return angle >= this.startAngle || angle < this.endAngle;
|
|
2272
|
+
// }
|
|
2273
|
+
if (wrappedStart <= wrappedEnd) {
|
|
2274
|
+
return wrappedAngle >= wrappedStart && wrappedAngle < wrappedEnd;
|
|
1987
2275
|
}
|
|
1988
2276
|
else {
|
|
1989
2277
|
// startAngle > endAngle
|
|
1990
|
-
return
|
|
2278
|
+
return wrappedAngle >= wrappedStart || wrappedAngle < wrappedEnd;
|
|
1991
2279
|
}
|
|
1992
2280
|
};
|
|
1993
2281
|
/**
|
|
@@ -2081,6 +2369,54 @@ var CircleSector = /** @class */ (function () {
|
|
|
2081
2369
|
}
|
|
2082
2370
|
return resultSector;
|
|
2083
2371
|
};
|
|
2372
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
2373
|
+
/**
|
|
2374
|
+
* Get the line intersections as vectors with this ellipse.
|
|
2375
|
+
*
|
|
2376
|
+
* @method lineIntersections
|
|
2377
|
+
* @instance
|
|
2378
|
+
* @param {VertTuple<Vector> ray - The line/ray to intersect this ellipse with.
|
|
2379
|
+
* @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.
|
|
2380
|
+
* @returns
|
|
2381
|
+
*/
|
|
2382
|
+
CircleSector.prototype.lineIntersections = function (ray, inVectorBoundsOnly) {
|
|
2383
|
+
var _this = this;
|
|
2384
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
2385
|
+
// First get all line intersections from underlying ellipse.
|
|
2386
|
+
var ellipseIntersections = this.circle.lineIntersections(ray, inVectorBoundsOnly);
|
|
2387
|
+
// Drop all intersection points that are not contained in the circle sectors bounds.
|
|
2388
|
+
var tmpLine = new Line_1.Line(this.circle.center, new Vertex_1.Vertex());
|
|
2389
|
+
return ellipseIntersections.filter(function (intersectionPoint) {
|
|
2390
|
+
tmpLine.b.set(intersectionPoint);
|
|
2391
|
+
var lineAngle = tmpLine.angle();
|
|
2392
|
+
return _this.containsAngle(geomutils_1.geomutils.wrapMinMax(lineAngle, 0, Math.PI * 2));
|
|
2393
|
+
});
|
|
2394
|
+
};
|
|
2395
|
+
/**
|
|
2396
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
2397
|
+
*
|
|
2398
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
2399
|
+
*
|
|
2400
|
+
* @param line
|
|
2401
|
+
* @param lineIntersectionTangents
|
|
2402
|
+
* @returns
|
|
2403
|
+
*/
|
|
2404
|
+
CircleSector.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
2405
|
+
var _this = this;
|
|
2406
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
2407
|
+
// Find the intersections of all lines plus their tangents inside the circle bounds
|
|
2408
|
+
var interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);
|
|
2409
|
+
return interSectionPoints.map(function (vert) {
|
|
2410
|
+
// Calculate angle
|
|
2411
|
+
var lineFromCenter = new Line_1.Line(_this.circle.center, vert);
|
|
2412
|
+
var angle = lineFromCenter.angle();
|
|
2413
|
+
// console.log("angle", (angle / Math.PI) * 180.0);
|
|
2414
|
+
// const angle = Math.random() * Math.PI * 2; // TODO
|
|
2415
|
+
// Calculate tangent at angle
|
|
2416
|
+
return _this.circle.tangentAt(angle);
|
|
2417
|
+
});
|
|
2418
|
+
};
|
|
2419
|
+
//--- END --- Implement interface `Intersectable`
|
|
2084
2420
|
/**
|
|
2085
2421
|
* This function should invalidate any installed listeners and invalidate this object.
|
|
2086
2422
|
* After calling this function the object might not hold valid data any more and
|
|
@@ -2186,7 +2522,17 @@ exports.CircleSector = CircleSector;
|
|
|
2186
2522
|
* @modified 2022-10-17 The `CubicBezierCurve` class now implements the new `PathSegment` interface.
|
|
2187
2523
|
* @modified 2023-09-30 Added the function `CubicbezierCurve.getSubCurve(number,number)` – similar to `getSubCurveAt(...)` but with absolute position parameters.
|
|
2188
2524
|
* @modified 2023-10-07 Added the `trimEnd`, `trimEndAt`, `trimStart`, `trimStartAt` methods.
|
|
2189
|
-
* @
|
|
2525
|
+
* @modified 2025-04-09 Added the `CubicBezierCurve.move` method to match the convention – which just calls `translate`.
|
|
2526
|
+
* @modified 2025-04-09 Modified the `CubicBezierCurve.translate` method: chaning parameter `Vertex` to more generalized `XYCoords`.
|
|
2527
|
+
* @modified 2025-04-13 Changed visibility of `CubicBezierCurve.utils` from 'private' to 'public'.
|
|
2528
|
+
* @modified 2025-04-13 Added helper function `CubicBezierCurve.utils.bezierCoeffs`.
|
|
2529
|
+
* @modified 2025-04-13 Added helper functopn `CubicBezierCurve.utils.sgn(number)` for division safe sign calculation.
|
|
2530
|
+
* @modified 2025-03-13 Class `CubicBezierCurve` is now implementing interface `Intersectable`.
|
|
2531
|
+
* @modified 2025-04-18 Added evaluation method for cubic Bézier curves `CubicBezierCurve.utils.evaluateT`.
|
|
2532
|
+
* @modified 2025-04-18 Refactored method `CubicBezierCurve.getPointAt` to use `evaluateT`.
|
|
2533
|
+
* @modified 2025-04-18 Fixed the `CubicBezierCurve.getBounds` method: now returning the real bounding box. Before it was an approximated one.
|
|
2534
|
+
* @modified 2025-ß4-18 Added helper methods for bounding box calculation `CubucBezierCurve.util.cubicPolyMinMax` and `cubicPoly`.
|
|
2535
|
+
* @version 2.9.0
|
|
2190
2536
|
*
|
|
2191
2537
|
* @file CubicBezierCurve
|
|
2192
2538
|
* @public
|
|
@@ -2281,7 +2627,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2281
2627
|
* Translate the whole curve by the given {x,y} amount: moves all four points.
|
|
2282
2628
|
*
|
|
2283
2629
|
* @method translate
|
|
2284
|
-
* @param {
|
|
2630
|
+
* @param {XYCoords} amount - The amount to translate this curve by.
|
|
2285
2631
|
* @instance
|
|
2286
2632
|
* @memberof CubicBezierCurve
|
|
2287
2633
|
* @return {CubicBezierCurve} this (for chaining).
|
|
@@ -2293,6 +2639,18 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2293
2639
|
this.endPoint.add(amount);
|
|
2294
2640
|
return this;
|
|
2295
2641
|
};
|
|
2642
|
+
/**
|
|
2643
|
+
* Translate the whole curve by the given {x,y} amount: moves all four points.
|
|
2644
|
+
*
|
|
2645
|
+
* @method translate
|
|
2646
|
+
* @param {XYCoords} amount - The amount to translate this curve by.
|
|
2647
|
+
* @instance
|
|
2648
|
+
* @memberof CubicBezierCurve
|
|
2649
|
+
* @return {CubicBezierCurve} this (for chaining).
|
|
2650
|
+
**/
|
|
2651
|
+
CubicBezierCurve.prototype.move = function (amount) {
|
|
2652
|
+
return this.translate(amount);
|
|
2653
|
+
};
|
|
2296
2654
|
/**
|
|
2297
2655
|
* Reverse this curve, means swapping start- and end-point and swapping
|
|
2298
2656
|
* start-control- and end-control-point.
|
|
@@ -2373,6 +2731,9 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2373
2731
|
*
|
|
2374
2732
|
* This function uses a recursive approach by cutting the curve into several linear segments.
|
|
2375
2733
|
*
|
|
2734
|
+
* @method getClosestT
|
|
2735
|
+
* @instance
|
|
2736
|
+
* @memberof CubicBezierCurve
|
|
2376
2737
|
* @param {Vertex} p - The point to find the closest position ('t' on the curve).
|
|
2377
2738
|
* @return {number}
|
|
2378
2739
|
**/
|
|
@@ -2422,27 +2783,35 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2422
2783
|
tNext: tStart + tDiff * (Math.min(stepCount, minIndex + 1) / stepCount)
|
|
2423
2784
|
};
|
|
2424
2785
|
};
|
|
2786
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
2425
2787
|
/**
|
|
2426
2788
|
* Get the bounds of this bezier curve.
|
|
2427
2789
|
*
|
|
2428
2790
|
* The bounds are approximated by the underlying segment buffer; the more segment there are,
|
|
2429
2791
|
* the more accurate will be the returned bounds.
|
|
2430
2792
|
*
|
|
2431
|
-
* @
|
|
2793
|
+
* @method getClosestT
|
|
2794
|
+
* @instance
|
|
2795
|
+
* @memberof CubicBezierCurve
|
|
2796
|
+
* @return {Bounds} The bounds of this ellipse.
|
|
2432
2797
|
**/
|
|
2433
2798
|
CubicBezierCurve.prototype.getBounds = function () {
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
var
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2799
|
+
// Thanks to Richard "RM" for the Bézier bounds calculatin
|
|
2800
|
+
// https://jsfiddle.net/SalixAlba/QQnvm/4/
|
|
2801
|
+
var xMinMax = CubicBezierCurve.utils.cubicPolyMinMax(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x);
|
|
2802
|
+
var xl = xMinMax.min;
|
|
2803
|
+
var xh = xMinMax.max;
|
|
2804
|
+
var yMinMax = CubicBezierCurve.utils.cubicPolyMinMax(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y);
|
|
2805
|
+
var yl = yMinMax.min;
|
|
2806
|
+
var yh = yMinMax.max;
|
|
2807
|
+
return Bounds_1.Bounds.computeFromVertices([
|
|
2808
|
+
{ x: xl, y: yl },
|
|
2809
|
+
{ x: xl, y: yh },
|
|
2810
|
+
{ x: xh, y: yh },
|
|
2811
|
+
{ x: xh, y: yl }
|
|
2812
|
+
]);
|
|
2813
|
+
};
|
|
2814
|
+
//--- END --- Implement interface `IBounded`
|
|
2446
2815
|
/**
|
|
2447
2816
|
* Get the start point of the curve.<br>
|
|
2448
2817
|
* <br>
|
|
@@ -2529,14 +2898,19 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2529
2898
|
**/
|
|
2530
2899
|
CubicBezierCurve.prototype.getPointAt = function (t) {
|
|
2531
2900
|
// Perform some powerful math magic
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2901
|
+
// TODO: cleanup
|
|
2902
|
+
// const x: number =
|
|
2903
|
+
// this.startPoint.x * Math.pow(1.0 - t, 3) +
|
|
2904
|
+
// this.startControlPoint.x * 3 * t * Math.pow(1.0 - t, 2) +
|
|
2905
|
+
// this.endControlPoint.x * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
2906
|
+
// this.endPoint.x * Math.pow(t, 3);
|
|
2907
|
+
// const y: number =
|
|
2908
|
+
// this.startPoint.y * Math.pow(1.0 - t, 3) +
|
|
2909
|
+
// this.startControlPoint.y * 3 * t * Math.pow(1.0 - t, 2) +
|
|
2910
|
+
// this.endControlPoint.y * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
2911
|
+
// this.endPoint.y * Math.pow(t, 3);
|
|
2912
|
+
var x = CubicBezierCurve.utils.evaluateT(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x, t);
|
|
2913
|
+
var y = CubicBezierCurve.utils.evaluateT(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y, t);
|
|
2540
2914
|
return new Vertex_1.Vertex(x, y);
|
|
2541
2915
|
};
|
|
2542
2916
|
/**
|
|
@@ -2677,17 +3051,7 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2677
3051
|
* @return {CubicBezierCurve} The sub curve as a new curve.
|
|
2678
3052
|
**/
|
|
2679
3053
|
CubicBezierCurve.prototype.getSubCurveAt = function (tStart, tEnd) {
|
|
2680
|
-
//
|
|
2681
|
-
// const endVec: Vector = new Vector(this.getPointAt(tEnd), this.getTangentAt(tEnd).inv());
|
|
2682
|
-
// // Tangents are relative. Make absolute.
|
|
2683
|
-
// startVec.b.add(startVec.a);
|
|
2684
|
-
// endVec.b.add(endVec.a);
|
|
2685
|
-
// // This 'splits' the curve at the given point at t.
|
|
2686
|
-
// startVec.scale(0.33333333 * (tEnd - tStart));
|
|
2687
|
-
// endVec.scale(0.33333333 * (tEnd - tStart));
|
|
2688
|
-
// // Draw the bezier curve
|
|
2689
|
-
// // pb.draw.cubicBezier( startVec.a, endVec.a, startVec.b, endVec.b, '#8800ff', 2 );
|
|
2690
|
-
// return new CubicBezierCurve(startVec.a, endVec.a, startVec.b, endVec.b);
|
|
3054
|
+
// This 'splits' the curve at the given point at t.
|
|
2691
3055
|
var subCurbePoints = CubicBezierCurve.utils.getSubCurvePointsAt(this, tStart, tEnd);
|
|
2692
3056
|
return new CubicBezierCurve(subCurbePoints[0], subCurbePoints[1], subCurbePoints[2], subCurbePoints[3]);
|
|
2693
3057
|
};
|
|
@@ -2779,6 +3143,73 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2779
3143
|
return this.endControlPoint;
|
|
2780
3144
|
};
|
|
2781
3145
|
//---END PathSegment-------------------------
|
|
3146
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
3147
|
+
/**
|
|
3148
|
+
* Get all line intersections with this shape.
|
|
3149
|
+
*
|
|
3150
|
+
* This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
|
|
3151
|
+
*
|
|
3152
|
+
* @param {VertTuple} line - The line to find intersections with.
|
|
3153
|
+
* @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).
|
|
3154
|
+
* @returns {Array<Vertex>} - An array of all intersections with the shape outline.
|
|
3155
|
+
*/
|
|
3156
|
+
CubicBezierCurve.prototype.lineIntersections = function (line, inVectorBoundsOnly) {
|
|
3157
|
+
var _this = this;
|
|
3158
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
3159
|
+
var intersectionTs = this.lineIntersectionTs(line);
|
|
3160
|
+
var intersectionPoints = intersectionTs.map(function (t) {
|
|
3161
|
+
return _this.getPointAt(t);
|
|
3162
|
+
});
|
|
3163
|
+
if (inVectorBoundsOnly) {
|
|
3164
|
+
// const maxDist = line.length();
|
|
3165
|
+
return intersectionPoints.filter(function (vert) { return line.hasPoint(vert, true); });
|
|
3166
|
+
}
|
|
3167
|
+
else {
|
|
3168
|
+
return intersectionPoints;
|
|
3169
|
+
}
|
|
3170
|
+
};
|
|
3171
|
+
/**
|
|
3172
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
3173
|
+
*
|
|
3174
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
3175
|
+
*
|
|
3176
|
+
* @param line
|
|
3177
|
+
* @param lineIntersectionTangents
|
|
3178
|
+
* @returns
|
|
3179
|
+
*/
|
|
3180
|
+
CubicBezierCurve.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
3181
|
+
var _this = this;
|
|
3182
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
3183
|
+
var intersectionTs = this.lineIntersectionTs(line);
|
|
3184
|
+
var intersectionTangents = intersectionTs.map(function (t) {
|
|
3185
|
+
var startPoint = _this.getPointAt(t);
|
|
3186
|
+
var endPoint = _this.getTangentAt(t);
|
|
3187
|
+
return new Vector_1.Vector(startPoint, endPoint.add(startPoint));
|
|
3188
|
+
});
|
|
3189
|
+
if (inVectorBoundsOnly) {
|
|
3190
|
+
return intersectionTangents.filter(function (vec) { return line.hasPoint(vec.a, true); });
|
|
3191
|
+
}
|
|
3192
|
+
else {
|
|
3193
|
+
return intersectionTangents;
|
|
3194
|
+
}
|
|
3195
|
+
};
|
|
3196
|
+
//--- END --- Implement interface `Intersectable`
|
|
3197
|
+
CubicBezierCurve.prototype.lineIntersectionTs = function (line) {
|
|
3198
|
+
var A = line.b.y - line.a.y; // A=y2-y1
|
|
3199
|
+
var B = line.a.x - line.b.x; // B=x1-x2
|
|
3200
|
+
var C = line.a.x * (line.a.y - line.b.y) + line.a.y * (line.b.x - line.a.x); //C=x1*(y1-y2)+y1*(x2-x1)
|
|
3201
|
+
// var bx = bezierCoeffs(px[0], px[1], px[2], px[3]);
|
|
3202
|
+
// var by = bezierCoeffs(py[0], py[1], py[2], py[3]);
|
|
3203
|
+
var bx = CubicBezierCurve.utils.bezierCoeffs(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x);
|
|
3204
|
+
var by = CubicBezierCurve.utils.bezierCoeffs(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y);
|
|
3205
|
+
var poly = Array(4);
|
|
3206
|
+
poly[0] = A * bx[0] + B * by[0]; /*t^3*/
|
|
3207
|
+
poly[1] = A * bx[1] + B * by[1]; /*t^2*/
|
|
3208
|
+
poly[2] = A * bx[2] + B * by[2]; /*t*/
|
|
3209
|
+
poly[3] = A * bx[3] + B * by[3] + C; /*1*/
|
|
3210
|
+
var roots = CubicBezierCurve.utils.cubicRoots(poly);
|
|
3211
|
+
return roots.filter(function (root) { return root != -1; });
|
|
3212
|
+
};
|
|
2782
3213
|
/**
|
|
2783
3214
|
* Check if this and the specified curve are equal.<br>
|
|
2784
3215
|
* <br>
|
|
@@ -2945,6 +3376,71 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2945
3376
|
* Helper utils.
|
|
2946
3377
|
*/
|
|
2947
3378
|
CubicBezierCurve.utils = {
|
|
3379
|
+
evaluateT: function (p0, p1, p2, p3, t) {
|
|
3380
|
+
return p0 * Math.pow(1.0 - t, 3) +
|
|
3381
|
+
p1 * 3 * t * Math.pow(1.0 - t, 2) +
|
|
3382
|
+
p2 * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
3383
|
+
p3 * Math.pow(t, 3);
|
|
3384
|
+
},
|
|
3385
|
+
cubicPolyMinMax: function (p0, p1, p2, p3) {
|
|
3386
|
+
// var polyX = CubicBezierCurve.utils.cubicPoly2(
|
|
3387
|
+
// p0, // P[0].X, // bezierCurve.startPoint.x,
|
|
3388
|
+
// p1, // P[1].X, // bezierCurve.startControlPoint.x,
|
|
3389
|
+
// p2, // P[2].X, // bezierCurve.endControlPoint.x,
|
|
3390
|
+
// p3 // P[3].X // bezierCurve.endPoint.x
|
|
3391
|
+
// );
|
|
3392
|
+
// var a = polyX.a;
|
|
3393
|
+
// var b = polyX.b;
|
|
3394
|
+
// var c = polyX.c;
|
|
3395
|
+
// var disc = polyX.b * polyX.b - 4 * polyX.a * polyX.c;
|
|
3396
|
+
var polyX = CubicBezierCurve.utils.cubicPoly(p0, // P[0].X, // bezierCurve.startPoint.x,
|
|
3397
|
+
p1, // P[1].X, // bezierCurve.startControlPoint.x,
|
|
3398
|
+
p2, // P[2].X, // bezierCurve.endControlPoint.x,
|
|
3399
|
+
p3 // P[3].X // bezierCurve.endPoint.x
|
|
3400
|
+
);
|
|
3401
|
+
var a = polyX[0]; // .a;
|
|
3402
|
+
var b = polyX[1]; // .b;
|
|
3403
|
+
var c = polyX[2]; // .c;
|
|
3404
|
+
//alert("a "+a+" "+b+" "+c);
|
|
3405
|
+
// var disc = b * b - 4 * a * c;
|
|
3406
|
+
var disc = polyX[1] * polyX[1] - 4 * polyX[0] * polyX[2];
|
|
3407
|
+
// var polyX = CubicBezierCurve.utils.bezierCoeffs(p3,p2,p1,p0);
|
|
3408
|
+
// var a = polyX[0]; //polyX.a;
|
|
3409
|
+
// var b = polyX[1]; // .b;
|
|
3410
|
+
// var c = polyX[2]; //.c;
|
|
3411
|
+
// var disc = polyX[1] * polyX[1] - 4 * polyX[0] * polyX[2];
|
|
3412
|
+
// var xl = Math.min(bCurve.endPoint.x, bCurve.startPoint.x); // P[0].X;
|
|
3413
|
+
// var xh = Math.max(bCurve.endPoint.x, bCurve.startPoint.x); // P[0].X;
|
|
3414
|
+
var xl = Math.min(p3, p0); // P[0].X;
|
|
3415
|
+
var xh = Math.max(p3, p0); // P[0].X;
|
|
3416
|
+
// if (P[3].X < xl) xl = P[3].X;
|
|
3417
|
+
// if (P[3].X > xh) xh = P[3].X;
|
|
3418
|
+
if (disc >= 0) {
|
|
3419
|
+
var t1 = (-b + Math.sqrt(disc)) / (2 * a);
|
|
3420
|
+
// alert("t1 " + t1);
|
|
3421
|
+
if (t1 > 0 && t1 < 1) {
|
|
3422
|
+
// var x1 = evalBez(PX, t1);
|
|
3423
|
+
// var x1 = bCurve.getPointAt(t1).x;
|
|
3424
|
+
var x1 = CubicBezierCurve.utils.evaluateT(p0, p1, p2, p3, t1); // bCurve.getPointAt(t1).x;
|
|
3425
|
+
if (x1 < xl)
|
|
3426
|
+
xl = x1;
|
|
3427
|
+
if (x1 > xh)
|
|
3428
|
+
xh = x1;
|
|
3429
|
+
}
|
|
3430
|
+
var t2 = (-b - Math.sqrt(disc)) / (2 * a);
|
|
3431
|
+
// alert("t2 " + t2);
|
|
3432
|
+
if (t2 > 0 && t2 < 1) {
|
|
3433
|
+
// var x2 = evalBez(PX, t2);
|
|
3434
|
+
// var x2 = bCurve.getPointAt(t2).x;
|
|
3435
|
+
var x2 = CubicBezierCurve.utils.evaluateT(p0, p1, p2, p3, t2); //
|
|
3436
|
+
if (x2 < xl)
|
|
3437
|
+
xl = x2;
|
|
3438
|
+
if (x2 > xh)
|
|
3439
|
+
xh = x2;
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
return { min: xl, max: xh };
|
|
3443
|
+
},
|
|
2948
3444
|
/**
|
|
2949
3445
|
* Get the points of a sub curve at the given start end end offsets (values between 0.0 and 1.0).
|
|
2950
3446
|
*
|
|
@@ -2968,6 +3464,94 @@ var CubicBezierCurve = /** @class */ (function () {
|
|
|
2968
3464
|
startVec.scale(0.33333333 * (tEnd - tStart));
|
|
2969
3465
|
endVec.scale(0.33333333 * (tEnd - tStart));
|
|
2970
3466
|
return [startVec.a, endVec.a, startVec.b, endVec.b];
|
|
3467
|
+
},
|
|
3468
|
+
/**
|
|
3469
|
+
* Compute the cubic roots for the given cubic polynomial coefficients.
|
|
3470
|
+
*
|
|
3471
|
+
* Based on
|
|
3472
|
+
* http://mysite.verizon.net/res148h4j/javascript/script_exact_cubic.html#the%20source%20code
|
|
3473
|
+
* Inspired by
|
|
3474
|
+
* https://www.particleincell.com/2013/cubic-line-intersection/
|
|
3475
|
+
* Thanks to Stephan Schmitt and Particle-In-Cell!
|
|
3476
|
+
*
|
|
3477
|
+
* @param poly
|
|
3478
|
+
* @returns
|
|
3479
|
+
*/
|
|
3480
|
+
cubicRoots: function (poly) {
|
|
3481
|
+
var a = poly[0];
|
|
3482
|
+
var b = poly[1];
|
|
3483
|
+
var c = poly[2];
|
|
3484
|
+
var d = poly[3];
|
|
3485
|
+
var A = b / a;
|
|
3486
|
+
var B = c / a;
|
|
3487
|
+
var C = d / a;
|
|
3488
|
+
var S, T, Im;
|
|
3489
|
+
var Q = (3 * B - Math.pow(A, 2)) / 9;
|
|
3490
|
+
var R = (9 * A * B - 27 * C - 2 * Math.pow(A, 3)) / 54;
|
|
3491
|
+
var D = Math.pow(Q, 3) + Math.pow(R, 2); // polynomial discriminant
|
|
3492
|
+
var ts = []; // Array();
|
|
3493
|
+
if (D >= 0) {
|
|
3494
|
+
// complex or duplicate roots
|
|
3495
|
+
S = CubicBezierCurve.utils.sgn(R + Math.sqrt(D)) * Math.pow(Math.abs(R + Math.sqrt(D)), 1 / 3);
|
|
3496
|
+
T = CubicBezierCurve.utils.sgn(R - Math.sqrt(D)) * Math.pow(Math.abs(R - Math.sqrt(D)), 1 / 3);
|
|
3497
|
+
ts[0] = -A / 3 + (S + T); // real root
|
|
3498
|
+
ts[1] = -A / 3 - (S + T) / 2; // real part of complex root
|
|
3499
|
+
ts[2] = -A / 3 - (S + T) / 2; // real part of complex root
|
|
3500
|
+
Im = Math.abs((Math.sqrt(3) * (S - T)) / 2); // complex part of root pair
|
|
3501
|
+
// Mark complex roots to be discarded
|
|
3502
|
+
if (Im != 0) {
|
|
3503
|
+
ts[1] = -1;
|
|
3504
|
+
ts[2] = -1;
|
|
3505
|
+
}
|
|
3506
|
+
} // distinct real roots
|
|
3507
|
+
else {
|
|
3508
|
+
var th = Math.acos(R / Math.sqrt(-Math.pow(Q, 3)));
|
|
3509
|
+
ts[0] = 2 * Math.sqrt(-Q) * Math.cos(th / 3) - A / 3;
|
|
3510
|
+
ts[1] = 2 * Math.sqrt(-Q) * Math.cos((th + 2 * Math.PI) / 3) - A / 3;
|
|
3511
|
+
ts[2] = 2 * Math.sqrt(-Q) * Math.cos((th + 4 * Math.PI) / 3) - A / 3;
|
|
3512
|
+
Im = 0.0;
|
|
3513
|
+
}
|
|
3514
|
+
// Discard all t's out of spec and sort the rest
|
|
3515
|
+
return ts.filter(function (t) { return t >= 0 && t <= 1.0; }).sort();
|
|
3516
|
+
},
|
|
3517
|
+
/**
|
|
3518
|
+
* Compute the Bézier coefficients from the given Bézier point coordinates.
|
|
3519
|
+
*
|
|
3520
|
+
* @param {number} p0 - The start point coordinate.
|
|
3521
|
+
* @param {number} p1 - The start control point coordinate.
|
|
3522
|
+
* @param {number} p2 - The end control point coordinate.
|
|
3523
|
+
* @param {number} p3 - The end point coordinate.
|
|
3524
|
+
* @returns {[number,number,number,number]}
|
|
3525
|
+
*/
|
|
3526
|
+
bezierCoeffs: function (p0, p1, p2, p3) {
|
|
3527
|
+
var coeffs = [NaN, NaN, NaN, NaN]; //Array(4);
|
|
3528
|
+
coeffs[0] = -p0 + 3 * p1 + -3 * p2 + p3;
|
|
3529
|
+
coeffs[1] = 3 * p0 - 6 * p1 + 3 * p2;
|
|
3530
|
+
coeffs[2] = -3 * p0 + 3 * p1;
|
|
3531
|
+
coeffs[3] = p0;
|
|
3532
|
+
return coeffs;
|
|
3533
|
+
},
|
|
3534
|
+
/**
|
|
3535
|
+
* Calculate the cubic polynomial coefficients used to find the bounding box.
|
|
3536
|
+
*
|
|
3537
|
+
* @param {number} p0 - The start point coordinate.
|
|
3538
|
+
* @param {number} p1 - The start control point coordinate.
|
|
3539
|
+
* @param {number} p2 - The end control point coordinate.
|
|
3540
|
+
* @param {number} p3 - The end point coordinate.
|
|
3541
|
+
* @returns {[number,number,number]}
|
|
3542
|
+
*/
|
|
3543
|
+
cubicPoly: function (p0, p1, p2, p3) {
|
|
3544
|
+
return [
|
|
3545
|
+
3 * p3 - 9 * p2 + 9 * p1 - 3 * p0,
|
|
3546
|
+
6 * p0 - 12 * p1 + 6 * p2,
|
|
3547
|
+
3 * p1 - 3 * p0
|
|
3548
|
+
];
|
|
3549
|
+
},
|
|
3550
|
+
/**
|
|
3551
|
+
* sign of number, but is division safe: no zero returned :)
|
|
3552
|
+
*/
|
|
3553
|
+
sgn: function (x) {
|
|
3554
|
+
return x < 0.0 ? -1 : 1;
|
|
2971
3555
|
}
|
|
2972
3556
|
};
|
|
2973
3557
|
return CubicBezierCurve;
|
|
@@ -3536,7 +4120,9 @@ exports.KeyHandler = KeyHandler;
|
|
|
3536
4120
|
* @modified 2022-10-09 Changed the actual return value of the `intersection` function to null (was undefined before).
|
|
3537
4121
|
* @modified 2022-10-17 Adding these methods from the `PathSegment` interface: getStartPoint, getEndPoint, revert.
|
|
3538
4122
|
* @modified 2023-09-25 Changed param type of `intersection()` from Line to VertTuple.
|
|
3539
|
-
* @
|
|
4123
|
+
* @modified 2025-04-15 Class `Line` now implements interface `Intersectable`.
|
|
4124
|
+
* @modified 2025-04-16 Class `Line` now implements interface `IBounded`.
|
|
4125
|
+
* @version 2.4.0
|
|
3540
4126
|
*
|
|
3541
4127
|
* @file Line
|
|
3542
4128
|
* @public
|
|
@@ -3558,6 +4144,8 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
3558
4144
|
})();
|
|
3559
4145
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3560
4146
|
exports.Line = void 0;
|
|
4147
|
+
var Bounds_1 = __webpack_require__(76);
|
|
4148
|
+
var Vector_1 = __webpack_require__(30);
|
|
3561
4149
|
var VertTuple_1 = __webpack_require__(590);
|
|
3562
4150
|
var Vertex_1 = __webpack_require__(787);
|
|
3563
4151
|
/**
|
|
@@ -3616,6 +4204,19 @@ var Line = /** @class */ (function (_super) {
|
|
|
3616
4204
|
// if we cast these lines infinitely in both directions, they intersect here:
|
|
3617
4205
|
return new Vertex_1.Vertex(x, y);
|
|
3618
4206
|
};
|
|
4207
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
4208
|
+
/**
|
|
4209
|
+
* Get the bounding box (bounds) of this Line.
|
|
4210
|
+
*
|
|
4211
|
+
* @method getBounds
|
|
4212
|
+
* @instance
|
|
4213
|
+
* @memberof Line
|
|
4214
|
+
* @return {Bounds} The rectangular bounds of this Line.
|
|
4215
|
+
**/
|
|
4216
|
+
Line.prototype.getBounds = function () {
|
|
4217
|
+
return Bounds_1.Bounds.computeFromVertices([this.a, this.b]);
|
|
4218
|
+
};
|
|
4219
|
+
//--- END --- Implement interface `IBounded`
|
|
3619
4220
|
//--- Implement PathSegment ---
|
|
3620
4221
|
/**
|
|
3621
4222
|
* Get the start point of this path segment.
|
|
@@ -3670,6 +4271,52 @@ var Line = /** @class */ (function (_super) {
|
|
|
3670
4271
|
this.b = tmp;
|
|
3671
4272
|
return this;
|
|
3672
4273
|
};
|
|
4274
|
+
//--- END Implement PathSegment ---
|
|
4275
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
4276
|
+
/**
|
|
4277
|
+
* Get all line intersections with this polygon.
|
|
4278
|
+
*
|
|
4279
|
+
* This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
|
|
4280
|
+
*
|
|
4281
|
+
* See demo `47-closest-vector-projection-on-polygon` for how it works.
|
|
4282
|
+
*
|
|
4283
|
+
* @param {VertTuple} line - The line to find intersections with.
|
|
4284
|
+
* @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).
|
|
4285
|
+
* @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.
|
|
4286
|
+
*/
|
|
4287
|
+
Line.prototype.lineIntersections = function (line, inVectorBoundsOnly) {
|
|
4288
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
4289
|
+
// Find the intersections of all lines inside the edge bounds
|
|
4290
|
+
var intersection = this.intersection(line);
|
|
4291
|
+
if (!intersection) {
|
|
4292
|
+
return []; // Both lines parallel
|
|
4293
|
+
}
|
|
4294
|
+
if (this.hasPoint(intersection, true) && (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {
|
|
4295
|
+
return [intersection];
|
|
4296
|
+
}
|
|
4297
|
+
else {
|
|
4298
|
+
return [];
|
|
4299
|
+
}
|
|
4300
|
+
};
|
|
4301
|
+
/**
|
|
4302
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
4303
|
+
*
|
|
4304
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
4305
|
+
*
|
|
4306
|
+
* @param line
|
|
4307
|
+
* @param inVectorBoundsOnly
|
|
4308
|
+
* @returns
|
|
4309
|
+
*/
|
|
4310
|
+
Line.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
4311
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
4312
|
+
// Find the intersection tangents of all lines inside the edge bounds
|
|
4313
|
+
var intersections = this.lineIntersections(line, inVectorBoundsOnly);
|
|
4314
|
+
if (intersections.length === 0) {
|
|
4315
|
+
return [];
|
|
4316
|
+
}
|
|
4317
|
+
var intrsctn = intersections[0];
|
|
4318
|
+
return [new Vector_1.Vector(this.a.clone(), this.b.clone()).moveTo(intrsctn)];
|
|
4319
|
+
};
|
|
3673
4320
|
return Line;
|
|
3674
4321
|
}(VertTuple_1.VertTuple));
|
|
3675
4322
|
exports.Line = Line;
|
|
@@ -4333,8 +4980,9 @@ exports.PBText = PBText;
|
|
|
4333
4980
|
* @modified 2023-09-29 Adding proper dicionary key and value types to the params of `PlotBoilerplate.utils.safeMergeByKeys` (was `object` before).
|
|
4334
4981
|
* @modified 2024-07-08 Adding `PlotBoilerplate.getGUI()` to retrieve the GUI instance.
|
|
4335
4982
|
* @modified 2024-08-25 Extending main class `PlotBoilerplate` optional param `isBackdropFiltersEnabled`.
|
|
4983
|
+
* @modified 2024-12-02 Adding the `triggerRedraw` to the `removeAll` method.
|
|
4336
4984
|
*
|
|
4337
|
-
* @version 1.
|
|
4985
|
+
* @version 1.20.0
|
|
4338
4986
|
*
|
|
4339
4987
|
* @file PlotBoilerplate
|
|
4340
4988
|
* @fileoverview The main class.
|
|
@@ -5094,16 +5742,19 @@ var PlotBoilerplate = /** @class */ (function () {
|
|
|
5094
5742
|
*
|
|
5095
5743
|
* @method removeAll
|
|
5096
5744
|
* @param {boolean=false} keepVertices
|
|
5745
|
+
* @param {boolean=true} triggerRedraw - By default this method triggers the redraw routine; passing `false` will suppress redrawing.
|
|
5097
5746
|
* @instance
|
|
5098
5747
|
* @memberof PlotBoilerplate
|
|
5099
5748
|
* @return {void}
|
|
5100
5749
|
*/
|
|
5101
|
-
PlotBoilerplate.prototype.removeAll = function (keepVertices) {
|
|
5750
|
+
PlotBoilerplate.prototype.removeAll = function (keepVertices, triggerRedraw) {
|
|
5102
5751
|
this.drawables = [];
|
|
5103
5752
|
if (!Boolean(keepVertices)) {
|
|
5104
5753
|
this.vertices = [];
|
|
5105
5754
|
}
|
|
5106
|
-
|
|
5755
|
+
if (triggerRedraw || typeof triggerRedraw === "undefined") {
|
|
5756
|
+
this.redraw();
|
|
5757
|
+
}
|
|
5107
5758
|
};
|
|
5108
5759
|
/**
|
|
5109
5760
|
* Find the vertex near the given position.
|
|
@@ -5308,18 +5959,17 @@ var PlotBoilerplate = /** @class */ (function () {
|
|
|
5308
5959
|
}
|
|
5309
5960
|
else if (d instanceof Triangle_1.Triangle) {
|
|
5310
5961
|
draw.polyline([d.a, d.b, d.c], false, this.drawConfig.triangle.color, this.drawConfig.triangle.lineWidth);
|
|
5311
|
-
if (!this.drawConfig.drawHandlePoints)
|
|
5962
|
+
if (!this.drawConfig.drawHandlePoints) {
|
|
5312
5963
|
d.a.attr.renderTime = d.b.attr.renderTime = d.c.attr.renderTime = renderTime;
|
|
5964
|
+
}
|
|
5313
5965
|
}
|
|
5314
5966
|
else if (d instanceof VEllipse_1.VEllipse) {
|
|
5315
5967
|
if (this.drawConfig.drawHandleLines) {
|
|
5316
5968
|
draw.setCurrentId("".concat(d.uid, "_e0"));
|
|
5317
5969
|
draw.setCurrentClassName("".concat(d.className, "-v-line"));
|
|
5318
|
-
// draw.line( d.center.clone().add(0,d.axis.y-d.center.y), d.axis, '#c8c8c8' );
|
|
5319
5970
|
draw.handleLine(d.center.clone().add(0, d.signedRadiusV()).rotate(d.rotation, d.center), d.axis); // , "#c8c8c8");
|
|
5320
5971
|
draw.setCurrentId("".concat(d.uid, "_e1"));
|
|
5321
5972
|
draw.setCurrentClassName("".concat(d.className, "-h-line"));
|
|
5322
|
-
// draw.line( d.center.clone().add(d.axis.x-d.center.x,0), d.axis, '#c8c8c8' );
|
|
5323
5973
|
draw.handleLine(d.center.clone().add(d.signedRadiusH(), 0).rotate(d.rotation, d.center), d.axis); // , "#c8c8c8");
|
|
5324
5974
|
}
|
|
5325
5975
|
draw.setCurrentId(d.uid);
|
|
@@ -5335,12 +5985,6 @@ var PlotBoilerplate = /** @class */ (function () {
|
|
|
5335
5985
|
else if (d instanceof VEllipseSector_1.VEllipseSector) {
|
|
5336
5986
|
draw.setCurrentId(d.uid);
|
|
5337
5987
|
draw.setCurrentClassName("".concat(d.className));
|
|
5338
|
-
/* draw.ellipse( d.center,
|
|
5339
|
-
// Math.abs(d.axis.x-d.center.x), Math.abs(d.axis.y-d.center.y),
|
|
5340
|
-
d.radiusH(), d.radiusV(),
|
|
5341
|
-
this.drawConfig.ellipse.color,
|
|
5342
|
-
this.drawConfig.ellipse.lineWidth,
|
|
5343
|
-
d.rotation ); */
|
|
5344
5988
|
var data = VEllipseSector_1.VEllipseSector.ellipseSectorUtils.describeSVGArc(d.ellipse.center.x, d.ellipse.center.y, d.ellipse.radiusH(), d.ellipse.radiusV(), d.startAngle, d.endAngle, d.ellipse.rotation, { moveToStart: true });
|
|
5345
5989
|
draw.path(data, this.drawConfig.ellipseSector.color, this.drawConfig.ellipseSector.lineWidth);
|
|
5346
5990
|
}
|
|
@@ -6526,7 +7170,15 @@ exports["default"] = PlotBoilerplate;
|
|
|
6526
7170
|
* @modified 2023-09-25 Added the `Polygon.lineIntersections(Line,boolean)` function.
|
|
6527
7171
|
* @modified 2023-09-29 Added the `Polygon.closestLineIntersection(Line,boolean)` function.
|
|
6528
7172
|
* @modified 2023-11-24 Added the `Polygon.containsPolygon(Polygon)' function.
|
|
6529
|
-
* @
|
|
7173
|
+
* @modified 2024-10-12 Added the `getEdgeAt` method.
|
|
7174
|
+
* @modified 2024-10-30 Added the `getEdges` method.
|
|
7175
|
+
* @modified 2024-12-02 Added the `elimitateColinearEdges` method.
|
|
7176
|
+
* @modified 2025-02-12 Added the `containsVerts` method to test multiple vertices for containment.
|
|
7177
|
+
* @modified 2025-03-28 Added the `Polygon.utils.locateLineIntersecion` static helper method.
|
|
7178
|
+
* @modified 2025-03-28 Added the `Polygon.lineIntersectionTangents` method.
|
|
7179
|
+
* @modified 2025-04-09 Added the `Polygon.getCentroid` method.
|
|
7180
|
+
* @modified 2025-05-16 Class `Polygon` now implements `IBounded`.
|
|
7181
|
+
* @version 1.15.0
|
|
6530
7182
|
*
|
|
6531
7183
|
* @file Polygon
|
|
6532
7184
|
* @public
|
|
@@ -6536,8 +7188,11 @@ exports.Polygon = void 0;
|
|
|
6536
7188
|
var BezierPath_1 = __webpack_require__(733);
|
|
6537
7189
|
var Bounds_1 = __webpack_require__(76);
|
|
6538
7190
|
var Line_1 = __webpack_require__(939);
|
|
7191
|
+
var Triangle_1 = __webpack_require__(737);
|
|
6539
7192
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
7193
|
+
var Vector_1 = __webpack_require__(30);
|
|
6540
7194
|
var Vertex_1 = __webpack_require__(787);
|
|
7195
|
+
var geomutils_1 = __webpack_require__(328);
|
|
6541
7196
|
/**
|
|
6542
7197
|
* @classdesc A polygon class. Any polygon consists of an array of vertices; polygons can be open or closed.
|
|
6543
7198
|
*
|
|
@@ -6564,15 +7219,16 @@ var Polygon = /** @class */ (function () {
|
|
|
6564
7219
|
**/
|
|
6565
7220
|
this.className = "Polygon";
|
|
6566
7221
|
this.uid = UIDGenerator_1.UIDGenerator.next();
|
|
6567
|
-
if (typeof vertices == "undefined")
|
|
7222
|
+
if (typeof vertices == "undefined") {
|
|
6568
7223
|
vertices = [];
|
|
7224
|
+
}
|
|
6569
7225
|
this.vertices = vertices;
|
|
6570
7226
|
this.isOpen = isOpen || false;
|
|
6571
7227
|
}
|
|
6572
7228
|
/**
|
|
6573
7229
|
* Add a vertex to the end of the `vertices` array.
|
|
6574
7230
|
*
|
|
6575
|
-
* @method
|
|
7231
|
+
* @method addVertex
|
|
6576
7232
|
* @param {Vertex} vert - The vertex to add.
|
|
6577
7233
|
* @instance
|
|
6578
7234
|
* @memberof Polygon
|
|
@@ -6580,6 +7236,108 @@ var Polygon = /** @class */ (function () {
|
|
|
6580
7236
|
Polygon.prototype.addVertex = function (vert) {
|
|
6581
7237
|
this.vertices.push(vert);
|
|
6582
7238
|
};
|
|
7239
|
+
/**
|
|
7240
|
+
* Add a vertex at a particular position of the `vertices` array.
|
|
7241
|
+
*
|
|
7242
|
+
* @method addVertexAt
|
|
7243
|
+
* @param {Vertex} vert - The vertex to add.
|
|
7244
|
+
* @param {number} index - The position to add the vertex at. Will be handled modulo.
|
|
7245
|
+
* @instance
|
|
7246
|
+
* @memberof Polygon
|
|
7247
|
+
**/
|
|
7248
|
+
Polygon.prototype.addVertexAt = function (vert, index) {
|
|
7249
|
+
// var moduloIndex = index % (this.vertices.length + 1);
|
|
7250
|
+
this.vertices.splice(index, 0, vert);
|
|
7251
|
+
};
|
|
7252
|
+
/**
|
|
7253
|
+
* Get a new instance of the line at the given start index. The returned line will consist
|
|
7254
|
+
* of the vertex at `vertIndex` and `vertIndex+1` (will be handled modulo).
|
|
7255
|
+
*
|
|
7256
|
+
* @method getEdgeAt
|
|
7257
|
+
* @param {number} vertIndex - The vertex index of the line to start.
|
|
7258
|
+
* @instance
|
|
7259
|
+
* @memberof Polygon
|
|
7260
|
+
* @return {Line}
|
|
7261
|
+
**/
|
|
7262
|
+
Polygon.prototype.getEdgeAt = function (vertIndex) {
|
|
7263
|
+
return new Line_1.Line(this.getVertexAt(vertIndex), this.getVertexAt(vertIndex + 1));
|
|
7264
|
+
};
|
|
7265
|
+
/**
|
|
7266
|
+
* Converts this polygon into a sequence of lines. Please note that each time
|
|
7267
|
+
* this method is called new lines are created. The underlying line vertices are no clones
|
|
7268
|
+
* (instances).
|
|
7269
|
+
*
|
|
7270
|
+
* @method getEdges
|
|
7271
|
+
* @instance
|
|
7272
|
+
* @memberof Polygon
|
|
7273
|
+
* @return {Array<Line>}
|
|
7274
|
+
*/
|
|
7275
|
+
Polygon.prototype.getEdges = function () {
|
|
7276
|
+
var lines = [];
|
|
7277
|
+
for (var i = 0; i + 1 < this.vertices.length; i++) {
|
|
7278
|
+
// var line = this.getLineAt(i).clone();
|
|
7279
|
+
lines.push(this.getEdgeAt(i));
|
|
7280
|
+
}
|
|
7281
|
+
if (!this.isOpen && this.vertices.length > 0) {
|
|
7282
|
+
lines.push(this.getEdgeAt(this.vertices.length - 1));
|
|
7283
|
+
}
|
|
7284
|
+
return lines;
|
|
7285
|
+
};
|
|
7286
|
+
/**
|
|
7287
|
+
* Checks if the angle at the given polygon vertex (index) is acute. Please not that this is
|
|
7288
|
+
* only working for clockwise polygons. If this polygon is not clockwise please use the
|
|
7289
|
+
* `isClockwise` method and reverse polygon vertices if needed.
|
|
7290
|
+
*
|
|
7291
|
+
* @method isAngleAcute
|
|
7292
|
+
* @instance
|
|
7293
|
+
* @memberof Polygon
|
|
7294
|
+
* @param {number} vertIndex - The index of the polygon vertex to check.
|
|
7295
|
+
* @returns {boolean} `true` is angle is acute, `false` is obtuse.
|
|
7296
|
+
*/
|
|
7297
|
+
Polygon.prototype.getInnerAngleAt = function (vertIndex) {
|
|
7298
|
+
var p2 = this.vertices[vertIndex];
|
|
7299
|
+
var p1 = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();
|
|
7300
|
+
var p3 = this.vertices[(vertIndex + 1) % this.vertices.length].clone();
|
|
7301
|
+
// See
|
|
7302
|
+
// https://math.stackexchange.com/questions/149959/how-to-find-the-interior-angle-of-an-irregular-pentagon-or-polygon
|
|
7303
|
+
// π−arccos((P2−P1)⋅(P3−P2)|P2−P1||P3−P2|)
|
|
7304
|
+
// Check if triangle is acute (will be used later)
|
|
7305
|
+
// Acute angles and obtuse angles need to be handled differently.
|
|
7306
|
+
var isAcute = this.isAngleAcute(vertIndex);
|
|
7307
|
+
// Differences
|
|
7308
|
+
var zero = new Vertex_1.Vertex(0, 0);
|
|
7309
|
+
var p2mp1 = new Vertex_1.Vertex(p2.x - p1.x, p2.y - p1.y);
|
|
7310
|
+
var p3mp2 = new Vertex_1.Vertex(p3.x - p2.x, p3.y - p2.y);
|
|
7311
|
+
var p2mp1_len = zero.distance(p2mp1);
|
|
7312
|
+
var p3mp2_len = zero.distance(p3mp2);
|
|
7313
|
+
// Dot products
|
|
7314
|
+
var dotProduct = geomutils_1.geomutils.dotProduct(p2mp1, p3mp2);
|
|
7315
|
+
var lengthProduct = p2mp1_len * p3mp2_len;
|
|
7316
|
+
if (isAcute) {
|
|
7317
|
+
return Math.PI - Math.acos(dotProduct / lengthProduct);
|
|
7318
|
+
}
|
|
7319
|
+
else {
|
|
7320
|
+
return Math.PI + Math.acos(dotProduct / lengthProduct);
|
|
7321
|
+
}
|
|
7322
|
+
};
|
|
7323
|
+
/**
|
|
7324
|
+
* Checks if the angle at the given polygon vertex (index) is acute.
|
|
7325
|
+
*
|
|
7326
|
+
* @method isAngleAcute
|
|
7327
|
+
* @instance
|
|
7328
|
+
* @memberof Polygon
|
|
7329
|
+
* @param {number} vertIndex - The index of the polygon vertex to check.
|
|
7330
|
+
* @returns {boolean} `true` is angle is acute, `false` is obtuse.
|
|
7331
|
+
*/
|
|
7332
|
+
Polygon.prototype.isAngleAcute = function (vertIndex) {
|
|
7333
|
+
var A = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();
|
|
7334
|
+
var B = this.vertices[vertIndex];
|
|
7335
|
+
var C = this.vertices[(vertIndex + 1) % this.vertices.length].clone();
|
|
7336
|
+
// Find local winding number for triangle A B C
|
|
7337
|
+
var windingNumber = Triangle_1.Triangle.utils.determinant(A, B, C);
|
|
7338
|
+
// console.log("vertIndex", vertIndex, "windingNumber", windingNumber);
|
|
7339
|
+
return windingNumber < 0;
|
|
7340
|
+
};
|
|
6583
7341
|
/**
|
|
6584
7342
|
* Get the polygon vertex at the given position (index).
|
|
6585
7343
|
*
|
|
@@ -6590,17 +7348,19 @@ var Polygon = /** @class */ (function () {
|
|
|
6590
7348
|
* - getVertexAt( vertices.length + k ) == getVertexAt( k )
|
|
6591
7349
|
* - getVertexAt( -k ) == getVertexAt( vertices.length -k )
|
|
6592
7350
|
*
|
|
6593
|
-
* @
|
|
7351
|
+
* @method getVertexAt
|
|
6594
7352
|
* @param {number} index - The index of the desired vertex.
|
|
6595
7353
|
* @instance
|
|
6596
7354
|
* @memberof Polygon
|
|
6597
7355
|
* @return {Vertex} At the given index.
|
|
6598
7356
|
**/
|
|
6599
7357
|
Polygon.prototype.getVertexAt = function (index) {
|
|
6600
|
-
if (index < 0)
|
|
7358
|
+
if (index < 0) {
|
|
6601
7359
|
return this.vertices[this.vertices.length - (Math.abs(index) % this.vertices.length)];
|
|
6602
|
-
|
|
7360
|
+
}
|
|
7361
|
+
else {
|
|
6603
7362
|
return this.vertices[index % this.vertices.length];
|
|
7363
|
+
}
|
|
6604
7364
|
};
|
|
6605
7365
|
/**
|
|
6606
7366
|
* Move the polygon's vertices by the given amount.
|
|
@@ -6624,7 +7384,7 @@ var Polygon = /** @class */ (function () {
|
|
|
6624
7384
|
* https://stackoverflow.com/questions/22521982/check-if-point-inside-a-polygon
|
|
6625
7385
|
*
|
|
6626
7386
|
* @method containsVert
|
|
6627
|
-
* @param {XYCoords} vert - The vertex to check.
|
|
7387
|
+
* @param {XYCoords} vert - The vertex to check.
|
|
6628
7388
|
* @return {boolean} True if the passed vertex is inside this polygon. The polygon is considered closed.
|
|
6629
7389
|
* @instance
|
|
6630
7390
|
* @memberof Polygon
|
|
@@ -6642,6 +7402,21 @@ var Polygon = /** @class */ (function () {
|
|
|
6642
7402
|
}
|
|
6643
7403
|
return inside;
|
|
6644
7404
|
};
|
|
7405
|
+
/**
|
|
7406
|
+
* Check if all given vertices are inside this polygon.<br>
|
|
7407
|
+
* <br>
|
|
7408
|
+
* This method just uses the `Polygon.containsVert` method.
|
|
7409
|
+
*
|
|
7410
|
+
* @method containsVerts
|
|
7411
|
+
* @param {XYCoords[]} verts - The vertices to check.
|
|
7412
|
+
* @return {boolean} True if all passed vertices are inside this polygon. The polygon is considered closed.
|
|
7413
|
+
* @instance
|
|
7414
|
+
* @memberof Polygon
|
|
7415
|
+
**/
|
|
7416
|
+
Polygon.prototype.containsVerts = function (verts) {
|
|
7417
|
+
var _this = this;
|
|
7418
|
+
return verts.every(function (vert) { return _this.containsVert(vert); });
|
|
7419
|
+
};
|
|
6645
7420
|
/**
|
|
6646
7421
|
* Check if the passed polygon is completly contained inside this polygon.
|
|
6647
7422
|
*
|
|
@@ -6704,7 +7479,8 @@ var Polygon = /** @class */ (function () {
|
|
|
6704
7479
|
* @return {boolean}
|
|
6705
7480
|
*/
|
|
6706
7481
|
Polygon.prototype.isClockwise = function () {
|
|
6707
|
-
return Polygon.utils.signedArea(this.vertices) < 0;
|
|
7482
|
+
// return Polygon.utils.signedArea(this.vertices) < 0;
|
|
7483
|
+
return Polygon.utils.isClockwise(this.vertices);
|
|
6708
7484
|
};
|
|
6709
7485
|
/**
|
|
6710
7486
|
* Get the perimeter of this polygon.
|
|
@@ -6763,9 +7539,66 @@ var Polygon = /** @class */ (function () {
|
|
|
6763
7539
|
}
|
|
6764
7540
|
return this;
|
|
6765
7541
|
};
|
|
7542
|
+
/**
|
|
7543
|
+
* Get the mean `center` of this polygon by calculating the mean value of all vertices.
|
|
7544
|
+
*
|
|
7545
|
+
* Mean: (v[0] + v[1] + ... v[n-1]) / n
|
|
7546
|
+
*
|
|
7547
|
+
* @method getMeanCenter
|
|
7548
|
+
* @instance
|
|
7549
|
+
* @memberof Polygon
|
|
7550
|
+
* @return {Vertex|null} `null` is no vertices are available.
|
|
7551
|
+
*/
|
|
7552
|
+
Polygon.prototype.getMeanCenter = function () {
|
|
7553
|
+
if (this.vertices.length === 0) {
|
|
7554
|
+
return null;
|
|
7555
|
+
}
|
|
7556
|
+
var center = this.vertices[0].clone();
|
|
7557
|
+
for (var i = 1; i < this.vertices.length; i++) {
|
|
7558
|
+
center.add(this.vertices[i]);
|
|
7559
|
+
}
|
|
7560
|
+
center.x /= this.vertices.length;
|
|
7561
|
+
center.y /= this.vertices.length;
|
|
7562
|
+
return center;
|
|
7563
|
+
};
|
|
7564
|
+
/**
|
|
7565
|
+
* Get centroid.
|
|
7566
|
+
* Centroids define the barycenter of any non self-intersecting convex polygon.
|
|
7567
|
+
*
|
|
7568
|
+
* If the polygon is self intersecting or non konvex then the barycenter is not well defined.
|
|
7569
|
+
*
|
|
7570
|
+
* https://mathworld.wolfram.com/PolygonCentroid.html
|
|
7571
|
+
*
|
|
7572
|
+
* @method getCentroid
|
|
7573
|
+
* @instance
|
|
7574
|
+
* @memberof Polygon
|
|
7575
|
+
* @returns {Vertex|null}
|
|
7576
|
+
*/
|
|
7577
|
+
Polygon.prototype.getCentroid = function () {
|
|
7578
|
+
if (this.vertices.length === 0) {
|
|
7579
|
+
return null;
|
|
7580
|
+
}
|
|
7581
|
+
var center = new Vertex_1.Vertex(0.0, 0.0);
|
|
7582
|
+
var n = this.vertices.length;
|
|
7583
|
+
for (var i = 0; i < n; i++) {
|
|
7584
|
+
// center.add(this.vertices[i]);
|
|
7585
|
+
var cur = this.vertices[i];
|
|
7586
|
+
var next = this.vertices[(i + 1) % n];
|
|
7587
|
+
var factor = cur.x * next.y - next.x * cur.y;
|
|
7588
|
+
center.x += (cur.x + next.x) * factor;
|
|
7589
|
+
center.y += (cur.y + next.y) * factor;
|
|
7590
|
+
}
|
|
7591
|
+
var area = this.area();
|
|
7592
|
+
center.x *= 1 / (6 * area);
|
|
7593
|
+
center.y *= 1 / (6 * area);
|
|
7594
|
+
return center;
|
|
7595
|
+
};
|
|
7596
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
6766
7597
|
/**
|
|
6767
7598
|
* Get all line intersections with this polygon.
|
|
6768
7599
|
*
|
|
7600
|
+
* This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
|
|
7601
|
+
*
|
|
6769
7602
|
* See demo `47-closest-vector-projection-on-polygon` for how it works.
|
|
6770
7603
|
*
|
|
6771
7604
|
* @param {VertTuple} line - The line to find intersections with.
|
|
@@ -6775,21 +7608,29 @@ var Polygon = /** @class */ (function () {
|
|
|
6775
7608
|
Polygon.prototype.lineIntersections = function (line, inVectorBoundsOnly) {
|
|
6776
7609
|
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
6777
7610
|
// Find the intersections of all lines inside the edge bounds
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
7611
|
+
return Polygon.utils
|
|
7612
|
+
.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly)
|
|
7613
|
+
.map(function (intersectionTuple) { return intersectionTuple.intersectionPoint; });
|
|
7614
|
+
};
|
|
7615
|
+
/**
|
|
7616
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
7617
|
+
*
|
|
7618
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
7619
|
+
*
|
|
7620
|
+
* @param line
|
|
7621
|
+
* @param inVectorBoundsOnly
|
|
7622
|
+
* @returns
|
|
7623
|
+
*/
|
|
7624
|
+
Polygon.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
7625
|
+
var _this = this;
|
|
7626
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
7627
|
+
// Find the intersection tangents of all lines inside the edge bounds
|
|
7628
|
+
return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(function (intersectionTuple) {
|
|
7629
|
+
var polyLine = _this.getEdgeAt(intersectionTuple.edgeIndex);
|
|
7630
|
+
return new Vector_1.Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersectionPoint);
|
|
7631
|
+
});
|
|
6792
7632
|
};
|
|
7633
|
+
//--- END --- Implement interface `Intersectable`
|
|
6793
7634
|
/**
|
|
6794
7635
|
* Get the closest line-polygon-intersection point (closest the line point A).
|
|
6795
7636
|
*
|
|
@@ -6891,6 +7732,7 @@ var Polygon = /** @class */ (function () {
|
|
|
6891
7732
|
}
|
|
6892
7733
|
return result;
|
|
6893
7734
|
};
|
|
7735
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
6894
7736
|
/**
|
|
6895
7737
|
* Get the bounding box (bounds) of this polygon.
|
|
6896
7738
|
*
|
|
@@ -6902,13 +7744,66 @@ var Polygon = /** @class */ (function () {
|
|
|
6902
7744
|
Polygon.prototype.getBounds = function () {
|
|
6903
7745
|
return Bounds_1.Bounds.computeFromVertices(this.vertices);
|
|
6904
7746
|
};
|
|
7747
|
+
//--- END --- Implement interface `IBounded`
|
|
6905
7748
|
/**
|
|
6906
7749
|
* Create a deep copy of this polygon.
|
|
6907
7750
|
*
|
|
7751
|
+
* @method clone
|
|
7752
|
+
* @instance
|
|
7753
|
+
* @memberof Polygon
|
|
6908
7754
|
* @return {Polygon} The cloned polygon.
|
|
6909
7755
|
*/
|
|
6910
|
-
Polygon.prototype.clone = function () {
|
|
6911
|
-
return new Polygon(this.vertices.map(function (vert) { return vert.clone(); }), this.isOpen);
|
|
7756
|
+
Polygon.prototype.clone = function () {
|
|
7757
|
+
return new Polygon(this.vertices.map(function (vert) { return vert.clone(); }), this.isOpen);
|
|
7758
|
+
};
|
|
7759
|
+
/**
|
|
7760
|
+
* Create a new polygon without colinear adjacent edges. This method does not midify the current polygon
|
|
7761
|
+
* but creates a new one.
|
|
7762
|
+
*
|
|
7763
|
+
* Please note that this method does NOT create deep clones of the vertices. Use Polygon.clone() if you need to.
|
|
7764
|
+
*
|
|
7765
|
+
* Please also note that the `tolerance` may become really large here, as the denominator of two closely
|
|
7766
|
+
* parallel lines is usually pretty large. See the demo `57-eliminate-colinear-polygon-edges` to get
|
|
7767
|
+
* an impression of how denominators work.
|
|
7768
|
+
*
|
|
7769
|
+
* @method elimitateColinearEdges
|
|
7770
|
+
* @instance
|
|
7771
|
+
* @memberof Polygon
|
|
7772
|
+
* @param {number?} tolerance - (default is 1.0) The epsilon to detect co-linear edges.
|
|
7773
|
+
* @return {Polygon} A new polygon without co-linear adjacent edges – respective the given epsilon.
|
|
7774
|
+
*/
|
|
7775
|
+
Polygon.prototype.elimitateColinearEdges = function (tolerance) {
|
|
7776
|
+
var eps = typeof tolerance === "undefined" ? 1.0 : tolerance;
|
|
7777
|
+
var verts = this.vertices.slice(); // Creates a shallow copy
|
|
7778
|
+
var i = 0;
|
|
7779
|
+
var lineA = new Line_1.Line(new Vertex_1.Vertex(), new Vertex_1.Vertex());
|
|
7780
|
+
var lineB = new Line_1.Line(new Vertex_1.Vertex(), new Vertex_1.Vertex());
|
|
7781
|
+
while (i + 1 < verts.length && verts.length > 2) {
|
|
7782
|
+
var vertA = verts[i];
|
|
7783
|
+
var vertB = verts[(i + 1) % verts.length];
|
|
7784
|
+
lineA.a = vertA;
|
|
7785
|
+
lineA.b = vertB;
|
|
7786
|
+
lineB.a = vertB;
|
|
7787
|
+
var areColinear = false;
|
|
7788
|
+
var j = i + 2;
|
|
7789
|
+
do {
|
|
7790
|
+
var vertC = verts[j % verts.length];
|
|
7791
|
+
lineB.b = vertC;
|
|
7792
|
+
areColinear = lineA.colinear(lineB, eps);
|
|
7793
|
+
// console.log("are colinear?", i, i + 1, j, areColinear);
|
|
7794
|
+
if (areColinear) {
|
|
7795
|
+
j++;
|
|
7796
|
+
}
|
|
7797
|
+
} while (areColinear);
|
|
7798
|
+
// Now j points to the first vertex that's NOT colinear to the current lineA
|
|
7799
|
+
// -> delete all vertices in between
|
|
7800
|
+
if (j - i > 2) {
|
|
7801
|
+
// Means: there have been 'colinear vertices' in between
|
|
7802
|
+
verts.splice(i + 1, j - i - 2);
|
|
7803
|
+
}
|
|
7804
|
+
i++;
|
|
7805
|
+
}
|
|
7806
|
+
return new Polygon(verts, this.isOpen);
|
|
6912
7807
|
};
|
|
6913
7808
|
/**
|
|
6914
7809
|
* Convert this polygon to a sequence of quadratic Bézier curves.<br>
|
|
@@ -7009,8 +7904,9 @@ var Polygon = /** @class */ (function () {
|
|
|
7009
7904
|
**/
|
|
7010
7905
|
Polygon.prototype.toCubicBezierSVGString = function (threshold) {
|
|
7011
7906
|
var qdata = this.toCubicBezierData(threshold);
|
|
7012
|
-
if (qdata.length == 0)
|
|
7907
|
+
if (qdata.length == 0) {
|
|
7013
7908
|
return "";
|
|
7909
|
+
}
|
|
7014
7910
|
var buffer = ["M " + qdata[0].x + " " + qdata[0].y];
|
|
7015
7911
|
for (var i = 1; i < qdata.length; i += 3) {
|
|
7016
7912
|
buffer.push("C " +
|
|
@@ -7080,6 +7976,9 @@ var Polygon = /** @class */ (function () {
|
|
|
7080
7976
|
}
|
|
7081
7977
|
return Math.abs(total);
|
|
7082
7978
|
},
|
|
7979
|
+
isClockwise: function (vertices) {
|
|
7980
|
+
return Polygon.utils.signedArea(vertices) < 0;
|
|
7981
|
+
},
|
|
7083
7982
|
/**
|
|
7084
7983
|
* Calulate the signed polyon area by interpreting the polygon as a matrix
|
|
7085
7984
|
* and calculating its determinant.
|
|
@@ -7095,6 +7994,32 @@ var Polygon = /** @class */ (function () {
|
|
|
7095
7994
|
sum += (vertices[j].x - vertices[i].x) * (vertices[i].y + vertices[j].y);
|
|
7096
7995
|
}
|
|
7097
7996
|
return sum;
|
|
7997
|
+
},
|
|
7998
|
+
/**
|
|
7999
|
+
* Find intersections of a line with a polygon (vertices).
|
|
8000
|
+
*
|
|
8001
|
+
* @param {VertTuple<any>} line - The line to find intersections with.
|
|
8002
|
+
* @param {Array<Vertex>} vertices - The polygon's vertices.
|
|
8003
|
+
* @param {boolean} isOpen - True if the polygon is open, false otherwise.
|
|
8004
|
+
* @param {boolean} inVectorBoundsOnly - If only intersections in strict vector bounds should be returned.
|
|
8005
|
+
* @returns
|
|
8006
|
+
*/
|
|
8007
|
+
locateLineIntersecion: function (line, vertices, isOpen, inVectorBoundsOnly) {
|
|
8008
|
+
// Find the intersections of all lines inside the edge bounds
|
|
8009
|
+
var intersectionPoints = [];
|
|
8010
|
+
var n = isOpen ? vertices.length - 1 : vertices.length;
|
|
8011
|
+
for (var i = 0; i < n; i++) {
|
|
8012
|
+
var polyLine = new Line_1.Line(vertices[i % n], vertices[(i + 1) % n]);
|
|
8013
|
+
var intersection = polyLine.intersection(line);
|
|
8014
|
+
// true => only inside bounds
|
|
8015
|
+
// ignore last edge if open
|
|
8016
|
+
if (intersection !== null &&
|
|
8017
|
+
polyLine.hasPoint(intersection, true) &&
|
|
8018
|
+
(!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {
|
|
8019
|
+
intersectionPoints.push({ edgeIndex: i, intersectionPoint: intersection });
|
|
8020
|
+
}
|
|
8021
|
+
}
|
|
8022
|
+
return intersectionPoints;
|
|
7098
8023
|
}
|
|
7099
8024
|
};
|
|
7100
8025
|
return Polygon;
|
|
@@ -7131,7 +8056,13 @@ exports.Polygon = Polygon;
|
|
|
7131
8056
|
* @modified 2021-01-22 Always updating circumcircle when retieving it.
|
|
7132
8057
|
* @modified 2022-02-02 Added the `destroy` method.
|
|
7133
8058
|
* @modified 2022-02-02 Cleared the `Triangle.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
7134
|
-
* @
|
|
8059
|
+
* @modified 2024-11-22 Added static utility function Triangle.utils.determinant; adapted method `determinant`.
|
|
8060
|
+
* @modified 2024-11-22 Changing visibility of `Triangle.utils` from `private` to `public`.
|
|
8061
|
+
* @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.
|
|
8062
|
+
* @modified 2025-14-16 Class `Triangle` now implements interface `IBounded`.
|
|
8063
|
+
* @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.
|
|
8064
|
+
* @modified 2025-14-16 Added method `Triangle.move`.
|
|
8065
|
+
* @version 2.10.0
|
|
7135
8066
|
*
|
|
7136
8067
|
* @file Triangle
|
|
7137
8068
|
* @fileoverview A simple triangle class: three vertices.
|
|
@@ -7144,6 +8075,7 @@ var Circle_1 = __webpack_require__(118);
|
|
|
7144
8075
|
var Line_1 = __webpack_require__(939);
|
|
7145
8076
|
var Polygon_1 = __webpack_require__(687);
|
|
7146
8077
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
8078
|
+
var Vector_1 = __webpack_require__(30);
|
|
7147
8079
|
var Vertex_1 = __webpack_require__(787);
|
|
7148
8080
|
var geomutils_1 = __webpack_require__(328);
|
|
7149
8081
|
/**
|
|
@@ -7245,6 +8177,35 @@ var Triangle = /** @class */ (function () {
|
|
|
7245
8177
|
this.c.scale(factor, centroid);
|
|
7246
8178
|
return this;
|
|
7247
8179
|
};
|
|
8180
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
8181
|
+
/**
|
|
8182
|
+
* Get the bounding box (bounds) of this Triangle.
|
|
8183
|
+
*
|
|
8184
|
+
* @method getBounds
|
|
8185
|
+
* @instance
|
|
8186
|
+
* @memberof Triangle
|
|
8187
|
+
* @return {Bounds} The rectangular bounds of this Triangle.
|
|
8188
|
+
**/
|
|
8189
|
+
Triangle.prototype.getBounds = function () {
|
|
8190
|
+
// return Bounds.computeFromVertices([this.a, this.b, this.c]);
|
|
8191
|
+
return this.bounds();
|
|
8192
|
+
};
|
|
8193
|
+
//--- END --- Implement interface `IBounded`
|
|
8194
|
+
/**
|
|
8195
|
+
* Move the Triangle's vertices by the given amount.
|
|
8196
|
+
*
|
|
8197
|
+
* @method move
|
|
8198
|
+
* @param {XYCoords} amount - The amount to move.
|
|
8199
|
+
* @instance
|
|
8200
|
+
* @memberof Triangle
|
|
8201
|
+
* @return {Triangle} this for chaining
|
|
8202
|
+
**/
|
|
8203
|
+
Triangle.prototype.move = function (amount) {
|
|
8204
|
+
this.a.add(amount);
|
|
8205
|
+
this.b.add(amount);
|
|
8206
|
+
this.c.add(amount);
|
|
8207
|
+
return this;
|
|
8208
|
+
};
|
|
7248
8209
|
/**
|
|
7249
8210
|
* Get the circumcircle of this triangle.
|
|
7250
8211
|
*
|
|
@@ -7370,6 +8331,51 @@ var Triangle = /** @class */ (function () {
|
|
|
7370
8331
|
Triangle.prototype.bounds = function () {
|
|
7371
8332
|
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)));
|
|
7372
8333
|
};
|
|
8334
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
8335
|
+
/**
|
|
8336
|
+
* Get all line intersections with this polygon.
|
|
8337
|
+
*
|
|
8338
|
+
* This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.
|
|
8339
|
+
*
|
|
8340
|
+
* See demo `47-closest-vector-projection-on-polygon` for how it works.
|
|
8341
|
+
*
|
|
8342
|
+
* @param {VertTuple} line - The line to find intersections with.
|
|
8343
|
+
* @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).
|
|
8344
|
+
* @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.
|
|
8345
|
+
*/
|
|
8346
|
+
Triangle.prototype.lineIntersections = function (line, inVectorBoundsOnly) {
|
|
8347
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
8348
|
+
// Find the intersections of all lines inside the edge bounds
|
|
8349
|
+
return Polygon_1.Polygon.utils
|
|
8350
|
+
.locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)
|
|
8351
|
+
.map(function (intersectionTuple) { return intersectionTuple.intersectionPoint; });
|
|
8352
|
+
};
|
|
8353
|
+
/**
|
|
8354
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
8355
|
+
*
|
|
8356
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
8357
|
+
*
|
|
8358
|
+
* @param line
|
|
8359
|
+
* @param inVectorBoundsOnly
|
|
8360
|
+
* @returns
|
|
8361
|
+
*/
|
|
8362
|
+
Triangle.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
8363
|
+
var _this = this;
|
|
8364
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
8365
|
+
// Find the intersection tangents of all lines inside the edge bounds
|
|
8366
|
+
return Polygon_1.Polygon.utils
|
|
8367
|
+
.locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)
|
|
8368
|
+
.map(function (intersectionTuple) {
|
|
8369
|
+
// const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
|
|
8370
|
+
var polyLine = _this.getEdgeAt(intersectionTuple.edgeIndex);
|
|
8371
|
+
return new Vector_1.Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersectionPoint);
|
|
8372
|
+
});
|
|
8373
|
+
};
|
|
8374
|
+
//--- END --- Implement interface `Intersectable`
|
|
8375
|
+
Triangle.prototype.getEdgeAt = function (edgeIndex) {
|
|
8376
|
+
var modIndex = edgeIndex % 3;
|
|
8377
|
+
return modIndex === 0 ? new Line_1.Line(this.a, this.b) : modIndex === 1 ? new Line_1.Line(this.b, this.c) : new Line_1.Line(this.c, this.a);
|
|
8378
|
+
};
|
|
7373
8379
|
/**
|
|
7374
8380
|
* Convert this triangle to a polygon instance.
|
|
7375
8381
|
*
|
|
@@ -7393,7 +8399,8 @@ var Triangle = /** @class */ (function () {
|
|
|
7393
8399
|
*/
|
|
7394
8400
|
Triangle.prototype.determinant = function () {
|
|
7395
8401
|
// (b.y - a.y)*(c.x - b.x) - (c.y - b.y)*(b.x - a.x);
|
|
7396
|
-
return (this.b.y - this.a.y) * (this.c.x - this.b.x) - (this.c.y - this.b.y) * (this.b.x - this.a.x);
|
|
8402
|
+
// return (this.b.y - this.a.y) * (this.c.x - this.b.x) - (this.c.y - this.b.y) * (this.b.x - this.a.x);
|
|
8403
|
+
return Triangle.utils.determinant(this.a, this.b, this.c);
|
|
7397
8404
|
};
|
|
7398
8405
|
/**
|
|
7399
8406
|
* Checks if the passed vertex (p) is inside this triangle.
|
|
@@ -7506,6 +8513,16 @@ var Triangle = /** @class */ (function () {
|
|
|
7506
8513
|
var s = (1 / (2 * area)) * (p0y * p2x - p0x * p2y + (p2y - p0y) * px + (p0x - p2x) * py);
|
|
7507
8514
|
var t = (1 / (2 * area)) * (p0x * p1y - p0y * p1x + (p0y - p1y) * px + (p1x - p0x) * py);
|
|
7508
8515
|
return s > 0 && t > 0 && 1 - s - t > 0;
|
|
8516
|
+
},
|
|
8517
|
+
/**
|
|
8518
|
+
* Calculate the determinant of the three vertices a, b and c (in this order).
|
|
8519
|
+
* @param {XYCords} a - The first vertex.
|
|
8520
|
+
* @param {XYCords} b - The first vertex.
|
|
8521
|
+
* @param {XYCords} c - The first vertex.
|
|
8522
|
+
* @returns {nmber}
|
|
8523
|
+
*/
|
|
8524
|
+
determinant: function (a, b, c) {
|
|
8525
|
+
return (b.y - a.y) * (c.x - b.x) - (c.y - b.y) * (b.x - a.x);
|
|
7509
8526
|
}
|
|
7510
8527
|
};
|
|
7511
8528
|
return Triangle;
|
|
@@ -7563,7 +8580,11 @@ exports.UIDGenerator = UIDGenerator;
|
|
|
7563
8580
|
* @modified 2021-03-19 Added the `VEllipse.rotate` function.
|
|
7564
8581
|
* @modified 2022-02-02 Added the `destroy` method.
|
|
7565
8582
|
* @modified 2022-02-02 Cleared the `VEllipse.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
7566
|
-
* @
|
|
8583
|
+
* @modified 2025-03-31 ATTENTION: modified the winding direction of the `tangentAt` method to match with the Circle method. This is a breaking change!
|
|
8584
|
+
* @modified 2025-03-31 Adding the `VEllipse.move(amount: XYCoords)` method.
|
|
8585
|
+
* @modified 2025-04-19 Adding the `VEllipse.getBounds()` method.
|
|
8586
|
+
* @modified 2025-04-24 Adding the `VEllipse.getExtremePoints()` method for calculating minima and maxima.
|
|
8587
|
+
* @version 1.4.0
|
|
7567
8588
|
*
|
|
7568
8589
|
* @file VEllipse
|
|
7569
8590
|
* @fileoverview Ellipses with a center and an x- and a y-axis (stored as a vertex).
|
|
@@ -7575,6 +8596,8 @@ var Vector_1 = __webpack_require__(30);
|
|
|
7575
8596
|
var Vertex_1 = __webpack_require__(787);
|
|
7576
8597
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
7577
8598
|
var CubicBezierCurve_1 = __webpack_require__(973);
|
|
8599
|
+
var Circle_1 = __webpack_require__(118);
|
|
8600
|
+
var Bounds_1 = __webpack_require__(76);
|
|
7578
8601
|
/**
|
|
7579
8602
|
* @classdesc An ellipse class based on two vertices [centerX,centerY] and [radiusX,radiusY].
|
|
7580
8603
|
*
|
|
@@ -7656,11 +8679,96 @@ var VEllipse = /** @class */ (function () {
|
|
|
7656
8679
|
* @return {number} The signed vertical radius of this ellipse.
|
|
7657
8680
|
*/
|
|
7658
8681
|
VEllipse.prototype.signedRadiusV = function () {
|
|
7659
|
-
// return Math.abs(this.axis.y - this.center.y);
|
|
7660
8682
|
// Rotate axis back to origin before calculating radius
|
|
7661
|
-
// return Math.abs(new Vertex(this.axis).rotate(-this.rotation,this.center).y - this.center.y);
|
|
7662
8683
|
return new Vertex_1.Vertex(this.axis).rotate(-this.rotation, this.center).y - this.center.y;
|
|
7663
8684
|
};
|
|
8685
|
+
/**
|
|
8686
|
+
* Get the the minima and maxima (points) of this (rotated) ellipse.
|
|
8687
|
+
*
|
|
8688
|
+
* @method getExtremePoints
|
|
8689
|
+
* @instance
|
|
8690
|
+
* @memberof VEllipse
|
|
8691
|
+
* @return {[Vertex, Vertex, Vertex, Vertex]} Get the the minima and maxima (points) of this (rotated) ellipse.
|
|
8692
|
+
*/
|
|
8693
|
+
VEllipse.prototype.getExtremePoints = function () {
|
|
8694
|
+
var a = this.radiusH();
|
|
8695
|
+
var b = this.radiusV();
|
|
8696
|
+
// Calculate t_x values
|
|
8697
|
+
var t_x1 = Math.atan2(-b * Math.sin(this.rotation), a * Math.cos(this.rotation));
|
|
8698
|
+
var t_x2 = t_x1 + Math.PI;
|
|
8699
|
+
// Calculate x values at t_x
|
|
8700
|
+
var x_x1 = this.center.x + a * Math.cos(t_x1) * Math.cos(this.rotation) - b * Math.sin(t_x1) * Math.sin(this.rotation);
|
|
8701
|
+
var y_x1 = this.center.y + a * Math.cos(t_x1) * Math.sin(this.rotation) + b * Math.sin(t_x1) * Math.cos(this.rotation);
|
|
8702
|
+
var x_x2 = this.center.x + a * Math.cos(t_x2) * Math.cos(this.rotation) - b * Math.sin(t_x2) * Math.sin(this.rotation);
|
|
8703
|
+
var y_x2 = this.center.y + a * Math.cos(t_x2) * Math.sin(this.rotation) + b * Math.sin(t_x2) * Math.cos(this.rotation);
|
|
8704
|
+
var x_max, x_min;
|
|
8705
|
+
if (x_x1 > x_x2) {
|
|
8706
|
+
x_max = new Vertex_1.Vertex(x_x1, y_x1);
|
|
8707
|
+
x_min = new Vertex_1.Vertex(x_x2, y_x2);
|
|
8708
|
+
}
|
|
8709
|
+
else {
|
|
8710
|
+
x_max = new Vertex_1.Vertex(x_x2, y_x2);
|
|
8711
|
+
x_min = new Vertex_1.Vertex(x_x1, y_x1);
|
|
8712
|
+
}
|
|
8713
|
+
// Calculate t_y values
|
|
8714
|
+
var t_y1 = Math.atan2(b * Math.cos(this.rotation), a * Math.sin(this.rotation));
|
|
8715
|
+
var t_y2 = t_y1 + Math.PI;
|
|
8716
|
+
// Calculate y values at t_y
|
|
8717
|
+
var x_y1 = this.center.x + a * Math.cos(t_y1) * Math.cos(this.rotation) - b * Math.sin(t_y1) * Math.sin(this.rotation);
|
|
8718
|
+
var y_y1 = this.center.y + a * Math.cos(t_y1) * Math.sin(this.rotation) + b * Math.sin(t_y1) * Math.cos(this.rotation);
|
|
8719
|
+
var x_y2 = this.center.x + a * Math.cos(t_y2) * Math.cos(this.rotation) - b * Math.sin(t_y2) * Math.sin(this.rotation);
|
|
8720
|
+
var y_y2 = this.center.y + a * Math.cos(t_y2) * Math.sin(this.rotation) + b * Math.sin(t_y2) * Math.cos(this.rotation);
|
|
8721
|
+
var y_max, y_min;
|
|
8722
|
+
if (y_y1 > y_y2) {
|
|
8723
|
+
y_max = new Vertex_1.Vertex(x_y1, y_y1);
|
|
8724
|
+
y_min = new Vertex_1.Vertex(x_y2, y_y2);
|
|
8725
|
+
}
|
|
8726
|
+
else {
|
|
8727
|
+
y_max = new Vertex_1.Vertex(x_y2, y_y2);
|
|
8728
|
+
y_min = new Vertex_1.Vertex(x_y1, y_y1);
|
|
8729
|
+
}
|
|
8730
|
+
return [x_max, x_min, y_max, y_min];
|
|
8731
|
+
};
|
|
8732
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
8733
|
+
/**
|
|
8734
|
+
* Get the bounds of this ellipse.
|
|
8735
|
+
*
|
|
8736
|
+
* The bounds are approximated by the underlying segment buffer; the more segment there are,
|
|
8737
|
+
* the more accurate will be the returned bounds.
|
|
8738
|
+
*
|
|
8739
|
+
* @method getBounds
|
|
8740
|
+
* @instance
|
|
8741
|
+
* @memberof VEllipse
|
|
8742
|
+
* @return {Bounds} The bounds of this ellipse.
|
|
8743
|
+
**/
|
|
8744
|
+
VEllipse.prototype.getBounds = function () {
|
|
8745
|
+
// Thanks to Cuixiping
|
|
8746
|
+
// https://stackoverflow.com/questions/87734/how-do-you-calculate-the-axis-aligned-bounding-box-of-an-ellipse
|
|
8747
|
+
var r1 = this.radiusH();
|
|
8748
|
+
var r2 = this.radiusV();
|
|
8749
|
+
var ux = r1 * Math.cos(this.rotation);
|
|
8750
|
+
var uy = r1 * Math.sin(this.rotation);
|
|
8751
|
+
var vx = r2 * Math.cos(this.rotation + Math.PI / 2);
|
|
8752
|
+
var vy = r2 * Math.sin(this.rotation + Math.PI / 2);
|
|
8753
|
+
var bbox_halfwidth = Math.sqrt(ux * ux + vx * vx);
|
|
8754
|
+
var bbox_halfheight = Math.sqrt(uy * uy + vy * vy);
|
|
8755
|
+
return new Bounds_1.Bounds({ x: this.center.x - bbox_halfwidth, y: this.center.y - bbox_halfheight }, { x: this.center.x + bbox_halfwidth, y: this.center.y + bbox_halfheight });
|
|
8756
|
+
};
|
|
8757
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
8758
|
+
/**
|
|
8759
|
+
* Move the ellipse by the given amount. This is equivalent by moving the `center` and `axis` points.
|
|
8760
|
+
*
|
|
8761
|
+
* @method move
|
|
8762
|
+
* @param {XYCoords} amount - The amount to move.
|
|
8763
|
+
* @instance
|
|
8764
|
+
* @memberof VEllipse
|
|
8765
|
+
* @return {VEllipse} this for chaining
|
|
8766
|
+
**/
|
|
8767
|
+
VEllipse.prototype.move = function (amount) {
|
|
8768
|
+
this.center.add(amount);
|
|
8769
|
+
this.axis.add(amount);
|
|
8770
|
+
return this;
|
|
8771
|
+
};
|
|
7664
8772
|
/**
|
|
7665
8773
|
* Scale this ellipse by the given factor from the center point. The factor will be applied to both radii.
|
|
7666
8774
|
*
|
|
@@ -7718,7 +8826,7 @@ var VEllipse = /** @class */ (function () {
|
|
|
7718
8826
|
* @param {number=1.0} length - [optional, default=1] The length of the returned vector.
|
|
7719
8827
|
*/
|
|
7720
8828
|
VEllipse.prototype.normalAt = function (angle, length) {
|
|
7721
|
-
var point = this.vertAt(angle);
|
|
8829
|
+
var point = this.vertAt(angle - this.rotation); // HERE IS THE CORRECT BEHAVIOR!
|
|
7722
8830
|
var foci = this.getFoci();
|
|
7723
8831
|
// Calculate the angle between [point,focusA] and [point,focusB]
|
|
7724
8832
|
var angleA = new Line_1.Line(point, foci[0]).angle();
|
|
@@ -7730,12 +8838,13 @@ var VEllipse = /** @class */ (function () {
|
|
|
7730
8838
|
.addX(50)
|
|
7731
8839
|
.clone()
|
|
7732
8840
|
.rotate(Math.PI + centerAngle, point);
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
8841
|
+
var resultVector = this.center.distance(endPointA) < this.center.distance(endPointB)
|
|
8842
|
+
? new Vector_1.Vector(point, endPointB)
|
|
8843
|
+
: new Vector_1.Vector(point, endPointA);
|
|
8844
|
+
if (typeof length === "number") {
|
|
8845
|
+
resultVector.setLength(length);
|
|
7738
8846
|
}
|
|
8847
|
+
return resultVector;
|
|
7739
8848
|
};
|
|
7740
8849
|
/**
|
|
7741
8850
|
* Get the tangent vector at the given angle.
|
|
@@ -7754,9 +8863,7 @@ var VEllipse = /** @class */ (function () {
|
|
|
7754
8863
|
*/
|
|
7755
8864
|
VEllipse.prototype.tangentAt = function (angle, length) {
|
|
7756
8865
|
var normal = this.normalAt(angle, length);
|
|
7757
|
-
|
|
7758
|
-
normal.b.rotate(Math.PI / 2, normal.a);
|
|
7759
|
-
return normal;
|
|
8866
|
+
return normal.inv().perp();
|
|
7760
8867
|
};
|
|
7761
8868
|
/**
|
|
7762
8869
|
* Get the perimeter of this ellipse.
|
|
@@ -7807,6 +8914,8 @@ var VEllipse = /** @class */ (function () {
|
|
|
7807
8914
|
/**
|
|
7808
8915
|
* Get equally distributed points on the outline of this ellipse.
|
|
7809
8916
|
*
|
|
8917
|
+
* @method getEquidistantVertices
|
|
8918
|
+
* @instance
|
|
7810
8919
|
* @param {number} pointCount - The number of points.
|
|
7811
8920
|
* @returns {Array<Vertex>}
|
|
7812
8921
|
*/
|
|
@@ -7818,6 +8927,78 @@ var VEllipse = /** @class */ (function () {
|
|
|
7818
8927
|
}
|
|
7819
8928
|
return result;
|
|
7820
8929
|
};
|
|
8930
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
8931
|
+
/**
|
|
8932
|
+
* Get the line intersections as vectors with this ellipse.
|
|
8933
|
+
*
|
|
8934
|
+
* @method lineIntersections
|
|
8935
|
+
* @instance
|
|
8936
|
+
* @param {VertTuple<Vector> ray - The line/ray to intersect this ellipse with.
|
|
8937
|
+
* @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.
|
|
8938
|
+
* @returns
|
|
8939
|
+
*/
|
|
8940
|
+
VEllipse.prototype.lineIntersections = function (ray, inVectorBoundsOnly) {
|
|
8941
|
+
// Question: what happens to extreme versions when ellipse is a line (width or height is zero)?
|
|
8942
|
+
// This would result in a Division_by_Zero exception!
|
|
8943
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
8944
|
+
// Step A: create clones for operations (keep originals unchanged)
|
|
8945
|
+
var ellipseCopy = this.clone(); // VEllipse
|
|
8946
|
+
var rayCopy = ray.clone(); // Vector
|
|
8947
|
+
// Step B: move both so ellipse's center is located at (0,0)
|
|
8948
|
+
var moveAmount = ellipseCopy.center.clone().inv();
|
|
8949
|
+
ellipseCopy.move(moveAmount);
|
|
8950
|
+
rayCopy.add(moveAmount);
|
|
8951
|
+
// Step C: rotate eclipse backwards it's rotation, so that rotation is zero (0.0).
|
|
8952
|
+
// Rotate together with ray!
|
|
8953
|
+
var rotationAmount = -ellipseCopy.rotation;
|
|
8954
|
+
ellipseCopy.rotate(rotationAmount); // Rotation around (0,0) = center of translated ellipse
|
|
8955
|
+
rayCopy.a.rotate(rotationAmount, ellipseCopy.center);
|
|
8956
|
+
rayCopy.b.rotate(rotationAmount, ellipseCopy.center);
|
|
8957
|
+
// Step D: find x/y factors to use for scaling to transform the ellipse to a circle.
|
|
8958
|
+
// Scale together with vector ray.
|
|
8959
|
+
var radiusH = ellipseCopy.radiusH();
|
|
8960
|
+
var radiusV = ellipseCopy.radiusV();
|
|
8961
|
+
var scalingFactors = radiusH > radiusV ? { x: radiusV / radiusH, y: 1.0 } : { x: 1.0, y: radiusH / radiusV };
|
|
8962
|
+
// Step E: scale ellipse AND ray by calculated factors.
|
|
8963
|
+
ellipseCopy.axis.scaleXY(scalingFactors);
|
|
8964
|
+
rayCopy.a.scaleXY(scalingFactors);
|
|
8965
|
+
rayCopy.b.scaleXY(scalingFactors);
|
|
8966
|
+
// Intermediate result: now the ellipse is transformed to a circle and we can calculate intersections :)
|
|
8967
|
+
// Step F: calculate circle+line intersecions
|
|
8968
|
+
var tmpCircle = new Circle_1.Circle(new Vertex_1.Vertex(), ellipseCopy.radiusH()); // radiusH() === radiusV()
|
|
8969
|
+
var intersections = tmpCircle.lineIntersections(rayCopy, inVectorBoundsOnly);
|
|
8970
|
+
// Step G: transform intersecions back to original configuration
|
|
8971
|
+
intersections.forEach(function (intersectionPoint) {
|
|
8972
|
+
// Reverse transformation from above.
|
|
8973
|
+
intersectionPoint.scaleXY({ x: 1 / scalingFactors.x, y: 1 / scalingFactors.y }, ellipseCopy.center);
|
|
8974
|
+
intersectionPoint.rotate(-rotationAmount, ellipseCopy.center);
|
|
8975
|
+
intersectionPoint.sub(moveAmount);
|
|
8976
|
+
});
|
|
8977
|
+
return intersections;
|
|
8978
|
+
};
|
|
8979
|
+
/**
|
|
8980
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
8981
|
+
*
|
|
8982
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
8983
|
+
*
|
|
8984
|
+
* @param line
|
|
8985
|
+
* @param lineIntersectionTangents
|
|
8986
|
+
* @returns
|
|
8987
|
+
*/
|
|
8988
|
+
VEllipse.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
8989
|
+
var _this = this;
|
|
8990
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
8991
|
+
// Find the intersections of all lines plus their tangents inside the circle bounds
|
|
8992
|
+
var interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);
|
|
8993
|
+
return interSectionPoints.map(function (vert) {
|
|
8994
|
+
// Calculate angle
|
|
8995
|
+
var lineFromCenter = new Line_1.Line(_this.center, vert);
|
|
8996
|
+
var angle = lineFromCenter.angle();
|
|
8997
|
+
// Calculate tangent at angle
|
|
8998
|
+
return _this.tangentAt(angle);
|
|
8999
|
+
});
|
|
9000
|
+
};
|
|
9001
|
+
//--- END --- Implement interface `Intersectable`
|
|
7821
9002
|
/**
|
|
7822
9003
|
* Convert this ellipse into cubic Bézier curves.
|
|
7823
9004
|
*
|
|
@@ -7830,7 +9011,7 @@ var VEllipse = /** @class */ (function () {
|
|
|
7830
9011
|
// Math by Luc Maisonobe
|
|
7831
9012
|
// http://www.spaceroots.org/documents/ellipse/node22.html
|
|
7832
9013
|
// Note that ellipses with radiusH=0 or radiusV=0 cannot be represented as Bézier curves.
|
|
7833
|
-
// Return a single line here (as a Bézier curve)
|
|
9014
|
+
// Return a single line here (as a Bézier curve)?
|
|
7834
9015
|
// if (Math.abs(this.radiusV()) < 0.00001) {
|
|
7835
9016
|
// const radiusH = this.radiusH();
|
|
7836
9017
|
// return [
|
|
@@ -7860,10 +9041,10 @@ var VEllipse = /** @class */ (function () {
|
|
|
7860
9041
|
var radiusV = this.radiusV();
|
|
7861
9042
|
var curves = [];
|
|
7862
9043
|
var angles = VEllipse.utils.equidistantVertAngles(radiusH, radiusV, segmentCount);
|
|
7863
|
-
var curAngle = angles[0];
|
|
9044
|
+
var curAngle = angles[0] + this.rotation;
|
|
7864
9045
|
var startPoint = this.vertAt(curAngle);
|
|
7865
9046
|
for (var i = 0; i < angles.length; i++) {
|
|
7866
|
-
var nextAngle = angles[(i + 1) % angles.length];
|
|
9047
|
+
var nextAngle = angles[(i + 1) % angles.length] + this.rotation;
|
|
7867
9048
|
var endPoint = this.vertAt(nextAngle);
|
|
7868
9049
|
if (Math.abs(radiusV) < 0.0001 || Math.abs(radiusH) < 0.0001) {
|
|
7869
9050
|
// Distorted ellipses can only be approximated by linear Bézier segments
|
|
@@ -7872,8 +9053,8 @@ var VEllipse = /** @class */ (function () {
|
|
|
7872
9053
|
curves.push(curve);
|
|
7873
9054
|
}
|
|
7874
9055
|
else {
|
|
7875
|
-
var startTangent = this.tangentAt(curAngle);
|
|
7876
|
-
var endTangent = this.tangentAt(nextAngle);
|
|
9056
|
+
var startTangent = this.tangentAt(curAngle + this.rotation);
|
|
9057
|
+
var endTangent = this.tangentAt(nextAngle + this.rotation);
|
|
7877
9058
|
// Find intersection (ignore that the result might be null in some extreme cases)
|
|
7878
9059
|
var intersection = startTangent.intersection(endTangent);
|
|
7879
9060
|
// What if intersection is undefined?
|
|
@@ -7974,10 +9155,18 @@ exports.VEllipse = VEllipse;
|
|
|
7974
9155
|
* @date 2021-02-26
|
|
7975
9156
|
* @modified 2022-02-02 Added the `destroy` method.
|
|
7976
9157
|
* @modified 2022-11-01 Tweaked the `endpointToCenterParameters` function to handle negative values, too, without errors.
|
|
7977
|
-
* @
|
|
9158
|
+
* @modified 2025-04-01 Adapting a the `toCubicBezier` calculation to match an underlying change in the vertAt and tangentAt calculation of ellipses (was required to hamonize both methods with circles).
|
|
9159
|
+
* @modified 2025-04-02 Adding `VEllipseSector.containsAngle` method.
|
|
9160
|
+
* @modified 2025-04-02 Adding `VEllipseSector.lineIntersections` and `VEllipseSector.lineIntersectionTangents` and implementing `Intersectable`.
|
|
9161
|
+
* @modified 2025-04-07 Adding value wrapping (0 to TWO_PI) to the `VEllipseSector.containsAngle` method.
|
|
9162
|
+
* @modified 2025-04-09 Adding the `VEllipseSector.move` method.
|
|
9163
|
+
* @modified 2025-04-19 Added the `VEllipseSector.getStartPoint` and `getEndPoint` methods.
|
|
9164
|
+
* @modified 2025-04-23 Added the `VEllipseSector.getBounds` method.
|
|
9165
|
+
* @version 1.2.0
|
|
7978
9166
|
*/
|
|
7979
9167
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
7980
9168
|
exports.VEllipseSector = void 0;
|
|
9169
|
+
var Bounds_1 = __webpack_require__(76);
|
|
7981
9170
|
var CubicBezierCurve_1 = __webpack_require__(973);
|
|
7982
9171
|
var geomutils_1 = __webpack_require__(328);
|
|
7983
9172
|
var Line_1 = __webpack_require__(939);
|
|
@@ -8018,6 +9207,142 @@ var VEllipseSector = /** @class */ (function () {
|
|
|
8018
9207
|
this.startAngle = geomutils_1.geomutils.wrapMinMax(startAngle, 0, Math.PI * 2);
|
|
8019
9208
|
this.endAngle = geomutils_1.geomutils.wrapMinMax(endAngle, 0, Math.PI * 2);
|
|
8020
9209
|
}
|
|
9210
|
+
/**
|
|
9211
|
+
* Move the ellipse sector by the given amount.
|
|
9212
|
+
*
|
|
9213
|
+
* @method move
|
|
9214
|
+
* @param {XYCoords} amount - The amount to move.
|
|
9215
|
+
* @instance
|
|
9216
|
+
* @memberof VEllipseSector
|
|
9217
|
+
* @return {VEllipseSector} this for chaining
|
|
9218
|
+
**/
|
|
9219
|
+
VEllipseSector.prototype.move = function (amount) {
|
|
9220
|
+
this.ellipse.move(amount);
|
|
9221
|
+
return this;
|
|
9222
|
+
};
|
|
9223
|
+
/**
|
|
9224
|
+
* Checks wether the given angle (must be inside 0 and PI*2) is contained inside this sector.
|
|
9225
|
+
*
|
|
9226
|
+
* @param {number} angle - The numeric angle to check.
|
|
9227
|
+
* @method containsAngle
|
|
9228
|
+
* @instance
|
|
9229
|
+
* @memberof VEllipseSectpr
|
|
9230
|
+
* @return {boolean} True if (and only if) this sector contains the given angle.
|
|
9231
|
+
*/
|
|
9232
|
+
VEllipseSector.prototype.containsAngle = function (angle) {
|
|
9233
|
+
angle = geomutils_1.geomutils.mapAngleTo2PI(angle); // wrapMinMax(angle, 0, Math.PI * 2);
|
|
9234
|
+
var sAngle = geomutils_1.geomutils.mapAngleTo2PI(this.startAngle);
|
|
9235
|
+
var eAngle = geomutils_1.geomutils.mapAngleTo2PI(this.endAngle);
|
|
9236
|
+
// TODO: cleanup
|
|
9237
|
+
// if (this.startAngle <= this.endAngle) {
|
|
9238
|
+
// return angle >= this.startAngle && angle < this.endAngle;
|
|
9239
|
+
// } else {
|
|
9240
|
+
// // startAngle > endAngle
|
|
9241
|
+
// return angle >= this.startAngle || angle < this.endAngle;
|
|
9242
|
+
// }
|
|
9243
|
+
if (sAngle <= eAngle) {
|
|
9244
|
+
return angle >= sAngle && angle < eAngle;
|
|
9245
|
+
}
|
|
9246
|
+
else {
|
|
9247
|
+
// startAngle > endAngle
|
|
9248
|
+
return angle >= sAngle || angle < eAngle;
|
|
9249
|
+
}
|
|
9250
|
+
};
|
|
9251
|
+
/**
|
|
9252
|
+
* Get the sectors starting point (on the underlying ellipse, located at the start angle).
|
|
9253
|
+
*
|
|
9254
|
+
* @method getStartPoint
|
|
9255
|
+
* @instance
|
|
9256
|
+
* @memberof VEllipseSector
|
|
9257
|
+
* @return {Vertex} The sector's stating point.
|
|
9258
|
+
*/
|
|
9259
|
+
VEllipseSector.prototype.getStartPoint = function () {
|
|
9260
|
+
return this.ellipse.vertAt(this.startAngle);
|
|
9261
|
+
};
|
|
9262
|
+
/**
|
|
9263
|
+
* Get the sectors ending point (on the underlying ellipse, located at the end angle).
|
|
9264
|
+
*
|
|
9265
|
+
* @method getEndPoint
|
|
9266
|
+
* @instance
|
|
9267
|
+
* @memberof VEllipseSector
|
|
9268
|
+
* @return {Vertex} The sector's ending point.
|
|
9269
|
+
*/
|
|
9270
|
+
VEllipseSector.prototype.getEndPoint = function () {
|
|
9271
|
+
return this.ellipse.vertAt(this.endAngle);
|
|
9272
|
+
};
|
|
9273
|
+
//--- BEGIN --- Implement interface `IBounded`
|
|
9274
|
+
/**
|
|
9275
|
+
* Get the bounds of this elliptic sector.
|
|
9276
|
+
*
|
|
9277
|
+
* The bounds are approximated by the underlying segment buffer; the more segment there are,
|
|
9278
|
+
* the more accurate will be the returned bounds.
|
|
9279
|
+
*
|
|
9280
|
+
* @method getBounds
|
|
9281
|
+
* @instance
|
|
9282
|
+
* @memberof VEllipse
|
|
9283
|
+
* @return {Bounds} The bounds of this elliptic sector.
|
|
9284
|
+
**/
|
|
9285
|
+
VEllipseSector.prototype.getBounds = function () {
|
|
9286
|
+
var _this = this;
|
|
9287
|
+
// Calculage angles from east, west, north and south box points and check if they are inside
|
|
9288
|
+
var extremes = this.ellipse.getExtremePoints();
|
|
9289
|
+
var candidates = extremes.filter(function (point) {
|
|
9290
|
+
var angle = new Line_1.Line(_this.ellipse.center, point).angle() - _this.ellipse.rotation;
|
|
9291
|
+
return _this.containsAngle(angle);
|
|
9292
|
+
});
|
|
9293
|
+
return Bounds_1.Bounds.computeFromVertices([this.getStartPoint(), this.getEndPoint()].concat(candidates));
|
|
9294
|
+
};
|
|
9295
|
+
//--- BEGIN --- Implement interface `Intersectable`
|
|
9296
|
+
/**
|
|
9297
|
+
* Get the line intersections as vectors with this ellipse.
|
|
9298
|
+
*
|
|
9299
|
+
* @method lineIntersections
|
|
9300
|
+
* @instance
|
|
9301
|
+
* @memberof VEllipseSectpr
|
|
9302
|
+
* @param {VertTuple<Vector>} ray - The line/ray to intersect this ellipse with.
|
|
9303
|
+
* @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.
|
|
9304
|
+
* @returns
|
|
9305
|
+
*/
|
|
9306
|
+
VEllipseSector.prototype.lineIntersections = function (ray, inVectorBoundsOnly) {
|
|
9307
|
+
var _this = this;
|
|
9308
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
9309
|
+
// First get all line intersections from underlying ellipse.
|
|
9310
|
+
var ellipseIntersections = this.ellipse.lineIntersections(ray, inVectorBoundsOnly);
|
|
9311
|
+
// Drop all intersection points that are not contained in the circle sectors bounds.
|
|
9312
|
+
var tmpLine = new Line_1.Line(this.ellipse.center, new Vertex_1.Vertex());
|
|
9313
|
+
return ellipseIntersections.filter(function (intersectionPoint) {
|
|
9314
|
+
tmpLine.b.set(intersectionPoint);
|
|
9315
|
+
var lineAngle = tmpLine.angle();
|
|
9316
|
+
return _this.containsAngle(lineAngle - _this.ellipse.rotation);
|
|
9317
|
+
});
|
|
9318
|
+
};
|
|
9319
|
+
/**
|
|
9320
|
+
* Get all line intersections of this polygon and their tangents along the shape.
|
|
9321
|
+
*
|
|
9322
|
+
* This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
|
|
9323
|
+
*
|
|
9324
|
+
* @method lineIntersections
|
|
9325
|
+
* @memberof VEllipseSectpr
|
|
9326
|
+
* @param line
|
|
9327
|
+
* @param lineIntersectionTangents
|
|
9328
|
+
* @returns
|
|
9329
|
+
*/
|
|
9330
|
+
VEllipseSector.prototype.lineIntersectionTangents = function (line, inVectorBoundsOnly) {
|
|
9331
|
+
var _this = this;
|
|
9332
|
+
if (inVectorBoundsOnly === void 0) { inVectorBoundsOnly = false; }
|
|
9333
|
+
// Find the intersections of all lines plus their tangents inside the circle bounds
|
|
9334
|
+
var interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);
|
|
9335
|
+
return interSectionPoints.map(function (vert) {
|
|
9336
|
+
// Calculate angle
|
|
9337
|
+
var lineFromCenter = new Line_1.Line(_this.ellipse.center, vert);
|
|
9338
|
+
var angle = lineFromCenter.angle();
|
|
9339
|
+
// console.log("angle", (angle / Math.PI) * 180.0);
|
|
9340
|
+
// const angle = Math.random() * Math.PI * 2; // TODO
|
|
9341
|
+
// Calculate tangent at angle
|
|
9342
|
+
return _this.ellipse.tangentAt(angle);
|
|
9343
|
+
});
|
|
9344
|
+
};
|
|
9345
|
+
//--- END --- Implement interface `Intersectable`
|
|
8021
9346
|
/**
|
|
8022
9347
|
* Convert this elliptic sector into cubic Bézier curves.
|
|
8023
9348
|
*
|
|
@@ -8045,8 +9370,8 @@ var VEllipseSector = /** @class */ (function () {
|
|
|
8045
9370
|
for (var i = 0; i + 1 < angles.length; i++) {
|
|
8046
9371
|
var nextAngle = angles[(i + 1) % angles.length];
|
|
8047
9372
|
var endPoint = this.ellipse.vertAt(nextAngle);
|
|
8048
|
-
var startTangent = this.ellipse.tangentAt(curAngle);
|
|
8049
|
-
var endTangent = this.ellipse.tangentAt(nextAngle);
|
|
9373
|
+
var startTangent = this.ellipse.tangentAt(curAngle + this.ellipse.rotation);
|
|
9374
|
+
var endTangent = this.ellipse.tangentAt(nextAngle + this.ellipse.rotation);
|
|
8050
9375
|
// Distorted ellipses can only be approximated by linear Bézier segments
|
|
8051
9376
|
if (Math.abs(radiusV) < 0.0001 || Math.abs(radiusH) < 0.0001) {
|
|
8052
9377
|
var diff = startPoint.difference(endPoint);
|
|
@@ -8156,7 +9481,7 @@ var VEllipseSector = /** @class */ (function () {
|
|
|
8156
9481
|
return angle >= startAngle || (angle <= endAngle && angle >= 0);
|
|
8157
9482
|
};
|
|
8158
9483
|
// Drop all angles outside the sector
|
|
8159
|
-
|
|
9484
|
+
ellipseAngles = ellipseAngles.filter(angleIsInRange);
|
|
8160
9485
|
// Now we need to sort the angles to the first one in the array is the closest to startAngle.
|
|
8161
9486
|
// --> find the angle that is closest to the start angle
|
|
8162
9487
|
var startIndex = VEllipseSector.ellipseSectorUtils.findClosestToStartAngle(startAngle, endAngle, ellipseAngles);
|
|
@@ -8270,7 +9595,8 @@ exports.VEllipseSector = VEllipseSector;
|
|
|
8270
9595
|
* @modified 2022-02-02 Added the `destroy` method.
|
|
8271
9596
|
* @modified 2022-02-02 Cleared the `Vector.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
8272
9597
|
* @modified 2022-10-25 Added the `getOrthogonal` method.
|
|
8273
|
-
* @
|
|
9598
|
+
* @modified 2025-04-14 Added the `Vector.rotate(number)` method.
|
|
9599
|
+
* @version 1.6.0
|
|
8274
9600
|
*
|
|
8275
9601
|
* @file Vector
|
|
8276
9602
|
* @public
|
|
@@ -8325,7 +9651,6 @@ var Vector = /** @class */ (function (_super) {
|
|
|
8325
9651
|
/**
|
|
8326
9652
|
* Get the perpendicular of this vector which is located at a.
|
|
8327
9653
|
*
|
|
8328
|
-
* @param {Number} t The position on the vector.
|
|
8329
9654
|
* @return {Vector} A new vector being the perpendicular of this vector sitting on a.
|
|
8330
9655
|
**/
|
|
8331
9656
|
Vector.prototype.perp = function () {
|
|
@@ -8401,6 +9726,19 @@ var Vector = /** @class */ (function (_super) {
|
|
|
8401
9726
|
startPoint.y = tmp;
|
|
8402
9727
|
return new Vector(linePoint, startPoint.add(this.a));
|
|
8403
9728
|
};
|
|
9729
|
+
/**
|
|
9730
|
+
* Rotate this vector by the given angle around the first point `a`.
|
|
9731
|
+
*
|
|
9732
|
+
* @name rotate
|
|
9733
|
+
* @method rotate
|
|
9734
|
+
* @return {Vector} this - for chaining.
|
|
9735
|
+
* @instance
|
|
9736
|
+
* @memberof Vector
|
|
9737
|
+
*/
|
|
9738
|
+
Vector.prototype.rotate = function (angle) {
|
|
9739
|
+
this.b.rotate(angle, this.a);
|
|
9740
|
+
return this;
|
|
9741
|
+
};
|
|
8404
9742
|
Vector.utils = {
|
|
8405
9743
|
/**
|
|
8406
9744
|
* Generate a four-point arrow head, starting at the vector end minus the
|
|
@@ -8460,7 +9798,13 @@ exports.Vector = Vector;
|
|
|
8460
9798
|
* @modified 2021-01-20 Added UID.
|
|
8461
9799
|
* @modified 2022-02-02 Added the `destroy` method.
|
|
8462
9800
|
* @modified 2023-09-29 Fixed a calculation error in the VertTuple.hasPoint() function; distance measure was broken!
|
|
8463
|
-
* @
|
|
9801
|
+
* @modified 2024-09-10 Chaging the first param of `pointDistance` from `Vertex` to less strict type `XYCoords`. This should not break anything.
|
|
9802
|
+
* @modified 2024-09-10 Adding the optional `epsilon` param to the `hasPoint` method.
|
|
9803
|
+
* @modified 2024-12-02 Added the `epsilon` param to the `colinear` method. Default is 1.0e-6.
|
|
9804
|
+
* @modified 2025-03-31 Added the `VertTuple.revert` method.
|
|
9805
|
+
* @modified 2025-04-15 Changed param of `VertTuple.moveTo` method from `Vertex` to `XYCoords`.
|
|
9806
|
+
* @modified 2025-04-15 Added method `VertTuple.move` method.
|
|
9807
|
+
* @version 1.4.0
|
|
8464
9808
|
*/
|
|
8465
9809
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
8466
9810
|
exports.VertTuple = void 0;
|
|
@@ -8529,15 +9873,31 @@ var VertTuple = /** @class */ (function () {
|
|
|
8529
9873
|
*
|
|
8530
9874
|
* @method add
|
|
8531
9875
|
* @param {XYCoords} amount The amount (x,y) to add.
|
|
8532
|
-
* @return {Line} this
|
|
8533
9876
|
* @instance
|
|
8534
9877
|
* @memberof VertTuple
|
|
9878
|
+
* @return {VertTuple<T>} this
|
|
8535
9879
|
**/
|
|
8536
9880
|
VertTuple.prototype.add = function (amount) {
|
|
8537
9881
|
this.a.add(amount);
|
|
8538
9882
|
this.b.add(amount);
|
|
8539
9883
|
return this;
|
|
8540
9884
|
};
|
|
9885
|
+
/**
|
|
9886
|
+
* Reverse this vertex tuple: a becomes b, and b becomes a.
|
|
9887
|
+
* This operation is in-place.
|
|
9888
|
+
*
|
|
9889
|
+
* @method add
|
|
9890
|
+
* @param {XYCoords} amount The amount (x,y) to add.
|
|
9891
|
+
* @instance
|
|
9892
|
+
* @memberof VertTuple
|
|
9893
|
+
* @return {VertTuple<T>} this
|
|
9894
|
+
*/
|
|
9895
|
+
VertTuple.prototype.revert = function () {
|
|
9896
|
+
var tmp = this.a;
|
|
9897
|
+
this.a = this.b;
|
|
9898
|
+
this.b = tmp;
|
|
9899
|
+
return this;
|
|
9900
|
+
};
|
|
8541
9901
|
/**
|
|
8542
9902
|
* Normalize this line (set to length 1).
|
|
8543
9903
|
*
|
|
@@ -8567,7 +9927,7 @@ var VertTuple = /** @class */ (function () {
|
|
|
8567
9927
|
* Move this line to a new location.
|
|
8568
9928
|
*
|
|
8569
9929
|
* @method moveTo
|
|
8570
|
-
* @param {
|
|
9930
|
+
* @param {XYCoords} newA - The new desired location of 'a'. Vertex 'b' will be moved, too.
|
|
8571
9931
|
* @return {VertTuple} this
|
|
8572
9932
|
* @instance
|
|
8573
9933
|
* @memberof VertTuple
|
|
@@ -8578,6 +9938,20 @@ var VertTuple = /** @class */ (function () {
|
|
|
8578
9938
|
this.b.add(diff);
|
|
8579
9939
|
return this;
|
|
8580
9940
|
};
|
|
9941
|
+
/**
|
|
9942
|
+
* Move this line by the given amount
|
|
9943
|
+
*
|
|
9944
|
+
* @method move
|
|
9945
|
+
* @param {XYCoords} amount - The amount to move both point of this tuple.
|
|
9946
|
+
* @return {VertTuple} this
|
|
9947
|
+
* @instance
|
|
9948
|
+
* @memberof VertTuple
|
|
9949
|
+
**/
|
|
9950
|
+
VertTuple.prototype.move = function (amount) {
|
|
9951
|
+
this.a.add(amount);
|
|
9952
|
+
this.b.add(amount);
|
|
9953
|
+
return this;
|
|
9954
|
+
};
|
|
8581
9955
|
/**
|
|
8582
9956
|
* Get the angle between this and the passed line (in radians).
|
|
8583
9957
|
*
|
|
@@ -8635,12 +10009,13 @@ var VertTuple = /** @class */ (function () {
|
|
|
8635
10009
|
*
|
|
8636
10010
|
* @method colinear
|
|
8637
10011
|
* @param {VertTuple} line
|
|
10012
|
+
* @param {epsilon?=1.0e-6} epsilon - The epsilon to use (default is 1.0e-6).
|
|
8638
10013
|
* @instance
|
|
8639
10014
|
* @memberof VertTuple
|
|
8640
10015
|
* @return true if both lines are co-linear.
|
|
8641
10016
|
*/
|
|
8642
|
-
VertTuple.prototype.colinear = function (line) {
|
|
8643
|
-
return Math.abs(this.denominator(line)) < Vertex_1.Vertex.EPSILON;
|
|
10017
|
+
VertTuple.prototype.colinear = function (line, epsilon) {
|
|
10018
|
+
return Math.abs(this.denominator(line)) < (typeof epsilon === "undefined" ? Vertex_1.Vertex.EPSILON : epsilon);
|
|
8644
10019
|
};
|
|
8645
10020
|
/**
|
|
8646
10021
|
* Get the closest position T from this line to the specified point.
|
|
@@ -8669,21 +10044,22 @@ var VertTuple = /** @class */ (function () {
|
|
|
8669
10044
|
* that point is located between point `a` and `b`.
|
|
8670
10045
|
*
|
|
8671
10046
|
* @method hasPoint
|
|
8672
|
-
* @param {Vertex} point The point to check.
|
|
8673
|
-
* @param {boolean=} insideBoundsOnly If set to to true (default=false) the point must be between start and end point of the line.
|
|
10047
|
+
* @param {Vertex} point - The point to check.
|
|
10048
|
+
* @param {boolean=} insideBoundsOnly - [optional] If set to to true (default=false) the point must be between start and end point of the line.
|
|
10049
|
+
* @param {number=Vertex.EPSILON} epsilon - [optional] A tolerance.
|
|
8674
10050
|
* @return {boolean} True if the given point is on this line.
|
|
8675
10051
|
* @instance
|
|
8676
10052
|
* @memberof VertTuple
|
|
8677
10053
|
*/
|
|
8678
|
-
VertTuple.prototype.hasPoint = function (point, insideBoundsOnly) {
|
|
10054
|
+
VertTuple.prototype.hasPoint = function (point, insideBoundsOnly, epsilon) {
|
|
8679
10055
|
var t = this.getClosestT(point);
|
|
8680
10056
|
// Compare to pointDistance?
|
|
8681
10057
|
var distance = Math.sqrt(VertTuple.vtutils.dist2(point, this.vertAt(t)));
|
|
8682
10058
|
if (typeof insideBoundsOnly !== "undefined" && insideBoundsOnly) {
|
|
8683
|
-
return distance < Vertex_1.Vertex.EPSILON && t >= 0 && t <= 1;
|
|
10059
|
+
return distance < (epsilon !== null && epsilon !== void 0 ? epsilon : Vertex_1.Vertex.EPSILON) && t >= 0 && t <= 1;
|
|
8684
10060
|
}
|
|
8685
10061
|
else {
|
|
8686
|
-
return distance < Vertex_1.Vertex.EPSILON; // t >= 0 && t <= 1;
|
|
10062
|
+
return distance < (epsilon !== null && epsilon !== void 0 ? epsilon : Vertex_1.Vertex.EPSILON); // t >= 0 && t <= 1;
|
|
8687
10063
|
}
|
|
8688
10064
|
};
|
|
8689
10065
|
/**
|
|
@@ -8703,7 +10079,7 @@ var VertTuple = /** @class */ (function () {
|
|
|
8703
10079
|
* The the minimal distance between this line and the specified point.
|
|
8704
10080
|
*
|
|
8705
10081
|
* @method pointDistance
|
|
8706
|
-
* @param {
|
|
10082
|
+
* @param {XYCoords} p The point (vertex) to measre the distance to.
|
|
8707
10083
|
* @return {number} The absolute minimal distance.
|
|
8708
10084
|
* @instance
|
|
8709
10085
|
* @memberof VertTuple
|
|
@@ -8798,7 +10174,10 @@ exports.VertTuple = VertTuple;
|
|
|
8798
10174
|
* @modified 2023-09-29 Downgraded types for the `Vertex.utils.buildArrowHead` function (replacing Vertex params by more generic XYCoords type).
|
|
8799
10175
|
* @modified 2023-09-29 Added the `Vertex.abs()` method as it seems useful.
|
|
8800
10176
|
* @modified 2024-03-08 Added the optional `precision` param to the `toString` method.
|
|
8801
|
-
* @
|
|
10177
|
+
* @modified 2024-12-17 Outsourced the euclidean distance calculation of `Vertex.distance` to `geomutils.dist4`.
|
|
10178
|
+
* @modified 2025-03-24 Making the second parameter `center` of the `Vertex.rotate` method optional.
|
|
10179
|
+
* @modified 2025-04-13 Adding the `Vertex.move(amount: XYCoords)` method (does the same as `add`, added by naming convention).
|
|
10180
|
+
* @version 2.10.0
|
|
8802
10181
|
*
|
|
8803
10182
|
* @file Vertex
|
|
8804
10183
|
* @public
|
|
@@ -8808,6 +10187,7 @@ exports.Vertex = void 0;
|
|
|
8808
10187
|
var VertexAttr_1 = __webpack_require__(476);
|
|
8809
10188
|
var UIDGenerator_1 = __webpack_require__(938);
|
|
8810
10189
|
var VertexListeners_1 = __webpack_require__(934);
|
|
10190
|
+
var geomutils_1 = __webpack_require__(328);
|
|
8811
10191
|
/**
|
|
8812
10192
|
* @classdesc A vertex is a pair of two numbers.<br>
|
|
8813
10193
|
* <br>
|
|
@@ -8994,6 +10374,21 @@ var Vertex = /** @class */ (function () {
|
|
|
8994
10374
|
}
|
|
8995
10375
|
return this;
|
|
8996
10376
|
};
|
|
10377
|
+
/**
|
|
10378
|
+
* Move this point by the given amount.
|
|
10379
|
+
*
|
|
10380
|
+
* This method just calls `add(amount).
|
|
10381
|
+
*
|
|
10382
|
+
*
|
|
10383
|
+
* @method move
|
|
10384
|
+
* @param {Vertex} amount - The amount to move this vertex.
|
|
10385
|
+
* @return {Vertex} this - For chaining.
|
|
10386
|
+
* @instance
|
|
10387
|
+
* @memberof Vertex
|
|
10388
|
+
*/
|
|
10389
|
+
Vertex.prototype.move = function (amount) {
|
|
10390
|
+
return this.add(amount);
|
|
10391
|
+
};
|
|
8997
10392
|
/**
|
|
8998
10393
|
* Add the passed amounts to the x- and y- components of this vertex.
|
|
8999
10394
|
*
|
|
@@ -9151,7 +10546,8 @@ var Vertex = /** @class */ (function () {
|
|
|
9151
10546
|
* @memberof Vertex
|
|
9152
10547
|
**/
|
|
9153
10548
|
Vertex.prototype.distance = function (vert) {
|
|
9154
|
-
return Math.sqrt(Math.pow(vert.x - this.x, 2) + Math.pow(vert.y - this.y, 2));
|
|
10549
|
+
// return Math.sqrt(Math.pow(vert.x - this.x, 2) + Math.pow(vert.y - this.y, 2));
|
|
10550
|
+
return geomutils_1.geomutils.dist4(this.x, this.y, vert.x, vert.y);
|
|
9155
10551
|
};
|
|
9156
10552
|
/**
|
|
9157
10553
|
* Get the angle of this point (relative to (0,0) or to the given other origin point).
|
|
@@ -9832,6 +11228,7 @@ exports.VertexListeners = VertexListeners;
|
|
|
9832
11228
|
* @modified 2023-09-29 Added the `lineDashes` attribute.
|
|
9833
11229
|
* @modified 2023-09-30 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.
|
|
9834
11230
|
* @modified 2023-10-07 Adding the optional `arrowHeadBasePositionBuffer` param to the arrowHead(...) method.
|
|
11231
|
+
* @modified 2024-09-13 Remoed the scaling of `lineWidth` in the `polygon` and `polyline` methods. This makes no sense here and doesn't match up with the behavior of other line functions.
|
|
9835
11232
|
* @version 1.13.0
|
|
9836
11233
|
**/
|
|
9837
11234
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
@@ -10762,7 +12159,7 @@ var drawutils = /** @class */ (function () {
|
|
|
10762
12159
|
this.ctx.save();
|
|
10763
12160
|
this.applyStrokeOpts(strokeOptions);
|
|
10764
12161
|
this.ctx.beginPath();
|
|
10765
|
-
this.ctx.lineWidth =
|
|
12162
|
+
this.ctx.lineWidth = lineWidth || 1.0;
|
|
10766
12163
|
this.ctx.moveTo(this.offset.x + vertices[0].x * this.scale.x, this.offset.y + vertices[0].y * this.scale.y);
|
|
10767
12164
|
for (var i = 0; i < vertices.length; i++) {
|
|
10768
12165
|
this.ctx.lineTo(this.offset.x + vertices[i].x * this.scale.x, this.offset.y + vertices[i].y * this.scale.y);
|
|
@@ -12690,6 +14087,30 @@ var drawutilssvg = /** @class */ (function () {
|
|
|
12690
14087
|
* @memberof drawutilssvg
|
|
12691
14088
|
*/
|
|
12692
14089
|
drawutilssvg.prototype.grid = function (center, width, height, sizeX, sizeY, color) {
|
|
14090
|
+
// console.log("grid");
|
|
14091
|
+
// const node: SVGElement = this.makeNode("pattern");
|
|
14092
|
+
// var patternId = "pattern_id_" + Math.floor(Math.random() * 65365);
|
|
14093
|
+
// node.setAttribute("id", patternId);
|
|
14094
|
+
// node.setAttribute("viewBox", `0,0,${sizeX},${sizeY}`);
|
|
14095
|
+
// node.setAttribute("width", `${sizeX}`);
|
|
14096
|
+
// node.setAttribute("height", `${sizeX}`);
|
|
14097
|
+
// var pattern: SVGElement = this.makeNode("path");
|
|
14098
|
+
// const d: SVGPathParams = [];
|
|
14099
|
+
// d.push("M", sizeX / 2.0, 0);
|
|
14100
|
+
// d.push("L", sizeX / 2.0, sizeY);
|
|
14101
|
+
// d.push("M", 0, sizeY / 2.0);
|
|
14102
|
+
// d.push("L", sizeX, sizeY / 2.0);
|
|
14103
|
+
// node.setAttribute("d", d.join(" "));
|
|
14104
|
+
// this.bufferedNodeDefs.append(pattern);
|
|
14105
|
+
// const fillNode: SVGElement = this.makeNode("rect");
|
|
14106
|
+
// // For some strange reason SVG rotation transforms use degrees instead of radians
|
|
14107
|
+
// // Note that the background does not scale with the zoom level (always covers full element)
|
|
14108
|
+
// fillNode.setAttribute("x", "0");
|
|
14109
|
+
// fillNode.setAttribute("y", "0");
|
|
14110
|
+
// fillNode.setAttribute("width", `${this.canvasSize.width}`);
|
|
14111
|
+
// fillNode.setAttribute("height", `${this.canvasSize.height}`);
|
|
14112
|
+
// fillNode.setAttribute("fill", `url(#${patternId})`);
|
|
14113
|
+
// return this._bindFillDraw(fillNode, "grid", "red", 1);
|
|
12693
14114
|
var node = this.makeNode("path");
|
|
12694
14115
|
var d = [];
|
|
12695
14116
|
var yMin = -Math.ceil((height * 0.5) / sizeY) * sizeY;
|
|
@@ -13415,7 +14836,10 @@ exports.drawutilssvg = drawutilssvg;
|
|
|
13415
14836
|
* @author Ikaros Kappler
|
|
13416
14837
|
* @date 2019-02-03
|
|
13417
14838
|
* @modified 2021-03-01 Added `wrapMax` function.
|
|
13418
|
-
* @
|
|
14839
|
+
* @modified 2024-11-15 Adding helper function `geomutils.mapAngleTo2PI(number)` for mapping any value into the interval [0,2*PI).
|
|
14840
|
+
* @modified 2024-11-22 Adding helper function `geomutils.dotProduct(number)` for calculating the dot product of two vertices (as vectors).
|
|
14841
|
+
*
|
|
14842
|
+
* @version 1.2.0
|
|
13419
14843
|
**/
|
|
13420
14844
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
13421
14845
|
exports.geomutils = void 0;
|
|
@@ -13427,6 +14851,49 @@ var Triangle_1 = __webpack_require__(737);
|
|
|
13427
14851
|
* @global
|
|
13428
14852
|
**/
|
|
13429
14853
|
exports.geomutils = {
|
|
14854
|
+
/**
|
|
14855
|
+
* Map any angle (any numeric value) to [0, Math.PI).
|
|
14856
|
+
*
|
|
14857
|
+
* @param {number} angle - The numeric value to map.
|
|
14858
|
+
* @return {number} The mapped angle inside [0,PI*2].
|
|
14859
|
+
**/
|
|
14860
|
+
mapAngleTo2PI: function (angle) {
|
|
14861
|
+
// Source: https://forums.codeguru.com/showthread.php?384172-get-angle-into-range-0-2*pi
|
|
14862
|
+
var new_angle = Math.asin(Math.sin(angle));
|
|
14863
|
+
if (Math.cos(angle) < 0) {
|
|
14864
|
+
return Math.PI - new_angle;
|
|
14865
|
+
}
|
|
14866
|
+
else if (new_angle < 0) {
|
|
14867
|
+
return new_angle + 2 * Math.PI;
|
|
14868
|
+
}
|
|
14869
|
+
else {
|
|
14870
|
+
return new_angle;
|
|
14871
|
+
}
|
|
14872
|
+
},
|
|
14873
|
+
/**
|
|
14874
|
+
* Calculate the euclidean distance between two points given by four coordinates (two coordinates each).
|
|
14875
|
+
*
|
|
14876
|
+
* @param {number} x1
|
|
14877
|
+
* @param {number} y1
|
|
14878
|
+
* @param {number} x2
|
|
14879
|
+
* @param {number} y2
|
|
14880
|
+
* @returns {number}
|
|
14881
|
+
*/
|
|
14882
|
+
dist4: function (x1, y1, x2, y2) {
|
|
14883
|
+
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y1 - y2, 2));
|
|
14884
|
+
},
|
|
14885
|
+
/**
|
|
14886
|
+
* Map any angle (any numeric value) to [0, Math.PI).
|
|
14887
|
+
*
|
|
14888
|
+
* A × B := (A.x * B.x) + (A.y * B.y)
|
|
14889
|
+
*
|
|
14890
|
+
* @param {XYCoords} vertA - The first vertex.
|
|
14891
|
+
* @param {XYCoords} vertB - The second vertex.
|
|
14892
|
+
* @return {number} The dot product of the two vertices.
|
|
14893
|
+
**/
|
|
14894
|
+
dotProduct: function (vertA, vertB) {
|
|
14895
|
+
return vertA.x * vertB.x + vertA.y * vertB.y;
|
|
14896
|
+
},
|
|
13430
14897
|
/**
|
|
13431
14898
|
* Compute the n-section of the angle – described as a triangle (A,B,C) – in point A.
|
|
13432
14899
|
*
|