plotboilerplate 1.26.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +2 -0
  2. package/dist/index.esm.js +33 -11
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.esm.min.js +1 -1
  5. package/dist/index.esm.min.js.map +1 -1
  6. package/dist/plotboilerplate.browser.min.js +1 -1
  7. package/dist/plotboilerplate.browser.min.js.map +1 -1
  8. package/dist/plotboilerplate.js +33 -11
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +6 -2
  11. package/src/cjs/PlotBoilerplate.d.ts +4 -3
  12. package/src/cjs/PlotBoilerplate.js +2 -1
  13. package/src/cjs/PlotBoilerplate.js.map +1 -1
  14. package/src/cjs/draw.d.ts +4 -2
  15. package/src/cjs/draw.js +9 -4
  16. package/src/cjs/draw.js.map +1 -1
  17. package/src/cjs/drawgl.d.ts +3 -2
  18. package/src/cjs/drawgl.js +2 -1
  19. package/src/cjs/drawgl.js.map +1 -1
  20. package/src/cjs/drawutilssvg.d.ts +9 -4
  21. package/src/cjs/drawutilssvg.js +20 -5
  22. package/src/cjs/drawutilssvg.js.map +1 -1
  23. package/src/cjs/interfaces/DrawLib.d.ts +2 -0
  24. package/src/cjs/interfaces/DrawLib.js +1 -0
  25. package/src/cjs/interfaces/DrawLib.js.map +1 -1
  26. package/src/cjs/utils/WebColors.d.ts +2 -1
  27. package/src/cjs/utils/WebColors.js +14 -25
  28. package/src/cjs/utils/WebColors.js.map +1 -1
  29. package/src/cjs/utils/algorithms/PolygonTesselationOutlines.d.ts +145 -0
  30. package/src/cjs/utils/algorithms/PolygonTesselationOutlines.js +269 -0
  31. package/src/cjs/utils/algorithms/PolygonTesselationOutlines.js.map +1 -0
  32. package/src/cjs/utils/datastructures/Color.js +0 -19
  33. package/src/cjs/utils/datastructures/Color.js.map +1 -1
  34. package/src/cjs/utils/datastructures/ColorGradient.d.ts +2 -0
  35. package/src/cjs/utils/datastructures/ColorGradient.js +5 -0
  36. package/src/cjs/utils/datastructures/ColorGradient.js.map +1 -1
  37. package/src/cjs/utils/datastructures/Girih.d.ts +38 -1
  38. package/src/cjs/utils/datastructures/Girih.js +71 -1
  39. package/src/cjs/utils/datastructures/Girih.js.map +1 -1
  40. package/src/cjs/utils/io/FileDrop.d.ts +2 -0
  41. package/src/cjs/utils/io/FileDrop.js +4 -0
  42. package/src/cjs/utils/io/FileDrop.js.map +1 -1
  43. package/src/esm/PlotBoilerplate.d.ts +4 -3
  44. package/src/esm/PlotBoilerplate.js +2 -1
  45. package/src/esm/PlotBoilerplate.js.map +1 -1
  46. package/src/esm/draw.d.ts +4 -2
  47. package/src/esm/draw.js +9 -4
  48. package/src/esm/draw.js.map +1 -1
  49. package/src/esm/drawgl.d.ts +3 -2
  50. package/src/esm/drawgl.js +2 -1
  51. package/src/esm/drawgl.js.map +1 -1
  52. package/src/esm/drawutilssvg.d.ts +9 -4
  53. package/src/esm/drawutilssvg.js +20 -5
  54. package/src/esm/drawutilssvg.js.map +1 -1
  55. package/src/esm/interfaces/DrawLib.d.ts +2 -0
  56. package/src/esm/interfaces/DrawLib.js +1 -0
  57. package/src/esm/interfaces/DrawLib.js.map +1 -1
  58. package/src/esm/utils/WebColors.d.ts +2 -1
  59. package/src/esm/utils/WebColors.js +14 -25
  60. package/src/esm/utils/WebColors.js.map +1 -1
  61. package/src/esm/utils/algorithms/PolygonTesselationOutlines.d.ts +145 -0
  62. package/src/esm/utils/algorithms/PolygonTesselationOutlines.js +262 -0
  63. package/src/esm/utils/algorithms/PolygonTesselationOutlines.js.map +1 -0
  64. package/src/esm/utils/datastructures/Color.js +0 -19
  65. package/src/esm/utils/datastructures/Color.js.map +1 -1
  66. package/src/esm/utils/datastructures/ColorGradient.d.ts +2 -0
  67. package/src/esm/utils/datastructures/ColorGradient.js +5 -0
  68. package/src/esm/utils/datastructures/ColorGradient.js.map +1 -1
  69. package/src/esm/utils/datastructures/Girih.d.ts +38 -1
  70. package/src/esm/utils/datastructures/Girih.js +71 -1
  71. package/src/esm/utils/datastructures/Girih.js.map +1 -1
  72. package/src/esm/utils/io/FileDrop.d.ts +2 -0
  73. package/src/esm/utils/io/FileDrop.js +4 -0
  74. package/src/esm/utils/io/FileDrop.js.map +1 -1
  75. package/src/ts/PlotBoilerplate.ts +4 -3
  76. package/src/ts/draw.ts +8 -3
  77. package/src/ts/drawgl.ts +3 -2
  78. package/src/ts/drawutilssvg.ts +27 -5
  79. package/src/ts/interfaces/DrawLib.ts +3 -0
  80. package/src/ts/utils/WebColors.ts +20 -33
  81. package/src/ts/utils/algorithms/PolygonTesselationOutlines.ts +296 -0
  82. package/src/ts/utils/datastructures/Color.ts +0 -19
  83. package/src/ts/utils/datastructures/ColorGradient.ts +6 -0
  84. package/src/ts/utils/datastructures/Girih.ts +78 -1
  85. package/src/ts/utils/datastructures/interfaces.ts +4 -4
  86. package/src/ts/utils/io/FileDrop.ts +5 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.min.js","sources":["../src/esm/VertexAttr.js","../src/esm/UIDGenerator.js","../src/esm/VertexListeners.js","../src/esm/Circle.js","../src/esm/Triangle.js","../src/esm/geomutils.js","../src/esm/Vertex.js","../src/esm/VertTuple.js","../src/esm/Vector.js","../src/esm/Line.js","../src/esm/Polygon.js","../src/esm/Bounds.js","../src/esm/CubicBezierCurve.js","../src/esm/BezierPath.js","../src/esm/CircleSector.js","../src/esm/drawutilssvg.js","../src/esm/draw.js","../src/esm/drawgl.js","../src/esm/Grid.js","../src/esm/KeyHandler.js","../src/esm/MouseHandler.js","../src/esm/PBImage.js","../src/esm/PBText.js","../node_modules/alloyfinger-typescript/src/esm/alloy_finger.js","../src/esm/VEllipse.js","../src/esm/VEllipseSector.js","../src/esm/PlotBoilerplate.js"],"sourcesContent":["/**\n * @author Ikaros Kappler\n * @date 2018-08-26\n * @modified 2018-11-17 Added the 'isSelected' attribute.\n * @modified 2018-11-27 Added the global model for instantiating with custom attributes.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2020-02-29 Added the 'selectable' attribute.\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2024-03-10 Fixed some types for Typescript 5 compatibility.\n * @version 1.1.2\n *\n * @file VertexAttr\n * @public\n **/\n/**\n * @classdesc The VertexAttr is a helper class to wrap together additional attributes\n * to vertices that do not belong to the 'standard canonical' vertex implementation.<br>\n * <br>\n * This is some sort of 'userData' object, but the constructor uses a global model\n * to obtain a (configurable) default attribute set to all instances.<br>\n */\nexport class VertexAttr {\n /**\n * The constructor.\n *\n * Attributes will be initialized as defined in the model object\n * which serves as a singleton.\n *\n * @constructor\n * @name VertexAttr\n **/\n constructor() {\n this.draggable = true;\n this.selectable = true;\n this.isSelected = false;\n this.visible = true;\n for (var key in VertexAttr.model)\n this[key] = VertexAttr.model[key];\n }\n ;\n}\n/**\n * This is the global attribute model. Set these object on the initialization\n * of your app to gain all VertexAttr instances have these attributes.\n *\n * @type {object}\n **/\nVertexAttr.model = {\n draggable: true,\n selectable: true,\n isSelected: false,\n visible: true\n};\n//# sourceMappingURL=VertexAttr.js.map","/**\n * @classdesc A static UIDGenerator.\n *\n * @author Ikaros Kappler\n * @date 2021-01-20\n * @version 1.0.0\n */\nexport class UIDGenerator {\n static next() {\n return `${UIDGenerator.current++}`;\n }\n}\nUIDGenerator.current = 0;\n//# sourceMappingURL=UIDGenerator.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-08-27\n * @modified 2018-11-28 Added the vertex-param to the constructor and extended the event. Vertex events now have a 'params' attribute object.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2020-02-22 Added 'return this' to the add* functions (for chanining).\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2020-11-17 Added the `click` handler.\n * @version 1.1.0\n *\n * @file VertexListeners\n * @public\n **/\n/**\n * @classdesc An event listeners wrapper. This is just a set of three listener\n * queues (drag, dragStart, dragEnd) and their respective firing\n * functions.\n *\n */\nexport class VertexListeners {\n /**\n * The constructor.\n *\n * @constructor\n * @name VertexListeners\n * @param {Vertex} vertex - The vertex to use these listeners on (just a backward reference).\n **/\n constructor(vertex) {\n this.click = [];\n this.drag = [];\n this.dragStart = [];\n this.dragEnd = [];\n this.vertex = vertex;\n }\n /**\n * Add a click listener.\n *\n * @method addClickListener\n * @param {VertexListeners~dragListener} listener - The click listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addClickListener(listener) {\n VertexListeners._addListener(this.click, listener);\n return this;\n }\n /**\n * The click listener is a function with a single drag event param.\n * @callback VertexListeners~clickListener\n * @param {Event} e - The (extended) click event.\n */\n /**\n * Remove a drag listener.\n *\n * @method removeDragListener\n * @param {VertexListeners~dragListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeClickListener(listener) {\n this.click = VertexListeners._removeListener(this.click, listener);\n return this;\n }\n /**\n * The click listener is a function with a single drag event param.\n * @callback VertexListeners~clickListener\n * @param {Event} e - The (extended) click event.\n */\n /**\n * Add a drag listener.\n *\n * @method addDragListener\n * @param {VertexListeners~dragListener} listener - The drag listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addDragListener(listener) {\n VertexListeners._addListener(this.drag, listener);\n return this;\n }\n /**\n * The drag listener is a function with a single drag event param.\n * @callback VertexListeners~dragListener\n * @param {Event} e - The (extended) drag event.\n */\n /**\n * Remove a drag listener.\n *\n * @method removeDragListener\n * @param {VertexListeners~dragListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeDragListener(listener) {\n this.drag = VertexListeners._removeListener(this.drag, listener);\n return this;\n }\n /**\n * Add a dragStart listener.\n *\n * @method addDragListener\n * @param {VertexListeners~dragStartListener} listener - The drag-start listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addDragStartListener(listener) {\n VertexListeners._addListener(this.dragStart, listener);\n return this;\n }\n /**\n * The drag-start listener is a function with a single drag event param.\n * @callback VertexListeners~dragStartListener\n * @param {Event} e - The (extended) drag event.\n */\n /**\n * Remove a dragStart listener.\n *\n * @method addDragStartListener\n * @param {VertexListeners~dragListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeDragStartListener(listener) {\n this.dragStart = VertexListeners._removeListener(this.dragStart, listener);\n return this;\n }\n /**\n * Add a dragEnd listener.\n *\n * @method addDragListener\n * @param {VertexListeners~dragEndListener} listener - The drag-end listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addDragEndListener(listener) {\n // this.dragEnd.push( listener );\n VertexListeners._addListener(this.dragEnd, listener);\n return this;\n }\n /**\n * The drag-end listener is a function with a single drag event param.\n * @callback VertexListeners~dragEndListener\n * @param {Event} e - The (extended) drag event.\n */\n /**\n * Remove a drag listener.\n *\n * @method removeDragEndListener\n * @param {VertexListeners~clickListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeDragEndListener(listener) {\n // this.drag.push( listener );\n this.dragEnd = VertexListeners._removeListener(this.dragEnd, listener);\n return this;\n }\n /**\n * Fire a click event with the given event instance to all\n * installed click listeners.\n *\n * @method fireClickEvent\n * @param {VertEvent|XMouseEvent} e - The click event itself to be fired to all installed drag listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireClickEvent(e) {\n VertexListeners._fireEvent(this, this.click, e);\n }\n /**\n * Fire a drag event with the given event instance to all\n * installed drag listeners.\n *\n * @method fireDragEvent\n * @param {VertEvent|XMouseEvent} e - The drag event itself to be fired to all installed drag listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireDragEvent(e) {\n VertexListeners._fireEvent(this, this.drag, e);\n }\n /**\n * Fire a dragStart event with the given event instance to all\n * installed drag-start listeners.\n *\n * @method fireDragStartEvent\n * @param {VertEvent|XMouseEvent} e - The drag-start event itself to be fired to all installed dragStart listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireDragStartEvent(e) {\n VertexListeners._fireEvent(this, this.dragStart, e);\n }\n /**\n * Fire a dragEnd event with the given event instance to all\n * installed drag-end listeners.\n *\n * @method fireDragEndEvent\n * @param {VertEvent|XMouseEvent} e - The drag-end event itself to be fired to all installed dragEnd listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireDragEndEvent(e) {\n VertexListeners._fireEvent(this, this.dragEnd, e);\n }\n /**\n * Removes all listeners from this listeners object.\n */\n removeAllListeners() {\n this.click = [];\n this.drag = [];\n this.dragStart = [];\n this.dragEnd = [];\n }\n /**\n * @private\n **/\n static _fireEvent(_self, listeners, e) {\n const ve = e;\n if (typeof ve.params == \"undefined\")\n ve.params = { vertex: _self.vertex };\n else\n ve.params.vertex = _self.vertex;\n for (var i in listeners) {\n listeners[i](ve);\n }\n }\n /**\n * @private\n */\n static _addListener(listeners, newListener) {\n for (var i in listeners) {\n if (listeners[i] == newListener)\n return false;\n }\n listeners.push(newListener);\n return true;\n }\n /**\n * @private\n */\n static _removeListener(listeners, oldListener) {\n for (var i = 0; i < listeners.length; i++) {\n if (listeners[i] == oldListener)\n return listeners.splice(i, 1);\n }\n return listeners;\n }\n}\n//# sourceMappingURL=VertexListeners.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-05-04\n * @modified 2020-05-09 Ported to typescript.\n * @modified 2020-05-25 Added the vertAt and tangentAt functions.\n * @mofidied 2020-09-07 Added the circleIntersection(Circle) function.\n * @modified 2020-09-07 Changed the vertAt function by switching sin and cos! The old version did not return the correct vertex (by angle) accoring to the assumed circle math.\n * @modified 2020-10-16 Added the containsCircle(...) function.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-08-15 Added the `containsPoint` function.\n * @modified 2022-08-23 Added the `lineIntersection` function.\n * @modified 2022-08-23 Added the `closestPoint` function.\n * @modified 2025-04-09 Added the `Circle.move(amount: XYCoords)` method.\n * @modified 2025-04-16 Class `Circle` now implements interface `Intersectable`.\n * @version 1.5.0\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Line } from \"./Line\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A simple circle: center point and radius.\n *\n * @requires Line\n * @requires Vector\n * @requires VertTuple\n * @requires Vertex\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class Circle {\n /**\n * Create a new circle with given center point and radius.\n *\n * @constructor\n * @name Circle\n * @param {Vertex} center - The center point of the circle.\n * @param {number} radius - The radius of the circle.\n */\n constructor(center, radius) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Circle\";\n this.uid = UIDGenerator.next();\n this.center = center;\n this.radius = radius;\n }\n /**\n * Move the circle by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof Circle\n * @return {Circle} this for chaining\n **/\n move(amount) {\n this.center.add(amount);\n return this;\n }\n /**\n * Check if the given circle is fully contained inside this circle.\n *\n * @method containsPoint\n * @param {XYCoords} point - The point to check if it is contained in this circle.\n * @instance\n * @memberof Circle\n * @return {boolean} `true` if the given point is inside this circle.\n */\n containsPoint(point) {\n return this.center.distance(point) < this.radius;\n }\n /**\n * Check if the given circle is fully contained inside this circle.\n *\n * @method containsCircle\n * @param {Circle} circle - The circle to check if it is contained in this circle.\n * @instance\n * @memberof Circle\n * @return {boolean} `true` if any only if the given circle is completely inside this circle.\n */\n containsCircle(circle) {\n return this.center.distance(circle.center) + circle.radius < this.radius;\n }\n /**\n * Calculate the distance from this circle to the given line.\n *\n * * If the line does not intersect this ciecle then the returned\n * value will be the minimal distance.\n * * If the line goes through this circle then the returned value\n * will be max inner distance and it will be negative.\n *\n * @method lineDistance\n * @param {Line} line - The line to measure the distance to.\n * @return {number} The minimal distance from the outline of this circle to the given line.\n * @instance\n * @memberof Circle\n */\n lineDistance(line) {\n const closestPointOnLine = line.getClosestPoint(this.center);\n return closestPointOnLine.distance(this.center) - this.radius;\n }\n /**\n * Get the vertex on the this circle for the given angle.\n *\n * @method vertAt\n * @param {number} angle - The angle (in radians) to use.\n * @return {Vertex} The vertex (point) at the given angle.\n * @instance\n * @memberof Circle\n **/\n vertAt(angle) {\n // Find the point on the circle respective the angle. Then move relative to center.\n return Circle.circleUtils.vertAt(angle, this.radius).add(this.center);\n }\n /**\n * Get a tangent line of this circle for a given angle.\n *\n * Point a of the returned line is located on the circle, the length equals the radius.\n *\n * @method tangentAt\n * @instance\n * @param {number} angle - The angle (in radians) to use.\n * @return {Line} The tangent line.\n * @memberof Circle\n **/\n tangentAt(angle) {\n const pointA = Circle.circleUtils.vertAt(angle, this.radius);\n // Construct the perpendicular of the line in point a. Then move relative to center.\n return new Vector(pointA, new Vertex(0, 0)).add(this.center).perp();\n // return (new Vector(this.center.clone(), pointA).add(pointA) as Vector).perp() as Vector;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the bounding box (bounds) of this Circle.\n *\n * @method getBounds\n * @instance\n * @memberof Circle\n * @return {Bounds} The rectangular bounds of this Circle.\n **/\n getBounds() {\n return new 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)));\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Calculate the intersection points (if exists) with the given circle.\n *\n * @method circleIntersection\n * @instance\n * @memberof Circle\n * @param {Circle} circle\n * @return {Line|null} The intersection points (as a line) or null if the two circles do not intersect.\n **/\n circleIntersection(circle) {\n // Circles do not intersect at all?\n if (this.center.distance(circle.center) > this.radius + circle.radius) {\n return null;\n }\n // One circle is fully inside the other?\n if (this.center.distance(circle.center) < Math.abs(this.radius - circle.radius)) {\n return null;\n }\n // Based on the C++ implementation by Robert King\n // https://stackoverflow.com/questions/3349125/circle-circle-intersection-points\n // and the 'Circles and spheres' article by Paul Bourke.\n // http://paulbourke.net/geometry/circlesphere/\n //\n // This is the original C++ implementation:\n //\n // pair<Point, Point> intersections(Circle c) {\n // Point P0(x, y);\n // Point P1(c.x, c.y);\n // float d, a, h;\n // d = P0.distance(P1);\n // a = (r*r - c.r*c.r + d*d)/(2*d);\n // h = sqrt(r*r - a*a);\n // Point P2 = P1.sub(P0).scale(a/d).add(P0);\n // float x3, y3, x4, y4;\n // x3 = P2.x + h*(P1.y - P0.y)/d;\n // y3 = P2.y - h*(P1.x - P0.x)/d;\n // x4 = P2.x - h*(P1.y - P0.y)/d;\n // y4 = P2.y + h*(P1.x - P0.x)/d;\n // return pair<Point, Point>(Point(x3, y3), Point(x4, y4));\n // }\n var p0 = this.center;\n var p1 = circle.center;\n var d = p0.distance(p1);\n var a = (this.radius * this.radius - circle.radius * circle.radius + d * d) / (2 * d);\n var h = Math.sqrt(this.radius * this.radius - a * a);\n var p2 = p1.clone().scale(a / d, p0);\n var x3 = p2.x + (h * (p1.y - p0.y)) / d;\n var y3 = p2.y - (h * (p1.x - p0.x)) / d;\n var x4 = p2.x - (h * (p1.y - p0.y)) / d;\n var y4 = p2.y + (h * (p1.x - p0.x)) / d;\n return new Line(new Vertex(x3, y3), new Vertex(x4, y4));\n }\n /**\n * Calculate the intersection points (if exists) with the given infinite line (defined by two points).\n *\n * @method lineIntersection\n * @instance\n * @memberof Circle\n * @param {Vertex} a- The first of the two points defining the line.\n * @param {XYCoords} b - The second of the two points defining the line.\n * @return {Line|null} The intersection points (as a line) or null if this circle does not intersect the line given.\n **/\n lineIntersection(a, b) {\n // Based on the math from\n // https://mathworld.wolfram.com/Circle-LineIntersection.html\n const interA = new Vertex();\n const interB = new Vertex();\n // First do a transformation, because the calculation is based on a cicle at (0,0)\n const transA = new Vertex(a).sub(this.center);\n const transB = new Vertex(b).sub(this.center);\n const diff = transA.difference(transB);\n // There is a special case if diff.y=0, where the intersection is not calcuatable.\n // Use an non-zero epsilon here to approximate this case.\n // TODO for the future: find a better solution\n if (Math.abs(diff.y) === 0) {\n diff.y = 0.000001;\n }\n const dist = transA.distance(transB);\n const det = transA.x * transB.y - transA.y * transB.x;\n const distSquared = dist * dist;\n const radiusSquared = this.radius * this.radius;\n // Check if circle and line have an intersection at all\n if (radiusSquared * distSquared - det * det < 0) {\n return null;\n }\n const belowSqrt = this.radius * this.radius * dist * dist - det * det;\n const sqrt = Math.sqrt(belowSqrt);\n interA.x = (det * diff.y + Math.sign(diff.y) * diff.x * sqrt) / distSquared;\n interB.x = (det * diff.y - Math.sign(diff.y) * diff.x * sqrt) / distSquared;\n interA.y = (-det * diff.x + Math.abs(diff.y) * sqrt) / distSquared;\n interB.y = (-det * diff.x - Math.abs(diff.y) * sqrt) / distSquared;\n return new Line(interA.add(this.center), interB.add(this.center));\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this circle.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections with the circle outline.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n const intersectioLine = this.lineIntersection(line.a, line.b);\n if (!intersectioLine) {\n return [];\n }\n if (inVectorBoundsOnly) {\n // const maxDist = line.length();\n return [intersectioLine.a, intersectioLine.b].filter((vert) => line.hasPoint(vert, true));\n }\n else {\n return [intersectioLine.a, intersectioLine.b];\n }\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.center, vert);\n const angle = lineFromCenter.angle();\n // console.log(\"angle\", (angle / Math.PI) * 180.0);\n // const angle = Math.random() * Math.PI * 2; // TODO\n // Calculate tangent at angle\n return this.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Calculate the closest point on the outline of this circle to the given point.\n *\n * @method closestPoint\n * @instance\n * @memberof Circle\n * @param {XYCoords} vert - The point to find the closest circle point for.\n * @return {Vertex} The closest point on this circle.\n **/\n closestPoint(vert) {\n const lineIntersection = this.lineIntersection(this.center, vert);\n if (!lineIntersection) {\n // Note: this case should not happen as a radial from the center always intersect this circle.\n return new Vertex();\n }\n // Return closed of both\n if (lineIntersection.a.distance(vert) < lineIntersection.b.distance(vert)) {\n return lineIntersection.a;\n }\n else {\n return lineIntersection.b;\n }\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.center.destroy();\n this.isDestroyed = true;\n }\n} // END class\nCircle.circleUtils = {\n vertAt: (angle, radius) => {\n /* return new Vertex( Math.sin(angle) * radius,\n Math.cos(angle) * radius ); */\n return new Vertex(Math.cos(angle) * radius, Math.sin(angle) * radius);\n }\n};\n//# sourceMappingURL=Circle.js.map","/**\n * @author Ikaros Kappler\n * @date_init 2012-10-17 (Wrote a first version of this in that year).\n * @date 2018-04-03 (Refactored the code into a new class).\n * @modified 2018-04-28 Added some documentation.\n * @modified 2019-09-11 Added the scaleToCentroid(Number) function (used by the walking triangle demo).\n * @modified 2019-09-12 Added beautiful JSDoc compliable comments.\n * @modified 2019-11-07 Added to toSVG(options) function to make Triangles renderable as SVG.\n * @modified 2019-12-09 Fixed the determinant() function. The calculation was just wrong.\n * @modified 2020-03-16 (Corona times) Added the 'fromArray' function.\n * @modified 2020-03-17 Added the Triangle.toPolygon() function.\n * @modified 2020-03-17 Added proper JSDoc comments.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-05-09 Added the new Circle class (ported to Typescript from the demos).\n * @modified 2020-05-12 Added getIncircularTriangle() function.\n * @modified 2020-05-12 Added getIncircle() function.\n * @modified 2020-05-12 Fixed the signature of getCircumcirle(). Was still a generic object.\n * @modified 2020-06-18 Added the `getIncenter` function.\n * @modified 2020-12-28 Added the `getArea` function.\n * @modified 2021-01-20 Added UID.\n * @modified 2021-01-22 Always updating circumcircle when retieving it.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Triangle.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2024-11-22 Added static utility function Triangle.utils.determinant; adapted method `determinant`.\n * @modified 2024-11-22 Changing visibility of `Triangle.utils` from `private` to `public`.\n * @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.\n * @modified 2025-14-16 Class `Triangle` now implements interface `IBounded`.\n * @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.\n * @modified 2025-14-16 Added method `Triangle.move`.\n * @version 2.10.0\n *\n * @file Triangle\n * @fileoverview A simple triangle class: three vertices.\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Circle } from \"./Circle\";\nimport { Line } from \"./Line\";\nimport { Polygon } from \"./Polygon\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { geomutils } from \"./geomutils\";\n/**\n * @classdesc A triangle class for triangulations.\n *\n * The class was written for a Delaunay trinagulation demo so it might\n * contain some strange and unexpected functions.\n *\n * @requires Bounds\n * @requires Circle\n * @requires Line\n * @requires Vertex\n * @requires Polygon\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n * @requires geomutils\n *\n */\nexport class Triangle {\n /**\n * The constructor.\n *\n * @constructor\n * @name Triangle\n * @param {Vertex} a - The first vertex of the triangle.\n * @param {Vertex} b - The second vertex of the triangle.\n * @param {Vertex} c - The third vertex of the triangle.\n **/\n constructor(a, b, c) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Triangle\";\n this.uid = UIDGenerator.next();\n this.a = a;\n this.b = b;\n this.c = c;\n this.calcCircumcircle();\n }\n /**\n * Create a new triangle from the given array of vertices.\n *\n * The array must have at least three vertices, otherwise an error will be raised.\n * This function will not create copies of the vertices.\n *\n * @method fromArray\n * @static\n * @param {Array<Vertex>} arr - The required array with at least three vertices.\n * @memberof Vertex\n * @return {Triangle}\n **/\n static fromArray(arr) {\n if (arr.length < 3)\n throw `Cannot create triangle from array with less than three vertices (${arr.length})`;\n return new Triangle(arr[0], arr[1], arr[2]);\n }\n /**\n * Get the area of this triangle. The returned area is never negative.\n *\n * If you are interested in the signed area, please consider using the\n * `Triangle.utils.signedArea` helper function. This method just returns\n * the absolute value of the signed area.\n *\n * @method getArea\n * @instance\n * @memberof Triangle\n * @return {number} The non-negative area of this triangle.\n */\n getArea() {\n return Math.abs(Triangle.utils.signedArea(this.a.x, this.a.y, this.b.x, this.b.y, this.c.x, this.c.y));\n }\n /**\n * Get the centroid of this triangle.\n *\n * The centroid is the average midpoint for each side.\n *\n * @method getCentroid\n * @return {Vertex} The centroid\n * @instance\n * @memberof Triangle\n **/\n getCentroid() {\n return new Vertex((this.a.x + this.b.x + this.c.x) / 3, (this.a.y + this.b.y + this.c.y) / 3);\n }\n /**\n * Scale the triangle towards its centroid.\n *\n * @method scaleToCentroid\n * @param {number} - The scale factor to use. That can be any scalar.\n * @return {Triangle} this (for chaining)\n * @instance\n * @memberof Triangle\n */\n scaleToCentroid(factor) {\n let centroid = this.getCentroid();\n this.a.scale(factor, centroid);\n this.b.scale(factor, centroid);\n this.c.scale(factor, centroid);\n return this;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this Triangle.\n *\n * @method getBounds\n * @instance\n * @memberof Triangle\n * @return {Bounds} The rectangular bounds of this Triangle.\n **/\n getBounds() {\n // return Bounds.computeFromVertices([this.a, this.b, this.c]);\n return this.bounds();\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Move the Triangle's vertices by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof Triangle\n * @return {Triangle} this for chaining\n **/\n move(amount) {\n this.a.add(amount);\n this.b.add(amount);\n this.c.add(amount);\n return this;\n }\n /**\n * Get the circumcircle of this triangle.\n *\n * The circumcircle is that unique circle on which all three\n * vertices of this triangle are located on.\n *\n * Please note that for performance reasons any changes to vertices will not reflect in changes\n * of the circumcircle (center or radius). Please call the calcCirumcircle() function\n * after triangle vertex changes.\n *\n * @method getCircumcircle\n * @return {Object} - { center:Vertex, radius:float }\n * @instance\n * @memberof Triangle\n */\n getCircumcircle() {\n // if( !this.center || !this.radius )\n this.calcCircumcircle();\n return new Circle(this.center.clone(), this.radius);\n }\n /**\n * Check if this triangle and the passed triangle share an\n * adjacent edge.\n *\n * For edge-checking Vertex.equals is used which uses an\n * an epsilon for comparison.\n *\n * @method isAdjacent\n * @param {Triangle} tri - The second triangle to check adjacency with.\n * @return {boolean} - True if this and the passed triangle have at least one common edge.\n * @instance\n * @memberof Triangle\n */\n isAdjacent(tri) {\n var a = this.a.equals(tri.a) || this.a.equals(tri.b) || this.a.equals(tri.c);\n var b = this.b.equals(tri.a) || this.b.equals(tri.b) || this.b.equals(tri.c);\n var c = this.c.equals(tri.a) || this.c.equals(tri.b) || this.c.equals(tri.c);\n return (a && b) || (a && c) || (b && c);\n }\n /**\n * Get that vertex of this triangle (a,b,c) that is not vert1 nor vert2 of\n * the passed two.\n *\n * @method getThirdVertex\n * @param {Vertex} vert1 - The first vertex.\n * @param {Vertex} vert2 - The second vertex.\n * @return {Vertex} - The third vertex of this triangle that makes up the whole triangle with vert1 and vert2.\n * @instance\n * @memberof Triangle\n */\n getThirdVertex(vert1, vert2) {\n if ((this.a.equals(vert1) && this.b.equals(vert2)) || (this.a.equals(vert2) && this.b.equals(vert1)))\n return this.c;\n if ((this.b.equals(vert1) && this.c.equals(vert2)) || (this.b.equals(vert2) && this.c.equals(vert1)))\n return this.a;\n //if( this.c.equals(vert1) && this.a.equals(vert2) || this.c.equals(vert2) && this.a.equals(vert1) )\n return this.b;\n }\n /**\n * Re-compute the circumcircle of this triangle (if the vertices\n * have changed).\n *\n * The circumcenter and radius are stored in this.center and\n * this.radius. There is a third result: radius_squared (for internal computations).\n *\n * @method calcCircumcircle\n * @return void\n * @instance\n * @memberof Triangle\n */\n calcCircumcircle() {\n // From\n // http://www.exaflop.org/docs/cgafaq/cga1.html\n const A = this.b.x - this.a.x;\n const B = this.b.y - this.a.y;\n const C = this.c.x - this.a.x;\n const D = this.c.y - this.a.y;\n const E = A * (this.a.x + this.b.x) + B * (this.a.y + this.b.y);\n const F = C * (this.a.x + this.c.x) + D * (this.a.y + this.c.y);\n const G = 2.0 * (A * (this.c.y - this.b.y) - B * (this.c.x - this.b.x));\n let dx, dy;\n if (Math.abs(G) < Triangle.EPSILON) {\n // Collinear - find extremes and use the midpoint\n const bounds = this.bounds();\n this.center = new Vertex((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2);\n dx = this.center.x - bounds.min.x;\n dy = this.center.y - bounds.min.y;\n }\n else {\n const cx = (D * E - B * F) / G;\n const cy = (A * F - C * E) / G;\n this.center = new Vertex(cx, cy);\n dx = this.center.x - this.a.x;\n dy = this.center.y - this.a.y;\n }\n this.radius_squared = dx * dx + dy * dy;\n this.radius = Math.sqrt(this.radius_squared);\n } // END calcCircumcircle\n /**\n * Check if the passed vertex is inside this triangle's\n * circumcircle.\n *\n * @method inCircumcircle\n * @param {Vertex} v - The vertex to check.\n * @return {boolean}\n * @instance\n * @memberof Triangle\n */\n inCircumcircle(v) {\n const dx = this.center.x - v.x;\n const dy = this.center.y - v.y;\n const dist_squared = dx * dx + dy * dy;\n return dist_squared <= this.radius_squared;\n }\n /**\n * Get the rectangular bounds for this triangle.\n *\n * @method bounds\n * @return {Bounds} - The min/max bounds of this triangle.\n * @instance\n * @memberof Triangle\n */\n bounds() {\n return new Bounds(new Vertex(Triangle.utils.min3(this.a.x, this.b.x, this.c.x), Triangle.utils.min3(this.a.y, this.b.y, this.c.y)), new Vertex(Triangle.utils.max3(this.a.x, this.b.x, this.c.x), Triangle.utils.max3(this.a.y, this.b.y, this.c.y)));\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this polygon.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n return Polygon.utils\n .locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)\n .map(intersectionTuple => intersectionTuple.intersection);\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n return Polygon.utils\n .locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)\n .map(intersectionTuple => {\n // const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection);\n });\n }\n //--- END --- Implement interface `Intersectable`\n getEdgeAt(edgeIndex) {\n var modIndex = edgeIndex % 3;\n return modIndex === 0 ? new Line(this.a, this.b) : modIndex === 1 ? new Line(this.b, this.c) : new Line(this.c, this.a);\n }\n /**\n * Convert this triangle to a polygon instance.\n *\n * Plase note that this conversion does not perform a deep clone.\n *\n * @method toPolygon\n * @return {Polygon} A new polygon representing this triangle.\n * @instance\n * @memberof Triangle\n **/\n toPolygon() {\n return new Polygon([this.a, this.b, this.c]);\n }\n /**\n * Get the determinant of this triangle.\n *\n * @method determinant\n * @return {number} - The determinant (float).\n * @instance\n * @memberof Triangle\n */\n determinant() {\n // (b.y - a.y)*(c.x - b.x) - (c.y - b.y)*(b.x - a.x);\n // 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);\n return Triangle.utils.determinant(this.a, this.b, this.c);\n }\n /**\n * Checks if the passed vertex (p) is inside this triangle.\n *\n * Note: matrix determinants rock.\n *\n * @method containsPoint\n * @param {Vertex} p - The vertex to check.\n * @return {boolean}\n * @instance\n * @memberof Triangle\n */\n containsPoint(p) {\n return Triangle.utils.pointIsInTriangle(p.x, p.y, this.a.x, this.a.y, this.b.x, this.b.y, this.c.x, this.c.y);\n }\n /**\n * Get that inner triangle which defines the maximal incircle.\n *\n * @return {Triangle} The triangle of those points in this triangle that define the incircle.\n */\n getIncircularTriangle() {\n const lineA = new Line(this.a, this.b);\n const lineB = new Line(this.b, this.c);\n const lineC = new Line(this.c, this.a);\n const bisector1 = geomutils.nsectAngle(this.b, this.a, this.c, 2)[0]; // bisector of first angle (in b)\n const bisector2 = geomutils.nsectAngle(this.c, this.b, this.a, 2)[0]; // bisector of second angle (in c)\n // Cast to non-null here because we know there _is_ an intersection\n const intersection = bisector1.intersection(bisector2);\n // Find the closest points on one of the polygon lines (all have same distance by construction)\n const circleIntersA = lineA.getClosestPoint(intersection);\n const circleIntersB = lineB.getClosestPoint(intersection);\n const circleIntersC = lineC.getClosestPoint(intersection);\n return new Triangle(circleIntersA, circleIntersB, circleIntersC);\n }\n /**\n * Get the incircle of this triangle. That is the circle that touches each side\n * of this triangle in exactly one point.\n *\n * Note this just calls getIncircularTriangle().getCircumcircle()\n *\n * @return {Circle} The incircle of this triangle.\n */\n getIncircle() {\n return this.getIncircularTriangle().getCircumcircle();\n }\n /**\n * Get the incenter of this triangle (which is the center of the circumcircle).\n *\n * Note: due to performance reasonst the incenter is buffered inside the triangle because\n * computing it is relatively expensive. If a, b or c have changed you should call the\n * calcCircumcircle() function first, otherwise you might get wrong results.\n * @return Vertex The incenter of this triangle.\n **/\n getIncenter() {\n if (!this.center || !this.radius)\n this.calcCircumcircle();\n return this.center.clone();\n }\n /**\n * Converts this triangle into a human-readable string.\n *\n * @method toString\n * @return {string}\n * @instance\n * @memberof Triangle\n */\n toString() {\n return \"{ a : \" + this.a.toString() + \", b : \" + this.b.toString() + \", c : \" + this.c.toString() + \"}\";\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.a.destroy();\n this.b.destroy();\n this.c.destroy();\n this.isDestroyed = true;\n }\n}\n/**\n * An epsilon for comparison.\n * This should be the same epsilon as in Vertex.\n *\n * @private\n **/\nTriangle.EPSILON = 1.0e-6;\nTriangle.utils = {\n // Used in the bounds() function.\n max3(a, b, c) {\n return a >= b && a >= c ? a : b >= a && b >= c ? b : c;\n },\n min3(a, b, c) {\n return a <= b && a <= c ? a : b <= a && b <= c ? b : c;\n },\n signedArea(p0x, p0y, p1x, p1y, p2x, p2y) {\n return 0.5 * (-p1y * p2x + p0y * (-p1x + p2x) + p0x * (p1y - p2y) + p1x * p2y);\n },\n /**\n * Used by the containsPoint() function.\n *\n * @private\n **/\n pointIsInTriangle(px, py, p0x, p0y, p1x, p1y, p2x, p2y) {\n //\n // Point-in-Triangle test found at\n // http://stackoverflow.com/questions/2049582/how-to-determine-a-point-in-a-2d-triangle\n // var area : number = 1/2*(-p1y*p2x + p0y*(-p1x + p2x) + p0x*(p1y - p2y) + p1x*p2y);\n var area = Triangle.utils.signedArea(p0x, p0y, p1x, p1y, p2x, p2y);\n var s = (1 / (2 * area)) * (p0y * p2x - p0x * p2y + (p2y - p0y) * px + (p0x - p2x) * py);\n var t = (1 / (2 * area)) * (p0x * p1y - p0y * p1x + (p0y - p1y) * px + (p1x - p0x) * py);\n return s > 0 && t > 0 && 1 - s - t > 0;\n },\n /**\n * Calculate the determinant of the three vertices a, b and c (in this order).\n * @param {XYCords} a - The first vertex.\n * @param {XYCords} b - The first vertex.\n * @param {XYCords} c - The first vertex.\n * @returns {nmber}\n */\n determinant(a, b, c) {\n return (b.y - a.y) * (c.x - b.x) - (c.y - b.y) * (b.x - a.x);\n }\n};\n//# sourceMappingURL=Triangle.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-02-03\n * @modified 2021-03-01 Added `wrapMax` function.\n * @modified 2024-11-15 Adding helper function `geomutils.mapAngleTo2PI(number)` for mapping any value into the interval [0,2*PI).\n * @modified 2024-11-22 Adding helper function `geomutils.dotProduct(number)` for calculating the dot product of two vertices (as vectors).\n *\n * @version 1.2.0\n **/\nimport { Line } from \"./Line\";\nimport { Triangle } from \"./Triangle\";\n/**\n * A collection of usefull geometry utilities.\n *\n * @global\n **/\nexport const geomutils = {\n /**\n * Map any angle (any numeric value) to [0, Math.PI).\n *\n * @param {number} angle - The numeric value to map.\n * @return {number} The mapped angle inside [0,PI*2].\n **/\n mapAngleTo2PI(angle) {\n // Source: https://forums.codeguru.com/showthread.php?384172-get-angle-into-range-0-2*pi\n const new_angle = Math.asin(Math.sin(angle));\n if (Math.cos(angle) < 0) {\n return Math.PI - new_angle;\n }\n else if (new_angle < 0) {\n return new_angle + 2 * Math.PI;\n }\n else {\n return new_angle;\n }\n },\n /**\n * Calculate the euclidean distance between two points given by four coordinates (two coordinates each).\n *\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @returns {number}\n */\n dist4(x1, y1, x2, y2) {\n return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y1 - y2, 2));\n },\n /**\n * Map any angle (any numeric value) to [0, Math.PI).\n *\n * A × B := (A.x * B.x) + (A.y * B.y)\n *\n * @param {XYCoords} vertA - The first vertex.\n * @param {XYCoords} vertB - The second vertex.\n * @return {number} The dot product of the two vertices.\n **/\n dotProduct(vertA, vertB) {\n return vertA.x * vertB.x + vertA.y * vertB.y;\n },\n /**\n * Compute the n-section of the angle – described as a triangle (A,B,C) – in point A.\n *\n * @param {Vertex} pA - The first triangle point.\n * @param {Vertex} pB - The second triangle point.\n * @param {Vertex} pC - The third triangle point.\n * @param {number} n - The number of desired angle sections (example: 2 means the angle will be divided into two sections,\n * means an returned array with length 1, the middle line).\n *\n * @return {Line[]} An array of n-1 lines secting the given angle in point A into n equal sized angle sections. The lines' first vertex is A.\n */\n nsectAngle(pA, pB, pC, n) {\n const triangle = new Triangle(pA, pB, pC);\n const lineAB = new Line(pA, pB);\n const lineAC = new Line(pA, pC);\n // Compute the difference; this is the angle between AB and AC\n var insideAngle = lineAB.angle(lineAC);\n // We want the inner angles of the triangle, not the outer angle;\n // which one is which depends on the triangle 'direction'\n const clockwise = triangle.determinant() > 0;\n // For convenience convert the angle [-PI,PI] to [0,2*PI]\n if (insideAngle < 0)\n insideAngle = 2 * Math.PI + insideAngle;\n if (!clockwise)\n insideAngle = (2 * Math.PI - insideAngle) * -1;\n // Scale the rotated lines to the max leg length (looks better)\n const lineLength = Math.max(lineAB.length(), lineAC.length());\n const scaleFactor = lineLength / lineAB.length();\n var result = [];\n for (var i = 1; i < n; i++) {\n // Compute the i-th inner sector line\n result.push(new Line(pA, pB.clone().rotate(-i * (insideAngle / n), pA)).scale(scaleFactor));\n }\n return result;\n },\n /**\n * Wrap the value (e.g. an angle) into the given range of [0,max).\n *\n * @name wrapMax\n * @param {number} x - The value to wrap.\n * @param {number} max - The max bound to use for the range.\n * @return {number} The wrapped value inside the range [0,max).\n */\n wrapMax(x, max) {\n // Found at\n // https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi\n return (max + (x % max)) % max;\n },\n /**\n * Wrap the value (e.g. an angle) into the given range of [min,max).\n *\n * @name wrapMinMax\n * @param {number} x - The value to wrap.\n * @param {number} min - The min bound to use for the range.\n * @param {number} max - The max bound to use for the range.\n * @return {number} The wrapped value inside the range [min,max).\n */\n // Currently un-used\n wrapMinMax(x, min, max) {\n return min + geomutils.wrapMax(x - min, max - min);\n }\n};\n//# sourceMappingURL=geomutils.js.map","/**\n * @author Ikaros Kappler\n * @date 2012-10-17\n * @modified 2018-04-03 Refactored the code of october 2012 into a new class.\n * @modified 2018-04-28 Added some documentation.\n * @modified 2018-08-16 Added the set() function.\n * @modified 2018-08-26 Added VertexAttr.\n * @modified 2018-10-31 Extended the constructor by object{x,y}.\n * @modified 2018-11-19 Extended the set(number,number) function to set(Vertex).\n * @modified 2018-11-28 Added 'this' to the VertexAttr constructor.\n * @modified 2018-12-05 Added the sub(...) function. Changed the signature of the add() function! add(Vertex) and add(number,number) are now possible.\n * @modified 2018-12-21 (It's winter solstice) Added the inv()-function.\n * @modified 2019-01-30 Added the setX(Number) and setY(Number) functions.\n * @modified 2019-02-19 Added the difference(Vertex) function.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-04-24 Added the randomVertex(ViewPort) function.\n * @modified 2019-11-07 Added toSVGString(object) function.\n * @modified 2019-11-18 Added the rotate(number,Vertex) function.\n * @modified 2019-11-21 Fixed a bug in the rotate(...) function (elements were moved).\n * @modified 2020-03-06 Added functions invX() and invY().\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2020-05-26 Added functions addX(number) and addY(number).\n * @modified 2020-10-30 Changed the warnings in `sub(...)` and `add(...)` into real errors.\n * @modified 2021-03-01 Changed the second param `center` in the `rotate` function from Vertex to XYCoords.\n * @modified 2021-12-01 Changed the type of param of `scale` to XYCoords.\n * @modified 2021-12-01 Added function `scaleXY` for non uniform scaling.\n * @modified 2021-12-17 Added the functions `lerp` and `lerpAbs` for linear interpolations.\n * @modified 2022-01-31 Added `Vertex.utils.arrayToJSON`.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Vertex.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-11-28 Added the `subXY`, `subX` and `subY` methods to the `Vertex` class.\n * @modified 2023-09-29 Downgraded types for the `Vertex.utils.buildArrowHead` function (replacing Vertex params by more generic XYCoords type).\n * @modified 2023-09-29 Added the `Vertex.abs()` method as it seems useful.\n * @modified 2024-03-08 Added the optional `precision` param to the `toString` method.\n * @modified 2024-12-17 Outsourced the euclidean distance calculation of `Vertex.distance` to `geomutils.dist4`.\n * @modified 2025-03-24 Making the second parameter `center` of the `Vertex.rotate` method optional.\n * @modified 2025-04-13 Adding the `Vertex.move(amount: XYCoords)` method (does the same as `add`, added by naming convention).\n * @modified 2025-05-07 Class `Vertex` is now implementing interface `IBounded` (to meet convention).\n * @version 2.11.0\n *\n * @file Vertex\n * @public\n **/\nimport { VertexAttr } from \"./VertexAttr\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { VertexListeners } from \"./VertexListeners\";\nimport { geomutils } from \"./geomutils\";\nimport { Bounds } from \"./Bounds\";\n/**\n * @classdesc A vertex is a pair of two numbers.<br>\n * <br>\n * It is used to identify a 2-dimensional point on the x-y-plane.\n *\n * @requires IVertexAttr\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n * @requires VertexAttr\n * @requires VertexListeners\n * @requires XYCoords\n *\n */\nexport class Vertex {\n /**\n * The constructor for the vertex class.\n *\n * @constructor\n * @name Vertex\n * @param {number} x - The x-coordinate of the new vertex.\n * @param {number} y - The y-coordinate of the new vertex.\n **/\n constructor(x, y) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Vertex\";\n this.uid = UIDGenerator.next();\n if (typeof x == \"undefined\") {\n this.x = 0;\n this.y = 0;\n }\n else if (typeof x == \"number\" && typeof y == \"number\") {\n this.x = x;\n this.y = y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x = tuple.x;\n this.y = tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x = x;\n else if (typeof x == \"undefined\")\n this.x = 0;\n else\n this.x = NaN;\n if (typeof y == \"number\")\n this.y = y;\n else if (typeof y == \"undefined\")\n this.y = 0;\n else\n this.y = NaN;\n }\n }\n this.attr = new VertexAttr();\n this.listeners = new VertexListeners(this);\n }\n /**\n * Set the x- and y- component of this vertex.\n *\n * @method set\n * @param {number} x - The new x-component.\n * @param {number} y - The new y-component.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n set(x, y) {\n if (typeof x == \"number\" && typeof y == \"number\") {\n this.x = x;\n this.y = y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x = tuple.x;\n this.y = tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x = x;\n else if (typeof x == \"undefined\")\n this.x = 0;\n else\n this.x = NaN;\n if (typeof y == \"number\")\n this.y = y;\n else if (typeof y == \"undefined\")\n this.y = 0;\n else\n this.y = NaN;\n }\n }\n return this;\n }\n /**\n * Set the x-component of this vertex.\n *\n * @method setX\n * @param {number} x - The new x-component.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n setX(x) {\n this.x = x;\n return this;\n }\n /**\n * Set the y-component of this vertex.\n *\n * @method setY\n * @param {number} y - The new y-component.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n setY(y) {\n this.y = y;\n return this;\n }\n /**\n * Set the x-component if this vertex to the inverse of its value.\n *\n * @method invX\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n invX() {\n this.x = -this.x;\n return this;\n }\n /**\n * Set the y-component if this vertex to the inverse of its value.\n *\n * @method invY\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n invY() {\n this.y = -this.y;\n return this;\n }\n /**\n * Add the passed amount to x- and y- component of this vertex.<br>\n * <br>\n * This function works with add( {number}, {number} ) and\n * add( {Vertex} ), as well.\n *\n * @method add\n * @param {(number|Vertex)} x - The amount to add to x (or a vertex itself).\n * @param {number=} y - The amount to add to y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n add(x, y) {\n if (typeof x == \"number\" && typeof y == \"number\") {\n this.x += x;\n this.y += y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x += tuple.x;\n this.y += tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x += x;\n else\n throw `Cannot add ${typeof x} to numeric x component!`;\n if (typeof y == \"number\")\n this.y += y;\n else\n throw `Cannot add ${typeof y} to numeric y component!`;\n }\n }\n return this;\n }\n /**\n * Move this point by the given amount.\n *\n * This method just calls `add(amount).\n *\n *\n * @method move\n * @param {Vertex} amount - The amount to move this vertex.\n * @return {Vertex} this - For chaining.\n * @instance\n * @memberof Vertex\n */\n move(amount) {\n return this.add(amount);\n }\n /**\n * Add the passed amounts to the x- and y- components of this vertex.\n *\n * @method addXY\n * @param {number} x - The amount to add to x.\n * @param {number} y - The amount to add to y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n addXY(amountX, amountY) {\n this.x += amountX;\n this.y += amountY;\n return this;\n }\n /**\n * Add the passed amounts to the x-component of this vertex.\n *\n * @method addX\n * @param {number} x - The amount to add to x.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n addX(amountX) {\n this.x += amountX;\n return this;\n }\n /**\n * Add the passed amounts to the y-component of this vertex.\n *\n * @method addY\n * @param {number} y - The amount to add to y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n addY(amountY) {\n this.y += amountY;\n return this;\n }\n /**\n * Substract the passed amount from x- and y- component of this vertex.<br>\n * <br>\n * This function works with sub( {number}, {number} ) and\n * sub( {Vertex} ), as well.\n *\n * @method sub\n * @param {(number|Vertex)} x - The amount to substract from x (or a vertex itself).\n * @param {number=} y - The amount to substract from y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n sub(x, y) {\n if (typeof x == \"number\" && typeof y == \"number\") {\n this.x -= x;\n this.y -= y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x -= tuple.x;\n this.y -= tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x -= x;\n else\n throw `Cannot add ${typeof x} to numeric x component!`;\n if (typeof y == \"number\")\n this.y -= y;\n else\n throw `Cannot add ${typeof y} to numeric y component!`;\n }\n }\n return this;\n }\n /**\n * Substract the passed amounts from the x- and y- components of this vertex.\n *\n * @method subXY\n * @param {number} x - The amount to substract from x.\n * @param {number} y - The amount to substract from y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n subXY(amountX, amountY) {\n this.x -= amountX;\n this.y -= amountY;\n return this;\n }\n /**\n * Substract the passed amounts from the x-component of this vertex.\n *\n * @method addX\n * @param {number} x - The amount to substract from x.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n subX(amountX) {\n this.x -= amountX;\n return this;\n }\n /**\n * Substract the passed amounts from the y-component of this vertex.\n *\n * @method subY\n * @param {number} y - The amount to substract from y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n subY(amountY) {\n this.y -= amountY;\n return this;\n }\n /**\n * Check if this vertex equals the passed one.\n * <br>\n * This function uses an internal epsilon as tolerance.\n *\n * @method equals\n * @param {Vertex} vertex - The vertex to compare this with.\n * @return {boolean}\n * @instance\n * @memberof Vertex\n **/\n equals(vertex) {\n var eqX = Math.abs(this.x - vertex.x) < Vertex.EPSILON;\n var eqY = Math.abs(this.y - vertex.y) < Vertex.EPSILON;\n var result = eqX && eqY;\n return result;\n }\n /**\n * Create a copy of this vertex.\n *\n * @method clone\n * @return {Vertex} A new vertex, an exact copy of this.\n * @instance\n * @memberof Vertex\n **/\n clone() {\n return new Vertex(this.x, this.y);\n }\n /**\n * Get the distance to the passed point (in euclidean metric)\n *\n * @method distance\n * @param {XYCoords} vert - The vertex to measure the distance to.\n * @return {number}\n * @instance\n * @memberof Vertex\n **/\n distance(vert) {\n // return Math.sqrt(Math.pow(vert.x - this.x, 2) + Math.pow(vert.y - this.y, 2));\n return geomutils.dist4(this.x, this.y, vert.x, vert.y);\n }\n /**\n * Get the angle of this point (relative to (0,0) or to the given other origin point).\n *\n * @method angle\n * @param {XYCoords} origin - The vertex to measure the angle from.\n * @return {number}\n * @instance\n * @memberof Vertex\n **/\n angle(origin) {\n const a = typeof origin === \"undefined\"\n ? Math.PI / 2 - Math.atan2(this.x, this.y)\n : Math.PI / 2 - Math.atan2(origin.x - this.x, origin.y - this.y);\n // Map to positive value\n return a < 0 ? Math.PI * 2 + a : a;\n }\n /**\n * Get the difference to the passed point.<br>\n * <br>\n * The difference is (vert.x-this.x, vert.y-this.y).\n *\n * @method difference\n * @param {Vertex} vert - The vertex to measure the x-y-difference to.\n * @return {Vertex} A new vertex.\n * @instance\n * @memberof Vertex\n **/\n difference(vert) {\n return new Vertex(vert.x - this.x, vert.y - this.y);\n }\n /**\n * This is a vector-like behavior and 'scales' this vertex\n * towards/from a given center by one uniform scale factor.\n *\n * @method scale\n * @param {number} factor - The factor to 'scale' this vertex; 1.0 means no change.\n * @param {XYCoords=} center - The origin of scaling; default is (0,0).\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n scale(factor, center) {\n return this.scaleXY({ x: factor, y: factor }, center);\n }\n /**\n * Perform a linear interpolation towards the given target vertex.\n * The amount value `t` is relative, `t=0.0` means no change, `t=1.0`\n * means this point will be moved to the exact target position.\n *\n * `t=0.5` will move this point to the middle of the connecting\n * linear segment.\n *\n * @param {XYCoords} target - The target position to lerp this vertex to.\n * @param {number} t - The relative amount, usually in [0..1], but other values will work, too.\n * @returns\n */\n lerp(target, t) {\n var diff = this.difference(target);\n // return new Vertex(this.x + diff.x * t, this.y + diff.y * t);\n this.x += diff.x * t;\n this.y += diff.y * t;\n return this;\n }\n /**\n * Perform a linear interpolation towards the given target vertex (absolute variant).\n * The amount value `t` is absolute, which means the lerp amount is a direct distance\n * value. This point will have move the amount of the passed distance `u`.\n *\n * @param {XYCoords} target - The target position to lerp this vertex to.\n * @param {number} t - The absolute move amount to use to lerping.\n * @returns\n */\n lerpAbs(target, u) {\n var dist = this.distance(target);\n var diff = this.difference(target);\n var step = { x: diff.x / dist, y: diff.y / dist };\n // return new Vertex(this.x + step.x * u, this.y + step.y * u);\n this.x += step.x * u;\n this.y += step.y * u;\n return this;\n }\n /**\n * This is a vector-like behavior and 'scales' this vertex\n * towards/from a given center by two independent x- and y- scale factors.\n *\n * @method scale\n * @param {number} factor - The factor to 'scale' this vertex; 1.0 means no change.\n * @param {XYCoords=} center - The origin of scaling; default is (0,0).\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n scaleXY(factors, center) {\n if (!center || typeof center === \"undefined\") {\n center = { x: 0, y: 0 };\n }\n this.x = center.x + (this.x - center.x) * factors.x;\n this.y = center.y + (this.y - center.y) * factors.y;\n return this;\n }\n /**\n * This is a vector-like behavior and 'rotates' this vertex\n * around given center.\n *\n * @method rotate\n * @param {number} angle - The angle to 'rotate' this vertex; 0.0 means no change.\n * @param {XYCoords=} center - The center of rotation; default is (0,0).\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n rotate(angle, center) {\n if (!center || typeof center === \"undefined\") {\n center = { x: 0, y: 0 };\n }\n this.sub(center);\n angle += Math.atan2(this.y, this.x);\n let len = this.distance(Vertex.ZERO); // {x:0,y:0});\n this.x = len * Math.cos(angle);\n this.y = len * Math.sin(angle);\n this.add(center);\n return this;\n }\n /**\n * Multiply both components of this vertex with the given scalar.<br>\n * <br>\n * Note: as in<br>\n * https://threejs.org/docs/#api/math/Vector2.multiplyScalar\n *\n * @method multiplyScalar\n * @param {number} scalar - The scale factor; 1.0 means no change.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n multiplyScalar(scalar) {\n this.x *= scalar;\n this.y *= scalar;\n return this;\n }\n /**\n * Round the two components x and y of this vertex.\n *\n * @method round\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n round() {\n this.x = Math.round(this.x);\n this.y = Math.round(this.y);\n return this;\n }\n /**\n * Change this vertex (x,y) to its inverse (-x,-y).\n *\n * @method inv\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n inv() {\n this.x = -this.x;\n this.y = -this.y;\n return this;\n }\n /**\n * Set both coordinates of this vertex to their absolute value (abs(x), abs(y)).\n *\n * @method abs\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n */\n abs() {\n this.x = Math.abs(this.x);\n this.y = Math.abs(this.y);\n return this;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this Vertex.\n * This is just by convention – any vertex is just a position without any useful with or height (0).\n *\n * @method getBounds\n * @instance\n * @memberof Vertex\n * @return {Bounds} The rectangular bounds of this Vertex (width and height are zero).\n **/\n getBounds() {\n // return Bounds.computeFromVertices([this.a, this.b, this.c]);\n return Bounds.computeFromVertices([this]);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Get a string representation of this vertex.\n *\n * @method toString\n * @return {string} The string representation of this vertex.\n * @instance\n * @memberof Vertex\n **/\n toString(precision) {\n if (typeof precision === \"undefined\") {\n return \"(\" + this.x + \",\" + this.y + \")\";\n }\n else {\n return \"(\" + this.x.toFixed(precision) + \",\" + this.y.toFixed(precision) + \")\";\n }\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.listeners.removeAllListeners();\n this.isDestroyed = true;\n }\n /**\n * Create a new random vertex inside the given viewport.\n *\n * @param {ViewPort} viewPort - A {min:Vertex, max:Vertex} viewport specifying the bounds.\n * @return A new vertex with a random position.\n **/\n static randomVertex(viewPort) {\n return new Vertex(viewPort.min.x + Math.random() * (viewPort.max.x - viewPort.min.x), viewPort.min.y + Math.random() * (viewPort.max.y - viewPort.min.y));\n }\n}\nVertex.ZERO = new Vertex(0, 0);\n/**\n * An epsilon for comparison\n *\n * @private\n * @readonly\n **/\nVertex.EPSILON = 1.0e-6;\nVertex.utils = {\n /**\n * Generate a four-point arrow head, starting at the vector end minus the\n * arrow head length.\n *\n * The first vertex in the returned array is guaranteed to be the located\n * at the vector line end minus the arrow head length.\n *\n *\n * Due to performance all params are required.\n *\n * The params scaleX and scaleY are required for the case that the scaling is not uniform (x and y\n * scaling different). Arrow heads should not look distored on non-uniform scaling.\n *\n * If unsure use 1.0 for scaleX and scaleY (=no distortion).\n * For headlen use 8, it's a good arrow head size.\n *\n * Example:\n * buildArrowHead( new Vertex(0,0), new Vertex(50,100), 8, 1.0, 1.0 )\n *\n * @param {XYCoords} zA - The start vertex of the vector to calculate the arrow head for.\n * @param {XYCoords} zB - The end vertex of the vector.\n * @param {number} headlen - The length of the arrow head (along the vector direction. A good value is 12).\n * @param {number} scaleX - The horizontal scaling during draw.\n * @param {number} scaleY - the vertical scaling during draw.\n **/\n // @DEPRECATED: use Vector.utils.buildArrowHead instead!!!\n buildArrowHead: (zA, zB, headlen, scaleX, scaleY) => {\n console.warn(\"[DEPRECATION] Vertex.utils.buildArrowHead is deprecated. Please use Vector.utils.buildArrowHead instead.\");\n var angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);\n var vertices = [];\n vertices.push(new Vertex(zB.x * scaleX - headlen * Math.cos(angle), zB.y * scaleY - headlen * Math.sin(angle)));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle - Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle - Math.PI / 8)));\n vertices.push(new Vertex(zB.x * scaleX, zB.y * scaleY));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle + Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle + Math.PI / 8)));\n return vertices;\n },\n /**\n * Convert the given vertices (array) to a JSON string.\n *\n * @param {number?} precision - (optional) The numeric precision to be used (number of precision digits).\n * @returns {string}\n */\n arrayToJSON(vertices, precision) {\n return JSON.stringify(vertices.map(function (vert) {\n return typeof precision === undefined\n ? { x: vert.x, y: vert.y }\n : { x: Number(vert.x.toFixed(precision)), y: Number(vert.y.toFixed(precision)) };\n }));\n }\n};\n//# sourceMappingURL=Vertex.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-03-24\n * @modified 2020-05-04 Fixed a serious bug in the pointDistance function.\n * @modified 2020-05-12 The angle(line) param was still not optional. Changed that.\n * @modified 2020-11-11 Generalized the `add` and `sub` param from `Vertex` to `XYCoords`.\n * @modified 2020-12-04 Changed`vtutils.dist2` params from `Vertex` to `XYCoords` (generalized).\n * @modified 2020-12-04 Changed `getClosestT` param from `Vertex` to `XYCoords` (generalized).\n * @modified 2020-12-04 Added the `hasPoint(XYCoords)` function.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2023-09-29 Fixed a calculation error in the VertTuple.hasPoint() function; distance measure was broken!\n * @modified 2024-09-10 Chaging the first param of `pointDistance` from `Vertex` to less strict type `XYCoords`. This should not break anything.\n * @modified 2024-09-10 Adding the optional `epsilon` param to the `hasPoint` method.\n * @modified 2024-12-02 Added the `epsilon` param to the `colinear` method. Default is 1.0e-6.\n * @modified 2025-03-31 Added the `VertTuple.revert` method.\n * @modified 2025-04-15 Changed param of `VertTuple.moveTo` method from `Vertex` to `XYCoords`.\n * @modified 2025-04-15 Added method `VertTuple.move` method.\n * @version 1.4.0\n */\nimport { Vertex } from \"./Vertex\";\nimport { UIDGenerator } from \"./UIDGenerator\";\n/**\n * @classdesc An abstract base classes for vertex tuple constructs, like Lines or Vectors.\n * @abstract\n * @requires UID\n * @requires Vertex\n * @requires XYCoords\n */\nexport class VertTuple {\n /**\n * Creates an instance.\n *\n * @constructor\n * @name VertTuple\n * @param {Vertex} a The tuple's first point.\n * @param {Vertex} b The tuple's second point.\n **/\n constructor(a, b, factory) {\n this.uid = UIDGenerator.next();\n this.a = a;\n this.b = b;\n this.factory = factory;\n }\n /**\n * Get the length of this line.\n *\n * @method length\n * @instance\n * @memberof VertTuple\n **/\n length() {\n return Math.sqrt(Math.pow(this.b.x - this.a.x, 2) + Math.pow(this.b.y - this.a.y, 2));\n }\n /**\n * Set the length of this vector to the given amount. This only works if this\n * vector is not a null vector.\n *\n * @method setLength\n * @param {number} length - The desired length.\n * @memberof VertTuple\n * @return {T} this (for chaining)\n **/\n setLength(length) {\n return this.scale(length / this.length());\n }\n /**\n * Substract the given vertex from this line's end points.\n *\n * @method sub\n * @param {XYCoords} amount The amount (x,y) to substract.\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n sub(amount) {\n this.a.sub(amount);\n this.b.sub(amount);\n return this;\n }\n /**\n * Add the given vertex to this line's end points.\n *\n * @method add\n * @param {XYCoords} amount The amount (x,y) to add.\n * @instance\n * @memberof VertTuple\n * @return {VertTuple<T>} this\n **/\n add(amount) {\n this.a.add(amount);\n this.b.add(amount);\n return this;\n }\n /**\n * Reverse this vertex tuple: a becomes b, and b becomes a.\n * This operation is in-place.\n *\n * @method add\n * @param {XYCoords} amount The amount (x,y) to add.\n * @instance\n * @memberof VertTuple\n * @return {VertTuple<T>} this\n */\n revert() {\n const tmp = this.a;\n this.a = this.b;\n this.b = tmp;\n return this;\n }\n /**\n * Normalize this line (set to length 1).\n *\n * @method normalize\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n normalize() {\n this.b.set(this.a.x + (this.b.x - this.a.x) / this.length(), this.a.y + (this.b.y - this.a.y) / this.length());\n return this;\n }\n /**\n * Scale this line by the given factor.\n *\n * @method scale\n * @param {number} factor The factor for scaling (1.0 means no scale).\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n scale(factor) {\n this.b.set(this.a.x + (this.b.x - this.a.x) * factor, this.a.y + (this.b.y - this.a.y) * factor);\n return this;\n }\n /**\n * Move this line to a new location.\n *\n * @method moveTo\n * @param {XYCoords} newA - The new desired location of 'a'. Vertex 'b' will be moved, too.\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n moveTo(newA) {\n let diff = this.a.difference(newA);\n this.a.add(diff);\n this.b.add(diff);\n return this;\n }\n /**\n * Move this line by the given amount\n *\n * @method move\n * @param {XYCoords} amount - The amount to move both point of this tuple.\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n move(amount) {\n this.a.add(amount);\n this.b.add(amount);\n return this;\n }\n /**\n * Get the angle between this and the passed line (in radians).\n *\n * @method angle\n * @param {VertTuple} line - (optional) The line to calculate the angle to. If null the baseline (x-axis) will be used.\n * @return {number} this\n * @instance\n * @memberof VertTuple\n **/\n angle(line) {\n if (line == null || typeof line == \"undefined\") {\n line = this.factory(new Vertex(0, 0), new Vertex(100, 0));\n }\n // Compute the angle from x axis and the return the difference :)\n const v0 = this.b.clone().sub(this.a);\n const v1 = line.b.clone().sub(line.a);\n // Thank you, Javascript, for this second atan function. No additional math is needed here!\n // The result might be negative, but isn't it usually nicer to determine angles in positive values only?\n return Math.atan2(v1.x, v1.y) - Math.atan2(v0.x, v0.y);\n }\n /**\n * Get line point at position t in [0 ... 1]:<br>\n * <pre>[P(0)]=[A]--------------------[P(t)]------[B]=[P(1)]</pre><br>\n * <br>\n * The counterpart of this function is Line.getClosestT(Vertex).\n *\n * @method vertAt\n * @param {number} t The position scalar.\n * @return {Vertex} The vertex a position t.\n * @instance\n * @memberof VertTuple\n **/\n vertAt(t) {\n return new Vertex(this.a.x + (this.b.x - this.a.x) * t, this.a.y + (this.b.y - this.a.y) * t);\n }\n /**\n * Get the denominator of this and the given line.\n *\n * If the denominator is zero (or close to zero) both line are co-linear.\n *\n * @method denominator\n * @param {VertTuple} line\n * @instance\n * @memberof VertTuple\n * @return {Number}\n **/\n denominator(line) {\n // http://jsfiddle.net/justin_c_rounds/Gd2S2/\n return (line.b.y - line.a.y) * (this.b.x - this.a.x) - (line.b.x - line.a.x) * (this.b.y - this.a.y);\n }\n /**\n * Checks if this and the given line are co-linear.\n *\n * The constant Vertex.EPSILON is used for tolerance.\n *\n * @method colinear\n * @param {VertTuple} line\n * @param {epsilon?=1.0e-6} epsilon - The epsilon to use (default is 1.0e-6).\n * @instance\n * @memberof VertTuple\n * @return true if both lines are co-linear.\n */\n colinear(line, epsilon) {\n return Math.abs(this.denominator(line)) < (typeof epsilon === \"undefined\" ? Vertex.EPSILON : epsilon);\n }\n /**\n * Get the closest position T from this line to the specified point.\n *\n * The counterpart for this function is Line.vertAt(Number).\n *\n * @name getClosetT\n * @method getClosestT\n * @param {XYCoords} p The point (vertex) to measure the distance to.\n * @return {number} The line position t of minimal distance to p.\n * @instance\n * @memberof VertTuple\n **/\n getClosestT(p) {\n var l2 = VertTuple.vtutils.dist2(this.a, this.b);\n if (l2 === 0)\n return 0;\n var t = ((p.x - this.a.x) * (this.b.x - this.a.x) + (p.y - this.a.y) * (this.b.y - this.a.y)) / l2;\n // Do not wrap to [0,1] here.\n // Other results are of interest, too.\n // t = Math.max(0, Math.min(1, t));\n return t;\n }\n /**\n * Check if the given point is located on this line. Optionally also check if\n * that point is located between point `a` and `b`.\n *\n * @method hasPoint\n * @param {Vertex} point - The point to check.\n * @param {boolean=} insideBoundsOnly - [optional] If set to to true (default=false) the point must be between start and end point of the line.\n * @param {number=Vertex.EPSILON} epsilon - [optional] A tolerance.\n * @return {boolean} True if the given point is on this line.\n * @instance\n * @memberof VertTuple\n */\n hasPoint(point, insideBoundsOnly, epsilon) {\n const t = this.getClosestT(point);\n // Compare to pointDistance?\n const distance = Math.sqrt(VertTuple.vtutils.dist2(point, this.vertAt(t)));\n if (typeof insideBoundsOnly !== \"undefined\" && insideBoundsOnly) {\n return distance < (epsilon !== null && epsilon !== void 0 ? epsilon : Vertex.EPSILON) && t >= 0 && t <= 1;\n }\n else {\n return distance < (epsilon !== null && epsilon !== void 0 ? epsilon : Vertex.EPSILON); // t >= 0 && t <= 1;\n }\n }\n /**\n * Get the closest point on this line to the specified point.\n *\n * @method getClosestPoint\n * @param {Vertex} p The point (vertex) to measre the distance to.\n * @return {Vertex} The point on the line that is closest to p.\n * @instance\n * @memberof VertTuple\n **/\n getClosestPoint(p) {\n var t = this.getClosestT(p);\n return this.vertAt(t);\n }\n /**\n * The the minimal distance between this line and the specified point.\n *\n * @method pointDistance\n * @param {XYCoords} p The point (vertex) to measre the distance to.\n * @return {number} The absolute minimal distance.\n * @instance\n * @memberof VertTuple\n **/\n pointDistance(p) {\n // Taken From:\n // https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment\n return Math.sqrt(VertTuple.vtutils.dist2(p, this.vertAt(this.getClosestT(p))));\n }\n /**\n * Create a deep clone of this instance.\n *\n * @method cloneLine\n * @return {T} A type safe clone if this instance.\n * @instance\n * @memberof VertTuple\n **/\n clone() {\n return this.factory(this.a.clone(), this.b.clone());\n }\n /**\n * Create a string representation of this line.\n *\n * @method totring\n * @return {string} The string representing this line.\n * @instance\n * @memberof VertTuple\n **/\n toString() {\n return \"{ a : \" + this.a.toString() + \", b : \" + this.b.toString() + \" }\";\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.a.destroy();\n this.b.destroy();\n this.isDestroyed = true;\n }\n}\n/**\n * @private\n **/\nVertTuple.vtutils = {\n dist2: (v, w) => {\n return (v.x - w.x) * (v.x - w.x) + (v.y - w.y) * (v.y - w.y);\n }\n};\n//# sourceMappingURL=VertTuple.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-01-30\n * @modified 2019-02-23 Added the toSVGString function, overriding Line.toSVGString.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-04-19 Added the clone function (overriding Line.clone()).\n * @modified 2019-09-02 Added the Vector.perp() function.\n * @modified 2019-09-02 Added the Vector.inverse() function.\n * @modified 2019-12-04 Added the Vector.inv() function.\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Vector.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-10-25 Added the `getOrthogonal` method.\n * @modified 2025-04-14 Added the `Vector.rotate(number)` method.\n * @version 1.6.0\n *\n * @file Vector\n * @public\n **/\nimport { VertTuple } from \"./VertTuple\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A vector (Vertex,Vertex) is a line with a visible direction.<br>\n * <br>\n * Vectors are drawn with an arrow at their end point.<br>\n * <b>The Vector class extends the Line class.</b>\n *\n * @requires VertTuple\n * @requires Vertex\n **/\nexport class Vector extends VertTuple {\n /**\n * The constructor.\n *\n * @constructor\n * @name Vector\n * @extends Line\n * @param {Vertex} vertA - The start vertex of the vector.\n * @param {Vertex} vertB - The end vertex of the vector.\n **/\n constructor(vertA, vertB) {\n super(vertA, vertB, (a, b) => new Vector(a, b));\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Vector\";\n }\n /**\n * Get the perpendicular of this vector which is located at a.\n *\n * @return {Vector} A new vector being the perpendicular of this vector sitting on a.\n **/\n perp() {\n var v = this.clone();\n v.sub(this.a);\n v = new Vector(new Vertex(), new Vertex(-v.b.y, v.b.x));\n v.a.add(this.a);\n v.b.add(this.a);\n return v;\n }\n /**\n * The inverse of a vector is a vector with the same magnitude but oppose direction.\n *\n * Please not that the origin of this vector changes here: a->b becomes b->a.\n *\n * @return {Vector}\n **/\n inverse() {\n var tmp = this.a;\n this.a = this.b;\n this.b = tmp;\n return this;\n }\n /**\n * This function computes the inverse of the vector, which means 'a' stays untouched.\n *\n * @return {Vector} this for chaining.\n **/\n inv() {\n this.b.x = this.a.x - (this.b.x - this.a.x);\n this.b.y = this.a.y - (this.b.y - this.a.y);\n return this;\n }\n /**\n * Get the intersection if this vector and the specified vector.\n *\n * @method intersection\n * @param {Vector} line The second vector.\n * @return {Vertex} The intersection (may lie outside the end-points).\n * @instance\n * @memberof Line\n **/\n intersection(line) {\n var denominator = this.denominator(line);\n if (denominator == 0)\n return null;\n var a = this.a.y - line.a.y;\n var b = this.a.x - line.a.x;\n var numerator1 = (line.b.x - line.a.x) * a - (line.b.y - line.a.y) * b;\n var numerator2 = (this.b.x - this.a.x) * a - (this.b.y - this.a.y) * b;\n a = numerator1 / denominator; // NaN if parallel lines\n b = numerator2 / denominator;\n // TODO:\n // FOR A VECTOR THE LINE-INTERSECTION MUST BE ON BOTH VECTORS\n // if we cast these lines infinitely in both directions, they intersect here:\n return new Vertex(this.a.x + a * (this.b.x - this.a.x), this.a.y + a * (this.b.y - this.a.y));\n }\n /**\n * Get the orthogonal \"vector\" of this vector (rotated by 90° clockwise).\n *\n * @name getOrthogonal\n * @method getOrthogonal\n * @return {Vector} A new vector with the same length that stands on this vector's point a.\n * @instance\n * @memberof Vector\n **/\n getOrthogonal() {\n // Orthogonal of vector (0,0)->(x,y) is (0,0)->(-y,x)\n const linePoint = this.a.clone();\n const startPoint = this.b.clone().sub(this.a);\n const tmp = startPoint.x;\n startPoint.x = -startPoint.y;\n startPoint.y = tmp;\n return new Vector(linePoint, startPoint.add(this.a));\n }\n /**\n * Rotate this vector by the given angle around the first point `a`.\n *\n * @name rotate\n * @method rotate\n * @return {Vector} this - for chaining.\n * @instance\n * @memberof Vector\n */\n rotate(angle) {\n this.b.rotate(angle, this.a);\n return this;\n }\n}\nVector.utils = {\n /**\n * Generate a four-point arrow head, starting at the vector end minus the\n * arrow head length.\n *\n * The first vertex in the returned array is guaranteed to be the located\n * at the vector line end minus the arrow head length.\n *\n *\n * Due to performance all params are required.\n *\n * The params scaleX and scaleY are required for the case that the scaling is not uniform (x and y\n * scaling different). Arrow heads should not look distored on non-uniform scaling.\n *\n * If unsure use 1.0 for scaleX and scaleY (=no distortion).\n * For headlen use 8, it's a good arrow head size.\n *\n * Example:\n * buildArrowHead( new Vertex(0,0), new Vertex(50,100), 8, 1.0, 1.0 )\n *\n * @param {XYCoords} zA - The start vertex of the vector to calculate the arrow head for.\n * @param {XYCoords} zB - The end vertex of the vector.\n * @param {number} headlen - The length of the arrow head (along the vector direction. A good value is 12).\n * @param {number} scaleX - The horizontal scaling during draw.\n * @param {number} scaleY - the vertical scaling during draw.\n **/\n buildArrowHead: (zA, zB, headlen, scaleX, scaleY) => {\n const angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);\n const vertices = [];\n vertices.push(new Vertex(zB.x * scaleX - headlen * Math.cos(angle), zB.y * scaleY - headlen * Math.sin(angle)));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle - Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle - Math.PI / 8)));\n vertices.push(new Vertex(zB.x * scaleX, zB.y * scaleY));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle + Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle + Math.PI / 8)));\n return vertices;\n }\n};\n//# sourceMappingURL=Vector.js.map","/**\n * @author Ikaros Kappler\n * @date 2016-03-12\n * @modified 2018-12-05 Refactored the code from the morley-triangle script.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-04-28 Fixed a bug in the Line.sub( Vertex ) function (was not working).\n * @modified 2019-09-02 Added the Line.add( Vertex ) function.\n * @modified 2019-09-02 Added the Line.denominator( Line ) function.\n * @modified 2019-09-02 Added the Line.colinear( Line ) function.\n * @modified 2019-09-02 Fixed an error in the Line.intersection( Line ) function (class Point was renamed to Vertex).\n * @modified 2019-12-15 Added the Line.moveTo(Vertex) function.\n * @modified 2020-03-16 The Line.angle(Line) parameter is now optional. The baseline (x-axis) will be used if not defined.\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2020-12-04 The `intersection` function returns undefined if both lines are parallel.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-10-09 Changed the actual return value of the `intersection` function to null (was undefined before).\n * @modified 2022-10-17 Adding these methods from the `PathSegment` interface: getStartPoint, getEndPoint, revert.\n * @modified 2023-09-25 Changed param type of `intersection()` from Line to VertTuple.\n * @modified 2025-04-15 Class `Line` now implements interface `Intersectable`.\n * @modified 2025-04-16 Class `Line` now implements interface `IBounded`.\n * @version 2.4.0\n *\n * @file Line\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Vector } from \"./Vector\";\nimport { VertTuple } from \"./VertTuple\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A line consists of two vertices a and b.<br>\n * <br>\n * This is some refactored code from my 'Morley Triangle' test<br>\n * https://github.com/IkarosKappler/morleys-trisector-theorem\n *\n * @requires Vertex\n */\nexport class Line extends VertTuple {\n /**\n * Creates an instance of Line.\n *\n * @constructor\n * @name Line\n * @param {Vertex} a The line's first point.\n * @param {Vertex} b The line's second point.\n **/\n constructor(a, b) {\n super(a, b, (a, b) => new Line(a, b));\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Line\";\n }\n /**\n * Get the intersection if this line and the specified line.\n *\n * @method intersection\n * @param {Line} line The second line.\n * @return {Vertex|undefined} The intersection (may lie outside the end-points) or `undefined` if both lines are parallel.\n * @instance\n * @memberof Line\n **/\n // !!! DO NOT MOVE TO VertTuple\n intersection(line) {\n const denominator = this.denominator(line);\n if (denominator == 0) {\n return null;\n }\n let a = this.a.y - line.a.y;\n let b = this.a.x - line.a.x;\n const numerator1 = (line.b.x - line.a.x) * a - (line.b.y - line.a.y) * b;\n const numerator2 = (this.b.x - this.a.x) * a - (this.b.y - this.a.y) * b;\n a = numerator1 / denominator; // NaN if parallel lines\n b = numerator2 / denominator;\n // Catch NaN?\n const x = this.a.x + a * (this.b.x - this.a.x);\n const y = this.a.y + a * (this.b.y - this.a.y);\n if (isNaN(a) || isNaN(x) || isNaN(y)) {\n return null;\n }\n // if we cast these lines infinitely in both directions, they intersect here:\n return new Vertex(x, y);\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this Line.\n *\n * @method getBounds\n * @instance\n * @memberof Line\n * @return {Bounds} The rectangular bounds of this Line.\n **/\n getBounds() {\n return Bounds.computeFromVertices([this.a, this.b]);\n }\n //--- END --- Implement interface `IBounded`\n //--- Implement PathSegment ---\n /**\n * Get the start point of this path segment.\n *\n * @method getStartPoint\n * @memberof PathSegment\n * @return {Vertex} The start point of this path segment.\n */\n getStartPoint() {\n return this.a;\n }\n /**\n * Get the end point of this path segment.\n *\n * @method getEndPoint\n * @memberof PathSegment\n * @return {Vertex} The end point of this path segment.\n */\n getEndPoint() {\n return this.b;\n }\n /**\n * Get the tangent's end point at the start point of this segment.\n *\n * @method getStartTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the starting point's tangent.\n */\n getStartTangent() {\n return this.b;\n }\n /**\n * Get the tangent's end point at the end point of this segment.\n *\n * @method getEndTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the ending point's tangent.\n */\n getEndTangent() {\n return this.a;\n }\n /**\n * Inverse this path segment (in-place) and return this same instance (useful for chaining).\n *\n * @method reverse\n * @memberof PathSegment\n * @return {PathSegment} This path segment instance (for chaining).\n */\n reverse() {\n var tmp = this.a;\n this.a = this.b;\n this.b = tmp;\n return this;\n }\n //--- END Implement PathSegment ---\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this polygon.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n const intersection = this.intersection(line);\n if (!intersection) {\n return []; // Both lines parallel\n }\n if (this.hasPoint(intersection, true) && (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {\n return [intersection];\n }\n else {\n return [];\n }\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n const intersections = this.lineIntersections(line, inVectorBoundsOnly);\n if (intersections.length === 0) {\n return [];\n }\n const intrsctn = intersections[0];\n return [new Vector(this.a.clone(), this.b.clone()).moveTo(intrsctn)];\n }\n}\n//# sourceMappingURL=Line.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-04-14\n * @modified 2018-11-17 Added the containsVert function.\n * @modified 2018-12-04 Added the toSVGString function.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-10-25 Added the scale function.\n * @modified 2019-11-06 JSDoc update.\n * @modified 2019-11-07 Added toCubicBezierPath(number) function.\n * @modified 2019-11-22 Added the rotate(number,Vertex) function.\n * @modified 2020-03-24 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-10-30 Added the `addVertex` function.\n * @modified 2020-10-31 Added the `getVertexAt` function.\n * @modified 2020-11-06 Added the `move` function.\n * @modified 2020-11-10 Added the `getBounds` function.\n * @modified 2020-11-11 Generalized `move(Vertex)` to `move(XYCoords)`.\n * @modified 2021-01-20 Added UID.\n * @modified 2021-01-29 Added the `signedArea` function (was global function in the demos before).\n * @modified 2021-01-29 Added the `isClockwise` function.\n * @modified 2021-01-29 Added the `area` function.\n * @modified 2021-01-29 Changed the param type for `containsVert` from Vertex to XYCoords.\n * @modified 2021-12-14 Added the `perimeter()` function.\n * @modified 2021-12-16 Added the `getEvenDistributionPolygon()` function.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Polygon.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-03-08 Added the `Polygon.clone()` function.\n * @modified 2023-09-25 Added the `Polygon.getInterpolationPolygon(number)` function.\n * @modified 2023-09-25 Added the `Polygon.lineIntersections(Line,boolean)` function.\n * @modified 2023-09-29 Added the `Polygon.closestLineIntersection(Line,boolean)` function.\n * @modified 2023-11-24 Added the `Polygon.containsPolygon(Polygon)' function.\n * @modified 2024-10-12 Added the `getEdgeAt` method.\n * @modified 2024-10-30 Added the `getEdges` method.\n * @modified 2024-12-02 Added the `elimitateColinearEdges` method.\n * @modified 2025-02-12 Added the `containsVerts` method to test multiple vertices for containment.\n * @modified 2025-03-28 Added the `Polygon.utils.locateLineIntersecion` static helper method.\n * @modified 2025-03-28 Added the `Polygon.lineIntersectionTangents` method.\n * @modified 2025-04-09 Added the `Polygon.getCentroid` method.\n * @modified 2025-05-16 Class `Polygon` now implements `IBounded`.\n * @modified 2025-05-20 Tweaking `Polygon.getInnerAngleAt` and `Polygo.isAngleAcute` to handle indices out of array bounds as well.\n * @modified 2025-06-07 Adding `Polygon.closestLineIntersectionIndex` to determine line intersections plus detected edge index.\n * @version 1.16.0\n *\n * @file Polygon\n * @public\n **/\nimport { BezierPath } from \"./BezierPath\";\nimport { Bounds } from \"./Bounds\";\nimport { Line } from \"./Line\";\nimport { Triangle } from \"./Triangle\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { geomutils } from \"./geomutils\";\n/**\n * @classdesc A polygon class. Any polygon consists of an array of vertices; polygons can be open or closed.\n *\n * @requires BezierPath\n * @requires Bounds\n * @requires SVGSerializabe\n * @requires UID\n * @requires UIDGenerator\n * @requires Vertex\n * @requires XYCoords\n */\nexport class Polygon {\n /**\n * The constructor.\n *\n * @constructor\n * @name Polygon\n * @param {Vertex[]} vertices - An array of 2d vertices that shape the polygon.\n * @param {boolean} isOpen - Indicates if the polygon should be rendered as an open or closed shape.\n **/\n constructor(vertices, isOpen) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Polygon\";\n this.uid = UIDGenerator.next();\n if (typeof vertices == \"undefined\") {\n vertices = [];\n }\n this.vertices = vertices;\n this.isOpen = isOpen || false;\n }\n /**\n * Add a vertex to the end of the `vertices` array.\n *\n * @method addVertex\n * @param {Vertex} vert - The vertex to add.\n * @instance\n * @memberof Polygon\n **/\n addVertex(vert) {\n this.vertices.push(vert);\n }\n /**\n * Add a vertex at a particular position of the `vertices` array.\n *\n * @method addVertexAt\n * @param {Vertex} vert - The vertex to add.\n * @param {number} index - The position to add the vertex at. Will be handled modulo.\n * @instance\n * @memberof Polygon\n **/\n addVertexAt(vert, index) {\n // var moduloIndex = index % (this.vertices.length + 1);\n this.vertices.splice(index, 0, vert);\n }\n /**\n * Get a new instance of the line at the given start index. The returned line will consist\n * of the vertex at `vertIndex` and `vertIndex+1` (will be handled modulo).\n *\n * @method getEdgeAt\n * @param {number} vertIndex - The vertex index of the line to start.\n * @instance\n * @memberof Polygon\n * @return {Line}\n **/\n getEdgeAt(vertIndex) {\n return new Line(this.getVertexAt(vertIndex), this.getVertexAt(vertIndex + 1));\n }\n /**\n * Converts this polygon into a sequence of lines. Please note that each time\n * this method is called new lines are created. The underlying line vertices are no clones\n * (instances).\n *\n * @method getEdges\n * @instance\n * @memberof Polygon\n * @return {Array<Line>}\n */\n getEdges() {\n const lines = [];\n for (var i = 0; i + 1 < this.vertices.length; i++) {\n // var line = this.getLineAt(i).clone();\n lines.push(this.getEdgeAt(i));\n }\n if (!this.isOpen && this.vertices.length > 0) {\n lines.push(this.getEdgeAt(this.vertices.length - 1));\n }\n return lines;\n }\n /**\n * Checks if the angle at the given polygon vertex (index) is acute. Please not that this is\n * only working for clockwise polygons. If this polygon is not clockwise please use the\n * `isClockwise` method and reverse polygon vertices if needed.\n *\n * @method isAngleAcute\n * @instance\n * @memberof Polygon\n * @param {number} vertIndex - The index of the polygon vertex to check.\n * @returns {boolean} `true` is angle is acute, `false` is obtuse.\n */\n getInnerAngleAt(vertIndex) {\n const p2 = this.vertices[vertIndex % this.vertices.length];\n const p1 = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();\n const p3 = this.vertices[(vertIndex + 1) % this.vertices.length].clone();\n // See\n // https://math.stackexchange.com/questions/149959/how-to-find-the-interior-angle-of-an-irregular-pentagon-or-polygon\n // π−arccos((P2−P1)⋅(P3−P2)|P2−P1||P3−P2|)\n // Check if triangle is acute (will be used later)\n // Acute angles and obtuse angles need to be handled differently.\n const isAcute = this.isAngleAcute(vertIndex);\n // Differences\n const zero = new Vertex(0, 0);\n const p2mp1 = new Vertex(p2.x - p1.x, p2.y - p1.y);\n const p3mp2 = new Vertex(p3.x - p2.x, p3.y - p2.y);\n const p2mp1_len = zero.distance(p2mp1);\n const p3mp2_len = zero.distance(p3mp2);\n // Dot products\n const dotProduct = geomutils.dotProduct(p2mp1, p3mp2);\n const lengthProduct = p2mp1_len * p3mp2_len;\n if (isAcute) {\n return Math.PI - Math.acos(dotProduct / lengthProduct);\n }\n else {\n return Math.PI + Math.acos(dotProduct / lengthProduct);\n }\n }\n /**\n * Checks if the angle at the given polygon vertex (index) is acute.\n *\n * @method isAngleAcute\n * @instance\n * @memberof Polygon\n * @param {number} vertIndex - The index of the polygon vertex to check.\n * @returns {boolean} `true` is angle is acute, `false` is obtuse.\n */\n isAngleAcute(vertIndex) {\n const A = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();\n const B = this.vertices[vertIndex % this.vertices.length];\n const C = this.vertices[(vertIndex + 1) % this.vertices.length].clone();\n // Find local winding number for triangle A B C\n const windingNumber = Triangle.utils.determinant(A, B, C);\n // console.log(\"vertIndex\", vertIndex, \"windingNumber\", windingNumber);\n return windingNumber < 0;\n }\n /**\n * Get the polygon vertex at the given position (index).\n *\n * The index may exceed the total vertex count, and will be wrapped around then (modulo).\n *\n * For k >= 0:\n * - getVertexAt( vertices.length ) == getVertexAt( 0 )\n * - getVertexAt( vertices.length + k ) == getVertexAt( k )\n * - getVertexAt( -k ) == getVertexAt( vertices.length -k )\n *\n * @method getVertexAt\n * @param {number} index - The index of the desired vertex.\n * @instance\n * @memberof Polygon\n * @return {Vertex} At the given index.\n **/\n getVertexAt(index) {\n if (index < 0) {\n return this.vertices[this.vertices.length - (Math.abs(index) % this.vertices.length)];\n }\n else {\n return this.vertices[index % this.vertices.length];\n }\n }\n /**\n * Move the polygon's vertices by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof Polygon\n * @return {Polygon} this for chaining\n **/\n move(amount) {\n for (var i in this.vertices) {\n this.vertices[i].add(amount);\n }\n return this;\n }\n /**\n * Check if the given vertex is inside this polygon.<br>\n * <br>\n * Ray-casting algorithm found at<br>\n * https://stackoverflow.com/questions/22521982/check-if-point-inside-a-polygon\n *\n * @method containsVert\n * @param {XYCoords} vert - The vertex to check.\n * @return {boolean} True if the passed vertex is inside this polygon. The polygon is considered closed.\n * @instance\n * @memberof Polygon\n **/\n containsVert(vert) {\n // ray-casting algorithm based on\n // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\n var inside = false;\n for (var i = 0, j = this.vertices.length - 1; i < this.vertices.length; j = i++) {\n let xi = this.vertices[i].x, yi = this.vertices[i].y;\n let xj = this.vertices[j].x, yj = this.vertices[j].y;\n var intersect = yi > vert.y != yj > vert.y && vert.x < ((xj - xi) * (vert.y - yi)) / (yj - yi) + xi;\n if (intersect) {\n inside = !inside;\n }\n }\n return inside;\n }\n /**\n * Check if all given vertices are inside this polygon.<br>\n * <br>\n * This method just uses the `Polygon.containsVert` method.\n *\n * @method containsVerts\n * @param {XYCoords[]} verts - The vertices to check.\n * @return {boolean} True if all passed vertices are inside this polygon. The polygon is considered closed.\n * @instance\n * @memberof Polygon\n **/\n containsVerts(verts) {\n return verts.every((vert) => this.containsVert(vert));\n }\n /**\n * Check if the passed polygon is completly contained inside this polygon.\n *\n * This means:\n * - all polygon's vertices must be inside this polygon.\n * - the polygon has no edge intersections with this polygon.\n *\n * @param {Polygon} polygon - The polygon to check if contained.\n * @return {boolean}\n */\n containsPolygon(polygon) {\n for (var i = 0; i < polygon.vertices.length; i++) {\n if (!this.containsVert(polygon.vertices[i])) {\n return false;\n }\n }\n // All vertices are inside; check for intersections\n const lineSegment = new Line(new Vertex(), new Vertex());\n for (var i = 0; i < polygon.vertices.length; i++) {\n lineSegment.a.set(polygon.vertices[i]);\n lineSegment.b.set(polygon.vertices[(i + 1) % polygon.vertices.length]);\n if (this.lineIntersections(lineSegment, true).length > 0) {\n // Current segment has intersection(s) with this polygon.\n return false;\n }\n }\n return true;\n }\n /**\n * Calculate the area of the given polygon (unsigned).\n *\n * Note that this does not work for self-intersecting polygons.\n *\n * @method area\n * @instance\n * @memberof Polygon\n * @return {number}\n */\n area() {\n return Polygon.utils.area(this.vertices);\n }\n /**\n * Calulate the signed polyon area by interpreting the polygon as a matrix\n * and calculating its determinant.\n *\n * @method signedArea\n * @instance\n * @memberof Polygon\n * @return {number}\n */\n signedArea() {\n return Polygon.utils.signedArea(this.vertices);\n }\n /**\n * Get the winding order of this polgon: clockwise or counterclockwise.\n *\n * @method isClockwise\n * @instance\n * @memberof Polygon\n * @return {boolean}\n */\n isClockwise() {\n // return Polygon.utils.signedArea(this.vertices) < 0;\n return Polygon.utils.isClockwise(this.vertices);\n }\n /**\n * Get the perimeter of this polygon.\n * The perimeter is the absolute length of the outline.\n *\n * If this polygon is open then the last segment (connecting the first and the\n * last vertex) will be skipped.\n *\n * @method perimeter\n * @instance\n * @memberof Polygon\n * @return {number}\n */\n perimeter() {\n let length = 0;\n for (var i = 1; i < this.vertices.length; i++) {\n length += this.vertices[i - 1].distance(this.vertices[i]);\n }\n if (!this.isOpen && this.vertices.length > 1) {\n length += this.vertices[0].distance(this.vertices[this.vertices.length - 1]);\n }\n return length;\n }\n /**\n * Scale the polygon relative to the given center.\n *\n * @method scale\n * @param {number} factor - The scale factor.\n * @param {Vertex} center - The center of scaling.\n * @return {Polygon} this, for chaining.\n * @instance\n * @memberof Polygon\n **/\n scale(factor, center) {\n for (var i in this.vertices) {\n if (typeof this.vertices[i].scale == \"function\")\n this.vertices[i].scale(factor, center);\n else\n console.log(\"There seems to be a null vertex!\", this.vertices[i]);\n }\n return this;\n }\n /**\n * Rotate the polygon around the given center.\n *\n * @method rotate\n * @param {number} angle - The rotation angle.\n * @param {Vertex} center - The center of rotation.\n * @instance\n * @memberof Polygon\n * @return {Polygon} this, for chaining.\n **/\n rotate(angle, center) {\n for (var i in this.vertices) {\n this.vertices[i].rotate(angle, center);\n }\n return this;\n }\n /**\n * Get the mean `center` of this polygon by calculating the mean value of all vertices.\n *\n * Mean: (v[0] + v[1] + ... v[n-1]) / n\n *\n * @method getMeanCenter\n * @instance\n * @memberof Polygon\n * @return {Vertex|null} `null` is no vertices are available.\n */\n getMeanCenter() {\n if (this.vertices.length === 0) {\n return null;\n }\n const center = this.vertices[0].clone();\n for (var i = 1; i < this.vertices.length; i++) {\n center.add(this.vertices[i]);\n }\n center.x /= this.vertices.length;\n center.y /= this.vertices.length;\n return center;\n }\n /**\n * Get centroid.\n * Centroids define the barycenter of any non self-intersecting convex polygon.\n *\n * If the polygon is self intersecting or non konvex then the barycenter is not well defined.\n *\n * https://mathworld.wolfram.com/PolygonCentroid.html\n *\n * @method getCentroid\n * @instance\n * @memberof Polygon\n * @returns {Vertex|null}\n */\n getCentroid() {\n if (this.vertices.length === 0) {\n return null;\n }\n const center = new Vertex(0.0, 0.0);\n const n = this.vertices.length;\n for (var i = 0; i < n; i++) {\n // center.add(this.vertices[i]);\n const cur = this.vertices[i];\n const next = this.vertices[(i + 1) % n];\n var factor = cur.x * next.y - next.x * cur.y;\n center.x += (cur.x + next.x) * factor;\n center.y += (cur.y + next.y) * factor;\n }\n const area = this.area();\n center.x *= 1 / (6 * area);\n center.y *= 1 / (6 * area);\n return center;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this polygon.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n return Polygon.utils\n .locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly)\n .map(intersectionTuple => intersectionTuple.intersection);\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {\n const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangentsIndices(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {\n const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n return {\n intersection: new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection),\n edgeIndex: intersectionTuple.edgeIndex\n };\n });\n }\n /**\n * Get the closest line-polygon-intersection point (closest the line point A).\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).\n * @returns {Vertex | null} - The intersection point within the polygon bounds.\n */\n closestLineIntersection(line, inVectorBoundsOnly = false) {\n var closestInterSectionIndex = this.closestLineIntersectionIndex(line, inVectorBoundsOnly);\n if (closestInterSectionIndex) {\n return closestInterSectionIndex.intersection;\n }\n else {\n return null;\n }\n }\n /**\n * Get the closest line-polygon-intersection point (closest the line point A) plus the edge index..\n *\n * See demo `63-measure-angles-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).\n * @returns {PolygonIntersectionTuple| null} - A pair containing the intersection point and the affected polygon edge index.\n */\n closestLineIntersectionIndex(line, inVectorBoundsOnly = false) {\n const allIntersections = this.lineIntersections(line, inVectorBoundsOnly);\n if (allIntersections.length <= 0) {\n // Empty polygon -> no intersections\n return null;\n }\n // Find the closest intersection\n let closestIntersection = new Vertex(Number.MAX_VALUE, Number.MAX_VALUE);\n let closestInterSectionIndex = -1;\n let curDist = Number.MAX_VALUE;\n for (var i = 0; i < allIntersections.length; i++) {\n const curVert = allIntersections[i];\n const dist = curVert.distance(line.a);\n if (dist < curDist) {\n // && line.hasPoint(curVert)) {\n curDist = dist;\n closestIntersection = curVert;\n closestInterSectionIndex = i;\n }\n }\n // return [closestIntersection, closestInterSectionIndex];\n return { edgeIndex: closestInterSectionIndex, intersection: closestIntersection };\n }\n /**\n * Construct a new polygon from this polygon with more vertices on each edge. The\n * interpolation count determines the number of additional vertices on each edge.\n * An interpolation count of `0` will return a polygon that equals the source\n * polygon.\n *\n * @param {number} interpolationCount\n * @returns {Polygon} A polygon with `interpolationCount` more vertices (as as factor).\n */\n getInterpolationPolygon(interpolationCount) {\n const verts = [];\n for (var i = 0; i < this.vertices.length; i++) {\n const curVert = this.vertices[i];\n const nextVert = this.vertices[(i + 1) % this.vertices.length];\n verts.push(curVert.clone());\n // Add interpolation points\n if (!this.isOpen || i + 1 !== this.vertices.length) {\n const lerpAmount = 1.0 / (interpolationCount + 1);\n for (var j = 1; j <= interpolationCount; j++) {\n verts.push(curVert.clone().lerp(nextVert, lerpAmount * j));\n }\n }\n }\n return new Polygon(verts, this.isOpen);\n }\n /**\n * Convert this polygon into a new polygon with n evenly distributed vertices.\n *\n * @param {number} pointCount - Must not be negative.\n */\n getEvenDistributionPolygon(pointCount) {\n if (pointCount <= 0) {\n throw new Error(\"pointCount must be larger than zero; is \" + pointCount + \".\");\n }\n const result = new Polygon([], this.isOpen);\n if (this.vertices.length === 0) {\n return result;\n }\n // Fetch and add the start point from the source polygon\n let polygonPoint = new Vertex(this.vertices[0]);\n result.vertices.push(polygonPoint);\n if (this.vertices.length === 1) {\n return result;\n }\n const perimeter = this.perimeter();\n const stepSize = perimeter / pointCount;\n const n = this.vertices.length;\n let polygonIndex = 1;\n let nextPolygonPoint = new Vertex(this.vertices[1]);\n let segmentLength = polygonPoint.distance(nextPolygonPoint);\n let loopMax = this.isOpen ? n : n + 1;\n let curSegmentU = stepSize;\n var i = 1;\n while (i < pointCount && polygonIndex < loopMax) {\n // Check if next eq point is inside this segment\n if (curSegmentU < segmentLength) {\n let newPoint = polygonPoint.clone().lerpAbs(nextPolygonPoint, curSegmentU);\n result.vertices.push(newPoint);\n curSegmentU += stepSize;\n i++;\n }\n else {\n polygonIndex++;\n polygonPoint = nextPolygonPoint;\n nextPolygonPoint = new Vertex(this.vertices[polygonIndex % n]);\n curSegmentU = curSegmentU - segmentLength;\n segmentLength = polygonPoint.distance(nextPolygonPoint);\n }\n }\n return result;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this polygon.\n *\n * @method getBounds\n * @instance\n * @memberof Polygon\n * @return {Bounds} The rectangular bounds of this polygon.\n **/\n getBounds() {\n return Bounds.computeFromVertices(this.vertices);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Create a deep copy of this polygon.\n *\n * @method clone\n * @instance\n * @memberof Polygon\n * @return {Polygon} The cloned polygon.\n */\n clone() {\n return new Polygon(this.vertices.map(vert => vert.clone()), this.isOpen);\n }\n /**\n * Create a new polygon without colinear adjacent edges. This method does not midify the current polygon\n * but creates a new one.\n *\n * Please note that this method does NOT create deep clones of the vertices. Use Polygon.clone() if you need to.\n *\n * Please also note that the `tolerance` may become really large here, as the denominator of two closely\n * parallel lines is usually pretty large. See the demo `57-eliminate-colinear-polygon-edges` to get\n * an impression of how denominators work.\n *\n * @method elimitateColinearEdges\n * @instance\n * @memberof Polygon\n * @param {number?} tolerance - (default is 1.0) The epsilon to detect co-linear edges.\n * @return {Polygon} A new polygon without co-linear adjacent edges – respective the given epsilon.\n */\n elimitateColinearEdges(tolerance) {\n const eps = typeof tolerance === \"undefined\" ? 1.0 : tolerance;\n const verts = this.vertices.slice(); // Creates a shallow copy\n let i = 0;\n var lineA = new Line(new Vertex(), new Vertex());\n var lineB = new Line(new Vertex(), new Vertex());\n while (i + 1 < verts.length && verts.length > 2) {\n const vertA = verts[i];\n const vertB = verts[(i + 1) % verts.length];\n lineA.a = vertA;\n lineA.b = vertB;\n lineB.a = vertB;\n let areColinear = false;\n let j = i + 2;\n do {\n let vertC = verts[j % verts.length];\n lineB.b = vertC;\n areColinear = lineA.colinear(lineB, eps);\n // console.log(\"are colinear?\", i, i + 1, j, areColinear);\n if (areColinear) {\n j++;\n }\n } while (areColinear);\n // Now j points to the first vertex that's NOT colinear to the current lineA\n // -> delete all vertices in between\n if (j - i > 2) {\n // Means: there have been 'colinear vertices' in between\n verts.splice(i + 1, j - i - 2);\n }\n i++;\n }\n return new Polygon(verts, this.isOpen);\n }\n /**\n * Convert this polygon to a sequence of quadratic Bézier curves.<br>\n * <br>\n * The first vertex in the returned array is the start point.<br>\n * The following sequence are pairs of control-point-and-end-point:\n * <pre>startPoint, controlPoint0, pathPoint1, controlPoint1, pathPoint2, controlPoint2, ..., endPoint</pre>\n *\n * @method toQuadraticBezierData\n * @return {Vertex[]} An array of 2d vertices that shape the quadratic Bézier curve.\n * @instance\n * @memberof Polygon\n **/\n toQuadraticBezierData() {\n if (this.vertices.length < 3)\n return [];\n var qbezier = [];\n var cc0 = this.vertices[0];\n var cc1 = this.vertices[1];\n var edgeCenter = new Vertex(cc0.x + (cc1.x - cc0.x) / 2, cc0.y + (cc1.y - cc0.y) / 2);\n qbezier.push(edgeCenter);\n var limit = this.isOpen ? this.vertices.length : this.vertices.length + 1;\n for (var t = 1; t < limit; t++) {\n cc0 = this.vertices[t % this.vertices.length];\n cc1 = this.vertices[(t + 1) % this.vertices.length];\n var edgeCenter = new Vertex(cc0.x + (cc1.x - cc0.x) / 2, cc0.y + (cc1.y - cc0.y) / 2);\n qbezier.push(cc0);\n qbezier.push(edgeCenter);\n cc0 = cc1;\n }\n return qbezier;\n }\n /**\n * Convert this polygon to a quadratic bezier curve, represented as an SVG data string.\n *\n * @method toQuadraticBezierSVGString\n * @return {string} The 'd' part for an SVG 'path' element.\n * @instance\n * @memberof Polygon\n **/\n toQuadraticBezierSVGString() {\n var qdata = this.toQuadraticBezierData();\n if (qdata.length == 0)\n return \"\";\n var buffer = [\"M \" + qdata[0].x + \" \" + qdata[0].y];\n for (var i = 1; i < qdata.length; i += 2) {\n buffer.push(\"Q \" + qdata[i].x + \" \" + qdata[i].y + \", \" + qdata[i + 1].x + \" \" + qdata[i + 1].y);\n }\n return buffer.join(\" \");\n }\n /**\n * Convert this polygon to a sequence of cubic Bézier curves.<br>\n * <br>\n * The first vertex in the returned array is the start point.<br>\n * The following sequence are triplets of (first-control-point, secnond-control-point, end-point):<br>\n * <pre>startPoint, controlPoint0_0, controlPoint1_1, pathPoint1, controlPoint1_0, controlPoint1_1, ..., endPoint</pre>\n *\n * @method toCubicBezierData\n * @param {number=} threshold - An optional threshold (default=1.0) how strong the curve segments\n * should over-/under-drive. Should be between 0.0 and 1.0 for best\n * results but other values are allowed.\n * @return {Vertex[]} An array of 2d vertices that shape the cubic Bézier curve.\n * @instance\n * @memberof Polygon\n **/\n toCubicBezierData(threshold) {\n if (typeof threshold == \"undefined\")\n threshold = 1.0;\n if (this.vertices.length < 3)\n return [];\n var cbezier = [];\n var a = this.vertices[0];\n var b = this.vertices[1];\n var edgeCenter = new Vertex(a.x + (b.x - a.x) / 2, a.y + (b.y - a.y) / 2);\n cbezier.push(edgeCenter);\n var limit = this.isOpen ? this.vertices.length - 1 : this.vertices.length;\n for (var t = 0; t < limit; t++) {\n var a = this.vertices[t % this.vertices.length];\n var b = this.vertices[(t + 1) % this.vertices.length];\n var c = this.vertices[(t + 2) % this.vertices.length];\n var aCenter = new Vertex(a.x + (b.x - a.x) / 2, a.y + (b.y - a.y) / 2);\n var bCenter = new Vertex(b.x + (c.x - b.x) / 2, b.y + (c.y - b.y) / 2);\n var a2 = new Vertex(aCenter.x + (b.x - aCenter.x) * threshold, aCenter.y + (b.y - aCenter.y) * threshold);\n var b0 = new Vertex(bCenter.x + (b.x - bCenter.x) * threshold, bCenter.y + (b.y - bCenter.y) * threshold);\n cbezier.push(a2);\n cbezier.push(b0);\n cbezier.push(bCenter);\n }\n return cbezier;\n }\n /**\n * Convert this polygon to a cubic bezier curve, represented as an SVG data string.\n *\n * @method toCubicBezierSVGString\n * @return {string} The 'd' part for an SVG 'path' element.\n * @instance\n * @memberof Polygon\n **/\n toCubicBezierSVGString(threshold) {\n var qdata = this.toCubicBezierData(threshold);\n if (qdata.length == 0) {\n return \"\";\n }\n var buffer = [\"M \" + qdata[0].x + \" \" + qdata[0].y];\n for (var i = 1; i < qdata.length; i += 3) {\n buffer.push(\"C \" +\n qdata[i].x +\n \" \" +\n qdata[i].y +\n \", \" +\n qdata[i + 1].x +\n \" \" +\n qdata[i + 1].y +\n \", \" +\n qdata[i + 2].x +\n \" \" +\n qdata[i + 2].y);\n }\n return buffer.join(\" \");\n }\n /**\n * Convert this polygon to a cubic bezier path instance.\n *\n * @method toCubicBezierPath\n * @param {number} threshold - The threshold, usually from 0.0 to 1.0.\n * @return {BezierPath} - A bezier path instance.\n * @instance\n * @memberof Polygon\n **/\n toCubicBezierPath(threshold) {\n var qdata = this.toCubicBezierData(threshold);\n // Conver the linear path vertices to a two-dimensional path array\n var pathdata = [];\n for (var i = 0; i + 3 < qdata.length; i += 3) {\n pathdata.push([qdata[i], qdata[i + 3], qdata[i + 1], qdata[i + 2]]);\n }\n return BezierPath.fromArray(pathdata);\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n for (var i = 0; i < this.vertices.length; i++) {\n this.vertices[i].destroy();\n }\n this.isDestroyed = true;\n }\n}\nPolygon.utils = {\n /**\n * Calculate the area of the given polygon (unsigned).\n *\n * Note that this does not work for self-intersecting polygons.\n *\n * @name area\n * @return {number}\n */\n area(vertices) {\n // Found at:\n // https://stackoverflow.com/questions/16285134/calculating-polygon-area\n let total = 0.0;\n for (var i = 0, l = vertices.length; i < l; i++) {\n const addX = vertices[i].x;\n const addY = vertices[(i + 1) % l].y;\n const subX = vertices[(i + 1) % l].x;\n const subY = vertices[i].y;\n total += addX * addY * 0.5;\n total -= subX * subY * 0.5;\n }\n return Math.abs(total);\n },\n isClockwise(vertices) {\n return Polygon.utils.signedArea(vertices) < 0;\n },\n /**\n * Calulate the signed polyon area by interpreting the polygon as a matrix\n * and calculating its determinant.\n *\n * @name signedArea\n * @return {number}\n */\n signedArea(vertices) {\n let sum = 0;\n const n = vertices.length;\n for (var i = 0; i < n; i++) {\n const j = (i + 1) % n;\n sum += (vertices[j].x - vertices[i].x) * (vertices[i].y + vertices[j].y);\n }\n return sum;\n },\n /**\n * Find intersections of a line with a polygon (vertices).\n *\n * @param {VertTuple<any>} line - The line to find intersections with.\n * @param {Array<Vertex>} vertices - The polygon's vertices.\n * @param {boolean} isOpen - True if the polygon is open, false otherwise.\n * @param {boolean} inVectorBoundsOnly - If only intersections in strict vector bounds should be returned.\n * @returns\n */\n locateLineIntersecion(line, vertices, isOpen, inVectorBoundsOnly) {\n // Find the intersections of all lines inside the edge bounds\n const intersectionPoints = [];\n var n = isOpen ? vertices.length - 1 : vertices.length;\n for (var i = 0; i < n; i++) {\n const polyLine = new Line(vertices[i % n], vertices[(i + 1) % n]);\n const intersection = polyLine.intersection(line);\n // true => only inside bounds\n // ignore last edge if open\n if (intersection !== null &&\n polyLine.hasPoint(intersection, true) &&\n (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {\n intersectionPoints.push({ edgeIndex: i, intersection: intersection });\n }\n }\n return intersectionPoints;\n }\n};\n//# sourceMappingURL=Polygon.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-05-11\n * @modified 2020-10-30 Added the static computeFromVertices function.\n * @modified 2020-11-19 Set min, max, width and height to private.\n * @modified 2021-02-02 Added the `toPolygon` method.\n * @modified 2021-06-21 (mid-summer) Added `getCenter` method.\n * @modified 2022-02-01 Added the `toString` function.\n * @modified 2022-10-09 Added the `fromDimension` function.\n * @modified 2022-11-28 Added the `clone` method.\n * @modified 2023-09-29 Added the `randomPoint` method.\n * @modified 2025-03-23 Added the `getMinDimension` and `getMaxDimension` methods.\n * @modified 2025-04-18 Change parameter type in `Bounds.computeFromVertices` from `Vertex` to more general `XYCoords`.\n * @modified 2025-04-19 Added methods to `Bounds` class: `getNorthPoint`, `getSouthPoint`, `getEastPoint` and `getWestPoint`.\n * @modified 2025-04-26 Added static method `Bounds.computeFromBoundsSet` to calculate containing bounds for a set of bounding boxes.\n * @modified 2025-10-17 Added the methods `Bounds.getSouthWestPoint`, `getNorthWestPoint`, `getNorthEastPoint` and `getSouthEastPoint`.\n * @modified 2025-10-18 Added method `Bounds.containsVert(XYCoords)`.\n * @modified 2025-10-28 Added the `Bounds.getWidth()` and `Bounds.getHeight()`.\n * @modified 2025-11-12 Added the `Bounds.getMoved()` method.\n * @version 1.11.0\n **/\nimport { Polygon } from \"./Polygon\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A bounds class with min and max values. Implementing IBounds.\n *\n * @requires XYCoords\n * @requires Vertex\n * @requires IBounds\n **/\nexport class Bounds {\n /**\n * The constructor.\n *\n * @constructor\n * @name Bounds\n * @param {XYCoords} min - The min values (x,y) as a XYCoords tuple.\n * @param {XYCoords} max - The max values (x,y) as a XYCoords tuple.\n **/\n constructor(min, max) {\n this.min = min;\n this.max = max;\n this.width = max.x - min.x;\n this.height = max.y - min.y;\n }\n /**\n * Check if the given vertex is inside this bounds.\n *\n * @method containsVert\n * @param {XYCoords} vert - The vertex to check.\n * @return {boolean} True if the passed vertex is inside this bounds.\n * @instance\n * @memberof Bounds\n **/\n containsVert(vert) {\n return this.min.x <= vert.x && vert.x < this.max.x && this.min.y <= vert.y && vert.y < this.max.y;\n }\n getWidth() {\n return this.max.x - this.min.x;\n }\n getHeight() {\n return this.max.y - this.min.y;\n }\n getScaled(scaleFactor) {\n const center = this.getCenter();\n const newMin = new Vertex(this.min).scale(scaleFactor, center);\n const newMax = new Vertex(this.max).scale(scaleFactor, center);\n return new Bounds(newMin, newMax);\n }\n getMoved(moveAmount) {\n const newMin = new Vertex(this.min).move(moveAmount);\n const newMax = new Vertex(this.max).move(moveAmount);\n return new Bounds(newMin, newMax);\n }\n /**\n * Get the center point of the north bound.\n *\n * @method getNorthPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"northmost\" centered point of this bounding box.\n */\n getNorthPoint() {\n return new Vertex(this.min.x + this.width / 2.0, this.min.y);\n }\n /**\n * Get the center point of the south bound.\n *\n * @method getNorthPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"southhmost\" centered point of this bounding box.\n */\n getSouthPoint() {\n return new Vertex(this.min.x + this.width / 2.0, this.max.y);\n }\n /**\n * Get the center point of the west bound.\n *\n * @method getWestPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"westhmost\" centered point of this bounding box.\n */\n getWestPoint() {\n return new Vertex(this.min.x, this.min.y + this.height / 2.0);\n }\n /**\n * Get the center point of the east bound.\n *\n * @method getEastPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"easthmost\" centered point of this bounding box.\n */\n getEastPoint() {\n return new Vertex(this.max.x, this.min.y + this.height / 2.0);\n }\n /**\n * Get the upper left corner point these bounds box.\n *\n * @method getNorthWestPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"northwestmost\" point of this bounding box.\n */\n getNorthWestPoint() {\n return new Vertex(this.min.x, this.min.y);\n }\n /**\n * Get the upper right corner point these bounds box.\n *\n * @method getNorthEastPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"northeastmost\" point of this bounding box.\n */\n getNorthEastPoint() {\n return new Vertex(this.max.x, this.min.y);\n }\n /**\n * Get the lower right corner point these bounds box.\n *\n * @method getSouthEastPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"southeastmost\" point of this bounding box.\n */\n getSouthEastPoint() {\n return new Vertex(this.max.x, this.max.y);\n }\n /**\n * Get the lower left corner point these bounds box.\n *\n * @method getSouthWestPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"southwestmost\" point of this bounding box.\n */\n getSouthWestPoint() {\n return new Vertex(this.min.x, this.max.y);\n }\n /**\n * Convert this rectangular bounding box to a polygon with four vertices.\n *\n * @method toPolygon\n * @instance\n * @memberof Bounds\n * @return {Polygon} This bound rectangle as a polygon.\n */\n toPolygon() {\n return new Polygon([new Vertex(this.min), new Vertex(this.max.x, this.min.y), new Vertex(this.max), new Vertex(this.min.x, this.max.y)], false);\n }\n /**\n * Get the center of this boinding box.\n *\n * @method getCenter\n * @instance\n * @memberof Bounds\n * @returns {Vertex} The center of these bounds.\n */\n getCenter() {\n return new Vertex(this.min.x + (this.max.x - this.min.x) / 2.0, this.min.y + (this.max.y - this.min.y) / 2);\n }\n /**\n * Get the minimum of `width` and `height`.\n *\n * @returns {number} The value of Math.min( this.width, this.height )\n */\n getMinDimension() {\n return Math.min(this.width, this.height);\n }\n /**\n * Get the minimum of `width` and `height`.\n *\n * @returns {number} The value of Math.min( this.width, this.height )\n */\n getMaxDimension() {\n return Math.max(this.width, this.height);\n }\n /**\n * Generate a random point inside this bounds object. Safe areas at the border to avoid\n * included.\n *\n * @method randomPoint\n * @instance\n * @memberof Bounds\n * @param {horizontalSafeArea} - (optional) The horizonal (left and right) safe area. No vertex will be created here. Can be used as percent in (0.0 ... 0.1) interval.\n * @param {verticalSafeArea} - (optional) The vertical (top and bottom) safe area. No vertex will be created here. Can be used as percent in (0.0 ... 0.1) interval\n * @returns {Vertex} A pseudo random point inside these bounds.\n */\n randomPoint(horizontalSafeArea = 0, verticalSafeArea = 0) {\n // Check if the safe areas are meant as percent\n const absHorizontalSafeArea = horizontalSafeArea > 0 && horizontalSafeArea < 1 ? this.width * horizontalSafeArea : horizontalSafeArea;\n const absVerticalSafeArea = verticalSafeArea > 0 && verticalSafeArea < 1 ? this.height * verticalSafeArea : verticalSafeArea;\n return new Vertex(this.min.x + absHorizontalSafeArea + Math.random() * (this.width - 2 * absHorizontalSafeArea), this.min.y + absVerticalSafeArea + Math.random() * (this.height - 2 * absVerticalSafeArea));\n }\n /**\n * Convert these bounds to a human readable form.\n *\n * Note: the returned format might change in the future, so please do not\n * rely on the returned string format.\n *\n * @method toString\n * @instance\n * @memberof Bounds\n * @returns {string} Get these bounds in a human readable form.\n */\n toString() {\n return `{ min: ${this.min.toString()}, max : ${this.max.toString()}, width: ${this.width}, height : ${this.height} }`;\n }\n /**\n * Clone this bounds object (create a deep clone).\n *\n * @method clone\n * @instance\n * @memberof Bounds\n * @returns {Bounds} Creates a deep clone of this bounds object.\n */\n clone() {\n return new Bounds({ x: this.min.x, y: this.min.y }, { x: this.max.x, y: this.max.y });\n }\n /**\n * Compute the minimal bounding box for a given set of vertices.\n *\n * An empty vertex array will return an empty bounding box located at (0,0).\n *\n * @static\n * @method computeFromVertices\n * @memberof Bounds\n * @param {Array<XYCoords>} vertices - The set of vertices you want to get the bounding box for.\n * @return The minimal Bounds for the given vertices.\n **/\n static computeFromVertices(vertices) {\n if (vertices.length == 0) {\n return new Bounds(new Vertex(0, 0), new Vertex(0, 0));\n }\n let xMin = vertices[0].x;\n let xMax = vertices[0].x;\n let yMin = vertices[0].y;\n let yMax = vertices[0].y;\n let vert;\n for (var i in vertices) {\n vert = vertices[i];\n xMin = Math.min(xMin, vert.x);\n xMax = Math.max(xMax, vert.x);\n yMin = Math.min(yMin, vert.y);\n yMax = Math.max(yMax, vert.y);\n }\n return new Bounds(new Vertex(xMin, yMin), new Vertex(xMax, yMax));\n }\n /**\n * Compute the minimal bounding box for a given set of existing bounding boxes.\n *\n * An empty vertex array will return an empty bounding box located at (0,0).\n *\n * @static\n * @method computeFromBoundsSet\n * @memberof Bounds\n * @param {Array<IBounds>} boundingBoxes - The set of existing bounding boxes to get the containing bounding box for.\n * @return The minimal Bounds for the given bounds instances.\n **/\n static computeFromBoundsSet(boundingBoxes) {\n if (boundingBoxes.length == 0) {\n return new Bounds(new Vertex(0, 0), new Vertex(0, 0));\n }\n let xMin = boundingBoxes[0].min.x;\n let xMax = boundingBoxes[0].max.x;\n let yMin = boundingBoxes[0].min.y;\n let yMax = boundingBoxes[0].min.y;\n let bounds;\n for (var i in boundingBoxes) {\n bounds = boundingBoxes[i];\n xMin = Math.min(xMin, bounds.min.x);\n xMax = Math.max(xMax, bounds.max.x);\n yMin = Math.min(yMin, bounds.min.y);\n yMax = Math.max(yMax, bounds.min.y);\n }\n return new Bounds(new Vertex(xMin, yMin), new Vertex(xMax, yMax));\n }\n /**\n * Create a new `Bounds` instance just from `width` and `height`, located at (0,0) or the optionally given origin.\n *\n * @param {number} width - The width of the bounds\n * @param {number} height - The height of the bounds\n * @param {XYCoords={x:0,y:0}} origin - [optional] A origin to locate the new Bounds object at.\n * @returns {Bounds} A new `Bounds` instance width given width and height, located at (0,0) or the given origin..\n */\n static fromDimension(width, height, origin) {\n return new Bounds(origin !== null && origin !== void 0 ? origin : { x: 0, y: 0 }, { x: (origin ? origin.x : 0) + width, y: (origin ? origin.y : 0) + height });\n }\n} // END class bounds\n//# sourceMappingURL=Bounds.js.map","/**\n * @author Ikaros Kappler\n * @date 2013-08-15\n * @modified 2018-08-16 Added a closure. Removed the wrapper class 'IKRS'. Replaced class THREE.Vector2 by Vertex class.\n * @modified 2018-11-19 Added the fromArray(Array) function.\n * @modified 2018-11-28 Added the locateCurveByPoint(Vertex) function.\n * @modified 2018-12-04 Added the toSVGPathData() function.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-03-23 Changed the signatures of getPoint, getPointAt and getTangent (!version 2.0).\n * @modified 2019-12-02 Fixed the updateArcLength function. It used the wrong pointAt function (was renamed before).\n * @modified 2020-02-06 Added the getSubCurveAt(number,number) function.\n * @modified 2020-02-06 Fixed a serious bug in the arc lenght calculation (length was never reset, urgh).\n * @modified 2020-02-07 Added the isInstance(any) function.\n * @modified 2020-02-10 Added the reverse() function.\n * @modified 2020-02-10 Fixed the translate(...) function (returning 'this' was missing).\n * @modified 2020-03-24 Ported this class from vanilla JS to Typescript.\n * @modified 2020-06-03 Added the getBounds() function.\n * @modified 2020-07-14 Changed the moveCurvePoint(...,Vertex) to moveCurvePoint(...,XYCoords), which is more generic.\n * @modified 2020-07-24 Added the getClosestT function and the helper function locateIntervalByDistance(...).\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `toSVGPathData` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-10-17 The `CubicBezierCurve` class now implements the new `PathSegment` interface.\n * @modified 2023-09-30 Added the function `CubicbezierCurve.getSubCurve(number,number)` – similar to `getSubCurveAt(...)` but with absolute position parameters.\n * @modified 2023-10-07 Added the `trimEnd`, `trimEndAt`, `trimStart`, `trimStartAt` methods.\n * @modified 2025-04-09 Added the `CubicBezierCurve.move` method to match the convention – which just calls `translate`.\n * @modified 2025-04-09 Modified the `CubicBezierCurve.translate` method: chaning parameter `Vertex` to more generalized `XYCoords`.\n * @modified 2025-04-13 Changed visibility of `CubicBezierCurve.utils` from 'private' to 'public'.\n * @modified 2025-04-13 Added helper function `CubicBezierCurve.utils.bezierCoeffs`.\n * @modified 2025-04-13 Added helper functopn `CubicBezierCurve.utils.sgn(number)` for division safe sign calculation.\n * @modified 2025-03-13 Class `CubicBezierCurve` is now implementing interface `Intersectable`.\n * @modified 2025-04-18 Added evaluation method for cubic Bézier curves `CubicBezierCurve.utils.evaluateT`.\n * @modified 2025-04-18 Refactored method `CubicBezierCurve.getPointAt` to use `evaluateT`.\n * @modified 2025-04-18 Fixed the `CubicBezierCurve.getBounds` method: now returning the real bounding box. Before it was an approximated one.\n * @modified 2025-ß4-18 Added helper methods for bounding box calculation `CubucBezierCurve.util.cubicPolyMinMax` and `cubicPoly`.\n * @version 2.9.0\n *\n * @file CubicBezierCurve\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\nimport { Vector } from \"./Vector\";\n/**\n * @classdesc A refactored cubic bezier curve class.\n *\n * @requires Bounds\n * @requires Vertex\n * @requires Vector\n * @requires XYCoords\n * @requires UID\n * @requires UIDGenerator\n */\nexport class CubicBezierCurve {\n /**\n * The constructor.\n *\n * @constructor\n * @name CubicBezierCurve\n * @param {Vertex} startPoint - The Bézier curve's start point.\n * @param {Vertex} endPoint - The Bézier curve's end point.\n * @param {Vertex} startControlPoint - The Bézier curve's start control point.\n * @param {Vertex} endControlPoint - The Bézier curve's end control point.\n **/\n constructor(startPoint, endPoint, startControlPoint, endControlPoint) {\n /** @constant {number} */\n this.START_POINT = CubicBezierCurve.START_POINT;\n /** @constant {number} */\n this.START_CONTROL_POINT = CubicBezierCurve.START_CONTROL_POINT;\n /** @constant {number} */\n this.END_CONTROL_POINT = CubicBezierCurve.END_CONTROL_POINT;\n /** @constant {number} */\n this.END_POINT = CubicBezierCurve.END_POINT;\n this.uid = UIDGenerator.next();\n this.startPoint = startPoint;\n this.startControlPoint = startControlPoint;\n this.endPoint = endPoint;\n this.endControlPoint = endControlPoint;\n this.curveIntervals = 30;\n // An array of vertices\n this.segmentCache = [];\n // An array of floats\n this.segmentLengths = [];\n // float\n // this.arcLength = null;\n this.updateArcLengths();\n }\n /**\n * Move the given curve point (the start point, end point or one of the two\n * control points).\n *\n * @method moveCurvePoint\n * @param {number} pointID - The numeric identicator of the point to move. Use one of the four eBezierPoint constants.\n * @param {XYCoords} moveAmount - The amount to move the specified point by.\n * @param {boolean} moveControlPoint - Move the control points along with their path point (if specified point is a path point).\n * @param {boolean} updateArcLengths - Specifiy if the internal arc segment buffer should be updated.\n * @instance\n * @memberof CubicBezierCurve\n * @return {void}\n **/\n moveCurvePoint(pointID, moveAmount, moveControlPoint, updateArcLengths) {\n if (pointID == this.START_POINT) {\n this.getStartPoint().add(moveAmount);\n if (moveControlPoint)\n this.getStartControlPoint().add(moveAmount);\n }\n else if (pointID == this.START_CONTROL_POINT) {\n this.getStartControlPoint().add(moveAmount);\n }\n else if (pointID == this.END_CONTROL_POINT) {\n this.getEndControlPoint().add(moveAmount);\n }\n else if (pointID == this.END_POINT) {\n this.getEndPoint().add(moveAmount);\n if (moveControlPoint)\n this.getEndControlPoint().add(moveAmount);\n }\n else {\n console.log(`[CubicBezierCurve.moveCurvePoint] pointID '${pointID}' invalid.`);\n }\n if (updateArcLengths)\n this.updateArcLengths();\n }\n /**\n * Translate the whole curve by the given {x,y} amount: moves all four points.\n *\n * @method translate\n * @param {XYCoords} amount - The amount to translate this curve by.\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} this (for chaining).\n **/\n translate(amount) {\n this.startPoint.add(amount);\n this.startControlPoint.add(amount);\n this.endControlPoint.add(amount);\n this.endPoint.add(amount);\n return this;\n }\n /**\n * Translate the whole curve by the given {x,y} amount: moves all four points.\n *\n * @method translate\n * @param {XYCoords} amount - The amount to translate this curve by.\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} this (for chaining).\n **/\n move(amount) {\n return this.translate(amount);\n }\n /**\n * Reverse this curve, means swapping start- and end-point and swapping\n * start-control- and end-control-point.\n *\n * @method reverse\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} this (for chaining).\n **/\n reverse() {\n let tmp = this.startPoint;\n this.startPoint = this.endPoint;\n this.endPoint = tmp;\n tmp = this.startControlPoint;\n this.startControlPoint = this.endControlPoint;\n this.endControlPoint = tmp;\n return this;\n }\n /**\n * Get the total curve length.<br>\n * <br>\n * As not all Bézier curved have a closed formula to calculate their lengths, this\n * implementation uses a segment buffer (with a length of 30 segments). So the\n * returned length is taken from the arc segment buffer.<br>\n * <br>\n * Note that if the curve points were changed and the segment buffer was not\n * updated this function might return wrong (old) values.\n *\n * @method getLength\n * @instance\n * @memberof CubicBezierCurve\n * @return {number} >= 0\n **/\n getLength() {\n return this.arcLength;\n }\n /**\n * Uptate the internal arc segment buffer and their lengths.<br>\n * <br>\n * All class functions update the buffer automatically; if any\n * curve point is changed by other reasons you should call this\n * function to keep actual values in the buffer.\n *\n * @method updateArcLengths\n * @instance\n * @memberof CubicBezierCurve\n * @return {void}\n **/\n updateArcLengths() {\n let pointA = this.startPoint.clone();\n let pointB = new Vertex(0, 0);\n let curveStep = 1.0 / this.curveIntervals;\n // Clear segment cache\n this.segmentCache = [];\n // Push start point into buffer\n this.segmentCache.push(this.startPoint);\n this.segmentLengths = [];\n let newLength = 0.0;\n var t = 0.0;\n let tmpLength;\n while (t <= 1.0) {\n pointB = this.getPointAt(t);\n // Store point into cache\n this.segmentCache.push(pointB);\n // Calculate segment length\n tmpLength = pointA.distance(pointB);\n this.segmentLengths.push(tmpLength);\n newLength += tmpLength;\n pointA = pointB;\n t += curveStep;\n }\n this.arcLength = newLength;\n }\n /**\n * Get a 't' (relative position on curve) with the closest distance to point 'p'.\n *\n * The returned number is 0.0 <= t <= 1.0. Use the getPointAt(t) function to retrieve the actual curve point.\n *\n * This function uses a recursive approach by cutting the curve into several linear segments.\n *\n * @method getClosestT\n * @instance\n * @memberof CubicBezierCurve\n * @param {Vertex} p - The point to find the closest position ('t' on the curve).\n * @return {number}\n **/\n getClosestT(p) {\n // We would like to have an error that's not larger than 1.0.\n var desiredEpsilon = 1.0;\n var result = { t: 0, tPrev: 0.0, tNext: 1.0 };\n var iteration = 0;\n do {\n result = this.locateIntervalByDistance(p, result.tPrev, result.tNext, this.curveIntervals);\n iteration++;\n // Be sure: stop after 4 iterations\n } while (iteration < 4 && this.getPointAt(result.tPrev).distance(this.getPointAt(result.tNext)) > desiredEpsilon);\n return result.t;\n }\n /**\n * This helper function locates the 't' on a fixed step interval with the minimal distance\n * between the curve (at 't') and the given point.\n *\n * Furthermore you must specify a sub curve (start 't' and end 't') you want to search on.\n * Using tStart=0.0 and tEnd=1.0 will search on the full curve.\n *\n * @param {Vertex} p - The point to find the closest curve point for.\n * @param {number} tStart - The start position (start 't' of the sub curve). Should be >= 0.0.\n * @param {number} tEnd - The end position (end 't' of the sub curve). Should be <= 1.0.\n * @param {number} stepCount - The number of steps to check within the interval.\n *\n * @return {object} - An object with t, tPrev and tNext (numbers).\n **/\n locateIntervalByDistance(p, tStart, tEnd, stepCount) {\n var minIndex = -1;\n var minDist = 0;\n var t = 0.0;\n const tDiff = tEnd - tStart;\n for (var i = 0; i <= stepCount; i++) {\n t = tStart + tDiff * (i / stepCount);\n var vert = this.getPointAt(t);\n var dist = vert.distance(p);\n if (minIndex == -1 || dist < minDist) {\n minIndex = i;\n minDist = dist;\n }\n }\n return {\n t: tStart + tDiff * (minIndex / stepCount),\n tPrev: tStart + tDiff * (Math.max(0, minIndex - 1) / stepCount),\n tNext: tStart + tDiff * (Math.min(stepCount, minIndex + 1) / stepCount)\n };\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this bezier curve.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getClosestT\n * @instance\n * @memberof CubicBezierCurve\n * @return {Bounds} The bounds of this ellipse.\n **/\n getBounds() {\n // Thanks to Richard \"RM\" for the Bézier bounds calculatin\n // https://jsfiddle.net/SalixAlba/QQnvm/4/\n const xMinMax = CubicBezierCurve.utils.cubicPolyMinMax(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x);\n const xl = xMinMax.min;\n const xh = xMinMax.max;\n const yMinMax = CubicBezierCurve.utils.cubicPolyMinMax(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y);\n const yl = yMinMax.min;\n const yh = yMinMax.max;\n return Bounds.computeFromVertices([\n { x: xl, y: yl },\n { x: xl, y: yh },\n { x: xh, y: yh },\n { x: xh, y: yl }\n ]);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Get the start point of the curve.<br>\n * <br>\n * This function just returns this.startPoint.\n *\n * @method getStartPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.startPoint\n **/\n getStartPoint() {\n return this.startPoint;\n }\n /**\n * Get the end point of the curve.<br>\n * <br>\n * This function just returns this.endPoint.\n *\n * @method getEndPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.endPoint\n **/\n getEndPoint() {\n return this.endPoint;\n }\n /**\n * Get the start control point of the curve.<br>\n * <br>\n * This function just returns this.startControlPoint.\n *\n * @method getStartControlPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.startControlPoint\n **/\n getStartControlPoint() {\n return this.startControlPoint;\n }\n /**\n * Get the end control point of the curve.<br>\n * <br>\n * This function just returns this.endControlPoint.\n *\n * @method getEndControlPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.endControlPoint\n **/\n getEndControlPoint() {\n return this.endControlPoint;\n }\n /**\n * Get one of the four curve points specified by the passt point ID.\n *\n * @method getEndControlPoint\n * @param {number} id - One of START_POINT, START_CONTROL_POINT, END_CONTROL_POINT or END_POINT.\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPointByID(id) {\n if (id == this.START_POINT)\n return this.startPoint;\n if (id == this.END_POINT)\n return this.endPoint;\n if (id == this.START_CONTROL_POINT)\n return this.startControlPoint;\n if (id == this.END_CONTROL_POINT)\n return this.endControlPoint;\n throw new Error(`Invalid point ID '${id}'.`);\n }\n /**\n * Get the curve point at a given position t, where t is in [0,1].<br>\n * <br>\n * @see Line.pointAt\n *\n * @method getPointAt\n * @param {number} t - The position on the curve in [0,1] (0 means at\n * start point, 1 means at end point, other values address points in bertween).\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPointAt(t) {\n // Perform some powerful math magic\n // TODO: cleanup\n // const x: number =\n // this.startPoint.x * Math.pow(1.0 - t, 3) +\n // this.startControlPoint.x * 3 * t * Math.pow(1.0 - t, 2) +\n // this.endControlPoint.x * 3 * Math.pow(t, 2) * (1.0 - t) +\n // this.endPoint.x * Math.pow(t, 3);\n // const y: number =\n // this.startPoint.y * Math.pow(1.0 - t, 3) +\n // this.startControlPoint.y * 3 * t * Math.pow(1.0 - t, 2) +\n // this.endControlPoint.y * 3 * Math.pow(t, 2) * (1.0 - t) +\n // this.endPoint.y * Math.pow(t, 3);\n const x = CubicBezierCurve.utils.evaluateT(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x, t);\n const y = CubicBezierCurve.utils.evaluateT(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y, t);\n return new Vertex(x, y);\n }\n /**\n * Get the curve point at a given position u, where u is in [0,arcLength].<br>\n * <br>\n * @see CubicBezierCurve.getPointAt\n *\n * @method getPoint\n * @param {number} u - The position on the curve in [0,arcLength] (0 means at\n * start point, arcLength means at end point, other values address points in bertween).\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPoint(u) {\n return this.getPointAt(u / this.arcLength);\n }\n /**\n * Get the curve tangent vector at a given absolute curve position t in [0,1].<br>\n * <br>\n * Note that the returned tangent vector (end point) is not normalized and relative to (0,0).\n *\n * @method getTangent\n * @param {number} t - The position on the curve in [0,1].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getTangentAt(t) {\n const a = this.getStartPoint();\n const b = this.getStartControlPoint();\n const c = this.getEndControlPoint();\n const d = this.getEndPoint();\n // This is the shortened one\n const t2 = t * t;\n // (1 - t)^2 = (1-t)*(1-t) = 1 - t - t + t^2 = 1 - 2*t + t^2\n const nt2 = 1 - 2 * t + t2;\n const tX = -3 * a.x * nt2 + b.x * (3 * nt2 - 6 * (t - t2)) + c.x * (6 * (t - t2) - 3 * t2) + 3 * d.x * t2;\n const tY = -3 * a.y * nt2 + b.y * (3 * nt2 - 6 * (t - t2)) + c.y * (6 * (t - t2) - 3 * t2) + 3 * d.y * t2;\n // Note: my implementation does NOT normalize tangent vectors!\n return new Vertex(tX, tY);\n }\n /**\n * Trim off a start section of this curve. The position parameter `uValue` is the absolute position on the\n * curve in `[0...arcLength]`.\n * The remaining curve will be the one in the bounds `[uValue,1]` (so `[0.0,uValue]` is cut off).\n *\n * Note this function just converts the absolute parameter to a relative one and call `trimStartAt`.\n *\n * @method trimStart\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} uValue - The absolute position parameter where to cut off the head curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimStart(uValue) {\n return this.trimStartAt(this.convertU2T(uValue));\n }\n /**\n * Trim off a start section of this curve. The position parameter `t` is the relative position in [0..1].\n * The remaining curve will be the one in the bounds `[uValue,1]` (so `[0.0,uValue]` is cut off).\n *\n * @method trimStartAt\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} t - The relative position parameter where to cut off the head curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimStartAt(t) {\n const subCurbePoints = CubicBezierCurve.utils.getSubCurvePointsAt(this, t, 1.0);\n this.startPoint.set(subCurbePoints[0]);\n this.startControlPoint.set(subCurbePoints[2]);\n this.endPoint.set(subCurbePoints[1]);\n this.endControlPoint.set(subCurbePoints[3]);\n this.updateArcLengths();\n return this;\n }\n /**\n * Trim off the end of this curve. The position parameter `uValue` is the absolute position on the\n * curve in `[0...arcLength]`.\n * The remaining curve will be the one in the bounds `[0,uValue]` (so `[1.0-uValue,1.0]` is cut off).\n *\n * Note this function just converts the absolute parameter to a relative one and call `trimEndAt`.\n *\n * @method trimEnd\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} uValue - The absolute position parameter where to cut off the tail curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimEnd(uValue) {\n return this.trimEndAt(this.convertU2T(uValue));\n }\n /**\n * Trim off the end of this curve. The position parameter `t` is the relative position in [0..1].\n * The remaining curve will be the one in the bounds `[0,t]` (so `[1.0-t,1.0]` is cut off).\n *\n * @method trimEndAt\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} t - The relative position parameter where to cut off the tail curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimEndAt(t) {\n const subCurbePoints = CubicBezierCurve.utils.getSubCurvePointsAt(this, 0.0, t);\n this.startPoint.set(subCurbePoints[0]);\n this.startControlPoint.set(subCurbePoints[2]);\n this.endPoint.set(subCurbePoints[1]);\n this.endControlPoint.set(subCurbePoints[3]);\n this.updateArcLengths();\n return this;\n }\n /**\n * Get a sub curve at the given start end end positions (values on the curve's length, between 0 and curve.arcLength).\n *\n * tStart >= tEnd is allowed, you will get a reversed sub curve then.\n *\n * @method getSubCurve\n * @param {number} tStart – The start position of the desired sub curve (must be in [0..arcLength]).\n * @param {number} tEnd – The end position if the desired cub curve (must be in [0..arcLength]).\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} The sub curve as a new curve.\n **/\n getSubCurve(uStart, uEnd) {\n return this.getSubCurveAt(this.convertU2T(uStart), this.convertU2T(uEnd));\n }\n /**\n * Get a sub curve at the given start end end offsets (values between 0.0 and 1.0).\n *\n * tStart >= tEnd is allowed, you will get a reversed sub curve then.\n *\n * @method getSubCurveAt\n * @param {number} tStart – The start offset of the desired sub curve (must be in [0..1]).\n * @param {number} tEnd – The end offset if the desired cub curve (must be in [0..1]).\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} The sub curve as a new curve.\n **/\n getSubCurveAt(tStart, tEnd) {\n // This 'splits' the curve at the given point at t.\n const subCurbePoints = CubicBezierCurve.utils.getSubCurvePointsAt(this, tStart, tEnd);\n return new CubicBezierCurve(subCurbePoints[0], subCurbePoints[1], subCurbePoints[2], subCurbePoints[3]);\n }\n /**\n * Convert a relative curve position u to the absolute curve position t.\n *\n * @method convertU2t\n * @param {number} u - The relative position on the curve in [0,arcLength].\n * @instance\n * @memberof CubicBezierCurve\n * @return {number}\n **/\n convertU2T(u) {\n return Math.max(0.0, Math.min(1.0, u / this.arcLength));\n }\n /**\n * Get the curve tangent vector at a given relative position u in [0,arcLength].<br>\n * <br>\n * Note that the returned tangent vector (end point) is not normalized.\n *\n * @method getTangent\n * @param {number} u - The position on the curve in [0,arcLength].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getTangent(u) {\n return this.getTangentAt(this.convertU2T(u));\n }\n /**\n * Get the curve perpendicular at a given relative position u in [0,arcLength] as a vector.<br>\n * <br>\n * Note that the returned vector (end point) is not normalized.\n *\n * @method getPerpendicular\n * @param {number} u - The relative position on the curve in [0,arcLength].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPerpendicular(u) {\n return this.getPerpendicularAt(this.convertU2T(u));\n }\n /**\n * Get the curve perpendicular at a given absolute position t in [0,1] as a vector.<br>\n * <br>\n * Note that the returned vector (end point) is not normalized.\n *\n * @method getPerpendicularAt\n * @param {number} u - The absolute position on the curve in [0,1].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPerpendicularAt(t) {\n const tangentVector = this.getTangentAt(t);\n return new Vertex(tangentVector.y, -tangentVector.x);\n }\n /**\n * Clone this Bézier curve (deep clone).\n *\n * @method clone\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve}\n **/\n clone() {\n return new CubicBezierCurve(this.getStartPoint().clone(), this.getEndPoint().clone(), this.getStartControlPoint().clone(), this.getEndControlPoint().clone());\n }\n //---BEGIN PathSegment-------------------------\n /**\n * Get the tangent's end point at the start point of this segment.\n *\n * @method getStartTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the starting point's tangent.\n */\n getStartTangent() {\n return this.startControlPoint;\n }\n /**\n * Get the tangent's end point at the end point of this segment.\n *\n * @method getEndTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the ending point's tangent.\n */\n getEndTangent() {\n return this.endControlPoint;\n }\n //---END PathSegment-------------------------\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this shape.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections with the shape outline.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n const intersectionTs = this.lineIntersectionTs(line);\n const intersectionPoints = intersectionTs.map((t) => {\n return this.getPointAt(t);\n });\n if (inVectorBoundsOnly) {\n // const maxDist = line.length();\n return intersectionPoints.filter((vert) => line.hasPoint(vert, true));\n }\n else {\n return intersectionPoints;\n }\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n const intersectionTs = this.lineIntersectionTs(line);\n const intersectionTangents = intersectionTs.map((t) => {\n const startPoint = this.getPointAt(t);\n const endPoint = this.getTangentAt(t);\n return new Vector(startPoint, endPoint.add(startPoint));\n });\n if (inVectorBoundsOnly) {\n return intersectionTangents.filter((vec) => line.hasPoint(vec.a, true));\n }\n else {\n return intersectionTangents;\n }\n }\n //--- END --- Implement interface `Intersectable`\n lineIntersectionTs(line) {\n var A = line.b.y - line.a.y; // A=y2-y1\n var B = line.a.x - line.b.x; // B=x1-x2\n 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)\n // var bx = bezierCoeffs(px[0], px[1], px[2], px[3]);\n // var by = bezierCoeffs(py[0], py[1], py[2], py[3]);\n var bx = CubicBezierCurve.utils.bezierCoeffs(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x);\n var by = CubicBezierCurve.utils.bezierCoeffs(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y);\n const poly = Array(4);\n poly[0] = A * bx[0] + B * by[0]; /*t^3*/\n poly[1] = A * bx[1] + B * by[1]; /*t^2*/\n poly[2] = A * bx[2] + B * by[2]; /*t*/\n poly[3] = A * bx[3] + B * by[3] + C; /*1*/\n var roots = CubicBezierCurve.utils.cubicRoots(poly);\n return roots.filter((root) => root != -1);\n }\n /**\n * Check if this and the specified curve are equal.<br>\n * <br>\n * All four points need to be equal for this, the Vertex.equals function is used.<br>\n * <br>\n * Please note that this function is not type safe (comparison with any object will fail).\n *\n * @method clone\n * @param {CubicBezierCurve} curve - The curve to compare with.\n * @instance\n * @memberof CubicBezierCurve\n * @return {boolean}\n **/\n equals(curve) {\n // Note: in the earlier vanilla-JS version this was callable with plain objects.\n // Let's see if this restricted version works out.\n if (!curve)\n return false;\n if (!curve.startPoint || !curve.endPoint || !curve.startControlPoint || !curve.endControlPoint)\n return false;\n return (this.startPoint.equals(curve.startPoint) &&\n this.endPoint.equals(curve.endPoint) &&\n this.startControlPoint.equals(curve.startControlPoint) &&\n this.endControlPoint.equals(curve.endControlPoint));\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.startPoint.destroy();\n this.endPoint.destroy();\n this.startControlPoint.destroy();\n this.endControlPoint.destroy();\n this.isDestroyed = true;\n }\n /**\n * Quick check for class instance.\n * Is there a better way?\n *\n * @method isInstance\n * @param {any} obj - Check if the passed object/value is an instance of CubicBezierCurve.\n * @instance\n * @memberof CubicBezierCurve\n * @return {boolean}\n **/\n static isInstance(obj) {\n // Note: check this again\n /* OLD VANILLA JS IMPLEMENTATION */\n /* if( typeof obj != \"object\" )\n return false;\n function hasXY(v) {\n return typeof v != \"undefined\" && typeof v.x == \"number\" && typeof v.y == \"number\";\n }\n return typeof obj.startPoint == \"object\" && hasXY(obj.startPoint)\n && typeof obj.endPoint == \"object\" && hasXY(obj.endPoint)\n && typeof obj.startControlPoint == \"object\" && hasXY(obj.startControlPoint)\n && typeof obj.endControlPoint == \"object\" && hasXY(obj.endControlPoint);\n */\n return obj instanceof CubicBezierCurve;\n }\n /**\n * Convert this curve to a JSON string.\n *\n * @method toJSON\n * @param {boolean=} [prettyFormat=false] - If set to true the function will add line breaks.\n * @instance\n * @memberof CubicBezierCurve\n * @return {string} The JSON data.\n **/\n toJSON(prettyFormat) {\n var jsonString = \"{ \" + // begin object\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"startPoint\" : [' +\n this.getStartPoint().x +\n \",\" +\n this.getStartPoint().y +\n \"], \" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"endPoint\" : [' +\n this.getEndPoint().x +\n \",\" +\n this.getEndPoint().y +\n \"], \" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"startControlPoint\": [' +\n this.getStartControlPoint().x +\n \",\" +\n this.getStartControlPoint().y +\n \"], \" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"endControlPoint\" : [' +\n this.getEndControlPoint().x +\n \",\" +\n this.getEndControlPoint().y +\n \"]\" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n \" }\"; // end object\n return jsonString;\n }\n /**\n * Parse a Bézier curve from the given JSON string.\n *\n * @method fromJSON\n * @param {string} jsonString - The JSON data to parse.\n * @memberof CubicBezierCurve\n * @static\n * @throws An exception if the JSON string is malformed.\n * @return {CubicBezierCurve}\n **/\n static fromJSON(jsonString) {\n var obj = JSON.parse(jsonString);\n return CubicBezierCurve.fromObject(obj);\n }\n /**\n * Try to convert the passed object to a CubicBezierCurve.\n *\n * @method fromObject\n * @param {object} obj - The object to convert.\n * @memberof CubicBezierCurve\n * @static\n * @throws An exception if the passed object is malformed.\n * @return {CubicBezierCurve}\n **/\n static fromObject(obj) {\n if (typeof obj !== \"object\")\n throw \"Can only build from object.\";\n if (!obj.startPoint)\n throw 'Object member \"startPoint\" missing.';\n if (!obj.endPoint)\n throw 'Object member \"endPoint\" missing.';\n if (!obj.startControlPoint)\n throw 'Object member \"startControlPoint\" missing.';\n if (!obj.endControlPoint)\n throw 'Object member \"endControlPoint\" missing.';\n return new CubicBezierCurve(new Vertex(obj.startPoint[0], obj.startPoint[1]), new Vertex(obj.endPoint[0], obj.endPoint[1]), new Vertex(obj.startControlPoint[0], obj.startControlPoint[1]), new Vertex(obj.endControlPoint[0], obj.endControlPoint[1]));\n }\n /**\n * Convert a 4-element array of vertices to a cubic bézier curve.\n *\n * @method fromArray\n * @param {Vertex[]} arr - [ startVertex, endVertex, startControlVertex, endControlVertex ]\n * @memberof CubicBezierCurve\n * @throws An exception if the passed array is malformed.\n * @return {CubicBezierCurve}\n **/\n static fromArray(arr) {\n if (!Array.isArray(arr))\n throw \"Can only build from object.\";\n if (arr.length != 4)\n throw \"Can only build from array with four elements.\";\n return new CubicBezierCurve(arr[0], arr[1], arr[2], arr[3]);\n }\n}\n/** @constant {number} */\nCubicBezierCurve.START_POINT = 0;\n/** @constant {number} */\nCubicBezierCurve.START_CONTROL_POINT = 1;\n/** @constant {number} */\nCubicBezierCurve.END_CONTROL_POINT = 2;\n/** @constant {number} */\nCubicBezierCurve.END_POINT = 3;\n/**\n * Helper utils.\n */\nCubicBezierCurve.utils = {\n evaluateT: (p0, p1, p2, p3, t) => {\n return p0 * Math.pow(1.0 - t, 3) +\n p1 * 3 * t * Math.pow(1.0 - t, 2) +\n p2 * 3 * Math.pow(t, 2) * (1.0 - t) +\n p3 * Math.pow(t, 3);\n },\n cubicPolyMinMax: (p0, p1, p2, p3) => {\n // var polyX = CubicBezierCurve.utils.cubicPoly2(\n // p0, // P[0].X, // bezierCurve.startPoint.x,\n // p1, // P[1].X, // bezierCurve.startControlPoint.x,\n // p2, // P[2].X, // bezierCurve.endControlPoint.x,\n // p3 // P[3].X // bezierCurve.endPoint.x\n // );\n // var a = polyX.a;\n // var b = polyX.b;\n // var c = polyX.c;\n // var disc = polyX.b * polyX.b - 4 * polyX.a * polyX.c;\n var polyX = CubicBezierCurve.utils.cubicPoly(p0, // P[0].X, // bezierCurve.startPoint.x,\n p1, // P[1].X, // bezierCurve.startControlPoint.x,\n p2, // P[2].X, // bezierCurve.endControlPoint.x,\n p3 // P[3].X // bezierCurve.endPoint.x\n );\n var a = polyX[0]; // .a;\n var b = polyX[1]; // .b;\n var c = polyX[2]; // .c;\n //alert(\"a \"+a+\" \"+b+\" \"+c);\n // var disc = b * b - 4 * a * c;\n var disc = polyX[1] * polyX[1] - 4 * polyX[0] * polyX[2];\n // var polyX = CubicBezierCurve.utils.bezierCoeffs(p3,p2,p1,p0);\n // var a = polyX[0]; //polyX.a;\n // var b = polyX[1]; // .b;\n // var c = polyX[2]; //.c;\n // var disc = polyX[1] * polyX[1] - 4 * polyX[0] * polyX[2];\n // var xl = Math.min(bCurve.endPoint.x, bCurve.startPoint.x); // P[0].X;\n // var xh = Math.max(bCurve.endPoint.x, bCurve.startPoint.x); // P[0].X;\n var xl = Math.min(p3, p0); // P[0].X;\n var xh = Math.max(p3, p0); // P[0].X;\n // if (P[3].X < xl) xl = P[3].X;\n // if (P[3].X > xh) xh = P[3].X;\n if (disc >= 0) {\n var t1 = (-b + Math.sqrt(disc)) / (2 * a);\n // alert(\"t1 \" + t1);\n if (t1 > 0 && t1 < 1) {\n // var x1 = evalBez(PX, t1);\n // var x1 = bCurve.getPointAt(t1).x;\n var x1 = CubicBezierCurve.utils.evaluateT(p0, p1, p2, p3, t1); // bCurve.getPointAt(t1).x;\n if (x1 < xl)\n xl = x1;\n if (x1 > xh)\n xh = x1;\n }\n var t2 = (-b - Math.sqrt(disc)) / (2 * a);\n // alert(\"t2 \" + t2);\n if (t2 > 0 && t2 < 1) {\n // var x2 = evalBez(PX, t2);\n // var x2 = bCurve.getPointAt(t2).x;\n var x2 = CubicBezierCurve.utils.evaluateT(p0, p1, p2, p3, t2); //\n if (x2 < xl)\n xl = x2;\n if (x2 > xh)\n xh = x2;\n }\n }\n return { min: xl, max: xh };\n },\n /**\n * Get the points of a sub curve at the given start end end offsets (values between 0.0 and 1.0).\n *\n * tStart >= tEnd is allowed, you will get a reversed sub curve then.\n *\n * @method getSubCurvePointsAt\n * @param {CubicBezierCurve} curve – The curve to get the sub curve points from.\n * @param {number} tStart – The start offset of the desired sub curve (must be in [0..1]).\n * @param {number} tEnd – The end offset if the desired cub curve (must be in [0..1]).\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} The sub curve as a new curve.\n **/\n getSubCurvePointsAt: (curve, tStart, tEnd) => {\n const startVec = new Vector(curve.getPointAt(tStart), curve.getTangentAt(tStart));\n const endVec = new Vector(curve.getPointAt(tEnd), curve.getTangentAt(tEnd).inv());\n // Tangents are relative. Make absolute.\n startVec.b.add(startVec.a);\n endVec.b.add(endVec.a);\n // This 'splits' the curve at the given point at t.\n startVec.scale(0.33333333 * (tEnd - tStart));\n endVec.scale(0.33333333 * (tEnd - tStart));\n return [startVec.a, endVec.a, startVec.b, endVec.b];\n },\n /**\n * Compute the cubic roots for the given cubic polynomial coefficients.\n *\n * Based on\n * http://mysite.verizon.net/res148h4j/javascript/script_exact_cubic.html#the%20source%20code\n * Inspired by\n * https://www.particleincell.com/2013/cubic-line-intersection/\n * Thanks to Stephan Schmitt and Particle-In-Cell!\n *\n * @param poly\n * @returns\n */\n cubicRoots: (poly) => {\n const a = poly[0];\n const b = poly[1];\n const c = poly[2];\n const d = poly[3];\n const A = b / a;\n const B = c / a;\n const C = d / a;\n var S, T, Im;\n const Q = (3 * B - Math.pow(A, 2)) / 9;\n const R = (9 * A * B - 27 * C - 2 * Math.pow(A, 3)) / 54;\n const D = Math.pow(Q, 3) + Math.pow(R, 2); // polynomial discriminant\n const ts = []; // Array();\n if (D >= 0) {\n // complex or duplicate roots\n S = CubicBezierCurve.utils.sgn(R + Math.sqrt(D)) * Math.pow(Math.abs(R + Math.sqrt(D)), 1 / 3);\n T = CubicBezierCurve.utils.sgn(R - Math.sqrt(D)) * Math.pow(Math.abs(R - Math.sqrt(D)), 1 / 3);\n ts[0] = -A / 3 + (S + T); // real root\n ts[1] = -A / 3 - (S + T) / 2; // real part of complex root\n ts[2] = -A / 3 - (S + T) / 2; // real part of complex root\n Im = Math.abs((Math.sqrt(3) * (S - T)) / 2); // complex part of root pair\n // Mark complex roots to be discarded\n if (Im != 0) {\n ts[1] = -1;\n ts[2] = -1;\n }\n } // distinct real roots\n else {\n const th = Math.acos(R / Math.sqrt(-Math.pow(Q, 3)));\n ts[0] = 2 * Math.sqrt(-Q) * Math.cos(th / 3) - A / 3;\n ts[1] = 2 * Math.sqrt(-Q) * Math.cos((th + 2 * Math.PI) / 3) - A / 3;\n ts[2] = 2 * Math.sqrt(-Q) * Math.cos((th + 4 * Math.PI) / 3) - A / 3;\n Im = 0.0;\n }\n // Discard all t's out of spec and sort the rest\n return ts.filter((t) => t >= 0 && t <= 1.0).sort();\n },\n /**\n * Compute the Bézier coefficients from the given Bézier point coordinates.\n *\n * @param {number} p0 - The start point coordinate.\n * @param {number} p1 - The start control point coordinate.\n * @param {number} p2 - The end control point coordinate.\n * @param {number} p3 - The end point coordinate.\n * @returns {[number,number,number,number]}\n */\n bezierCoeffs: (p0, p1, p2, p3) => {\n const coeffs = [NaN, NaN, NaN, NaN]; //Array(4);\n coeffs[0] = -p0 + 3 * p1 + -3 * p2 + p3;\n coeffs[1] = 3 * p0 - 6 * p1 + 3 * p2;\n coeffs[2] = -3 * p0 + 3 * p1;\n coeffs[3] = p0;\n return coeffs;\n },\n /**\n * Calculate the cubic polynomial coefficients used to find the bounding box.\n *\n * @param {number} p0 - The start point coordinate.\n * @param {number} p1 - The start control point coordinate.\n * @param {number} p2 - The end control point coordinate.\n * @param {number} p3 - The end point coordinate.\n * @returns {[number,number,number]}\n */\n cubicPoly: (p0, p1, p2, p3) => {\n return [\n 3 * p3 - 9 * p2 + 9 * p1 - 3 * p0,\n 6 * p0 - 12 * p1 + 6 * p2,\n 3 * p1 - 3 * p0\n ];\n },\n /**\n * sign of number, but is division safe: no zero returned :)\n */\n sgn(x) {\n return x < 0.0 ? -1 : 1;\n }\n};\n//# sourceMappingURL=CubicBezierCurve.js.map","/**\n * @author Ikaros Kappler\n * @date 2013-08-19\n * @modified 2018-08-16 Added closure. Removed the 'IKRS' wrapper.\n * @modified 2018-11-20 Added circular auto-adjustment.\n * @modified 2018-11-25 Added the point constants to the BezierPath class itself.\n * @modified 2018-11-28 Added the locateCurveByStartPoint() function.\n * @modified 2018-12-04 Added the toSVGString() function.\n * @modified 2019-03-23 Added JSDoc tags.\n * @modified 2019-03-23 Changed the fuctions getPoint and getPointAt to match semantics in the Line class.\n * @modified 2019-11-18 Fixed the clone function: adjustCircular attribute was not cloned.\n * @modified 2019-12-02 Removed some excessive comments.\n * @modified 2019-12-04 Fixed the missing obtainHandleLengths behavior in the adjustNeightbourControlPoint function.\n * @modified 2020-02-06 Added function locateCurveByEndPoint( Vertex ).\n * @modified 2020-02-11 Added 'return this' to the scale(Vertex,number) and to the translate(Vertex) function.\n * @modified 2020-03-24 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-06-03 Made the private helper function _locateUIndex to a private function.\n * @modified 2020-06-03 Added the getBounds() function.\n * @modified 2020-07-14 Changed the moveCurvePoint(...,Vertex) to moveCurvePoint(...,XYCoords).\n * @modified 2020-07-24 Added the getClosestT(Vertex) function.\n * @modified 2020-12-29 Constructor is now private (no explicit use intended).\n * @modified 2021-05-25 Added BezierPath.fromReducedList( Array<number> ).\n * @modified 2022-01-31 Added `BezierPath.getEvenDistributionVertices(number)`.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2023-10-06 Adding the `BezierPath.toPathPoints()` method.\n * @modified 2023-10-07 Adding the `BezierPath.fromCurve(CubicBezierCurve)` static function.\n * @modified 2025-04-09 Added the `BezierPath.move` method to match the convention – which just calls `translate`.\n * @modified 2025-04-09 Modified the `BezierPath.translate` method: chaning parameter `Vertex` to more generalized `XYCoords`.\n * @modified 2025-04-14 Class `BezierPath` is now implementing interface `Intersectable`.\n * @version 2.7.0\n *\n * @file BezierPath\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A BezierPath class.\n *\n * This was refactored from an older project.\n *\n * @requires Bounds\n * @requires Vertex\n * @requires CubicBezierCurve\n * @requires XYCoords\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class BezierPath {\n /**\n * The constructor.<br>\n * <br>\n * This constructor expects a sequence of path points and will approximate\n * the location of control points by picking some between the points.<br>\n * You should consider just constructing empty paths and then add more curves later using\n * the addCurve() function.\n *\n * @constructor\n * @name BezierPath\n * @param {Vertex[]} pathPoints - An array of path vertices (no control points).\n **/\n constructor() {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"BezierPath\";\n /** @constant {number} */\n this.START_POINT = 0;\n /** @constant {number} */\n this.START_CONTROL_POINT = 1;\n /** @constant {number} */\n this.END_CONTROL_POINT = 2;\n /** @constant {number} */\n this.END_POINT = 3;\n // pathPoints: Array<Vertex> | undefined | null) {\n this.uid = UIDGenerator.next();\n // if (!pathPoints) {\n // pathPoints = [];\n // }\n this.totalArcLength = 0.0;\n // Set this flag to true if you want the first point and\n // last point of the path to be auto adjusted, too.\n this.adjustCircular = false;\n this.bezierCurves = [];\n }\n /**\n * Add a cubic bezier curve to the end of this path.\n *\n * @method addCurve\n * @param {CubicBezierCurve} curve - The curve to be added to the end of the path.\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n addCurve(curve) {\n if (curve == null || typeof curve == \"undefined\")\n throw \"Cannot add null curve to bézier path.\";\n this.bezierCurves.push(curve);\n if (this.bezierCurves.length > 1) {\n curve.startPoint = this.bezierCurves[this.bezierCurves.length - 2].endPoint;\n this.adjustSuccessorControlPoint(this.bezierCurves.length - 2, // curveIndex,\n true, // obtainHandleLength,\n true // updateArcLengths\n );\n }\n else {\n this.totalArcLength += curve.getLength();\n }\n }\n /**\n * Locate the curve with the given start point (function returns the index).\n *\n * @method locateCurveByStartPoint\n * @param {Vertex} point - The (curve start-) point to look for.\n * @instance\n * @memberof BezierPath\n * @return {number} The curve index or -1 if curve (start-) point not found\n **/\n locateCurveByStartPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].startPoint.equals(point))\n return i;\n }\n return -1;\n }\n /**\n * Locate the curve with the given end point (function returns the index).\n *\n * @method locateCurveByEndPoint\n * @param {Vertex} point - The (curve end-) point to look for.\n * @instance\n * @memberof BezierPath\n * @return {number} The curve index or -1 if curve (end-) point not found\n **/\n locateCurveByEndPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].endPoint.equals(point))\n return i;\n }\n return -1;\n }\n /**\n * Locate the curve with the given start point (function returns the index).\n *\n * @method locateCurveByStartControlPoint\n * @param {Vertex} point - The (curve endt-) point to look for.\n * @instance\n * @memberof BezierPath\n * @return {number} The curve index or -1 if curve (end-) point not found\n **/\n locateCurveByStartControlPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].startControlPoint.equals(point))\n return i;\n }\n return -1;\n }\n // +---------------------------------------------------------------------------------\n // | Locate the curve with the given end control point.\n // |\n // | @param point:Vertex The point to look for.\n // | @return Number The index or -1 if not found.\n // +-------------------------------\n locateCurveByEndControlPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].endControlPoint.equals(point))\n return i;\n }\n return -1;\n }\n /**\n * Get the total length of this path.<br>\n * <br>\n * Note that the returned value comes from the curve buffer. Unregistered changes\n * to the curve points will result in invalid path length values.\n *\n * @method getLength\n * @instance\n * @memberof BezierPath\n * @return {number} The (buffered) length of the path.\n **/\n getLength() {\n return this.totalArcLength;\n }\n /**\n * This function is internally called whenever the curve or path configuration\n * changed. It updates the attribute that stores the path length information.<br>\n * <br>\n * If you perform any unregistered changes to the curve points you should call\n * this function afterwards to update the curve buffer. Not updating may\n * result in unexpected behavior.\n *\n * @method updateArcLengths\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n updateArcLengths() {\n this.totalArcLength = 0.0;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n this.bezierCurves[i].updateArcLengths();\n this.totalArcLength += this.bezierCurves[i].getLength();\n }\n }\n /**\n * Get the number of curves in this path.\n *\n * @method getCurveCount\n * @instance\n * @memberof BezierPath\n * @return {number} The number of curves in this path.\n **/\n getCurveCount() {\n return this.bezierCurves.length;\n }\n /**\n * Get the cubic bezier curve at the given index.\n *\n * @method getCurveAt\n * @param {number} index - The curve index from 0 to getCurveCount()-1.\n * @instance\n * @memberof BezierPath\n * @return {CubicBezierCurve} The curve at the specified index.\n **/\n getCurveAt(curveIndex) {\n return this.bezierCurves[curveIndex];\n }\n /**\n * Move the whole bezier path by the given (x,y)-amount.\n *\n * @method translate\n * @param {XYCoords} amount - The amount to be added (amount.x and amount.y)\n * to each vertex of the curve.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining\n **/\n translate(amount) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n curve.getStartPoint().add(amount);\n curve.getStartControlPoint().add(amount);\n curve.getEndControlPoint().add(amount);\n }\n // Don't forget to translate the last curve's last point\n var curve = this.bezierCurves[this.bezierCurves.length - 1];\n curve.getEndPoint().add(amount);\n this.updateArcLengths();\n return this;\n }\n /**\n * Move the whole bezier path by the given (x,y)-amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to be added (amount.x and amount.y)\n * to each vertex of the curve.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining\n **/\n move(amount) {\n return this.translate(amount);\n }\n /**\n * Scale the whole bezier path by the given uniform factor.\n *\n * @method scale\n * @param {Vertex} anchor - The scale origin to scale from.\n * @param {number} scaleFactor - The scalar to be multiplied with.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining.\n **/\n scale(anchor, scaleFactor) {\n return this.scaleXY({ x: scaleFactor, y: scaleFactor }, anchor);\n }\n /**\n * Scale the whole bezier path by the given (x,y)-factors.\n *\n * @method scale\n * @param {Vertex} anchor - The scale origin to scale from.\n * @param {number} amount - The scalar to be multiplied with.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining.\n **/\n scaleXY(scaleFactors, anchor) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n curve.getStartPoint().scaleXY(scaleFactors, anchor);\n curve.getStartControlPoint().scaleXY(scaleFactors, anchor);\n curve.getEndControlPoint().scaleXY(scaleFactors, anchor);\n // Do NOT scale the end point here!\n // Don't forget that the curves are connected and on curve's end point\n // the the successor's start point (same instance)!\n }\n // Finally move the last end point (was not scaled yet)\n if (this.bezierCurves.length > 0 && !this.adjustCircular) {\n this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().scaleXY(scaleFactors, anchor);\n }\n this.updateArcLengths();\n return this;\n }\n /**\n * Rotate the whole bezier path around a point..\n *\n * @method rotate\n * @param {Vertex} angle - The angle to rotate this path by.\n * @param {Vertex} center - The rotation center.\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n rotate(angle, center) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n curve.getStartPoint().rotate(angle, center);\n curve.getStartControlPoint().rotate(angle, center);\n curve.getEndControlPoint().rotate(angle, center);\n // Do NOT rotate the end point here!\n // Don't forget that the curves are connected and on curve's end point\n // the the successor's start point (same instance)!\n }\n // Finally move the last end point (was not scaled yet)\n if (this.bezierCurves.length > 0 && !this.adjustCircular) {\n this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().rotate(angle, center);\n }\n }\n /**\n * Get the 't' position on this curve with the minimal distance to point p.\n *\n * @param {Vertex} p - The point to find the closest curve point for.\n * @return {number} A value t with 0.0 <= t <= 1.0.\n **/\n getClosestT(p) {\n // Find the spline to extract the value from\n var minIndex = -1;\n var minDist = 0.0;\n var dist = 0.0;\n var curveT = 0.0;\n var uMin = 0.0;\n var u = 0.0;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n curveT = this.bezierCurves[i].getClosestT(p);\n dist = this.bezierCurves[i].getPointAt(curveT).distance(p);\n if (minIndex == -1 || dist < minDist) {\n minIndex = i;\n minDist = dist;\n uMin = u + curveT * this.bezierCurves[i].getLength();\n }\n u += this.bezierCurves[i].getLength();\n }\n return Math.max(0.0, Math.min(1.0, uMin / this.totalArcLength));\n }\n /**\n * Get the point on the bézier path at the given relative path location.\n *\n * @method getPoint\n * @param {number} u - The relative path position: <pre>0 <= u <= this.getLength()</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The point at the relative path position.\n **/\n getPoint(u) {\n if (u < 0 || u > this.totalArcLength) {\n console.warn(\"[BezierPath.getPoint(u)] u is out of bounds: \" + u + \".\");\n u = Math.min(this.totalArcLength, Math.max(u, 0));\n }\n // Find the spline to extract the value from\n var i = 0;\n var uTemp = 0.0;\n while (i < this.bezierCurves.length && uTemp + this.bezierCurves[i].getLength() < u) {\n uTemp += this.bezierCurves[i].getLength();\n i++;\n }\n // if u == arcLength\n // -> i is max\n if (i >= this.bezierCurves.length)\n return this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().clone();\n var bCurve = this.bezierCurves[i];\n var relativeU = u - uTemp;\n return bCurve.getPoint(relativeU);\n }\n /**\n * Get the point on the bézier path at the given path fraction.\n *\n * @method getPointAt\n * @param {number} t - The absolute path position: <pre>0.0 <= t <= 1.0</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The point at the absolute path position.\n **/\n getPointAt(t) {\n return this.getPoint(t * this.totalArcLength);\n }\n /**\n * Get the tangent of the bézier path at the given path fraction.<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getTangentAt\n * @param {number} t - The absolute path position: <pre>0.0 <= t <= 1.0</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The tangent vector at the absolute path position.\n **/\n getTangentAt(t) {\n return this.getTangent(t * this.totalArcLength);\n }\n /**\n * Get the tangent of the bézier path at the given path location.<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getTangent\n * @param {number} u - The relative path position: <pre>0 <= u <= getLength()</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The tangent vector at the relative path position.\n **/\n getTangent(u) {\n if (u < 0 || u > this.totalArcLength) {\n console.warn(\"[BezierPath.getTangent(u)] u is out of bounds: \" + u + \".\");\n // return undefined;\n u = Math.min(this.totalArcLength, Math.max(0, u));\n }\n // Find the spline to extract the value from\n var i = 0;\n var uTemp = 0.0;\n while (i < this.bezierCurves.length && uTemp + this.bezierCurves[i].getLength() < u) {\n uTemp += this.bezierCurves[i].getLength();\n i++;\n }\n var bCurve = this.bezierCurves[i];\n var relativeU = u - uTemp;\n return bCurve.getTangent(relativeU);\n }\n /**\n * Get the perpendicular of the bézier path at the given absolute path location (fraction).<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getPerpendicularAt\n * @param {number} t - The absolute path position: <pre>0.0 <= t <= 1.0</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The perpendicluar vector at the absolute path position.\n **/\n getPerpendicularAt(t) {\n return this.getPerpendicular(t * this.totalArcLength);\n }\n /**\n * Get the perpendicular of the bézier path at the given relative path location.<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getPerpendicular\n * @param {number} u - The relative path position: <pre>0 <= u <= getLength()</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The perpendicluar vector at the relative path position.\n **/\n getPerpendicular(u) {\n if (u < 0 || u > this.totalArcLength) {\n console.log(\"[BezierPath.getPerpendicular(u)] u is out of bounds: \" + u + \".\");\n u = Math.min(this.totalArcLength, Math.max(0, u));\n }\n // Find the spline to extract the value from\n var uResult = BezierPath._locateUIndex(this, u);\n var bCurve = this.bezierCurves[uResult.i];\n var relativeU = u - uResult.uPart;\n return bCurve.getPerpendicular(relativeU);\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this shape.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections with the shape's outline.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n return this.bezierCurves.reduce((accu, curCurve) => {\n return accu.concat(curCurve.lineIntersections(line, inVectorBoundsOnly));\n }, []);\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n return this.bezierCurves.reduce((accu, curCurve) => {\n return accu.concat(curCurve.lineIntersectionTangents(line, inVectorBoundsOnly));\n }, []);\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * This is a helper function to locate the curve index for a given\n * absolute path position u.\n *\n * I decided to put this into privat scope as it is really specific. Maybe\n * put this into a utils wrapper.\n *\n * Returns:\n * - {number} i - the index of the containing curve.\n * - {number} uPart - the absolute curve length sum (length from the beginning to u, should equal u itself).\n * - {number} uBefore - the absolute curve length for all segments _before_ the matched curve (usually uBefore <= uPart).\n **/\n static _locateUIndex(path, u) {\n var i = 0;\n var uTemp = 0.0;\n var uBefore = 0.0;\n while (i < path.bezierCurves.length && uTemp + path.bezierCurves[i].getLength() < u) {\n uTemp += path.bezierCurves[i].getLength();\n if (i + 1 < path.bezierCurves.length)\n uBefore += path.bezierCurves[i].getLength();\n i++;\n }\n return { i: i, uPart: uTemp, uBefore: uBefore };\n }\n /**\n * Get a specific sub path from this path. The start and end position are specified by\n * ratio number in [0..1].\n *\n * 0.0 is at the beginning of the path.\n * 1.0 is at the end of the path.\n *\n * Values below 0 or beyond 1 are cropped down to the [0..1] interval.\n *\n * startT > endT is allowed, the returned sub path will have inverse direction then.\n *\n * @method getSubPathAt\n * @param {number} startT - The start position of the sub path.\n * @param {number} endT - The end position of the sub path.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} The desired sub path in the bounds [startT..endT].\n **/\n getSubPathAt(startT, endT) {\n startT = Math.max(0, startT);\n endT = Math.min(1.0, endT);\n let startU = startT * this.totalArcLength;\n let endU = endT * this.totalArcLength;\n var uStartResult = BezierPath._locateUIndex(this, startU); // { i:int, uPart:float, uBefore:float }\n var uEndResult = BezierPath._locateUIndex(this, endU); // { i:int, uPart:float, uBefore:float }\n var firstT = (startU - uStartResult.uBefore) / this.bezierCurves[uStartResult.i].getLength();\n if (uStartResult.i == uEndResult.i) {\n // Subpath begins and ends in the same path segment (just get a simple sub curve from that path element).\n var lastT = (endU - uEndResult.uBefore) / this.bezierCurves[uEndResult.i].getLength();\n var firstCurve = this.bezierCurves[uStartResult.i].getSubCurveAt(firstT, lastT);\n return BezierPath.fromArray([firstCurve]);\n }\n else {\n var curves = [];\n if (uStartResult.i > uEndResult.i) {\n // Back to front direction\n var firstCurve = this.bezierCurves[uStartResult.i].getSubCurveAt(firstT, 0.0);\n curves.push(firstCurve);\n for (var i = uStartResult.i - 1; i > uEndResult.i; i--) {\n curves.push(this.bezierCurves[i].clone().reverse());\n }\n var lastT = (endU - uEndResult.uBefore) / this.bezierCurves[uEndResult.i].getLength();\n curves.push(this.bezierCurves[uEndResult.i].getSubCurveAt(1.0, lastT));\n }\n else {\n // Front to back direction\n var firstCurve = this.bezierCurves[uStartResult.i].getSubCurveAt(firstT, 1.0);\n curves.push(firstCurve);\n for (var i = uStartResult.i + 1; i < uEndResult.i && i < this.bezierCurves.length; i++) {\n curves.push(this.bezierCurves[i].clone());\n }\n var lastT = (endU - uEndResult.uBefore) / this.bezierCurves[uEndResult.i].getLength();\n curves.push(this.bezierCurves[uEndResult.i].getSubCurveAt(0, lastT));\n }\n return BezierPath.fromArray(curves);\n }\n }\n /**\n * This function moves the addressed curve point (or control point) with\n * keeping up the path's curve integrity.<br>\n * <br>\n * Thus is done by moving neighbour- and control- points as needed.\n *\n * @method moveCurvePoint\n * @param {number} curveIndex - The curve index to move a point from.\n * @param {number} pointID - One of the curve's four point IDs (START_POINT,\n * START_CONTROL_POINT, END_CONTRO_POINT or END_POINT).\n * @param {XYCoords} moveAmount - The amount to move the addressed vertex by.\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n moveCurvePoint(curveIndex, pointID, moveAmount) {\n var bCurve = this.getCurveAt(curveIndex);\n bCurve.moveCurvePoint(pointID, moveAmount, true, // move control point, too\n true // updateArcLengths\n );\n // If inner point and NOT control point\n // --> move neightbour\n if (pointID == this.START_POINT && (curveIndex > 0 || this.adjustCircular)) {\n // Set predecessor's control point!\n var predecessor = this.getCurveAt(curveIndex - 1 < 0 ? this.bezierCurves.length + (curveIndex - 1) : curveIndex - 1);\n predecessor.moveCurvePoint(this.END_CONTROL_POINT, moveAmount, true, // move control point, too\n false // updateArcLengths\n );\n }\n else if (pointID == this.END_POINT && (curveIndex + 1 < this.bezierCurves.length || this.adjustCircular)) {\n // Set successcor\n var successor = this.getCurveAt((curveIndex + 1) % this.bezierCurves.length);\n successor.moveCurvePoint(this.START_CONTROL_POINT, moveAmount, true, // move control point, too\n false // updateArcLengths\n );\n }\n else if (pointID == this.START_CONTROL_POINT && curveIndex > 0) {\n this.adjustPredecessorControlPoint(curveIndex, true, // obtain handle length?\n false // update arc lengths\n );\n }\n else if (pointID == this.END_CONTROL_POINT && curveIndex + 1 < this.getCurveCount()) {\n this.adjustSuccessorControlPoint(curveIndex, true, // obtain handle length?\n false // update arc lengths\n );\n }\n // Don't forget to update the arc lengths!\n // Note: this can be optimized as only two curves have changed their lengths!\n this.updateArcLengths();\n }\n /**\n * This helper function adjusts the given point's predecessor's control point.\n *\n * @method adjustPredecessorControlPoint\n * @param {number} curveIndex - The curve index to move a point from.\n * @param {boolean} obtainHandleLength - Moves the point with keeping the original handle length.\n * @param {boolean} updateArcLength - The amount to move the addressed vertex by.\n * @instance\n * @private\n * @memberof BezierPath\n * @return {void}\n **/\n adjustPredecessorControlPoint(curveIndex, obtainHandleLength, updateArcLengths) {\n if (!this.adjustCircular && curveIndex <= 0)\n return; // false;\n var mainCurve = this.getCurveAt(curveIndex);\n var neighbourCurve = this.getCurveAt(curveIndex - 1 < 0 ? this.getCurveCount() + (curveIndex - 1) : curveIndex - 1);\n BezierPath.adjustNeighbourControlPoint(mainCurve, neighbourCurve, mainCurve.getStartPoint(), // the reference point\n mainCurve.getStartControlPoint(), // the dragged control point\n neighbourCurve.getEndPoint(), // the neighbour's point\n neighbourCurve.getEndControlPoint(), // the neighbour's control point to adjust\n obtainHandleLength, updateArcLengths);\n }\n /**\n * This helper function adjusts the given point's successor's control point.\n *\n * @method adjustSuccessorControlPoint\n * @param {number} curveIndex - The curve index to move a point from.\n * @param {boolean} obtainHandleLength - Moves the point with keeping the original handle length.\n * @param {boolean} updateArcLength - The amount to move the addressed vertex by.\n * @instance\n * @private\n * @memberof BezierPath\n * @return {void}\n **/\n adjustSuccessorControlPoint(curveIndex, obtainHandleLength, updateArcLengths) {\n if (!this.adjustCircular && curveIndex + 1 > this.getCurveCount())\n return; // false;\n var mainCurve = this.getCurveAt(curveIndex);\n var neighbourCurve = this.getCurveAt((curveIndex + 1) % this.getCurveCount());\n /* return */ BezierPath.adjustNeighbourControlPoint(mainCurve, neighbourCurve, mainCurve.getEndPoint(), // the reference point\n mainCurve.getEndControlPoint(), // the dragged control point\n neighbourCurve.getStartPoint(), // the neighbour's point\n neighbourCurve.getStartControlPoint(), // the neighbour's control point to adjust\n obtainHandleLength, updateArcLengths);\n }\n /**\n * This helper function adjusts the given point's successor's control point.\n *\n * @method adjustNeighbourControlPoint\n * @param {CubicBezierCurve} mainCurve\n * @param {CubicBezierCurve} neighbourCurve\n * @param {Vertex} mainPoint\n * @param {Vertex} mainControlPoint\n * @param {Vertex} neighbourPoint\n * @param {Vertex} neighbourControlPoint\n * @param {boolean} obtainHandleLengths\n * @param {boolean} updateArcLengths\n * @instance\n * @private\n * @memberof BezierPath\n * @return {void}\n **/\n static adjustNeighbourControlPoint(_mainCurve, // TODO: remove param\n neighbourCurve, mainPoint, mainControlPoint, neighbourPoint, neighbourControlPoint, obtainHandleLengths, _updateArcLengths // TODO: remove param\n ) {\n // Calculate start handle length\n var mainHandleBounds = new Vertex(mainControlPoint.x - mainPoint.x, mainControlPoint.y - mainPoint.y);\n var neighbourHandleBounds = new Vertex(neighbourControlPoint.x - neighbourPoint.x, neighbourControlPoint.y - neighbourPoint.y);\n var mainHandleLength = Math.sqrt(Math.pow(mainHandleBounds.x, 2) + Math.pow(mainHandleBounds.y, 2));\n var neighbourHandleLength = Math.sqrt(Math.pow(neighbourHandleBounds.x, 2) + Math.pow(neighbourHandleBounds.y, 2));\n if (mainHandleLength <= 0.1)\n return; // no secure length available for division? What about zoom? Use EPSILON?\n // Just invert the main handle (keep length or not?\n if (obtainHandleLengths) {\n neighbourControlPoint.set(neighbourPoint.x - mainHandleBounds.x * (neighbourHandleLength / mainHandleLength), neighbourPoint.y - mainHandleBounds.y * (neighbourHandleLength / mainHandleLength));\n }\n else {\n neighbourControlPoint.set(neighbourPoint.x - mainHandleBounds.x, neighbourPoint.y - mainHandleBounds.y);\n }\n neighbourCurve.updateArcLengths();\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this Bézier path.\n *\n * Note the the curves' underlyung segment buffers are used to determine the bounds. The more\n * elements the segment buffers have, the more precise the returned bounds will be.\n *\n * @return {Bounds} The bounds of this Bézier path.\n **/\n getBounds() {\n const min = new Vertex(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);\n const max = new Vertex(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);\n var b;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n b = this.bezierCurves[i].getBounds();\n min.x = Math.min(min.x, b.min.x);\n min.y = Math.min(min.y, b.min.y);\n max.x = Math.max(max.x, b.max.x);\n max.y = Math.max(max.y, b.max.y);\n }\n return new Bounds(min, max);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Get n 'equally' distributed vertices along this Bézier path.\n *\n * As the changing curvature of the B slines makes prediction of distances difficult, the\n * returned vertices' distances are only relatively equal:\n * - the distance grows where curvature is large.\n * - the distance shrinks where curvature is small.\n *\n * Only the distance mean of all consecutive is 1/n-th of the total arc length.\n *\n * Usually this approximation is good enough for most use cases.\n *\n * @param {number} pointCount - (must be at least 2) The number of desired points (start and end point included).\n * @return {Array<Vertex>}\n */\n getEvenDistributionVertices(pointCount) {\n if (pointCount < 2) {\n throw new Error(\"pointCount must be larger than one; is \" + pointCount + \".\");\n }\n const result = [];\n if (this.bezierCurves.length === 0) {\n return result;\n }\n // Fetch and add the start point from the source polygon\n var polygonPoint = new Vertex(this.bezierCurves[0].startPoint);\n result.push(polygonPoint);\n // if (this.bezierCurves.length === 1) {\n // return result;\n // }\n const perimeter = this.totalArcLength;\n const stepSize = perimeter / (pointCount - 1);\n const n = this.bezierCurves.length;\n let curveIndex = 0;\n let segmentLength = this.bezierCurves[0].arcLength;\n let curSegmentU = stepSize;\n let i = 1;\n while (i < pointCount && curveIndex < n) {\n // Check if next eq point is inside this segment\n if (curSegmentU < segmentLength) {\n var newPoint = this.bezierCurves[curveIndex].getPoint(curSegmentU);\n result.push(newPoint);\n curSegmentU += stepSize;\n i++;\n }\n else {\n curveIndex++;\n curSegmentU = curSegmentU - segmentLength;\n segmentLength = curveIndex < n ? this.bezierCurves[curveIndex].arcLength : 0;\n }\n }\n result.push(new Vertex(this.bezierCurves[n - 1].endPoint));\n return result;\n }\n /**\n * Clone this BezierPath (deep clone).\n *\n * @method clone\n * @instance\n * @memberof BezierPath\n * @return {BezierPath}\n **/\n clone() {\n var path = new BezierPath(); // undefined);\n for (var i = 0; i < this.bezierCurves.length; i++) {\n path.bezierCurves.push(this.bezierCurves[i].clone());\n // Connect splines\n if (i > 0)\n path.bezierCurves[i - 1].endPoint = path.bezierCurves[i].startPoint;\n }\n path.updateArcLengths();\n path.adjustCircular = this.adjustCircular;\n return path;\n }\n /**\n * Compare this and the passed Bézier path.\n *\n * @method equals\n * @param {BezierPath} path - The pass to compare with.\n * @instance\n * @memberof BezierPath\n * @return {boolean}\n **/\n equals(path) {\n if (!path)\n return false;\n // Check if path contains the credentials\n if (!path.bezierCurves)\n return false;\n if (typeof path.bezierCurves.length == \"undefined\")\n return false;\n if (path.bezierCurves.length != this.bezierCurves.length)\n return false;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (!this.bezierCurves[i].equals(path.bezierCurves[i]))\n return false;\n }\n return true;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n *\n * @method destroy\n * @instance\n * @memberof BezierPath\n */\n destroy() {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n this.bezierCurves[i].destroy();\n }\n this.isDestroyed = true;\n }\n /**\n * Convert this path to an array of path points that can be drawn by the default DrawLib\n * implementations.\n *\n * @method toPathPoints\n * @instance\n * @memberof BezierPath\n * @return {Array<XYCoords>}\n */\n toPathPoints() {\n if (this.bezierCurves.length === 0) {\n return [];\n }\n if (this.bezierCurves.length === 1) {\n return [\n this.bezierCurves[0].startPoint,\n this.bezierCurves[0].startControlPoint,\n this.bezierCurves[0].endControlPoint,\n this.bezierCurves[0].endPoint\n ];\n }\n const arr = [];\n arr.push(this.bezierCurves[0].startPoint);\n arr.push(this.bezierCurves[0].startControlPoint);\n for (var i = 1; i < this.bezierCurves.length; i++) {\n arr.push(this.bezierCurves[i - 1].endControlPoint);\n arr.push(this.bezierCurves[i - 1].endPoint);\n arr.push(this.bezierCurves[i].startPoint);\n arr.push(this.bezierCurves[i].startControlPoint);\n }\n arr.push(this.bezierCurves[0].endControlPoint);\n arr.push(this.bezierCurves[0].endPoint);\n return arr;\n }\n /**\n * Create a JSON string representation of this bézier curve.\n *\n * @method toJSON\n * @param {boolean} prettyFormat - If true then the function will add line breaks.\n * @instance\n * @memberof BezierPath\n * @return {string} The JSON string.\n **/\n toJSON(prettyFormat) {\n var buffer = [];\n buffer.push(\"[\"); // array begin\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (i > 0)\n buffer.push(\",\");\n if (prettyFormat)\n buffer.push(\"\\n\\t\");\n else\n buffer.push(\" \");\n buffer.push(this.bezierCurves[i].toJSON(prettyFormat));\n }\n if (this.bezierCurves.length != 0)\n buffer.push(\" \");\n buffer.push(\"]\"); // array end\n return buffer.join(\"\"); // Convert to string, with empty separator.\n }\n /**\n * Parse a BezierPath from the given JSON string.\n *\n * @method fromJSON\n * @param {string} jsonString - The string with the JSON data.\n * @throw An error if the string is not JSON or does not contain a bezier path object.\n * @static\n * @memberof BezierPath\n * @return {BezierPath} The parsed bezier path instance.\n **/\n static fromJSON(jsonString) {\n var obj = JSON.parse(jsonString);\n return BezierPath.fromArray(obj);\n }\n /**\n * Construct a new path with a single curve. Adding more curves is always possible.\n *\n * @method fromCurve\n * @param {CubicBezierCurve} curve - The curve to construct a new path from.\n * @static\n * @memberof BezierPath\n * @return {BezierPath} The constructed bezier path instance.\n */\n static fromCurve(curve) {\n const path = new BezierPath(); // []);\n path.addCurve(curve);\n return path;\n }\n /**\n * Create a BezierPath instance from the given array.\n *\n * @method fromArray\n * @param {Vertex[][]} arr - A two-dimensional array containing the bezier path vertices.\n * @throw An error if the array does not contain proper bezier path data.\n * @static\n * @memberof BezierPath\n * @return {BezierPath} The bezier path instance retrieved from the array data.\n **/\n static fromArray(obj) {\n if (!Array.isArray(obj)) {\n throw \"[BezierPath.fromArray] Passed object must be an array.\";\n }\n const arr = obj; // FORCE?\n if (arr.length < 1) {\n throw \"[BezierPath.fromArray] Passed array must contain at least one bezier curve (has \" + arr.length + \").\";\n }\n // Create an empty bezier path\n var bPath = new BezierPath(); // undefined);\n var lastCurve = null;\n for (var i = 0; i < arr.length; i++) {\n // Convert object (or array?) to bezier curve\n var bCurve;\n if (CubicBezierCurve.isInstance(arr[i])) {\n bCurve = arr[i].clone();\n }\n else if (0 in arr[i] && 1 in arr[i] && 2 in arr[i] && 3 in arr[i]) {\n if (!arr[i][0] || !arr[i][1] || !arr[i][2] || !arr[i][3])\n throw \"Cannot convert path data to BezierPath instance. At least one element is undefined (index=\" + i + \"): \" + arr[i];\n bCurve = CubicBezierCurve.fromArray(arr[i]);\n }\n else {\n bCurve = CubicBezierCurve.fromObject(arr[i]);\n }\n // Set curve start point?\n // (avoid duplicate point instances!)\n if (lastCurve)\n bCurve.startPoint = lastCurve.endPoint;\n // Add to path's internal list\n bPath.bezierCurves.push(bCurve);\n // bPath.totalArcLength += bCurve.getLength();\n lastCurve = bCurve;\n }\n bPath.updateArcLengths();\n // Bezier segments added. Done\n return bPath;\n }\n /**\n * This function converts the bezier path into a string containing\n * integer values only.\n * The points' float values are rounded to 1 digit after the comma.\n *\n * The returned string represents a JSON array (with leading '[' and\n * trailing ']', the separator is ',').\n *\n * @method toReducedListRepresentation\n * @param {number} digits - The number of digits to be used after the comma '.'.\n * @instance\n * @memberof BezierPath\n * @return {string} The reduced list representation of this path.\n **/\n toReducedListRepresentation(digits) {\n if (typeof digits == \"undefined\")\n digits = 1;\n var buffer = [];\n buffer.push(\"[\"); // array begin\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n buffer.push(curve.getStartPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getStartPoint().y.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getStartControlPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getStartControlPoint().y.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getEndControlPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getEndControlPoint().y.toFixed(digits));\n buffer.push(\",\");\n }\n if (this.bezierCurves.length != 0) {\n var curve = this.bezierCurves[this.bezierCurves.length - 1];\n buffer.push(curve.getEndPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getEndPoint().y.toFixed(digits));\n }\n buffer.push(\"]\"); // array end\n return buffer.join(\"\"); // Convert to string, with empty separator.\n }\n /**\n * Parse a BezierPath instance from the reduced list representation.<br>\n * <br>\n * The passed string must represent a JSON array containing numbers only.\n *\n * @method fromReducedListRepresentation\n * @param {string} listJSON - The number of digits to be used after the floating point.\n * @throw An error if the string is malformed.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} The bezier path instance retrieved from the string.\n **/\n static fromReducedListRepresentation(listJSON, adjustCircular) {\n // Parse the array\n var pointArray = JSON.parse(listJSON);\n if (!pointArray.length) {\n console.log(\"Cannot parse bezier path from non-array object nor from empty point list.\");\n throw \"Cannot parse bezier path from non-array object nor from empty point list.\";\n }\n if (pointArray.length < 8) {\n console.log(\"Cannot build bezier path. The passed array must contain at least 8 elements (numbers).\");\n throw \"Cannot build bezier path. The passed array must contain at least 8 elements (numbers).\";\n }\n return BezierPath.fromReducedList(pointArray, adjustCircular);\n }\n /**\n * Convert a reduced list representation (array of numeric coordinates) to a BezierPath instance.\n *\n * The array's length must be 6*n + 2:\n * - [sx, sy, scx, scy, ecx, ecy, ... , ex, ey ]\n * | | | |\n * +--- sequence of curves --------+ +-end-+\n *\n * @param {number[]} pointArray\n * @returns BezierPath\n */\n static fromReducedList(pointArray, adjustCircular) {\n // Convert to object\n var bezierPath = new BezierPath(); // null); // No points yet\n var startPoint = new Vertex();\n var startControlPoint;\n var endControlPoint;\n var endPoint;\n var i = 0;\n do {\n if (i == 0) {\n // firstStartPoint =\n startPoint = new Vertex(pointArray[i], pointArray[i + 1]);\n }\n startControlPoint = new Vertex(pointArray[i + 2], pointArray[i + 3]);\n endControlPoint = new Vertex(pointArray[i + 4], pointArray[i + 5]);\n // if (i + 8 >= pointArray.length) {\n // endPoint = firstStartPoint;\n // } else {\n endPoint = new Vertex(pointArray[i + 6], pointArray[i + 7]);\n // }\n var bCurve = new CubicBezierCurve(startPoint, endPoint, startControlPoint, endControlPoint);\n bezierPath.bezierCurves.push(bCurve);\n startPoint = endPoint;\n i += 6;\n } while (i + 2 < pointArray.length);\n bezierPath.adjustCircular = adjustCircular !== null && adjustCircular !== void 0 ? adjustCircular : false;\n if (adjustCircular) {\n bezierPath.bezierCurves[bezierPath.bezierCurves.length - 1].endPoint = bezierPath.bezierCurves[0].startPoint;\n }\n bezierPath.updateArcLengths();\n return bezierPath;\n }\n}\n// +---------------------------------------------------------------------------------\n// | These constants equal the values from CubicBezierCurve.\n// +-------------------------------\n/** @constant {number} */\nBezierPath.START_POINT = 0;\n/** @constant {number} */\nBezierPath.START_CONTROL_POINT = 1;\n/** @constant {number} */\nBezierPath.END_CONTROL_POINT = 2;\n/** @constant {number} */\nBezierPath.END_POINT = 3;\n//# sourceMappingURL=BezierPath.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-12-17\n * @modified 2021-01-20 Added UID.\n * @modified 2021-02-26 Fixed an error in the svg-arc-calculation (case angle<90deg and anti-clockwise).\n * @modified 2024-01-30 Added a missing type in the `describeSVGArc` function.\n * @modified 2024-03-01 Added the `getStartPoint` and `getEndPoint` methods.\n * @modified 2024-03-08 Added the `containsAngle` method.\n * @modified 2024-03-09 Added the `circleSectorIntersection` method to find coherent sector intersections..\n * @modified 2024-03-09 Added the `angleAt` method to determine any angle at some ratio.\n * @modified 2025-04-02 Adding the `CircleSector.lineIntersections` and `CircleSector.lineIntersectionTangents` and implementing `Intersectable`.\n * @modified 2025-04-09 Adding the `CircleSector.move()` method.\n * @modified 2025-04-19 Tweaking the `CircleSector.containsAngle` method: all values (input angle, start- and end- angle) are wrapped into [0,2*PI) now.\n * @modified 2025-04-19 Class `CircleSector` implements interface `Bounded` now (method `getBounds` added).\n * @version 1.2.0\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Circle } from \"./Circle\";\nimport { Line } from \"./Line\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\nimport { geomutils } from \"./geomutils\";\n/**\n * @classdesc A simple circle sector: circle, start- and end-angle.\n *\n * @requires Line\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n * @requires XYCoords\n **/\nexport class CircleSector {\n /**\n * Create a new circle sector with given circle, start- and end-angle.\n *\n * @constructor\n * @name CircleSector\n * @param {Circle} circle - The circle.\n * @param {number} startAngle - The start angle of the sector.\n * @param {number} endAngle - The end angle of the sector.\n */\n constructor(circle, startAngle, endAngle) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"CircleSector\";\n this.uid = UIDGenerator.next();\n this.circle = circle;\n this.startAngle = startAngle;\n this.endAngle = endAngle;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this ellipse.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getBounds\n * @instance\n * @memberof VEllipse\n * @return {Bounds} The bounds of this curve.\n **/\n getBounds() {\n const _self = this;\n const circleBounds = this.circle.getBounds();\n // Calculage angles from east, west, north and south box points and check if they are inside\n const candidates = [\n circleBounds.getNorthPoint(),\n circleBounds.getSouthPoint(),\n circleBounds.getWestPoint(),\n circleBounds.getEastPoint()\n ].filter((point) => {\n // Check for each candidate points if they are contained in this sector. Drop if not.\n const angle = new Line(_self.circle.center, point).angle();\n return _self.containsAngle(angle);\n });\n // Compute bounds and inlcude start end end point (they are definitely part of the bounds)\n return Bounds.computeFromVertices(candidates.concat([this.getStartPoint(), this.getEndPoint()]));\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Move the circle sector by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof CircleSector\n * @return {CircleSector} this for chaining\n **/\n move(amount) {\n this.circle.move(amount);\n return this;\n }\n /**\n * Checks wether the given angle (must be inside 0 and PI*2) is contained inside this sector.\n *\n * @param {number} angle - The numeric angle to check.\n * @method containsAngle\n * @instance\n * @memberof CircleSector\n * @return {boolean} True if (and only if) this sector contains the given angle.\n */\n containsAngle(angle) {\n var wrappedAngle = geomutils.mapAngleTo2PI(angle);\n var wrappedStart = geomutils.mapAngleTo2PI(this.startAngle);\n var wrappedEnd = geomutils.mapAngleTo2PI(this.endAngle);\n // TODO: cleanup\n // if (this.startAngle <= this.endAngle) {\n // return angle >= this.startAngle && angle < this.endAngle;\n // } else {\n // // startAngle > endAngle\n // return angle >= this.startAngle || angle < this.endAngle;\n // }\n if (wrappedStart <= wrappedEnd) {\n return wrappedAngle >= wrappedStart && wrappedAngle < wrappedEnd;\n }\n else {\n // startAngle > endAngle\n return wrappedAngle >= wrappedStart || wrappedAngle < wrappedEnd;\n }\n }\n /**\n * Get the angle inside this sector for a given ratio. 0.0 means startAngle, and 1.0 means endAngle.\n *\n * @param {number} t - The ratio inside [0..1].\n * @method angleAt\n * @instance\n * @memberof CircleSector\n * @return {number} The angle inside this sector at a given ratio.\n */\n angleAt(t) {\n if (this.startAngle <= this.endAngle) {\n const angleAtRatio = this.startAngle + (this.endAngle - this.startAngle) * t;\n return angleAtRatio % (Math.PI * 2.0);\n }\n else {\n // startAngle > endAngle\n const angleAtRatio = this.startAngle + (Math.PI * 2 - this.startAngle + this.endAngle) * t;\n return angleAtRatio % (Math.PI * 2.0);\n }\n }\n /**\n * Get the sectors starting point (on the underlying circle, located at the start angle).\n *\n * @method getStartPoint\n * @instance\n * @memberof CircleSector\n * @return {Vertex} The sector's stating point.\n */\n getStartPoint() {\n return this.circle.vertAt(this.startAngle);\n }\n /**\n * Get the sectors ending point (on the underlying circle, located at the end angle).\n *\n * @method getEndPoint\n * @instance\n * @memberof CircleSector\n * @return {Vertex} The sector's ending point.\n */\n getEndPoint() {\n return this.circle.vertAt(this.endAngle);\n }\n /**\n * Calculate the intersection of this circle sector and some other sector.\n *\n * If the two sectors do not corerently intersect (when not both points of the\n * radical line are containted in both source sectors) then null is returned.\n *\n * See demo/53-circle-sector-intersections for a geometric visualisation.\n *\n * @method circleSectorIntersection\n * @instance\n * @memberof CircleSector\n * @return {CircleSector | null} The intersecion of both sectors or null if they don't intersect.\n */\n circleSectorIntersection(sector) {\n const radicalLine = this.circle.circleIntersection(sector.circle);\n if (!radicalLine) {\n // The circles to not intersect at all.\n return null;\n }\n // Circles intersect. Check if this sector interval intersects, too.\n const thisIntersectionAngleA = this.circle.center.angle(radicalLine.a);\n const thisIntersectionAngleB = this.circle.center.angle(radicalLine.b);\n // Is intersection inside this sector?\n if (!this.containsAngle(thisIntersectionAngleA) || !this.containsAngle(thisIntersectionAngleB)) {\n // At least one circle intersection point is not located in this sector.\n // -> no valid intersection at all\n return null;\n }\n // Circles intersect. Check if the passed sector interval intersects, too.\n const thatIntersectionAngleA = sector.circle.center.angle(radicalLine.a);\n const thatIntersectionAngleB = sector.circle.center.angle(radicalLine.b);\n // Is intersection inside this sector?\n if (!sector.containsAngle(thatIntersectionAngleA) || !sector.containsAngle(thatIntersectionAngleB)) {\n // At least one circle intersection point is not located in this sector.\n // -> no valid intersection at all\n return null;\n }\n // The radical line has no direction. Thus the resulting sector _might_ be in reverse order.\n // Make a quick logical check: the center of the gap must still be located inside the result sector.\n // If not: reverse result.\n var gapSector = new CircleSector(this.circle, this.endAngle, this.startAngle);\n var centerOfOriginalGap = gapSector.angleAt(0.5);\n const resultSector = new CircleSector(new Circle(this.circle.center.clone(), this.circle.radius), thisIntersectionAngleA, thisIntersectionAngleB);\n if (resultSector.containsAngle(centerOfOriginalGap)) {\n resultSector.startAngle = thisIntersectionAngleB;\n resultSector.endAngle = thisIntersectionAngleA;\n }\n return resultSector;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the line intersections as vectors with this ellipse.\n *\n * @method lineIntersections\n * @instance\n * @param {VertTuple<Vector> ray - The line/ray to intersect this ellipse with.\n * @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.\n * @returns\n */\n lineIntersections(ray, inVectorBoundsOnly = false) {\n // First get all line intersections from underlying ellipse.\n const ellipseIntersections = this.circle.lineIntersections(ray, inVectorBoundsOnly);\n // Drop all intersection points that are not contained in the circle sectors bounds.\n const tmpLine = new Line(this.circle.center, new Vertex());\n return ellipseIntersections.filter((intersectionPoint) => {\n tmpLine.b.set(intersectionPoint);\n const lineAngle = tmpLine.angle();\n return this.containsAngle(geomutils.wrapMinMax(lineAngle, 0, Math.PI * 2));\n });\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.circle.center, vert);\n const angle = lineFromCenter.angle();\n // console.log(\"angle\", (angle / Math.PI) * 180.0);\n // const angle = Math.random() * Math.PI * 2; // TODO\n // Calculate tangent at angle\n return this.circle.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n describeSVGPath(options) {\n // const buffer: SVGPathParams = [];\n // const start = this.getStartPoint();\n // const end = this.getEndPoint();\n // // describeSVGArc\n // // x: number,\n // // y: number,\n // // radius: number,\n // // startAngle: number,\n // // endAngle: number,\n // // options?: { moveToStart: boolean }\n // // ): SVGPathParams => {\n // var arcRotation = 0.0;\n // var largeArcFlag = 1;\n // var sweepFlag = 0;\n // if (options && options.moveToStart) {\n // buffer.push(\"M\", start.x, start.y);\n // }\n // buffer.push(\"A\", cSector.circle.radius, cSector.circle.radius, arcRotation, largeArcFlag, sweepFlag, end.x, end.y);\n // return buffer;\n const arc = CircleSector.circleSectorUtils.describeSVGArc(this.circle.center.x, // end.x,\n this.circle.center.y, // end.y,\n this.circle.radius, this.startAngle, this.endAngle, options // options?: { moveToStart: boolean }\n );\n return arc;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n *\n * @method destroy\n * @instance\n * @memberof CircleSector\n * @return {void}\n */\n destroy() {\n this.circle.destroy();\n this.isDestroyed = true;\n }\n} // END class\nCircleSector.circleSectorUtils = {\n /**\n * Helper function to convert polar circle coordinates to cartesian coordinates.\n *\n * TODO: generalize for ellipses (two radii).\n *\n * @param {number} angle - The angle in radians.\n */\n polarToCartesian: (centerX, centerY, radius, angle) => {\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n },\n /**\n * Helper function to convert a circle section as SVG arc params (for the `d` attribute).\n * Found at: https://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle\n *\n * TODO: generalize for ellipses (two radii).\n *\n * @param {boolean} options.moveToStart - If false (default=true) the initial 'Move' command will not be used.\n * @return [ 'A', radiusx, radiusy, rotation=0, largeArcFlag=1|0, sweepFlag=0, endx, endy ]\n */\n describeSVGArc: (x, y, radius, startAngle, endAngle, options) => {\n if (typeof options === \"undefined\") {\n options = { moveToStart: true };\n }\n const end = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, endAngle);\n const start = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, startAngle);\n // Split full circles into two halves.\n // Some browsers have problems to render full circles (described by start==end).\n if (Math.PI * 2 - Math.abs(startAngle - endAngle) < 0.001) {\n const firstHalf = CircleSector.circleSectorUtils.describeSVGArc(x, y, radius, startAngle, startAngle + (endAngle - startAngle) / 2, options);\n const secondHalf = CircleSector.circleSectorUtils.describeSVGArc(x, y, radius, startAngle + (endAngle - startAngle) / 2, endAngle, options);\n return firstHalf.concat(secondHalf);\n }\n // Boolean stored as integers (0|1).\n const diff = endAngle - startAngle;\n var largeArcFlag;\n var sweepFlag;\n if (diff < 0) {\n largeArcFlag = Math.abs(diff) < Math.PI ? 1 : 0;\n sweepFlag = 1;\n }\n else {\n largeArcFlag = Math.abs(diff) > Math.PI ? 1 : 0;\n sweepFlag = 1;\n }\n const pathData = [];\n if (options.moveToStart) {\n pathData.push(\"M\", start.x, start.y);\n }\n pathData.push(\"A\", radius, radius, 0, largeArcFlag, sweepFlag, end.x, end.y);\n return pathData;\n }\n};\n//# sourceMappingURL=CircleSector.js.map","/**\n * Draws elements into an SVG node.\n *\n * Note that this library uses buffers and draw cycles. To draw onto an SVG canvas, do this:\n * const drawLib = new drawutilssvg( svgNode, ... );\n * const fillLib = drawLib.copyInstance(true);\n * // Begin draw cycle\n * drawLib.beginDrawCycle(time);\n * // ... draw or fill your stuff ...\n * drawLib.endDrawCycle(time); // Here the elements become visible\n *\n * @author Ikaros Kappler\n * @date 2021-01-03\n * @modified 2021-01-24 Fixed the `fillShapes` attribute in the copyInstance function.\n * @modified 2021-01-26 Changed the `isPrimary` (default true) attribute to `isSecondary` (default false).\n * @modified 2021-02-03 Added the static `createSvg` function.\n * @modified 2021-02-03 Fixed the currentId='background' bug on the clear() function.\n * @modified 2021-02-03 Fixed CSSProperty `stroke-width` (was line-width before, which is wrong).\n * @modified 2021-02-03 Added the static `HEAD_XML` attribute.\n * @modified 2021-02-19 Added the static helper function `transformPathData(...)` for svg path transformations (scale and translate).\n * @modified 2021-02-22 Added the static helper function `copyPathData(...)`.\n * @modified 2021-02-22 Added the `path` drawing function to draw SVG path data.\n * @modified 2021-03-01 Fixed a bug in the `clear` function (curClassName was not cleared).\n * @modified 2021-03-29 Fixed a bug in the `text` function (second y param was wrong, used x here).\n * @modified 2021-03-29 Moved this file from `src/ts/utils/helpers/` to `src/ts/`.\n * @modified 2021-03-31 Added 'ellipseSector' the the class names.\n * @modified 2021-03-31 Implemented buffering using a buffer <g> node and the beginDrawCycle and endDrawCycle methods.\n * @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.\n * @modified 2021-11-15 Adding more parameters tot the `text()` function: fontSize, textAlign, fontFamily, lineHeight.\n * @modified 2021-11-19 Fixing the `label(text,x,y)` position.\n * @modified 2021-11-19 Added the `color` param to the `label(...)` function.\n * @modified 2022-02-03 Added the `lineWidth` param to the `crosshair` function.\n * @modified 2022-02-03 Added the `cross(...)` function.\n * @modified 2022-03-26 Added the private `nodeDefs` and `bufferedNodeDefs` attributes.\n * @modified 2022-03-26 Added the `texturedPoly` function to draw textures polygons.\n * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.\n * @modified 2022-11-10 Tweaking some type issues.\n * @modified 2023-02-04 Fixed a typo in the CSS classname for cubic Bézier paths: cubicBezier (was cubierBezier).\n * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.\n * @modified 2023-09-29 Added initialization checks for null parameters.\n * @modified 2023-09-29 Added a missing implementation to the `drawurilssvg.do(XYCoords,string)` function. Didn't draw anything.\n * @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.\n * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.\n * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-10-04 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.\n * @modified 2024-01-30 Fixing an issue with immutable style sets; changes to the global draw config did not reflect here (do now).\n * @modified 2024-03-10 Fixing some types for Typescript 5 compatibility.\n * @modified 2024-07-24 Caching custom style defs in a private buffer variable.\n * @modified 2025-11-14 Fixing a bug in the CSS `mix-blend-mode` property handling (caused a runtime error).\n * @version 1.6.11\n **/\nimport { CircleSector } from \"./CircleSector\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { Vertex } from \"./Vertex\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nconst RAD_TO_DEG = 180 / Math.PI;\n/**\n * @classdesc A helper class for basic SVG drawing operations. This class should\n * be compatible to the default 'draw' class.\n *\n * @requires CubicBzierCurvce\n * @requires Polygon\n * @requires Vertex\n * @requires XYCoords\n */\nexport class drawutilssvg {\n /**\n * Passed from primary to secondary instance.\n */\n //private nodeStyle: SVGStyleElement;\n /**\n * The constructor.\n *\n * @constructor\n * @name drawutilssvg\n * @param {SVGElement} svgNode - The SVG node to use.\n * @param {XYCoords} offset - The draw offset to use.\n * @param {XYCoords} scale - The scale factors to use.\n * @param {XYDimension} canvasSize - The initial canvas size (use setSize to change).\n * @param {boolean} fillShapes - Indicates if the constructed drawutils should fill all drawn shapes (if possible).\n * @param {DrawConfig} drawConfig - The default draw config to use for CSS fallback styles.\n * @param {boolean=} isSecondary - (optional) Indicates if this is the primary or secondary instance. Only primary instances manage child nodes.\n * @param {SVGGElement=} gNode - (optional) Primary and seconday instances share the same &lt;g> node.\n **/\n constructor(svgNode, offset, scale, canvasSize, fillShapes, drawConfig, isSecondary, gNode, bufferGNode, nodeDefs, bufferNodeDefs, nodeStyle) {\n this.svgNode = svgNode;\n this.offset = new Vertex(0, 0).set(offset);\n this.scale = new Vertex(1, 1).set(scale);\n this.fillShapes = fillShapes;\n this.isSecondary = Boolean(isSecondary);\n this.drawConfig = drawConfig;\n this.drawlibConfiguration = {};\n this.cache = new Map();\n this.setSize(canvasSize);\n if (isSecondary) {\n if (!gNode || !bufferGNode || !nodeDefs || !bufferNodeDefs) {\n throw \"Cannot create secondary svg draw lib with undefinde gNode|bufferGNode|nodeDefs|bufferNodeDefs.\";\n }\n this.gNode = gNode;\n this.bufferGNode = bufferGNode;\n this.nodeDefs = nodeDefs;\n this.bufferedNodeDefs = bufferNodeDefs;\n if (nodeStyle) {\n this.nodeStyle = nodeStyle;\n }\n }\n else {\n this.addStyleDefs(drawConfig);\n this.addDefsNode();\n this.gNode = this.createSVGNode(\"g\");\n this.bufferGNode = this.createSVGNode(\"g\");\n this.svgNode.appendChild(this.gNode);\n }\n }\n /**\n * Adds a default style defintion based on the passed DrawConfig.\n * Twaek the draw config to change default colors or line thicknesses.\n *\n * @param {DrawConfig} drawConfig\n */\n addStyleDefs(drawConfig) {\n this.nodeStyle = this.createSVGNode(\"style\");\n this.svgNode.appendChild(this.nodeStyle);\n this.rebuildStyleDefs(drawConfig);\n }\n /**\n * This method is required to re-define the global style defs. It is needed\n * if any value in the DrawConfig changed in the meantime.\n * @param drawConfig\n */\n rebuildStyleDefs(drawConfig) {\n // Which default styles to add? -> All from the DrawConfig.\n // Compare with DrawConfig interface\n const keys = {\n \"bezier\": \"CubicBezierCurve\",\n //\"bezierPath\": \"BezierPath\", // TODO: is this correct?\n \"polygon\": \"Polygon\",\n \"triangle\": \"Triangle\",\n \"ellipse\": \"Ellipse\",\n \"ellipseSector\": \"EllipseSector\",\n \"circle\": \"Circle\",\n \"circleSector\": \"CircleSector\",\n \"vertex\": \"Vertex\",\n \"line\": \"Line\",\n \"vector\": \"Vector\",\n \"image\": \"Image\",\n \"text\": \"Text\"\n };\n // Question: why isn't this working if the svgNode is created dynamically? (nodeStyle.sheet is null)\n const rules = [];\n // console.log(\"drawConfig\", drawConfig);\n for (var k in keys) {\n const className = keys[k];\n const drawSettings = drawConfig[k];\n if (drawSettings) {\n rules.push(`.${className} { fill : none; stroke: ${drawSettings.color}; stroke-width: ${drawSettings.lineWidth}px }`);\n }\n else {\n console.warn(`Warning: your draw config is missing the key '${k}' which is required.`);\n }\n }\n if (this.customStyleDefs) {\n rules.push(\"\\n/* Custom styles */\\n\");\n this.customStyleDefs.forEach((value, key) => {\n rules.push(key + \" { \" + value + \" }\");\n });\n // this.nodeStyle.innerHTML += \"\\n/* Custom styles */\\n\" + rules.join(\"\\n\");\n }\n this.nodeStyle.innerHTML = rules.join(\"\\n\");\n }\n /**\n * Adds the internal <defs> node.\n */\n addDefsNode() {\n this.nodeDefs = this.createSVGNode(\"defs\");\n // this.svgNode.appendChild(this.nodeDefs);\n this.bufferedNodeDefs = this.createSVGNode(\"defs\");\n this.svgNode.appendChild(this.nodeDefs);\n }\n /**\n * This is a simple way to include custom CSS class mappings to the style defs of the generated SVG.\n *\n * The mapping should be of the form\n * [style-class] -> [style-def-string]\n *\n * Example:\n * \"rect.red\" -> \"fill: #ff0000; border: 1px solid red\"\n *\n * @param {Map<string,string>} defs\n */\n addCustomStyleDefs(defs) {\n this.customStyleDefs = defs;\n }\n /**\n * Retieve an old (cached) element.\n * Only if both – key and nodeName – match, the element will be returned (null otherwise).\n *\n * @method findElement\n * @private\n * @memberof drawutilssvg\n * @instance\n * @param {UID} key - The key of the desired element (used when re-drawing).\n * @param {string} nodeName - The expected node name.\n */\n findElement(key, nodeName) {\n if (!key) {\n return null;\n }\n var node = this.cache.get(key);\n if (node && node.nodeName.toUpperCase() === nodeName.toUpperCase()) {\n this.cache.delete(key);\n return node;\n }\n return null;\n }\n /**\n * Create a new DOM node &lt;svg&gt; in the SVG namespace.\n *\n * @method createSVGNode\n * @private\n * @memberof drawutilssvg\n * @instance\n * @param {string} nodeName - The node name (tag-name).\n * @return {SVGElement} A new element in the SVG namespace with the given node name.\n */\n createSVGNode(nodeName) {\n return document.createElementNS(\"http://www.w3.org/2000/svg\", nodeName);\n }\n /**\n * Make a new SVG node (or recycle an old one) with the given node name (circle, path, line, rect, ...).\n *\n * This function is used in draw cycles to re-use old DOM nodes (in hope to boost performance).\n *\n * @method makeNode\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {string} nodeName - The node name.\n * @return {SVGElement} The new node, which is not yet added to any document.\n */\n makeNode(nodeName) {\n // Try to find node in current DOM cache.\n // Unique node keys are strictly necessary.\n // Try to recycle an old element from cache.\n var node = this.findElement(this.curId, nodeName);\n if (!node) {\n // If no such old elements exists (key not found, tag name not matching),\n // then create a new one.\n node = this.createSVGNode(nodeName);\n }\n if (this.drawlibConfiguration.blendMode) {\n const blendMode = node.style[\"mix-blend-mode\"];\n if (typeof blendMode === \"function\") {\n blendMode(this.drawlibConfiguration.blendMode);\n }\n else {\n node.style[\"mix-blend-mode\"] = this.drawlibConfiguration.blendMode;\n }\n }\n // if (this.lineDashEnabled && this.lineDash && this.lineDash.length > 0 && drawutilssvg.nodeSupportsLineDash(nodeName)) {\n // node.setAttribute(\"stroke-dasharray\", this.lineDash.join(\" \"));\n // }\n return node;\n }\n /**\n * This is the final helper function for drawing and filling stuff and binding new\n * nodes to the SVG document.\n * It is not intended to be used from the outside.\n *\n * When in draw mode it draws the current shape.\n * When in fill mode it fills the current shape.\n *\n * This function is usually only called internally.\n *\n * @method _bindFillDraw\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {SVGElement} node - The node to draw/fill and bind.\n * @param {string} className - The class name(s) to use.\n * @param {string} color - A stroke/fill color to use.\n * @param {number=1} lineWidth - (optional) A line width to use for drawing (default is 1).\n * @return {SVGElement} The node itself (for chaining).\n */\n _bindFillDraw(node, className, color, lineWidth, strokeOptions) {\n this._configureNode(node, className, this.fillShapes, color, lineWidth, strokeOptions);\n return this._bindNode(node, undefined);\n }\n /**\n * Bind this given node to a parent. If no parent is passed then the global\n * node buffer will be used.\n *\n * @method _bindNode\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {SVGElement} node - The SVG node to bind.\n * @param {SVGElement=} bindingParent - (optional) You may pass node other than the glober buffer node.\n * @returns {SVGElement} The passed node itself.\n */\n _bindNode(node, bindingParent) {\n if (!node.parentNode) {\n // Attach to DOM only if not already attached\n (bindingParent !== null && bindingParent !== void 0 ? bindingParent : this.bufferGNode).appendChild(node);\n }\n return node;\n }\n /**\n * Add custom CSS class names and the globally defined CSS classname to the\n * given node.\n *\n * @method addCSSClasses\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {SVGElement} node - The SVG node to bind.\n * @param {string} className - The additional custom classname to add.\n * @returns {void}\n */\n _addCSSClasses(node, className) {\n if (this.curClassName) {\n node.setAttribute(\"class\", `${className} ${this.curClassName}`);\n }\n else {\n node.setAttribute(\"class\", className);\n }\n }\n _configureNode(node, className, fillMode, color, lineWidth, strokeOptions) {\n this._addCSSClasses(node, className);\n node.setAttribute(\"fill\", fillMode && color ? color : \"none\");\n node.setAttribute(\"stroke\", fillMode ? \"none\" : color || \"none\");\n node.setAttribute(\"stroke-width\", `${lineWidth || 1}`);\n if (this.curId) {\n node.setAttribute(\"id\", `${this.curId}`); // Maybe React-style 'key' would be better?\n }\n this.applyStrokeOpts(node, strokeOptions);\n return node;\n }\n /**\n * Sets the size and view box of the document. Call this if canvas size changes.\n *\n * @method setSize\n * @instance\n * @memberof drawutilssvg\n * @param {XYDimension} canvasSize - The new canvas size.\n */\n setSize(canvasSize) {\n this.canvasSize = canvasSize;\n this.svgNode.setAttribute(\"viewBox\", `0 0 ${this.canvasSize.width} ${this.canvasSize.height}`);\n this.svgNode.setAttribute(\"width\", `${this.canvasSize.width}`);\n this.svgNode.setAttribute(\"height\", `${this.canvasSize.height}`);\n }\n /**\n * Creates a 'shallow' (non deep) copy of this instance. This implies\n * that under the hood the same gl context and gl program will be used.\n */\n copyInstance(fillShapes) {\n var copy = new drawutilssvg(this.svgNode, this.offset, this.scale, this.canvasSize, fillShapes, this.drawConfig, // null as any as DrawConfig, // no DrawConfig – this will work as long as `isSecondary===true`\n true, // isSecondary\n this.gNode, this.bufferGNode, this.nodeDefs, this.bufferedNodeDefs, this.nodeStyle);\n return copy;\n }\n /**\n * Set the current drawlib configuration.\n *\n * @name setConfiguration\n * @method\n * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.\n */\n setConfiguration(configuration) {\n this.drawlibConfiguration = configuration;\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * It is used by some libraries for identifying elemente on re-renders.\n *\n * @name setCurrentId\n * @method\n * @param {UID|null} uid - A UID identifying the currently drawn element(s).\n * @instance\n * @memberof drawutilssvg\n **/\n setCurrentId(uid) {\n this.curId = uid;\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * Determine the class name for further usage here.\n *\n * @name setCurrentClassName\n * @method\n * @param {string|null} className - A class name for further custom use cases.\n * @instance\n * @memberof drawutilssvg\n **/\n setCurrentClassName(className) {\n this.curClassName = className;\n }\n /**\n * Called before each draw cycle.\n * This is required for compatibility with other draw classes in the library.\n *\n * @name beginDrawCycle\n * @method\n * @param {UID=} uid - (optional) A UID identifying the currently drawn element(s).\n * @instance\n * @memberof drawutilssvg\n **/\n beginDrawCycle(renderTime) {\n // Clear non-recycable elements from last draw cycle.\n this.cache.clear();\n // Clearing an SVG is equivalent to removing all its child elements.\n for (var i = 0; i < this.bufferGNode.childNodes.length; i++) {\n // Hide all nodes here. Don't throw them away.\n // We can probably re-use them in the next draw cycle.\n var child = this.bufferGNode.childNodes[i];\n this.cache.set(child.getAttribute(\"id\"), child);\n }\n this.removeAllChildNodes();\n }\n /**\n * Called after each draw cycle.\n *\n * This is required for compatibility with other draw classes in the library (like drawgl).\n *\n * @name endDrawCycle\n * @method\n * @param {number} renderTime\n * @instance\n **/\n endDrawCycle(renderTime) {\n this.rebuildStyleDefs(this.drawConfig);\n if (!this.isSecondary) {\n // All elements are drawn into the buffer; they are NOT yet visible, not did the browser perform any\n // layout updates.\n // Replace the old <g>-node with the buffer node.\n // https://stackoverflow.com/questions/27442464/how-to-update-a-svg-image-without-seeing-a-blinking\n this.svgNode.replaceChild(this.bufferedNodeDefs, this.nodeDefs);\n this.svgNode.replaceChild(this.bufferGNode, this.gNode);\n }\n const tmpGNode = this.gNode;\n this.gNode = this.bufferGNode;\n this.bufferGNode = tmpGNode;\n const tmpDefsNode = this.nodeDefs;\n this.nodeDefs = this.bufferedNodeDefs;\n this.bufferedNodeDefs = tmpDefsNode;\n }\n /**\n * A private helper method to apply stroke options to the current\n * context.\n * @param {StrokeOptions=} strokeOptions -\n */\n applyStrokeOpts(node, strokeOptions) {\n if (strokeOptions &&\n strokeOptions.dashArray &&\n strokeOptions.dashArray.length > 0 &&\n drawutilssvg.nodeSupportsLineDash(node.tagName)) {\n node.setAttribute(\"stroke-dasharray\", strokeOptions.dashArray\n .map((dashArayElem) => {\n return dashArayElem * this.scale.x;\n })\n .join(\" \"));\n if (strokeOptions.dashOffset) {\n node.setAttribute(\"stroke-dashoffset\", `${strokeOptions.dashOffset * this.scale.x}`);\n }\n }\n }\n _x(x) {\n return this.offset.x + this.scale.x * x;\n }\n _y(y) {\n return this.offset.y + this.scale.y * y;\n }\n /**\n * Draw the line between the given two points with the specified (CSS-) color.\n *\n * @method line\n * @param {XYCoords} zA - The start point of the line.\n * @param {XYCoords} zB - The end point of the line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth? - [optional] The line's width.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n line(zA, zB, color, lineWidth, strokeOptions) {\n // const line: SVGElement = this.makeNode(\"line\");\n // this.applyStrokeOpts(line, strokeOptions);\n // line.setAttribute(\"x1\", `${this._x(zA.x)}`);\n // line.setAttribute(\"y1\", `${this._y(zA.y)}`);\n // line.setAttribute(\"x2\", `${this._x(zB.x)}`);\n // line.setAttribute(\"y2\", `${this._y(zB.y)}`);\n const line = this.makeLineNode(zA, zB, color, lineWidth, strokeOptions);\n return this._bindFillDraw(line, \"line\", color, lineWidth || 1, strokeOptions);\n }\n /**\n * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n arrow(zA, zB, color, lineWidth, headLength = 8, strokeOptions) {\n const group = this.makeNode(\"g\");\n const arrowHeadBasePosition = { x: 0, y: 0 };\n // Just create the child nodes, don't bind them to the root node.\n const arrowHead = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, undefined, arrowHeadBasePosition);\n const line = this.makeLineNode(zA, arrowHeadBasePosition, color, lineWidth, strokeOptions);\n group.appendChild(line);\n group.appendChild(arrowHead);\n this._addCSSClasses(group, \"linear-arrow\");\n this._bindNode(group, undefined);\n return group;\n }\n /**\n * Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.\n *\n * @method cubicBezierArrow\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n */\n cubicBezierArrow(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, headLength = 8, strokeOptions) {\n const group = this.makeNode(\"g\");\n // Just create the child nodes, don't bind them to the root node.\n const arrowHeadBasePosition = new Vertex(0, 0);\n const arrowHead = this.makeArrowHeadNode(endControlPoint, endPoint, color, lineWidth, headLength, undefined, arrowHeadBasePosition);\n const diff = arrowHeadBasePosition.difference(endPoint);\n const bezier = this.makeCubicBezierNode(startPoint, { x: endPoint.x - diff.x, y: endPoint.y - diff.y }, startControlPoint, { x: endControlPoint.x - diff.x, y: endControlPoint.y - diff.y }, color, lineWidth, strokeOptions);\n group.appendChild(bezier);\n group.appendChild(arrowHead);\n this._addCSSClasses(group, \"cubicbezier-arrow\");\n this._bindNode(group, undefined);\n return group;\n }\n /**\n * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n **/\n arrowHead(zA, zB, color, lineWidth, headLength = 8, strokeOptions) {\n const node = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, strokeOptions);\n return this._bindFillDraw(node, \"arrowhead\", color, lineWidth || 1, strokeOptions);\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method image\n * @param {Image} image - The image object to draw.\n * @param {XYCoords} position - The position to draw the the upper left corner at.\n * @param {XYCoords} size - The x/y-size to draw the image with.\n * @param {number=0.0} alpha - (optional, default=0.0) The transparency (1.0=opaque, 0.0=transparent).\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n image(image, position, size, alpha = 1.0) {\n const node = this.makeNode(\"image\");\n // We need to re-adjust the image if it was not yet fully loaded before.\n const setImageSize = (image) => {\n if (image.naturalWidth) {\n const ratioX = size.x / image.naturalWidth;\n const ratioY = size.y / image.naturalHeight;\n node.setAttribute(\"width\", `${image.naturalWidth * this.scale.x}`);\n node.setAttribute(\"height\", `${image.naturalHeight * this.scale.y}`);\n node.setAttribute(\"display\", null); // Dislay when loaded\n // if (alpha) {\n node.setAttribute(\"opacity\", `${alpha}`);\n // }\n node.setAttribute(\"transform\", `translate(${this._x(position.x)} ${this._y(position.y)}) scale(${ratioX} ${ratioY})`);\n }\n };\n image.addEventListener(\"load\", event => {\n setImageSize(image);\n });\n // Safari has a transform-origin bug.\n // Use x=0, y=0 and translate/scale instead (see above)\n node.setAttribute(\"x\", `${0}`);\n node.setAttribute(\"y\", `${0}`);\n node.setAttribute(\"display\", \"none\"); // Hide before loaded\n setImageSize(image);\n node.setAttribute(\"href\", image.src);\n return this._bindFillDraw(node, \"image\", null, null);\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method texturedPoly\n * @param {Image} textureImage - The image object to draw.\n * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.\n * @param {Polygon} polygon - The polygon to use as clip path.\n * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.\n * @param {number} rotation - The rotation to use for the polygon (and for the texture).\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n texturedPoly(textureImage, textureSize, polygon, polygonPosition, rotation) {\n // const basePolygonBounds: Bounds = polygon.getBounds();\n const rotatedScalingOrigin = new Vertex(textureSize.min).clone().rotate(rotation, polygonPosition);\n // const rotationCenter = polygonPosition.clone().add(rotatedScalingOrigin.difference(textureSize.min).inv());\n // Create something like this\n // ...\n // <defs>\n // <clipPath id=\"shape\">\n // <path fill=\"none\" d=\"...\"/>\n // </clipPath>\n // </defs>\n // ...\n // <g clip-path=\"url(#shape)\">\n // <g transform=\"scale(...)\">\n // <image width=\"643\" height=\"643\" transform=\"rotate(...)\" xlink:href=\"https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg\" >\n // </g>\n // </g>\n // </image>\n // ...\n const clipPathNode = this.makeNode(\"clipPath\");\n const clipPathId = `clippath_${UIDGenerator.next()}`; // TODO: use a better UUID generator here?\n clipPathNode.setAttribute(\"id\", clipPathId);\n const gNode = this.makeNode(\"g\");\n const imageNode = this.makeNode(\"image\");\n imageNode.setAttribute(\"x\", `${this._x(rotatedScalingOrigin.x)}`);\n imageNode.setAttribute(\"y\", `${this._y(rotatedScalingOrigin.y)}`);\n imageNode.setAttribute(\"width\", `${textureSize.width}`);\n imageNode.setAttribute(\"height\", `${textureSize.height}`);\n imageNode.setAttribute(\"href\", textureImage.src);\n // imageNode.setAttribute(\"opacity\", \"0.5\");\n // SVG rotations in degrees\n imageNode.setAttribute(\"transform\", `rotate(${rotation * RAD_TO_DEG}, ${this._x(rotatedScalingOrigin.x)}, ${this._y(rotatedScalingOrigin.y)})`);\n const pathNode = this.makeNode(\"path\");\n const pathData = [];\n if (polygon.vertices.length > 0) {\n const self = this;\n pathData.push(\"M\", `${this._x(polygon.vertices[0].x)}`, `${this._y(polygon.vertices[0].y)}`);\n for (var i = 1; i < polygon.vertices.length; i++) {\n pathData.push(\"L\", `${this._x(polygon.vertices[i].x)}`, `${this._y(polygon.vertices[i].y)}`);\n }\n }\n pathNode.setAttribute(\"d\", pathData.join(\" \"));\n clipPathNode.appendChild(pathNode);\n this.bufferedNodeDefs.appendChild(clipPathNode);\n gNode.appendChild(imageNode);\n gNode.setAttribute(\"transform-origin\", `${this._x(rotatedScalingOrigin.x)} ${this._y(rotatedScalingOrigin.y)}`);\n gNode.setAttribute(\"transform\", `scale(${this.scale.x}, ${this.scale.y})`);\n const clipNode = this.makeNode(\"g\");\n clipNode.appendChild(gNode);\n clipNode.setAttribute(\"clip-path\", `url(#${clipPathId})`);\n // TODO: check if the image class is correct here or if we should use a 'clippedImage' class here\n this._bindFillDraw(clipNode, \"image\", null, null); // No color, no lineWidth\n return clipNode;\n }\n /**\n * Draw the given (cubic) bézier curve.\n *\n * @method cubicBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n cubicBezier(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions) {\n const node = this.makeCubicBezierNode(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions);\n return this._bindNode(node, undefined);\n }\n /**\n * Draw the given (cubic) Bézier path.\n *\n * The given path must be an array with n*3+1 vertices, where n is the number of\n * curves in the path:\n * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>\n *\n * @method cubicBezierPath\n * @param {XYCoords[]} path - The cubic bezier path as described above.\n * @param {string} color - The CSS colot to draw the path with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n cubicBezierPath(path, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, strokeOptions);\n if (!path || path.length == 0) {\n return node;\n }\n // Draw curve\n const d = [\"M\", this._x(path[0].x), this._y(path[0].y)];\n // Draw curve path\n var endPoint;\n var startControlPoint;\n var endControlPoint;\n for (var i = 1; i < path.length; i += 3) {\n startControlPoint = path[i];\n endControlPoint = path[i + 1];\n endPoint = path[i + 2];\n d.push(\"C\", this._x(startControlPoint.x), this._y(startControlPoint.y), this._x(endControlPoint.x), this._y(endControlPoint.y), this._x(endPoint.x), this._y(endPoint.y));\n }\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"cubicBezierPath\", color, lineWidth || 1);\n }\n /**\n * Draw the given handle and handle point (used to draw interactive Bézier curves).\n *\n * The colors for this are fixed and cannot be specified.\n *\n * @method handle\n * @param {Vertex} startPoint - The start of the handle.\n * @param {Vertex} endPoint - The end point of the handle.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n handle(startPoint, endPoint) {\n // TODO: redefine methods like these into an abstract class?\n this.point(startPoint, \"rgb(0,32,192)\");\n this.square(endPoint, 5, \"rgba(0,128,192,0.5)\");\n }\n /**\n * Draw a handle line (with a light grey).\n *\n * @method handleLine\n * @param {XYCoords} startPoint - The start point to draw the handle at.\n * @param {XYCoords} endPoint - The end point to draw the handle at.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n handleLine(startPoint, endPoint) {\n this.line(startPoint, endPoint, \"rgb(128,128,128,0.5)\");\n }\n /**\n * Draw a 1x1 dot with the specified (CSS-) color.\n *\n * @method dot\n * @param {XYCoords} p - The position to draw the dot at.\n * @param {string} color - The CSS color to draw the dot with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n dot(p, color) {\n const node = this.makeNode(\"line\");\n node.setAttribute(\"x1\", `${this._x(p.x)}`);\n node.setAttribute(\"y1\", `${this._y(p.y)}`);\n node.setAttribute(\"x2\", `${this._x(p.x)}`);\n node.setAttribute(\"y2\", `${this._y(p.y)}`);\n return this._bindFillDraw(node, \"dot\", color, 1);\n }\n /**\n * Draw the given point with the specified (CSS-) color and radius 3.\n *\n * @method point\n * @param {XYCoords} p - The position to draw the point at.\n * @param {string} color - The CSS color to draw the point with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n point(p, color) {\n var radius = 3;\n const node = this.makeNode(\"circle\");\n node.setAttribute(\"cx\", `${this._x(p.x)}`);\n node.setAttribute(\"cy\", `${this._y(p.y)}`);\n node.setAttribute(\"r\", `${radius}`);\n return this._bindFillDraw(node, \"point\", color, 1);\n }\n /**\n * Draw a circle with the specified (CSS-) color and radius.<br>\n * <br>\n * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.\n *\n * @method circle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n circle(center, radius, color, lineWidth, strokeOptions) {\n // Todo: draw ellipse when scalex!=scaley\n const node = this.makeNode(\"circle\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"cx\", `${this._x(center.x)}`);\n node.setAttribute(\"cy\", `${this._y(center.y)}`);\n node.setAttribute(\"r\", `${radius * this.scale.x}`); // y?\n return this._bindFillDraw(node, \"circle\", color, lineWidth || 1);\n }\n /**\n * Draw a circular arc (section of a circle) with the given CSS color.\n *\n * @method circleArc\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {number} startAngle - The angle to start at.\n * @param {number} endAngle - The angle to end at.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n circleArc(center, radius, startAngle, endAngle, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, strokeOptions);\n const arcData = CircleSector.circleSectorUtils.describeSVGArc(this._x(center.x), this._y(center.y), radius * this.scale.x, // y?\n startAngle, endAngle);\n node.setAttribute(\"d\", arcData.join(\" \"));\n return this._bindFillDraw(node, \"circleArc\", color, lineWidth || 1);\n }\n /**\n * Draw an ellipse with the specified (CSS-) color and thw two radii.\n *\n * @method ellipse\n * @param {XYCoords} center - The center of the ellipse.\n * @param {number} radiusX - The radius of the ellipse.\n * @param {number} radiusY - The radius of the ellipse.\n * @param {string} color - The CSS color to draw the ellipse with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n ellipse(center, radiusX, radiusY, color, lineWidth, rotation, strokeOptions) {\n if (typeof rotation === \"undefined\") {\n rotation = 0.0;\n }\n const node = this.makeNode(\"ellipse\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"cx\", `${this._x(center.x)}`);\n node.setAttribute(\"cy\", `${this._y(center.y)}`);\n node.setAttribute(\"rx\", `${radiusX * this.scale.x}`);\n node.setAttribute(\"ry\", `${radiusY * this.scale.y}`);\n // node.setAttribute( 'style', `transform: rotate(${rotation} ${center.x} ${center.y})` );\n node.setAttribute(\"transform\", `rotate(${(rotation * 180) / Math.PI} ${this._x(center.x)} ${this._y(center.y)})`);\n return this._bindFillDraw(node, \"ellipse\", color, lineWidth || 1);\n }\n /**\n * Draw square at the given center, size and with the specified (CSS-) color.<br>\n * <br>\n * Note that if the x-scale and the y-scale are different the result will be a rectangle rather than a square.\n *\n * @method square\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {SVGElement}\n * @instance\n * @memberof drawutilssvg\n */\n square(center, size, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"rectangle\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"x\", `${this._x(center.x - size / 2.0)}`);\n node.setAttribute(\"y\", `${this._y(center.y - size / 2.0)}`);\n node.setAttribute(\"width\", `${size * this.scale.x}`);\n node.setAttribute(\"height\", `${size * this.scale.y}`);\n return this._bindFillDraw(node, \"square\", color, lineWidth || 1);\n }\n /**\n * Draw a rectangle.\n *\n * @param {XYCoords} position - The upper left corner of the rectangle.\n * @param {number} width - The width of the rectangle.\n * @param {number} height - The height of the rectangle.\n * @param {string} color - The color to use.\n * @param {number=1} lineWidth - (optional) The line with to use (default is 1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {SVGElement}\n * @instance\n * @memberof drawutilssvg\n **/\n rect(position, width, height, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"rect\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"x\", `${this._x(position.x)}`);\n node.setAttribute(\"y\", `${this._y(position.y)}`);\n node.setAttribute(\"width\", `${width * this.scale.x}`);\n node.setAttribute(\"height\", `${height * this.scale.y}`);\n return this._bindFillDraw(node, \"rect\", color, lineWidth || 1);\n }\n /**\n * Draw a grid of horizontal and vertical lines with the given (CSS-) color.\n *\n * @method grid\n * @param {XYCoords} center - The center of the grid.\n * @param {number} width - The total width of the grid (width/2 each to the left and to the right).\n * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal grid size.\n * @param {number} sizeY - The vertical grid size.\n * @param {string} color - The CSS color to draw the grid with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n grid(center, width, height, sizeX, sizeY, color) {\n // console.log(\"grid\");\n // const node: SVGElement = this.makeNode(\"pattern\");\n // var patternId = \"pattern_id_\" + Math.floor(Math.random() * 65365);\n // node.setAttribute(\"id\", patternId);\n // node.setAttribute(\"viewBox\", `0,0,${sizeX},${sizeY}`);\n // node.setAttribute(\"width\", `${sizeX}`);\n // node.setAttribute(\"height\", `${sizeX}`);\n // var pattern: SVGElement = this.makeNode(\"path\");\n // const d: SVGPathParams = [];\n // d.push(\"M\", sizeX / 2.0, 0);\n // d.push(\"L\", sizeX / 2.0, sizeY);\n // d.push(\"M\", 0, sizeY / 2.0);\n // d.push(\"L\", sizeX, sizeY / 2.0);\n // node.setAttribute(\"d\", d.join(\" \"));\n // this.bufferedNodeDefs.append(pattern);\n // const fillNode: SVGElement = this.makeNode(\"rect\");\n // // For some strange reason SVG rotation transforms use degrees instead of radians\n // // Note that the background does not scale with the zoom level (always covers full element)\n // fillNode.setAttribute(\"x\", \"0\");\n // fillNode.setAttribute(\"y\", \"0\");\n // fillNode.setAttribute(\"width\", `${this.canvasSize.width}`);\n // fillNode.setAttribute(\"height\", `${this.canvasSize.height}`);\n // fillNode.setAttribute(\"fill\", `url(#${patternId})`);\n // return this._bindFillDraw(fillNode, \"grid\", \"red\", 1);\n const node = this.makeNode(\"path\");\n const d = [];\n var yMin = -Math.ceil((height * 0.5) / sizeY) * sizeY;\n var yMax = height / 2;\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n d.push(\"M\", this._x(center.x + x), this._y(center.y + yMin));\n d.push(\"L\", this._x(center.x + x), this._y(center.y + yMax));\n }\n var xMin = -Math.ceil((width * 0.5) / sizeX) * sizeX;\n var xMax = width / 2;\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n d.push(\"M\", this._x(center.x + xMin), this._y(center.y + y));\n d.push(\"L\", this._x(center.x + xMax), this._y(center.y + y));\n }\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"grid\", color, 1);\n }\n /**\n * Draw a raster of crosshairs in the given grid.<br>\n *\n * This works analogue to the grid() function\n *\n * @method raster\n * @param {XYCoords} center - The center of the raster.\n * @param {number} width - The total width of the raster (width/2 each to the left and to the right).\n * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal raster size.\n * @param {number} sizeY - The vertical raster size.\n * @param {string} color - The CSS color to draw the raster with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n raster(center, width, height, sizeX, sizeY, color) {\n const node = this.makeNode(\"path\");\n const d = [];\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n // Draw a crosshair\n d.push(\"M\", this._x(center.x + x) - 4, this._y(center.y + y));\n d.push(\"L\", this._x(center.x + x) + 4, this._y(center.y + y));\n d.push(\"M\", this._x(center.x + x), this._y(center.y + y) - 4);\n d.push(\"L\", this._x(center.x + x), this._y(center.y + y) + 4);\n }\n }\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"raster\", color, 1);\n }\n /**\n * Draw a diamond handle (square rotated by 45°) with the given CSS color.\n *\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped diamonds.\n *\n * @method diamondHandle\n * @param {XYCoords} center - The center of the diamond.\n * @param {number} size - The x/y-size of the diamond.\n * @param {string} color - The CSS color to draw the diamond with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n diamondHandle(center, size, color) {\n const node = this.makeNode(\"path\");\n const d = [\n \"M\",\n this._x(center.x) - size / 2.0,\n this._y(center.y),\n \"L\",\n this._x(center.x),\n this._y(center.y) - size / 2.0,\n \"L\",\n this._x(center.x) + size / 2.0,\n this._y(center.y),\n \"L\",\n this._x(center.x),\n this._y(center.y) + size / 2.0,\n \"Z\"\n ];\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"diamondHandle\", color, 1);\n }\n /**\n * Draw a square handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped squares.\n *\n * @method squareHandle\n * @param {XYCoords} center - The center of the square.\n * @param {XYCoords} size - The x/y-size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n squareHandle(center, size, color) {\n const node = this.makeNode(\"rect\");\n node.setAttribute(\"x\", `${this._x(center.x) - size / 2.0}`);\n node.setAttribute(\"y\", `${this._y(center.y) - size / 2.0}`);\n node.setAttribute(\"width\", `${size}`);\n node.setAttribute(\"height\", `${size}`);\n return this._bindFillDraw(node, \"squareHandle\", color, 1);\n }\n /**\n * Draw a circle handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped circles.\n *\n * @method circleHandle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n circleHandle(center, radius, color) {\n radius = radius || 3;\n const node = this.makeNode(\"circle\");\n node.setAttribute(\"cx\", `${this._x(center.x)}`);\n node.setAttribute(\"cy\", `${this._y(center.y)}`);\n node.setAttribute(\"r\", `${radius}`);\n return this._bindFillDraw(node, \"circleHandle\", color, 1);\n }\n /**\n * Draw a crosshair with given radius and color at the given position.<br>\n * <br>\n * Note that the crosshair radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=0.5} lineWidth - (optional, default=0.5) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n crosshair(center, radius, color, lineWidth) {\n const node = this.makeNode(\"path\");\n const d = [\n \"M\",\n this._x(center.x) - radius,\n this._y(center.y),\n \"L\",\n this._x(center.x) + radius,\n this._y(center.y),\n \"M\",\n this._x(center.x),\n this._y(center.y) - radius,\n \"L\",\n this._x(center.x),\n this._y(center.y) + radius\n ];\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"crosshair\", color, lineWidth || 0.5);\n }\n /**\n * Draw a cross with diagonal axes with given radius, color and lineWidth at the given position.<br>\n * <br>\n * Note that the x's radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=1} lineWidth - (optional, default=1.0) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cross(center, radius, color, lineWidth) {\n const node = this.makeNode(\"path\");\n const d = [\n \"M\",\n this._x(center.x) - radius,\n this._y(center.y) - radius,\n \"L\",\n this._x(center.x) + radius,\n this._y(center.y) + radius,\n \"M\",\n this._x(center.x) - radius,\n this._y(center.y) + radius,\n \"L\",\n this._x(center.x) + radius,\n this._y(center.y) - radius\n ];\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"cross\", color, lineWidth || 1.0);\n }\n /**\n * Draw a polygon.\n *\n * @method polygon\n * @param {Polygon} polygon - The polygon to draw.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n polygon(polygon, color, lineWidth) {\n return this.polyline(polygon.vertices, polygon.isOpen, color, lineWidth);\n }\n /**\n * Draw a polygon line (alternative function to the polygon).\n *\n * @method polyline\n * @param {XYCoords[]} vertices - The polygon vertices to draw.\n * @param {boolan} isOpen - If true the polyline will not be closed at its end.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n polyline(vertices, isOpen, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, strokeOptions);\n if (vertices.length == 0) {\n return node;\n }\n // Draw curve\n const d = [\"M\", this._x(vertices[0].x), this._y(vertices[0].y)];\n var n = vertices.length;\n for (var i = 1; i < n; i++) {\n d.push(\"L\", this._x(vertices[i].x), this._y(vertices[i].y));\n }\n if (!isOpen)\n d.push(\"Z\");\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"polygon\", color, lineWidth || 1);\n }\n /**\n * Draw a text at the given relative position.\n *\n * @method text\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {string=} options.color - The Color to use.\n * @param {string=} options.fontFamily - The font family to use.\n * @param {number=} options.fontSize - The font size (in pixels) to use.\n * @param {FontStyle=} options.fontStyle - The font style to use.\n * @param {FontWeight=} options.fontWeight - The font weight to use.\n * @param {number=} options.lineHeight - The line height (in pixels) to use.\n * @param {number=} options.rotation - The (optional) rotation in radians.\n * @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `\"left\" || \"right\" || \"center\" || \"start\" || \"end\"`.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n text(text, x, y, options) {\n var _a, _b, _c;\n options = options || {};\n const color = options.color || \"black\";\n const lineHeight = ((_b = (_a = options.lineHeight) !== null && _a !== void 0 ? _a : options.fontSize) !== null && _b !== void 0 ? _b : 0) * this.scale.x;\n // https://www.w3.org/TR/SVG/text.html#TextAnchorProperty\n // start | middle | end\n const textAlign = options.textAlign === \"left\" || options.textAlign === \"start\"\n ? \"start\"\n : options.textAlign === \"center\"\n ? \"middle\"\n : options.textAlign === \"right\" || options.textAlign === \"end\"\n ? \"end\"\n : \"start\";\n const transformOrigin = `${this._x(x)}px ${this._y(y)}px`;\n const translate = `translate(${this._x(x)} ${this._y(y) + lineHeight / 2})`;\n // Safari has a transform-origin/rotation bug.\n // It's essential to use rotate(r,x,y) here. \"rotate(r)\"\" with transform-origin(x,y) won't do the job.\n // And rotate and translate cannot be used is combination on a text object.\n // So wrap the text inside a <g>, translate the <g>, and rotate the text inside.\n const rotate = options.rotation ? `rotate(${options.rotation * RAD_TO_DEG} 0 0)` : ``;\n const node = this.makeNode(\"g\");\n const curId = this.curId;\n this.curId = curId + \"_text\";\n const textNode = this.makeNode(\"text\");\n node.appendChild(textNode);\n textNode.setAttribute(\"font-family\", (_c = options.fontFamily) !== null && _c !== void 0 ? _c : \"\"); // May be undefined\n textNode.setAttribute(\"font-size\", options.fontSize ? `${options.fontSize * this.scale.x}` : \"\");\n textNode.setAttribute(\"font-style\", options.fontStyle ? `${options.fontStyle}` : \"\");\n textNode.setAttribute(\"font-weight\", options.fontWeight ? `${options.fontWeight}` : \"\");\n textNode.setAttribute(\"text-anchor\", textAlign);\n textNode.setAttribute(\"transform-origin\", \"0 0\");\n textNode.setAttribute(\"transform\", rotate);\n node.setAttribute(\"transform-origin\", transformOrigin);\n node.setAttribute(\"transform\", translate);\n textNode.innerHTML = text;\n // Restore old ID\n this.curId = curId;\n return this._bindFillDraw(node, \"text\", color, 1);\n }\n /**\n * Draw a non-scaling text label at the given position.\n *\n * @method label\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {number=} rotation - The (optional) rotation in radians.\n * @param {string=\"black\"} color - The color to use (default is black).\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n label(text, x, y, rotation, color) {\n const node = this.makeNode(\"text\");\n // For some strange reason SVG rotation transforms use degrees instead of radians\n node.setAttribute(\"transform\", `translate(${x},${y}), rotate(${((rotation || 0) / Math.PI) * 180})`);\n node.setAttribute(\"font-family\", \"Arial\");\n node.setAttribute(\"font-size\", \"9pt\");\n node.setAttribute(\"font-style\", \"normal\");\n node.setAttribute(\"font-weight\", \"lighter\");\n node.innerHTML = text;\n return this._bindFillDraw(node, \"label\", color || \"black\", null);\n }\n /**\n * Draw an SVG-like path given by the specified path data.\n *\n * @method path\n * @param {SVGPathData} pathData - An array of path commands and params.\n * @param {string=null} color - (optional) The color to draw this path with (default is null).\n * @param {number=1} lineWidth - (optional) the line width to use (default is 1).\n * @param {boolean=false} options.inplace - (optional) If set to true then path transforamtions (scale and translate) will be done in-place in the array. This can boost the performance.\n * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.\n * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.\n *\n * @instance\n * @memberof drawutils\n * @return {R} An instance representing the drawn path.\n */\n path(pathData, color, lineWidth, options) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, options);\n // Transform the path: in-place (fast) or copy (slower)\n const d = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);\n drawutilssvg.transformPathData(d, this.offset, this.scale);\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"path\", color, lineWidth);\n }\n /**\n * Due to gl compatibility there is a generic 'clear' function required\n * to avoid accessing the context object itself directly.\n *\n * This function just fills the whole canvas with a single color.\n *\n * @param {string} color - The color to clear with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n clear(color) {\n // If this isn't the primary handler then do not remove anything here.\n // The primary handler will do that (no double work).\n if (this.isSecondary) {\n return;\n }\n // Add a covering rect with the given background color\n this.curId = \"background\";\n this.curClassName = null; // undefined;\n const node = this.makeNode(\"rect\");\n // For some strange reason SVG rotation transforms use degrees instead of radians\n // Note that the background does not scale with the zoom level (always covers full element)\n node.setAttribute(\"x\", \"0\");\n node.setAttribute(\"y\", \"0\");\n node.setAttribute(\"width\", `${this.canvasSize.width}`);\n node.setAttribute(\"height\", `${this.canvasSize.height}`);\n // Bind this special element into the document\n this._bindFillDraw(node, this.curId, null, null);\n node.setAttribute(\"fill\", typeof color === \"undefined\" ? \"none\" : color);\n // Clear the current ID again\n this.curId = null; // undefined;\n }\n /**\n * A private helper function to clear all SVG nodes from the &gt;g> node.\n *\n * @private\n */\n removeAllChildNodes() {\n while (this.bufferGNode.lastChild) {\n this.bufferGNode.removeChild(this.bufferGNode.lastChild);\n }\n while (this.bufferedNodeDefs.lastChild) {\n this.bufferedNodeDefs.removeChild(this.bufferedNodeDefs.lastChild);\n }\n }\n /**\n * Create a new and empty `SVGElement` &lt;svg&gt; in the svg-namespace.\n *\n * @name createSvg\n * @static\n * @memberof drawutilssvg\n * @return SVGElement\n */\n static createSvg() {\n return document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n }\n /**\n * Create a copy of the given path data. As path data only consists of strings and numbers,\n * the copy will be shallow by definition.\n *\n * @name copyPathData\n * @static\n * @memberof drawutilssvg\n */\n static copyPathData(data) {\n const copy = new Array(data.length);\n for (var i = 0, n = data.length; i < n; i++) {\n copy[i] = data[i];\n }\n return copy;\n }\n /**\n * Transform the given path data (translate and scale. rotating is not intended here).\n *\n * @name transformPathData\n * @static\n * @memberof drawutilssvg\n * @param {SVGPathParams} data - The data to transform.\n * @param {XYCoords} offset - The translation offset (neutral is x=0, y=0).\n * @param {XYCoords} scale - The scale factors (neutral is x=1, y=1).\n */\n static transformPathData(data, offset, scale) {\n // Scale and translate {x,y}\n const _stx = (index) => {\n data[index] = offset.x + scale.x * Number(data[index]);\n };\n const _sty = (index) => {\n data[index] = offset.y + scale.y * Number(data[index]);\n };\n // scale only {x,y}\n const _sx = (index) => {\n data[index] = scale.x * Number(data[index]);\n };\n const _sy = (index) => {\n data[index] = scale.y * Number(data[index]);\n };\n var i = 0;\n var lastPoint = { x: NaN, y: NaN };\n // \"save last point\"\n var _slp = (index) => {\n lastPoint.x = Number(data[index]);\n lastPoint.y = Number(data[index + 1]);\n };\n while (i < data.length) {\n const cmd = data[i];\n switch (cmd) {\n case \"M\":\n // MoveTo: M|m x y\n case \"L\":\n // LineTo L|l x y\n case \"T\":\n // Shorthand/smooth quadratic Bézier curveto: T|t x y\n _stx(i + 1);\n _sty(i + 2);\n _slp(i + 1);\n i += 3;\n break;\n case \"m\":\n // MoveTo: M|m x y\n case \"l\":\n // LineTo L|l x y\n case \"t\":\n // Shorthand/smooth quadratic Bézier curveto: T|t x y\n _sx(i + 1);\n _sy(i + 2);\n _slp(i + 1);\n i += 3;\n break;\n case \"H\":\n // HorizontalLineTo: H|h x\n _stx(i + 1);\n lastPoint.x = Number(data[i + 1]);\n i += 2;\n break;\n case \"h\":\n // HorizontalLineTo: H|h x\n _sx(i + 1);\n lastPoint.x = Number(data[i + 1]);\n i += 2;\n break;\n case \"V\":\n // VerticalLineTo: V|v y\n _sty(i + 1);\n lastPoint.y = Number(data[i + 1]);\n i += 2;\n break;\n case \"v\":\n // VerticalLineTo: V|v y\n _sy(i + 1);\n lastPoint.y = Number(data[i + 1]);\n i += 2;\n break;\n case \"C\":\n // CurveTo: C|c x1 y1 x2 y2 x y\n _stx(i + 1);\n _sty(i + 2);\n _stx(i + 3);\n _sty(i + 4);\n _stx(i + 5);\n _sty(i + 6);\n _slp(i + 5);\n i += 7;\n break;\n case \"c\":\n // CurveTo: C|c x1 y1 x2 y2 x y\n _sx(i + 1);\n _sy(i + 2);\n _sx(i + 3);\n _sy(i + 4);\n _sx(i + 5);\n _sy(i + 6);\n _slp(i + 5);\n i += 7;\n break;\n case \"S\":\n case \"Q\":\n // Shorthand-/SmoothCurveTo: S|s x2 y2 x y\n // QuadraticCurveTo: Q|q x1 y1 x y\n _stx(i + 1);\n _sty(i + 2);\n _stx(i + 3);\n _sty(i + 4);\n _slp(i + 3);\n i += 5;\n break;\n case \"s\":\n case \"q\":\n // Shorthand-/SmoothCurveTo: S|s x2 y2 x y\n // QuadraticCurveTo: Q|q x1 y1 x y\n _sx(i + 1);\n _sy(i + 2);\n _sx(i + 3);\n _sy(i + 4);\n _slp(i + 3);\n i += 5;\n break;\n case \"A\":\n // EllipticalArcTo: A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y\n // Uniform scale: just scale\n // NOTE: here is something TODO\n // * if scalex!=scaleY this won't work\n // * Arcs have to be converted to Bézier curves here in that case\n _sx(i + 1);\n _sy(i + 2);\n _stx(i + 6);\n _sty(i + 7);\n _slp(i + 6);\n // Update the arc flag when x _or_ y scale is negative\n if ((scale.x < 0 && scale.y >= 0) || (scale.x >= 0 && scale.y < 0)) {\n data[i + 5] = data[i + 5] ? 0 : 1;\n }\n i += 8;\n break;\n case \"a\":\n // EllipticalArcTo: A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y\n _sx(i + 1);\n _sy(i + 2);\n _sx(i + 6);\n _sy(i + 7);\n _slp(i + 6);\n i += 8;\n break;\n case \"z\":\n case \"Z\":\n // ClosePath: Z|z (no arguments)\n // lastPoint.x = firstPoint.x;\n // lastPoint.y = firstPoint.y;\n i++;\n break;\n // Safepoint: continue reading token by token until something is recognized again\n default:\n i++;\n }\n } // END while\n } // END transformPathData\n static nodeSupportsLineDash(nodeName) {\n return [\"line\", \"path\", \"circle\", \"ellipse\", \"rectangle\", \"rect\"].includes(nodeName);\n }\n /**\n * Creates a basic <line> node with start and end coordinates. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makeLineNode\n * @param {XYCoords} zA - The line's start position.\n * @param {XYCoords} zB - The line's start position.\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.\n * @return {SVGLineElement}\n * @instance\n * @memberof drawutilssvg\n */\n makeLineNode(zA, zB, color, lineWidth, strokeOptions, classNameOverride) {\n const line = this.makeNode(\"line\");\n line.setAttribute(\"x1\", `${this._x(zA.x)}`);\n line.setAttribute(\"y1\", `${this._y(zA.y)}`);\n line.setAttribute(\"x2\", `${this._x(zB.x)}`);\n line.setAttribute(\"y2\", `${this._y(zB.y)}`);\n this._configureNode(line, classNameOverride !== null && classNameOverride !== void 0 ? classNameOverride : \"line\", this.fillShapes, color, lineWidth || 1, strokeOptions);\n return line;\n }\n /**\n * Creates a basic <path> node with given path string data. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makePathNode\n * @param {string} pathString - The path data (must be a valid path data string).\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.\n * @return {SVGPathElement}\n * @instance\n * @memberof drawutilssvg\n */\n makePathNode(pathString, color, lineWidth, strokeOptions, classNameOverride) {\n const path = this.makeNode(\"path\");\n path.setAttribute(\"d\", pathString);\n this._configureNode(path, classNameOverride !== null && classNameOverride !== void 0 ? classNameOverride : \"path\", this.fillShapes, color, lineWidth || 1, strokeOptions);\n return path;\n }\n /**\n * Creates a basic arrow head node (<path> node) at the end of the given line coordinates. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makeArrowHeadNode\n * @param {string} pathString - The path data (must be a valid path data string).\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {number=8} headLength - (optional) The length of the arrow head; if none is specified then the head will be 8 absolute units long.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.\n * @return {SVGPathElement}\n * @instance\n * @memberof drawutilssvg\n */\n makeArrowHeadNode(zA, zB, color, lineWidth, headLength = 8, strokeOptions, arrowHeadBasePositionBuffer) {\n var vertices = Vector.utils.buildArrowHead(zA, zB, headLength, this.scale.x, this.scale.y);\n const d = [\"M\", this.offset.x + vertices[0].x, this.offset.y + vertices[0].y];\n if (arrowHeadBasePositionBuffer) {\n arrowHeadBasePositionBuffer.x = vertices[0].x / this.scale.x;\n arrowHeadBasePositionBuffer.y = vertices[0].y / this.scale.y;\n }\n for (var i = 1; i <= vertices.length; i++) {\n d.push(\"L\");\n // Note: only use offset here (the vertices are already scaled)\n d.push(this.offset.x + vertices[i % vertices.length].x);\n d.push(this.offset.y + vertices[i % vertices.length].y);\n }\n const node = this.makePathNode(d.join(\" \"), color, lineWidth, strokeOptions, \"arrowhead\");\n return node;\n }\n /**\n * Creates a basic cubic Bézier path node (<path> node) with the given cubic Bézier data. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makeCubicBezierNode\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.\n * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.\n * @return {SVGPathElement}\n * @instance\n * @memberof drawutilssvg\n */\n makeCubicBezierNode(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions) {\n if (startPoint instanceof CubicBezierCurve) {\n return this.cubicBezier(startPoint.startPoint, startPoint.endPoint, startPoint.startControlPoint, startPoint.endControlPoint, color, lineWidth);\n }\n // Draw curve\n const d = [\n \"M\",\n this._x(startPoint.x),\n this._y(startPoint.y),\n \"C\",\n this._x(startControlPoint.x),\n this._y(startControlPoint.y),\n this._x(endControlPoint.x),\n this._y(endControlPoint.y),\n this._x(endPoint.x),\n this._y(endPoint.y)\n ];\n const node = this.makePathNode(d.join(\" \"), color, lineWidth, strokeOptions, \"cubicBezier\");\n return node;\n }\n}\ndrawutilssvg.HEAD_XML = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>',\n '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" ',\n ' \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">',\n \"\"\n].join(\"\\n\");\n//# sourceMappingURL=drawutilssvg.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-04-22\n * @modified 2018-08-16 Added the curve() function to draw cubic bézier curves.\n * @modified 2018-10-23 Recognizing the offset param in the circle() function.\n * @modified 2018-11-27 Added the diamondHandle() function.\n * @modified 2018-11-28 Added the grid() function and the ellipse() function.\n * @modified 2018-11-30 Renamed the text() function to label() as it is not scaling.\n * @modified 2018-12-06 Added a test function for drawing arc in SVG style.\n * @modified 2018-12-09 Added the dot(Vertex,color) function (copied from Feigenbaum-plot-script).\n * @modified 2019-01-30 Added the arrow(Vertex,Vertex,color) function for drawing arrow heads.\n * @modified 2019-01-30 Added the image(Image,Vertex,Vertex) function for drawing images.\n * @modified 2019-04-27 Fixed a severe drawing bug in the arrow(...) function. Scaling arrows did not work properly.\n * @modified 2019-04-28 Added Math.round to the dot() drawing parameters to really draw a singlt dot.\n * @modified 2019-06-07 Fixed an issue in the cubicBezier() function. Paths were always closed.\n * @modified 2019-10-03 Added the beginDrawCycle hook.\n * @modified 2019-10-25 Polygons are no longer drawn with dashed lines (solid lines instead).\n * @modified 2019-11-18 Added the polyline function.\n * @modified 2019-11-22 Added a second workaround for th drawImage bug in Safari.\n * @modified 2019-12-07 Added the 'lineWidth' param to the line(...) function.\n * @modified 2019-12-07 Added the 'lineWidth' param to the cubicBezier(...) function.\n * @modified 2019-12-11 Added the 'color' param to the label(...) function.\n * @modified 2019-12-18 Added the quadraticBezier(...) function (for the sake of approximating Lissajous curves).\n * @modified 2019-12-20 Added the 'lineWidth' param to the polyline(...) function.\n * @modified 2020-01-09 Added the 'lineWidth' param to the ellipse(...) function.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-05-05 Added the 'lineWidth' param to the circle(...) function.\n * @modified 2020-05-12 Drawing any handles (square, circle, diamond) with lineWidth 1 now; this was not reset before.\n * @modified 2020-06-22 Added a context.clearRect() call to the clear() function; clearing with alpha channel did not work as expected.\n * @modified 2020-09-07 Added the circleArc(...) function to draw sections of circles.\n * @modified 2020-10-06 Removed the .closePath() instruction from the circleArc function.\n * @modified 2020-10-15 Re-added the text() function.\n * @modified 2020-10-28 Added the path(Path2D) function.\n * @modified 2020-12-28 Added the `singleSegment` mode (test).\n * @modified 2021-01-05 Added the image-loaded/broken check.\n * @modified 2021-01-24 Added the `setCurrentId` function from the `DrawLib` interface.\n * @modified 2021-02-22 Added the `path` drawing function to draw SVG path data.\n * @modified 2021-03-31 Added the `endDrawCycle` function from `DrawLib`.\n * @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.\n * @modified 2021-11-12 Adding more parameters tot the `text()` function: fontSize, textAlign, fontFamily, lineHeight.\n * @modified 2021-11-19 Added the `color` param to the `label(...)` function.\n * @modified 2022-02-03 Added the `lineWidth` param to the `crosshair` function.\n * @modified 2022-02-03 Added the `cross(...)` function.\n * @modified 2022-03-27 Added the `texturedPoly` function.\n * @modified 2022-06-01 Tweaked the `polyline` function; lineWidth now scales with scale.x.\n * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.\n * @modified 2022-08-23 Fixed a type issue in the `polyline` function.\n * @modified 2022-08-23 Fixed a type issue in the `setConfiguration` function.\n * @modified 2022-08-23 Fixed a type issue in the `path` function.\n * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.\n * @modified 2023-09-29 Removed unused method stub for texturedPoly helper function (cleanup).\n * @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.\n * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.\n * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `lineDashes` attribute.\n * @modified 2023-09-30 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.\n * @modified 2023-10-07 Adding the optional `arrowHeadBasePositionBuffer` param to the arrowHead(...) method.\n * @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.\n * @version 1.13.0\n **/\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { Vertex } from \"./Vertex\";\nimport { drawutilssvg } from \"./drawutilssvg\";\nimport { Vector } from \"./Vector\";\n// Todo: rename this class to Drawutils?\n/**\n * @classdesc A wrapper class for basic drawing operations.\n *\n * @requires CubicBzierCurvce\n * @requires Polygon\n * @requires Vertex\n * @requires XYCoords\n */\nexport class drawutils {\n /**\n * The constructor.\n *\n * @constructor\n * @name drawutils\n * @param {anvasRenderingContext2D} context - The drawing context.\n * @param {boolean} fillShaped - Indicates if the constructed drawutils should fill all drawn shapes (if possible).\n **/\n constructor(context, fillShapes) {\n this.ctx = context;\n // this.lineDash = [];\n this.offset = new Vertex(0, 0);\n this.scale = new Vertex(1, 1);\n this.fillShapes = fillShapes;\n }\n /**\n * A private helper method to apply stroke options to the current\n * context.\n * @param {StrokeOptions=} strokeOptions -\n */\n applyStrokeOpts(strokeOptions) {\n var _a, _b;\n this.ctx.setLineDash(((_a = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.dashArray) !== null && _a !== void 0 ? _a : []).map((dashArrayElem) => {\n // Note assume scale.x === scale.y\n // Invariant scale makes funny stuff anyway.\n return dashArrayElem * this.scale.x;\n }));\n this.ctx.lineDashOffset = ((_b = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.dashOffset) !== null && _b !== void 0 ? _b : 0) * this.scale.x;\n }\n // +---------------------------------------------------------------------------------\n // | This is the final helper function for drawing and filling stuff. It is not\n // | intended to be used from the outside.\n // |\n // | When in draw mode it draws the current shape.\n // | When in fill mode it fills the current shape.\n // |\n // | This function is usually only called internally.\n // |\n // | @param color A stroke/fill color to use.\n // +-------------------------------\n // TODO: convert this to a STATIC function.\n _fillOrDraw(color) {\n if (this.fillShapes) {\n this.ctx.fillStyle = color;\n this.ctx.fill();\n }\n else {\n this.ctx.strokeStyle = color;\n this.ctx.stroke();\n }\n }\n /**\n * Called before each draw cycle.\n * @param {UID=} uid - (optional) A UID identifying the currently drawn element(s).\n **/\n beginDrawCycle(renderTime) {\n // NOOP\n }\n /**\n * Called after each draw cycle.\n *\n * This is required for compatibility with other draw classes in the library (like drawgl).\n *\n * @name endDrawCycle\n * @method\n * @param {number} renderTime\n * @instance\n **/\n endDrawCycle(renderTime) {\n // NOOP\n }\n /**\n * Set the current drawlib configuration.\n *\n * @name setConfiguration\n * @method\n * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.\n */\n setConfiguration(configuration) {\n this.ctx.globalCompositeOperation = configuration.blendMode || \"source-over\";\n }\n // /**\n // * Set or clear the line-dash configuration. Pass `null` for un-dashed lines.\n // *\n // * See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray\n // * and https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash\n // * for how line dashes work.\n // *\n // * @method\n // * @param {Array<number> lineDashes - The line-dash array configuration.\n // * @returns {void}\n // */\n // setLineDash(lineDash: Array<number>) {\n // this.lineDash = lineDash;\n // }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * It is used by some libraries for identifying elemente on re-renders.\n *\n * @name setCurrentId\n * @method\n * @param {UID|null} uid - A UID identifying the currently drawn element(s).\n **/\n setCurrentId(uid) {\n // NOOP\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * Determine the class name for further usage here.\n *\n * @name setCurrentClassName\n * @method\n * @param {string|null} className - A class name for further custom use cases.\n **/\n setCurrentClassName(className) {\n // NOOP\n }\n /**\n * Draw the line between the given two points with the specified (CSS-) color.\n *\n * @method line\n * @param {XYCoords} zA - The start point of the line.\n * @param {XYCoords} zB - The end point of the line.\n * @param {string} color - Any valid CSS color string.\n * @param {number} lineWidth? - [optional] The line's width.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n line(zA, zB, color, lineWidth, strokeOptions) {\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + zA.x * this.scale.x, this.offset.y + zA.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + zB.x * this.scale.x, this.offset.y + zB.y * this.scale.y);\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = lineWidth || 1;\n this.ctx.stroke();\n this.ctx.restore();\n }\n /**\n * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n arrow(zA, zB, color, lineWidth, headLength = 8, strokeOptions) {\n const arrowHeadBasePosition = new Vertex(0, 0);\n this.arrowHead(zA, zB, color, lineWidth, headLength, undefined, arrowHeadBasePosition); // Will NOT use dash configuration\n this.line(zA, arrowHeadBasePosition, color, lineWidth, strokeOptions); // Will use dash configuration\n }\n /**\n * Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.\n *\n * @method cubicBezierArrow\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n */\n cubicBezierArrow(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, headLength, strokeOptions) {\n const arrowHeadBasePosition = new Vertex(0, 0);\n // Will NOT use dash configuration\n this.arrowHead(endControlPoint, endPoint, color, lineWidth, headLength, undefined, arrowHeadBasePosition);\n const diff = arrowHeadBasePosition.difference(endPoint);\n // Will use dash configuration\n this.cubicBezier(startPoint, { x: endPoint.x - diff.x, y: endPoint.y - diff.y }, startControlPoint, { x: endControlPoint.x - diff.x, y: endControlPoint.y - diff.y }, color, lineWidth, strokeOptions);\n }\n /**\n * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n **/\n arrowHead(zA, zB, color, lineWidth, headLength = 8, strokeOptions, arrowHeadBasePositionBuffer) {\n // var headLength: number = 8; // length of head in pixels\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n var vertices = Vector.utils.buildArrowHead(zA, zB, headLength, this.scale.x, this.scale.y);\n if (arrowHeadBasePositionBuffer) {\n arrowHeadBasePositionBuffer.x = vertices[0].x / this.scale.x;\n arrowHeadBasePositionBuffer.y = vertices[0].y / this.scale.y;\n }\n this.ctx.moveTo(this.offset.x + vertices[0].x, this.offset.y + vertices[0].y);\n for (var i = 0; i < vertices.length; i++) {\n this.ctx.lineTo(this.offset.x + vertices[i].x, this.offset.y + vertices[i].y);\n }\n this.ctx.lineTo(this.offset.x + vertices[0].x, this.offset.y + vertices[0].y);\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method image\n * @param {Image} image - The image object to draw.\n * @param {XYCoords} position - The position to draw the the upper left corner at.\n * @param {XYCoords} size - The x/y-size to draw the image with.\n * @param {number=0.0} alpha - (optional, default=0.0) The transparency (1.0=opaque, 0.0=transparent).\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n image(image, position, size, alpha = 1.0) {\n if (!image.complete || !image.naturalWidth) {\n // Avoid drawing un-unloaded or broken images\n return;\n }\n this.ctx.save();\n this.ctx.globalAlpha = alpha;\n // Note that there is a Safari bug with the 3 or 5 params variant.\n // Only the 9-param varaint works.\n this.ctx.drawImage(image, 0, 0, image.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n image.naturalHeight - 1, // To avoid errors substract 1 here.\n this.offset.x + position.x * this.scale.x, this.offset.y + position.y * this.scale.y, size.x * this.scale.x, size.y * this.scale.y);\n this.ctx.restore();\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method texturedPoly\n * @param {Image} textureImage - The image object to draw.\n * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.\n * @param {Polygon} polygon - The polygon to use as clip path.\n * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.\n * @param {number} rotation - The rotation to use for the polygon (and for the texture).\n * @param {XYCoords={x:0,y:0}} rotationCenter - (optional) The rotational center; default is center of bounding box.\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n texturedPoly(textureImage, textureSize, polygon, polygonPosition, rotation) {\n var basePolygonBounds = polygon.getBounds();\n // var targetCenterDifference = polygonPosition.clone().difference(basePolygonBounds.getCenter());\n var targetCenterDifference = new Vertex(polygonPosition.x, polygonPosition.y).difference(basePolygonBounds.getCenter());\n // var tileCenter = basePolygonBounds.getCenter().sub(targetCenterDifference);\n // Get the position offset of the polygon\n var targetTextureSize = new Vertex(textureSize.width, textureSize.height);\n // var targetTextureOffset = new Vertex(-textureSize.width / 2, -textureSize.height / 2).sub(targetCenterDifference);\n var targetTextureOffset = new Vertex(textureSize.min.x, textureSize.min.y).sub(polygonPosition);\n this.ctx.save();\n // this.ctx.translate(this.offset.x + rotationCenter.x * this.scale.x, this.offset.y + rotationCenter.y * this.scale.y);\n this.ctx.translate(this.offset.x + polygonPosition.x * this.scale.x, this.offset.y + polygonPosition.y * this.scale.y);\n drawutils.helpers.clipPoly(this.ctx, {\n x: -polygonPosition.x * this.scale.x,\n y: -polygonPosition.y * this.scale.y\n }, this.scale, polygon.vertices);\n this.ctx.scale(this.scale.x, this.scale.y);\n this.ctx.rotate(rotation);\n this.ctx.drawImage(textureImage, 0, 0, textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n textureImage.naturalHeight - 1, // To avoid errors substract 1 here.\n targetTextureOffset.x, // * this.scale.x,\n targetTextureOffset.y, // * this.scale.y,\n targetTextureSize.x, // * this.scale.x,\n targetTextureSize.y // * this.scale.y\n );\n this.ctx.restore();\n }\n /*\n _texturedPoly(\n textureImage: HTMLImageElement,\n textureSize: Bounds,\n polygon: Polygon,\n polygonPosition: XYCoords,\n rotation: number,\n rotationCenter: XYCoords = { x: 0, y: 0 }\n ): void {\n var basePolygonBounds = polygon.getBounds();\n var targetCenterDifference = polygonPosition.clone().difference(basePolygonBounds.getCenter());\n var rotationalOffset = rotationCenter ? polygonPosition.difference(rotationCenter) : { x: 0, y: 0 };\n // var rotationalOffset = { x: 0, y: 0 };\n var tileCenter = basePolygonBounds.getCenter().sub(targetCenterDifference);\n \n // Get the position offset of the polygon\n var targetTextureSize = new Vertex(textureSize.width, textureSize.height);\n var targetTextureOffset = new Vertex(-textureSize.width / 2, -textureSize.height / 2).sub(targetCenterDifference);\n \n this.ctx.save();\n \n // this.ctx.translate(\n // this.offset.x + (tileCenter.x - rotationalOffset.x * 0 + targetTextureOffset.x * 0.0) * this.scale.x,\n // this.offset.y + (tileCenter.y - rotationalOffset.y * 0 + targetTextureOffset.y * 0.0) * this.scale.y\n // );\n this.ctx.translate(\n this.offset.x + (tileCenter.x - rotationalOffset.x * 0 + targetTextureOffset.x * 0.0) * this.scale.x,\n this.offset.y + (tileCenter.y - rotationalOffset.y * 0 + targetTextureOffset.y * 0.0) * this.scale.y\n );\n this.ctx.rotate(rotation);\n \n drawutils.helpers.clipPoly(\n this.ctx,\n {\n x: (-targetCenterDifference.x * 1 - tileCenter.x - rotationalOffset.x) * this.scale.x,\n y: (-targetCenterDifference.y * 1 - tileCenter.y - rotationalOffset.y) * this.scale.y\n },\n this.scale,\n polygon.vertices\n );\n this.ctx.drawImage(\n textureImage,\n 0,\n 0,\n textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n textureImage.naturalHeight - 1, // To avoid errors substract 1 here.\n (-polygonPosition.x + targetTextureOffset.x * 1 - rotationalOffset.x * 1) * this.scale.x,\n (-polygonPosition.y + targetTextureOffset.y * 1 - rotationalOffset.y * 1) * this.scale.y,\n targetTextureSize.x * this.scale.x,\n targetTextureSize.y * this.scale.y\n );\n \n // const scaledTextureSize = new Bounds(\n // new Vertex(\n // -polygonPosition.x + targetTextureOffset.x - rotationalOffset.x,\n // -polygonPosition.y + targetTextureOffset.y - rotationalOffset.y\n // ).scaleXY(this.scale, rotationCenter),\n // new Vertex(\n // -polygonPosition.x + targetTextureOffset.x - rotationalOffset.x + targetTextureSize.x,\n // -polygonPosition.y + targetTextureOffset.y - rotationalOffset.y + targetTextureSize.y\n // ).scaleXY(this.scale, rotationCenter)\n // );\n // this.ctx.drawImage(\n // textureImage,\n // 0,\n // 0,\n // textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n // textureImage.naturalHeight - 1, // To avoid errors substract 1 here.\n // scaledTextureSize.min.x,\n // scaledTextureSize.min.y,\n // scaledTextureSize.width,\n // scaledTextureSize.height\n // );\n \n this.ctx.restore();\n }\n */\n /**\n * Draw a rectangle.\n *\n * @param {XYCoords} position - The upper left corner of the rectangle.\n * @param {number} width - The width of the rectangle.\n * @param {number} height - The height of the rectangle.\n * @param {string} color - The color to use.\n * @param {number=1} lineWidth - (optional) The line with to use (default is 1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n rect(position, width, height, color, lineWidth, strokeOptions) {\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + position.x * this.scale.x, this.offset.y + position.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + (position.x + width) * this.scale.x, this.offset.y + position.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + (position.x + width) * this.scale.x, this.offset.y + (position.y + height) * this.scale.y);\n this.ctx.lineTo(this.offset.x + position.x * this.scale.x, this.offset.y + (position.y + height) * this.scale.y);\n // this.ctx.lineTo( this.offset.x+position.x*this.scale.x, this.offset.y+position.y*this.scale.y );\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given (cubic) bézier curve.\n *\n * @method cubicBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezier(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions) {\n if (startPoint instanceof CubicBezierCurve) {\n this.cubicBezier(startPoint.startPoint, startPoint.endPoint, startPoint.startControlPoint, startPoint.endControlPoint, color, lineWidth);\n return;\n }\n // Draw curve\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + startPoint.x * this.scale.x, this.offset.y + startPoint.y * this.scale.y);\n this.ctx.bezierCurveTo(this.offset.x + startControlPoint.x * this.scale.x, this.offset.y + startControlPoint.y * this.scale.y, this.offset.x + endControlPoint.x * this.scale.x, this.offset.y + endControlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);\n //this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 2;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given (quadratic) bézier curve.\n *\n * @method quadraticBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} controlPoint - The control point the cubic Bézier curve.\n * @param {XYCoords} endPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number|string} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n quadraticBezier(startPoint, controlPoint, endPoint, color, lineWidth, strokeOptions) {\n // Draw curve\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + startPoint.x * this.scale.x, this.offset.y + startPoint.y * this.scale.y);\n this.ctx.quadraticCurveTo(this.offset.x + controlPoint.x * this.scale.x, this.offset.y + controlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);\n this.ctx.lineWidth = lineWidth || 2;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given (cubic) Bézier path.\n *\n * The given path must be an array with n*3+1 vertices, where n is the number of\n * curves in the path:\n * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>\n *\n * @method cubicBezierPath\n * @param {XYCoords[]} path - The cubic bezier path as described above.\n * @param {string} color - The CSS colot to draw the path with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezierPath(path, color, lineWidth, strokeOptions) {\n if (!path || path.length == 0) {\n return;\n }\n // Draw curve\n this.ctx.save();\n this.ctx.beginPath();\n var endPoint;\n var startControlPoint;\n var endControlPoint;\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + path[0].x * this.scale.x, this.offset.y + path[0].y * this.scale.y);\n for (var i = 1; i < path.length; i += 3) {\n startControlPoint = path[i];\n endControlPoint = path[i + 1];\n endPoint = path[i + 2];\n this.ctx.bezierCurveTo(this.offset.x + startControlPoint.x * this.scale.x, this.offset.y + startControlPoint.y * this.scale.y, this.offset.x + endControlPoint.x * this.scale.x, this.offset.y + endControlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);\n }\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given handle and handle point (used to draw interactive Bézier curves).\n *\n * The colors for this are fixed and cannot be specified.\n *\n * @method handle\n * @param {XYCoords} startPoint - The start of the handle.\n * @param {XYCoords} endPoint - The end point of the handle.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handle(startPoint, endPoint) {\n // Draw handles\n // (No need to save and restore here)\n this.point(startPoint, \"rgb(0,32,192)\");\n this.square(endPoint, 5, \"rgba(0,128,192,0.5)\");\n }\n /**\n * Draw a handle line (with a light grey).\n *\n * @method handleLine\n * @param {XYCoords} startPoint - The start point to draw the handle at.\n * @param {XYCoords} endPoint - The end point to draw the handle at.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handleLine(startPoint, endPoint) {\n // Draw handle lines\n this.line(startPoint, endPoint, \"rgba(128,128,128, 0.5)\", undefined);\n }\n /**\n * Draw a 1x1 dot with the specified (CSS-) color.\n *\n * @method dot\n * @param {XYCoords} p - The position to draw the dot at.\n * @param {string} color - The CSS color to draw the dot with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n dot(p, color) {\n this.ctx.save();\n this.ctx.beginPath();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.moveTo(Math.round(this.offset.x + this.scale.x * p.x), Math.round(this.offset.y + this.scale.y * p.y));\n this.ctx.lineTo(Math.round(this.offset.x + this.scale.x * p.x + 1), Math.round(this.offset.y + this.scale.y * p.y + 1));\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given point with the specified (CSS-) color and radius 3.\n *\n * @method point\n * @param {XYCoords} p - The position to draw the point at.\n * @param {string} color - The CSS color to draw the point with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n point(p, color) {\n var radius = 3;\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.arc(this.offset.x + p.x * this.scale.x, this.offset.y + p.y * this.scale.y, radius, 0, 2 * Math.PI, false);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a circle with the specified (CSS-) color and radius.<br>\n * <br>\n * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.\n *\n * @method circle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {number} lineWidth - The line width (optional, default=1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circle(center, radius, color, lineWidth, strokeOptions) {\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius * this.scale.x, radius * this.scale.y, 0.0, 0.0, Math.PI * 2);\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a circular arc (section of a circle) with the given CSS color.\n *\n * @method circleArc\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {number} startAngle - The angle to start at.\n * @param {number} endAngle - The angle to end at.\n * @param {string=#000000} color - The CSS color to draw the circle with.\n * @param {number=1} lineWidth - The line width to use\n * @param {boolean=false} options.asSegment - If `true` then no beginPath and no draw will be applied (as part of larger path).\n * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.\n * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleArc(center, radius, startAngle, endAngle, color, lineWidth, options) {\n if (!options || !options.asSegment) {\n this.ctx.beginPath();\n }\n this.applyStrokeOpts(options);\n this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius * this.scale.x, radius * this.scale.y, 0.0, startAngle, endAngle, false);\n if (!options || !options.asSegment) {\n // this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color || \"#000000\");\n }\n }\n /**\n * Draw an ellipse with the specified (CSS-) color and thw two radii.\n *\n * @method ellipse\n * @param {XYCoords} center - The center of the ellipse.\n * @param {number} radiusX - The radius of the ellipse.\n * @param {number} radiusY - The radius of the ellipse.\n * @param {string} color - The CSS color to draw the ellipse with.\n * @param {number} lineWidth=1 - An optional line width param (default is 1).\n * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n ellipse(center, radiusX, radiusY, color, lineWidth, rotation, strokeOptions) {\n if (typeof rotation === \"undefined\") {\n rotation = 0.0;\n }\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radiusX * this.scale.x, radiusY * this.scale.y, rotation, 0.0, Math.PI * 2);\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw square at the given center, size and with the specified (CSS-) color.<br>\n * <br>\n * Note that if the x-scale and the y-scale are different the result will be a rectangle rather than a square.\n *\n * @method square\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @param {number} lineWidth - The line with to use (optional, default is 1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n square(center, size, color, lineWidth, strokeOptions) {\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.rect(this.offset.x + (center.x - size / 2.0) * this.scale.x, this.offset.y + (center.y - size / 2.0) * this.scale.y, size * this.scale.x, size * this.scale.y);\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a grid of horizontal and vertical lines with the given (CSS-) color.\n *\n * @method grid\n * @param {XYCoords} center - The center of the grid.\n * @param {number} width - The total width of the grid (width/2 each to the left and to the right).\n * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal grid size.\n * @param {number} sizeY - The vertical grid size.\n * @param {string} color - The CSS color to draw the grid with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n grid(center, width, height, sizeX, sizeY, color) {\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n var yMin = -Math.ceil((height * 0.5) / sizeY) * sizeY;\n var yMax = height / 2;\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n this.ctx.moveTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + yMin) * this.scale.y);\n this.ctx.lineTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + yMax) * this.scale.y);\n }\n var xMin = -Math.ceil((width * 0.5) / sizeX) * sizeX; // -Math.ceil((height*0.5)/sizeY)*sizeY;\n var xMax = width / 2; // height/2;\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n this.ctx.moveTo(this.offset.x + (center.x + xMin) * this.scale.x - 4, this.offset.y + (center.y + y) * this.scale.y);\n this.ctx.lineTo(this.offset.x + (center.x + xMax) * this.scale.x + 4, this.offset.y + (center.y + y) * this.scale.y);\n }\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = 1.0;\n this.ctx.stroke();\n this.ctx.closePath();\n }\n /**\n * Draw a raster of crosshairs in the given grid.<br>\n *\n * This works analogue to the grid() function\n *\n * @method raster\n * @param {XYCoords} center - The center of the raster.\n * @param {number} width - The total width of the raster (width/2 each to the left and to the right).\n * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal raster size.\n * @param {number} sizeY - The vertical raster size.\n * @param {string} color - The CSS color to draw the raster with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n raster(center, width, height, sizeX, sizeY, color) {\n this.ctx.save();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n // Draw a crosshair\n this.ctx.moveTo(this.offset.x + (center.x + x) * this.scale.x - 4, this.offset.y + (center.y + y) * this.scale.y);\n this.ctx.lineTo(this.offset.x + (center.x + x) * this.scale.x + 4, this.offset.y + (center.y + y) * this.scale.y);\n this.ctx.moveTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + y) * this.scale.y - 4);\n this.ctx.lineTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + y) * this.scale.y + 4);\n }\n }\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = 1.0;\n this.ctx.stroke();\n this.ctx.closePath();\n this.ctx.restore();\n }\n /**\n * Draw a diamond handle (square rotated by 45°) with the given CSS color.\n *\n * It is an inherent feature of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped diamonds.\n *\n * @method diamondHandle\n * @param {XYCoords} center - The center of the diamond.\n * @param {number} size - The x/y-size of the diamond.\n * @param {string} color - The CSS color to draw the diamond with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n diamondHandle(center, size, color) {\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - size / 2.0, this.offset.y + center.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y - size / 2.0);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + size / 2.0, this.offset.y + center.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y + size / 2.0);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a square handle with the given CSS color.<br>\n * <br>\n * It is an inherent feature of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped squares.\n *\n * @method squareHandle\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The x/y-size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n squareHandle(center, size, color) {\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.rect(this.offset.x + center.x * this.scale.x - size / 2.0, this.offset.y + center.y * this.scale.y - size / 2.0, size, size);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a circle handle with the given CSS color.<br>\n * <br>\n * It is an inherent feature of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped circles.\n *\n * @method circleHandle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleHandle(center, radius, color) {\n radius = radius || 3;\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.arc(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius, 0, 2 * Math.PI, false);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a crosshair with given radius and color at the given position.<br>\n * <br>\n * Note that the crosshair radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=0.5} lineWidth - (optional, default=0.5) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n crosshair(center, radius, color, lineWidth) {\n this.ctx.save();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - radius, this.offset.y + center.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + radius, this.offset.y + center.y * this.scale.y);\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y - radius);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y + radius);\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = lineWidth || 0.5;\n this.ctx.stroke();\n this.ctx.closePath();\n this.ctx.restore();\n }\n /**\n * Draw a cross with diagonal axes with given radius, color and lineWidth at the given position.<br>\n * <br>\n * Note that the x's radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=1} lineWidth - (optional, default=1.0) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cross(center, radius, color, lineWidth) {\n this.ctx.save();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - radius, this.offset.y + center.y * this.scale.y - radius);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + radius, this.offset.y + center.y * this.scale.y + radius);\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - radius, this.offset.y + center.y * this.scale.y + radius);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + radius, this.offset.y + center.y * this.scale.y - radius);\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = lineWidth || 1.0;\n this.ctx.stroke();\n this.ctx.closePath();\n this.ctx.restore();\n }\n /**\n * Draw a polygon.\n *\n * @method polygon\n * @param {Polygon} polygon - The polygon to draw.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {string} lineWidth - The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polygon(polygon, color, lineWidth, strokeOptions) {\n this.polyline(polygon.vertices, polygon.isOpen, color, lineWidth, strokeOptions);\n }\n /**\n * Draw a polygon line (alternative function to the polygon).\n *\n * @method polyline\n * @param {XYCoords[]} vertices - The polygon vertices to draw.\n * @param {boolan} isOpen - If true the polyline will not be closed at its end.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number} lineWidth - The line width (default is 1.0);\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polyline(vertices, isOpen, color, lineWidth, strokeOptions) {\n if (vertices.length <= 1) {\n return;\n }\n this.ctx.save();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.lineWidth = lineWidth || 1.0;\n this.ctx.moveTo(this.offset.x + vertices[0].x * this.scale.x, this.offset.y + vertices[0].y * this.scale.y);\n for (var i = 0; i < vertices.length; i++) {\n this.ctx.lineTo(this.offset.x + vertices[i].x * this.scale.x, this.offset.y + vertices[i].y * this.scale.y);\n }\n if (!isOpen)\n // && vertices.length > 2 )\n this.ctx.closePath();\n this._fillOrDraw(color);\n this.ctx.closePath();\n this.ctx.setLineDash([]);\n this.ctx.restore();\n }\n /**\n * Draw a text at the given relative position.\n *\n * @method text\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {string=} options.color - The Color to use.\n * @param {string=} options.fontFamily - The font family to use.\n * @param {number=} options.fontSize - The font size (in pixels) to use.\n * @param {FontStyle=} options.fontStyle - The font style to use.\n * @param {FontWeight=} options.fontWeight - The font weight to use.\n * @param {number=} options.lineHeight - The line height (in pixels) to use.\n * @param {number=} options.rotation - The (optional) rotation in radians.\n * @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `\"left\" || \"right\" || \"center\" || \"start\" || \"end\"`.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n text(text, x, y, options) {\n // See https://stackoverflow.com/a/23523697\n var _a, _b, _c;\n options = options || {};\n this.ctx.save();\n let relX = this.offset.x + x * this.scale.x;\n let relY = this.offset.y + y * this.scale.y;\n const color = options.color || \"black\";\n if (options.fontSize || options.fontFamily) {\n // Scaling of text only works in uniform mode\n this.ctx.font =\n (options.fontWeight ? options.fontWeight + \" \" : \"\") +\n (options.fontStyle ? options.fontStyle + \" \" : \"\") +\n (options.fontSize ? options.fontSize * this.scale.x + \"px \" : \" \") +\n (options.fontFamily\n ? options.fontFamily.indexOf(\" \") === -1\n ? options.fontFamily\n : `\"${options.fontFamily}\"`\n : \"Arial\");\n }\n if (options.textAlign) {\n this.ctx.textAlign = options.textAlign;\n }\n const rotation = (_a = options.rotation) !== null && _a !== void 0 ? _a : 0.0;\n const lineHeight = ((_c = (_b = options.lineHeight) !== null && _b !== void 0 ? _b : options.fontSize) !== null && _c !== void 0 ? _c : 0) * this.scale.x;\n this.ctx.translate(relX, relY);\n this.ctx.rotate(rotation);\n if (this.fillShapes) {\n this.ctx.fillStyle = color;\n this.ctx.fillText(text, 0, lineHeight / 2);\n }\n else {\n this.ctx.strokeStyle = color;\n this.ctx.strokeText(text, 0, lineHeight / 2);\n }\n // this.ctx.translate(-relX, -relY);\n // this.ctx.rotate(-rotation); // is this necessary before 'restore()'?\n this.ctx.restore();\n }\n /**\n * Draw a non-scaling text label at the given position.\n *\n * Note that these are absolute label positions, they are not affected by offset or scale.\n *\n * @method label\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {number=} rotation - The (optional) rotation in radians (default=0).\n * @param {string=} color - The color to render the text with (default=black).\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n label(text, x, y, rotation, color) {\n this.ctx.save();\n this.ctx.font = \"lighter 9pt Arial\";\n this.ctx.translate(x, y);\n if (typeof rotation !== \"undefined\")\n this.ctx.rotate(rotation);\n this.ctx.fillStyle = color || \"black\";\n if (this.fillShapes) {\n this.ctx.fillText(text, 0, 0);\n }\n else {\n this.ctx.strokeText(text, 0, 0);\n }\n this.ctx.restore();\n }\n /**\n * Draw an SVG-like path given by the specified path data.\n *\n *\n * @method path\n * @param {SVGPathData} pathData - An array of path commands and params.\n * @param {string=null} color - (optional) The color to draw this path with (default is null).\n * @param {number=1} lineWidth - (optional) the line width to use (default is 1).\n * @param {boolean=false} options.inplace - (optional) If set to true then path transforamtions (scale and translate) will be done in-place in the array. This can boost the performance.\n * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.\n * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.\n * @instance\n * @memberof drawutils\n * @return {R} An instance representing the drawn path.\n */\n path(pathData, color, lineWidth, options) {\n const d = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);\n drawutilssvg.transformPathData(d, this.offset, this.scale);\n if (color) {\n this.ctx.strokeStyle = color;\n }\n this.ctx.lineWidth = lineWidth || 1;\n this.applyStrokeOpts(options);\n if (this.fillShapes) {\n if (color) {\n this.ctx.fillStyle = color;\n }\n this.ctx.fill(new Path2D(d.join(\" \")));\n }\n else {\n if (color) {\n this.ctx.strokeStyle = color;\n }\n this.ctx.stroke(new Path2D(d.join(\" \")));\n }\n }\n /**\n * Due to gl compatibility there is a generic 'clear' function required\n * to avoid accessing the context object itself directly.\n *\n * This function just fills the whole canvas with a single color.\n *\n * @param {string} color - The color to clear with.\n **/\n clear(color) {\n this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n this.ctx.fillStyle = color;\n this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n }\n}\ndrawutils.helpers = {\n // A helper function to define the clipping path.\n // This could be a candidate for the draw library.\n clipPoly: (ctx, offset, scale, vertices) => {\n ctx.beginPath();\n // Set clip mask\n ctx.moveTo(offset.x + vertices[0].x * scale.x, offset.y + vertices[0].y * scale.y);\n for (var i = 1; i < vertices.length; i++) {\n const vert = vertices[i];\n ctx.lineTo(offset.x + vert.x * scale.x, offset.y + vert.y * scale.y);\n }\n ctx.closePath();\n ctx.clip();\n }\n};\n//# sourceMappingURL=draw.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-09-18\n * @modified 2019-10-03 Added the beginDrawCycle hook.\n * @modified 2020-03-25 Ported stub to Typescript.\n * @modified 2020-10-15 Re-added the text() function.\n * @modified 2021-01-24 Added the `setCurrentId` function.\n * @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.\n * @modified 2022-02-03 Added the `lineWidth` param to the `crosshair` function.\n * @modified 2022-02-03 Added the `cross(...)` function.\n * @modified 2022-03-27 Added the `texturedPoly` function.\n * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.\n * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.\n * @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.\n * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.\n * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `lineDashes` attribute.\n * @version 0.0.10\n **/\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A wrapper class for basic drawing operations. This is the WebGL\n * implementation whih sould work with shaders.\n *\n * @requires CubicBzierCurvce\n * @requires Polygon\n * @requires SVGSerializable\n * @requires Vertex\n * @requires XYCoords\n */\nexport class drawutilsgl {\n /**\n * The constructor.\n *\n * @constructor\n * @name drawutils\n * @param {WebGLRenderingContext|null} context - The drawing context.\n * @param {boolean} fillShaped - Indicates if the constructed drawutils should fill all drawn shapes (if possible).\n **/\n constructor(context, fillShapes) {\n this.gl = context;\n this.offset = new Vertex(0, 0);\n this.scale = new Vertex(1, 1);\n this.fillShapes = fillShapes;\n this._zindex = 0.0;\n if (context == null || typeof context === \"undefined\")\n return;\n this.glutils = new GLU(context);\n // PROBLEM: CANNOT USE MULTIPLE SHADER PROGRAM INSTANCES ON THE SAME CONTEXT!\n // SOLUTION: USE SHARED SHADER PROGRAM!!! ... somehow ...\n // This needs to be considered in the overlying component; both draw-instances need to\n // share their gl context.\n // That's what the copyInstace(boolean) method is good for.\n this._vertShader = this.glutils.compileShader(drawutilsgl.vertCode, this.gl.VERTEX_SHADER);\n this._fragShader = this.glutils.compileShader(drawutilsgl.fragCode, this.gl.FRAGMENT_SHADER);\n this._program = this.glutils.makeProgram(this._vertShader, this._fragShader);\n // Create an empty buffer object\n this.vertex_buffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n // this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertex_buffer);\n console.log(\"gl initialized\");\n }\n _x2rel(x) {\n return ((this.scale.x * x + this.offset.x) / this.gl.canvas.width) * 2.0 - 1.0;\n }\n _y2rel(y) {\n return ((this.offset.y - this.scale.y * y) / this.gl.canvas.height) * 2.0 - 1.0;\n }\n /**\n * Creates a 'shallow' (non deep) copy of this instance. This implies\n * that under the hood the same gl context and gl program will be used.\n */\n copyInstance(fillShapes) {\n var copy = new drawutilsgl(null, fillShapes);\n copy.gl = this.gl;\n copy.glutils = this.glutils;\n copy._vertShader = this._vertShader;\n copy._fragShader = this._fragShader;\n copy._program = this._program;\n return copy;\n }\n /**\n * Called before each draw cycle.\n * @param {number} renderTime\n **/\n beginDrawCycle(renderTime) {\n this._zindex = 0.0;\n this.renderTime = renderTime;\n }\n /**\n * Called after each draw cycle.\n *\n * This is required for compatibility with other draw classes in the library (like drawgl).\n *\n * @name endDrawCycle\n * @method\n * @param {number} renderTime\n * @instance\n **/\n endDrawCycle(renderTime) {\n // NOOP\n }\n /**\n * Set the current drawlib configuration.\n *\n * @name setConfiguration\n * @method\n * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.\n */\n setConfiguration(configuration) {\n // TODO\n }\n // /**\n // * Set or clear the line-dash configuration. Pass `null` for un-dashed lines.\n // *\n // * See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray\n // * and https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash\n // * for how line dashes work.\n // *\n // * @method\n // * @param {Array<number> lineDashes - The line-dash array configuration.\n // * @returns {void}\n // */\n // setLineDash(lineDashes: Array<number>) {\n // // TODO\n // }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * It is used by some libraries for identifying elemente on re-renders.\n *\n * @name setCurrentId\n * @method\n * @param {UID|null} uid - A UID identifying the currently drawn element(s).es.\n **/\n setCurrentId(uid) {\n // NOOP\n this.curId = uid;\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * Determine the class name for further usage here.\n *\n * @name setCurrentClassName\n * @method\n * @param {string|null} className - A class name for further custom use cases.\n **/\n setCurrentClassName(className) {\n // NOOP\n }\n /**\n * Draw the line between the given two points with the specified (CSS-) color.\n *\n * @method line\n * @param {XYCoords} zA - The start point of the line.\n * @param {XYCoords} zB - The end point of the line.\n * @param {string} color - Any valid CSS color string.\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n line(zA, zB, color) {\n const vertices = new Float32Array(6);\n vertices[0] = this._x2rel(zA.x);\n vertices[1] = this._y2rel(zA.y);\n vertices[2] = this._zindex;\n vertices[3] = this._x2rel(zB.x);\n vertices[4] = this._y2rel(zB.y);\n vertices[5] = this._zindex;\n this._zindex += 0.001;\n // Create an empty buffer object\n // const vertex_buffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertex_buffer);\n // Pass the vertex data to the buffer\n this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);\n // Bind vertex buffer object\n // this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertex_buffer);\n // Get the attribute location\n var coord = this.gl.getAttribLocation(this._program, \"position\");\n // Point an attribute to the currently bound VBO\n this.gl.vertexAttribPointer(coord, 3, this.gl.FLOAT, false, 0, 0);\n // Enable the attribute\n this.gl.enableVertexAttribArray(coord);\n // Unbind the buffer?\n //this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n // Set the view port\n this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);\n let uRotationVector = this.gl.getUniformLocation(this._program, \"uRotationVector\");\n // let radians = currentAngle * Math.PI / 180.0;\n let currentRotation = [0.0, 1.0];\n //currentRotation[0] = Math.sin(radians);\n //currentRotation[1] = Math.cos(radians);\n this.gl.uniform2fv(uRotationVector, currentRotation);\n this.gl.lineWidth(5);\n // Draw the line\n this.gl.drawArrays(this.gl.LINES, 0, vertices.length / 3);\n // POINTS, LINE_STRIP, LINE_LOOP, LINES,\n // TRIANGLE_STRIP,TRIANGLE_FAN, TRIANGLES\n }\n /**\n * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n arrow(zA, zB, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.\n *\n * @method cubicBezierArrow\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n */\n cubicBezierArrow(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, headLength) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).\n * @return {void}\n * @instance\n * @memberof DrawLib\n **/\n arrowHead(zA, zB, color, lineWidth, headLength) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method image\n * @param {Image} image - The image object to draw.\n * @param {XYCoords} position - The position to draw the the upper left corner at.\n * @param {XYCoords} size - The x/y-size to draw the image with.\n * @param {number=0.0} alpha - (optional, default=0.0) The transparency (0.0=opaque, 1.0=transparent).\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n image(image, position, size, alpha = 0.0) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method texturedPoly\n * @param {Image} textureImage - The image object to draw.\n * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.\n * @param {Polygon} polygon - The polygon to use as clip path.\n * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.\n * @param {number} rotation - The rotation to use for the polygon (and for the texture).\n * @return {void}\n * @instance\n * @memberof drawutilsgl\n **/\n texturedPoly(textureImage, textureSize, polygon, polygonPosition, rotation) {\n // NOT YET IMPLEMENTED\n }\n // +---------------------------------------------------------------------------------\n // | This is the final helper function for drawing and filling stuff. It is not\n // | intended to be used from the outside.\n // |\n // | When in draw mode it draws the current shape.\n // | When in fill mode it fills the current shape.\n // |\n // | This function is usually only called internally.\n // |\n // | @param color A stroke/fill color to use.\n // +-------------------------------\n _fillOrDraw(color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given (cubic) bézier curve.\n *\n * @method cubicBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {VertXYCoordsex} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezier(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given (cubic) Bézier path.\n *\n * The given path must be an array with n*3+1 vertices, where n is the number of\n * curves in the path:\n * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>\n *\n * @method cubicBezierPath\n * @param {XYCoords[]} path - The cubic bezier path as described above.\n * @param {string} color - The CSS colot to draw the path with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezierPath(path, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given handle and handle point (used to draw interactive Bézier curves).\n *\n * The colors for this are fixed and cannot be specified.\n *\n * @method handle\n * @param {XYCoords} startPoint - The start of the handle.\n * @param {XYCoords} endPoint - The end point of the handle.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handle(startPoint, endPoint) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a handle line (with a light grey).\n *\n * @method handleLine\n * @param {XYCoords} startPoint - The start point to draw the handle at.\n * @param {XYCoords} endPoint - The end point to draw the handle at.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handleLine(startPoint, endPoint) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a 1x1 dot with the specified (CSS-) color.\n *\n * @method dot\n * @param {XYCoords} p - The position to draw the dot at.\n * @param {string} color - The CSS color to draw the dot with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n dot(p, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given point with the specified (CSS-) color and radius 3.\n *\n * @method point\n * @param {XYCoords} p - The position to draw the point at.\n * @param {string} color - The CSS color to draw the point with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n point(p, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a circle with the specified (CSS-) color and radius.<br>\n * <br>\n * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.\n *\n * @method circle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circle(center, radius, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a circular arc (section of a circle) with the given CSS color.\n *\n * @method circleArc\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {number} startAngle - The angle to start at.\n * @param {number} endAngle - The angle to end at.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleArc(center, radius, startAngle, endAngle, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an ellipse with the specified (CSS-) color and thw two radii.\n *\n * @method ellipse\n * @param {XYCoords} center - The center of the ellipse.\n * @param {number} radiusX - The radius of the ellipse.\n * @param {number} radiusY - The radius of the ellipse.\n * @param {string} color - The CSS color to draw the ellipse with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n ellipse(center, radiusX, radiusY, color, lineWidth, rotation) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw square at the given center, size and with the specified (CSS-) color.<br>\n * <br>\n * Note that if the x-scale and the y-scale are different the result will be a rectangle rather than a square.\n *\n * @method square\n * @param {XYCords} center - The center of the square.\n * @param {number} size - The size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n square(center, size, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a rectangle.\n *\n * @param {XYCoords} position - The upper left corner of the rectangle.\n * @param {number} width - The width of the rectangle.\n * @param {number} height - The height of the rectangle.\n * @param {string} color - The color to use.\n * @param {number=1} lineWidth - (optional) The line with to use (default is 1).\n **/\n rect(position, width, height, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a grid of horizontal and vertical lines with the given (CSS-) color.\n *\n * @method grid\n * @param {XYCoords} center - The center of the grid.\n * @param {number} width - The total width of the grid (width/2 each to the left and to the right).\n * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal grid size.\n * @param {number} sizeY - The vertical grid size.\n * @param {string} color - The CSS color to draw the grid with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n grid(center, width, height, sizeX, sizeY, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a raster of crosshairs in the given grid.<br>\n *\n * This works analogue to the grid() function\n *\n * @method raster\n * @param {XYCoords} center - The center of the raster.\n * @param {number} width - The total width of the raster (width/2 each to the left and to the right).\n * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal raster size.\n * @param {number} sizeY - The vertical raster size.\n * @param {string} color - The CSS color to draw the raster with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n raster(center, width, height, sizeX, sizeY, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a diamond handle (square rotated by 45°) with the given CSS color.\n *\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped diamonds.\n *\n * @method diamondHandle\n * @param {XYCoords} center - The center of the diamond.\n * @param {number} size - The x/y-size of the diamond.\n * @param {string} color - The CSS color to draw the diamond with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n diamondHandle(center, size, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a square handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped squares.\n *\n * @method squareHandle\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The x/y-size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n squareHandle(center, size, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a circle handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped circles.\n *\n * @method circleHandle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleHandle(center, size, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a crosshair with given radius and color at the given position.<br>\n * <br>\n * Note that the crosshair radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=0.5} lineWidth - (optional, default=0.5) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n crosshair(center, radius, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a cross with diagonal axes with given radius, color and lineWidth at the given position.<br>\n * <br>\n * Note that the x's radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=1} lineWidth - (optional, default=1.0) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cross(center, radius, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a polygon.\n *\n * @method polygon\n * @param {Polygon} polygon - The polygon to draw.\n * @param {string} color - The CSS color to draw the polygon with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polygon(polygon, color, lineWidth) {\n const vertices = new Float32Array(polygon.vertices.length * 3);\n for (var i = 0; i < polygon.vertices.length; i++) {\n vertices[i * 3 + 0] = this._x2rel(polygon.vertices[i].x);\n vertices[i * 3 + 1] = this._y2rel(polygon.vertices[i].y);\n vertices[i * 3 + 2] = this._zindex;\n }\n this._zindex += 0.001;\n //console.log( vertices );\n // Create an empty buffer object\n // const vertex_buffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertex_buffer);\n // Pass the vertex data to the buffer\n this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);\n // Bind vertex buffer object\n // this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertex_buffer);\n // Get the attribute location\n var coord = this.gl.getAttribLocation(this._program, \"position\");\n // Point an attribute to the currently bound VBO\n this.gl.vertexAttribPointer(coord, 3, this.gl.FLOAT, false, 0, 0);\n // Enable the attribute\n this.gl.enableVertexAttribArray(coord);\n // Unbind the buffer?\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n // Set the view port\n this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);\n let uRotationVector = this.gl.getUniformLocation(this._program, \"uRotationVector\");\n // let radians = currentAngle * Math.PI / 180.0;\n let currentRotation = [0.0, 1.0];\n //currentRotation[0] = Math.sin(radians);\n //currentRotation[1] = Math.cos(radians);\n this.gl.uniform2fv(uRotationVector, currentRotation);\n // Draw the polygon\n this.gl.drawArrays(this.gl.TRIANGLE_FAN, 0, vertices.length / 3);\n // POINTS, LINE_STRIP, LINE_LOOP, LINES,\n // TRIANGLE_STRIP,TRIANGLE_FAN, TRIANGLES\n }\n /**\n * Draw a polygon line (alternative function to the polygon).\n *\n * @method polyline\n * @param {XYCoords[]} vertices - The polygon vertices to draw.\n * @param {boolan} isOpen - If true the polyline will not be closed at its end.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polyline(vertices, isOpen, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a text at the given relative position.\n *\n * @method text\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {string=} options.color - The Color to use.\n * @param {string=} options.fontFamily - The font family to use.\n * @param {number=} options.fontSize - The font size (in pixels) to use.\n * @param {FontStyle=} options.fontStyle - The font style to use.\n * @param {FontWeight=} options.fontWeight - The font weight to use.\n * @param {number=} options.lineHeight - The line height (in pixels) to use.\n * @param {number=} options.rotation - The (optional) rotation in radians.\n * @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `\"left\" || \"right\" || \"center\" || \"start\" || \"end\"`.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n text(text, x, y, options) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a non-scaling text label at the given position.\n *\n * @method label\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {number=} rotation - The (aoptional) rotation in radians.\n * @param {string=\"black\"} color - The color to use (default is black).\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n label(text, x, y, rotation, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an SVG-like path given by the specified path data.\n *\n * @method path\n * @param {SVGPathData} pathData - An array of path commands and params.\n * @param {string=null} color - (optional) The color to draw this path with (default is null).\n * @param {number=1} lineWidth - (optional) the line width to use (default is 1).\n * @param {boolean=false} options.inplace - (optional) If set to true then path transforamtions (scale and translate) will be done in-place in the array. This can boost the performance.\n * @instance\n * @memberof drawutils\n * @return {R} An instance representing the drawn path.\n */\n path(pathData, color, lineWidth, options) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Due to gl compatibility there is a generic 'clear' function required\n * to avoid accessing the context object itself directly.\n *\n * This function just fills the whole canvas with a single color.\n *\n * @param {string} color - The color to clear with.\n **/\n clear(color) {\n // NOT YET IMPLEMENTED\n // if( typeof color == 'string' )\n // color = Color.parse(color); // Color class does not yet exist in TS\n // Clear the canvas\n this.gl.clearColor(1.0, 1.0, 1.0, 1.0);\n // Enable the depth test\n this.gl.enable(this.gl.DEPTH_TEST);\n // Clear the color and depth buffer\n this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n }\n}\n// Vertex shader source code\ndrawutilsgl.vertCode = `\n precision mediump float;\n\n attribute vec3 position;\n\n uniform vec2 uRotationVector;\n\n void main(void) {\n\tvec2 rotatedPosition = vec2(\n\t position.x * uRotationVector.y +\n\t\tposition.y * uRotationVector.x,\n\t position.y * uRotationVector.y -\n\t\tposition.x * uRotationVector.x\n\t);\n\n\tgl_Position = vec4(rotatedPosition, position.z, 1.0);\n }`;\n// Fragment shader source code\ndrawutilsgl.fragCode = `\n precision highp float;\n\n void main(void) {\n\tgl_FragColor = vec4(0.0,0.75,1.0,1.0);\n }`;\n/**\n * Some GL helper utils.\n **/\nclass GLU {\n constructor(gl) {\n this.gl = gl;\n }\n bufferData(verts) {\n // Create an empty buffer object\n var vbuffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vbuffer);\n // Pass the vertex data to the buffer\n this.gl.bufferData(this.gl.ARRAY_BUFFER, verts, this.gl.STATIC_DRAW);\n // Unbind the buffer\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n return vbuffer;\n }\n /*=================== Shaders ====================*/\n compileShader(shaderCode, shaderType) {\n // Create a vertex shader object\n var shader = this.gl.createShader(shaderType);\n // Attach vertex shader source code\n this.gl.shaderSource(shader, shaderCode);\n // Compile the vertex shader\n this.gl.compileShader(shader);\n const vertStatus = this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS);\n if (!vertStatus) {\n console.warn(\"Error in shader:\" + this.gl.getShaderInfoLog(shader));\n this.gl.deleteShader(shader);\n return null;\n }\n return shader;\n }\n makeProgram(vertShader, fragShader) {\n // Create a shader program object to store\n // the combined shader program\n var program = this.gl.createProgram();\n // Attach a vertex shader\n this.gl.attachShader(program, vertShader);\n // Attach a fragment shader\n this.gl.attachShader(program, fragShader);\n // Link both the programs\n this.gl.linkProgram(program);\n // Use the combined shader program object\n this.gl.useProgram(program);\n /*======= Do some cleanup ======*/\n this.gl.detachShader(program, vertShader);\n this.gl.detachShader(program, fragShader);\n this.gl.deleteShader(vertShader);\n this.gl.deleteShader(fragShader);\n return program;\n }\n}\n//# sourceMappingURL=drawgl.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-11-28\n * @modified 2018-12-09 Added the utils: baseLog(Number,Number) and mapRasterScale(Number,Number).\n * @version 1.0.1\n *\n * @file Grid\n * @fileoverview Note that the PlotBoilerplate already has a Grid instance member. The Grid is not meant\n * to be added to the canvas as a drawable as it encapsulates more an abstract concept of the canvas\n * rather than a drawable object.\n * @public\n **/\n/**\n * @classdesc A grid class with vertical and horizontal lines (or a raster).\n *\n * Note that the PlotBoilerplate already has a Grid instance member. The Grid is not meant\n * to be added to the canvas as a drawable as it encapsulates more an abstract concept of the canvas\n * rather than a drawable object.\n *\n * @requires Vertex\n */\nexport class Grid {\n /**\n * The constructor.\n *\n * @constructor\n * @name Grid\n * @param {Vertex} center - The offset of the grid (default is [0,0]).\n * @param {Vertex} size - The x- and y-size of the grid.\n **/\n constructor(center, size) {\n this.center = center;\n this.size = size;\n }\n ;\n}\n/**\n * @memberof Grid\n **/\nGrid.utils = {\n /**\n * Calculate the logarithm of the given number (num) to a given base.<br>\n * <br>\n * This function returns the number l with<br>\n * <pre>num == Math.pow(base,l)</pre>\n *\n * @member baseLog\n * @function\n * @memberof Grid\n * @inner\n * @param {number} base - The base to calculate the logarithm to.\n * @param {number} num - The number to calculate the logarithm for.\n * @return {number} <pre>log(base)/log(num)</pre>\n **/\n baseLog: (base, num) => { return Math.log(base) / Math.log(num); },\n /**\n * Calculate the raster scale for a given logarithmic mapping.<br>\n * <br>\n * Example (with adjustFactor=2):<br>\n * <pre>\n * If scale is 4.33, then the mapping is 1/2 (because 2^2 <= 4.33 <= 2^3)<br>\n * If scale is 0.33, then the mapping is 2 because (2^(1/2) >= 0.33 >= 2^(1/4)\n * </pre>\n *\n * @member mapRasterScale\n * @function\n * @memberof Grid\n * @inner\n * @param {number} adjustFactor The base for the logarithmic raster scaling when zoomed.\n * @param {number} scale The currently used scale factor.\n * @return {number}\n **/\n mapRasterScale: (adjustFactor, scale) => {\n var gf = 1.0;\n if (scale >= 1) {\n gf = Math.abs(Math.floor(1 / Grid.utils.baseLog(adjustFactor, scale)));\n gf = 1 / Math.pow(adjustFactor, gf);\n }\n else {\n gf = Math.abs(Math.floor(Grid.utils.baseLog(1 / adjustFactor, 1 / (scale + 1))));\n }\n return gf;\n }\n};\n//# sourceMappingURL=Grid.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-11-11 (Alaaf)\n * @modified 2020-03-28 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-07-28 Changed the `delete` key code from 8 to 46.\n * @modified 2020-10-04 Changed `window` to `globalThis`.\n * @modified 2020-10-04 Added extended JSDoc.\n * @modified 2022-02-02 Added the `destroy` method.\n * @version 1.1.0\n *\n * @file KeyHandler\n * @public\n **/\n/**\n * @classdesc A generic key handler.\n *\n * Example\n * =======\n * @example\n * // Javascript\n *\tnew KeyHandler( { trackAll : true } )\n *\t .down('enter',function() { console.log('ENTER was hit.'); } )\n *\t .press('enter',function() { console.log('ENTER was pressed.'); } )\n *\t .up('enter',function() { console.log('ENTER was released.'); } )\n *\n * .down('e',function() { console.log('e was hit. shift is pressed?',keyHandler.isDown('shift')); } )\n *\n *\t .up('windows',function() { console.log('windows was released.'); } )\n *\t;\n */\nexport class KeyHandler {\n /**\n * The constructor.\n *\n * @constructor\n * @instance\n * @memberof KeyHandler\n * @param {HTMLElement} options.element (optional) The HTML element to listen on; if null then 'window' will be used.\n * @param {boolean} options.trackAll (optional) Set to true if you want to keep track of _all_ keys (keyStatus).\n **/\n constructor(options) {\n this.downListeners = [];\n this.pressListeners = [];\n this.upListeners = [];\n this.keyStates = {};\n options = options || {};\n this.element = options.element ? options.element : globalThis;\n this.downListeners = [];\n this.pressListeners = [];\n this.upListeners = [];\n this.keyStates = [];\n // This could be made configurable in a later version. It allows to\n // keep track of the key status no matter if there are any listeners\n // on the key or not.\n this.trackAllKeys = options.trackAll || false;\n // Install the listeners\n this.installListeners();\n }\n /**\n * A helper function to fire key events from this KeyHandler.\n *\n * @param {KeyboardEvent} event - The key event to fire.\n * @param {Array<XKeyListener>} listener - The listeners to fire to.\n */\n fireEvent(event, listeners) {\n let hasListener = false;\n for (var i in listeners) {\n var lis = listeners[i];\n if (lis.keyCode != event.keyCode)\n continue;\n lis.listener(event);\n hasListener = true;\n }\n return hasListener;\n }\n /**\n * Internal function to fire a new keydown event to all listeners.\n * You should not call this function on your own unless you know what you do.\n *\n * @name fireDownEvent\n * @memberof KeyHandler\n * @instance\n * @private\n * @param {KeyboardEvent} e\n * @param {KeyHandler} handler\n * @return {void}\n */\n fireDownEvent(e, handler) {\n if (handler.fireEvent(e, handler.downListeners) || handler.trackAllKeys) {\n // Down event has listeners. Update key state.\n handler.keyStates[e.keyCode] = \"down\";\n }\n }\n /**\n * Internal function to fire a new keypress event to all listeners.\n * You should not call this function on your own unless you know what you do.\n *\n * @name firePressEvent\n * @memberof KeyHandler\n * @instance\n * @private\n * @param {KeyboardEvent} e\n * @param {KeyHandler} handler\n * @return void\n */\n firePressEvent(e, handler) {\n handler.fireEvent(e, handler.pressListeners);\n }\n /**\n * Internal function to fire a new keyup event to all listeners.\n * You should not call this function on your own unless you know what you do.\n *\n * @name fireUpEvent\n * @memberof KeyHandler\n * @instance\n * @private\n * @param {KeyboardEvent} e\n * @param {KeyHandler} handler\n * @return {void}\n */\n fireUpEvent(e, handler) {\n if (handler.fireEvent(e, handler.upListeners) || handler.trackAllKeys) {\n // Up event has listeners. Clear key state.\n delete handler.keyStates[e.keyCode];\n }\n }\n /**\n * Resolve the key/name code.\n */\n static key2code(key) {\n if (typeof key == \"number\")\n return key;\n if (typeof key != \"string\")\n throw \"Unknown key name or key type (should be a string or integer): \" + key;\n if (KeyHandler.KEY_CODES[key])\n return KeyHandler.KEY_CODES[key];\n throw \"Unknown key (cannot resolve key code): \" + key;\n }\n /**\n * Install the required listeners into the initially passed element.\n *\n * By default the listeners are installed into the root element specified on\n * construction (or 'window').\n */\n installListeners() {\n var _self = this;\n this.element.addEventListener(\"keydown\", (this._keyDownListener = (e) => {\n _self.fireDownEvent(e, _self);\n }));\n this.element.addEventListener(\"keypress\", (this._keyPressListener = (e) => {\n _self.firePressEvent(e, _self);\n }));\n this.element.addEventListener(\"keyup\", (this._keyUpListener = (e) => {\n _self.fireUpEvent(e, _self);\n }));\n }\n /**\n * Remove all installed event listeners from the underlying element.\n */\n releaseListeners() {\n this.element.removeEventListener(\"keydown\", this._keyDownListener);\n this.element.removeEventListener(\"keypress\", this._keyPressListener);\n this.element.removeEventListener(\"keyup\", this._keyUpListener);\n }\n /**\n * Listen for key down. This function allows chaining.\n *\n * Example: new KeyHandler().down('enter',function() {console.log('Enter hit.')});\n *\n * @name down\n * @memberof KeyHandler\n * @instance\n * @param {string|number} key - Any key identifier, key code or one from the KEY_CODES list.\n * @param {(e:KeyboardEvent)=>void} e - The callback to be triggered.\n * @return {KeyHandler} this\n */\n down(key, listener) {\n this.downListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });\n return this;\n }\n /**\n * Listen for key press.\n *\n * Example: new KeyHandler().press('enter',function() {console.log('Enter pressed.')});\n *\n * @name press\n * @memberof KeyHandler\n * @instance\n * @param {string|number} key - Any key identifier, key code or one from the KEY_CODES list.\n * @param {(e:KeyboardEvent)=>void} listener - The callback to be triggered.\n * @return {KeyHandler} this\n */\n press(key, listener) {\n this.pressListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });\n return this;\n }\n /**\n * Listen for key up.\n *\n * Example: new KeyHandler().up('enter',function() {console.log('Enter released.')});\n *\n * @name up\n * @memberof KeyHandler\n * @instance\n * @param {string} key - Any key identifier, key code or one from the KEY_CODES list.\n * @param {(e:KeyboardEvent)=>void)} e - The callback to be triggered.\n * @return {KeyHandler} this\n */\n up(key, listener) {\n this.upListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });\n return this;\n }\n /**\n * Check if a specific key is currently held pressed.\n *\n * @param {string|number} key - Any key identifier, key code or one from the KEY_CODES list.\n */\n isDown(key) {\n if (typeof key == \"number\")\n return this.keyStates[key] ? true : false;\n else\n return this.keyStates[KeyHandler.key2code(key)] ? true : false;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used any more.\n */\n destroy() {\n this.releaseListeners();\n }\n}\n/**\n * Source:\n * https://keycode.info/\n */\n// prettier-ignore\nKeyHandler.KEY_CODES = {\n 'break': 3, // alternate: 19\n 'backspace': 8,\n // 'delete'\t : 8, // alternate: 46\n 'tab': 9,\n 'clear': 12,\n 'enter': 13,\n 'shift': 16,\n 'ctrl': 17,\n 'alt': 18,\n 'pause': 19,\n // 'break'\t : 19,\n 'capslock': 20,\n 'hangul': 21,\n 'hanja': 25,\n 'escape': 27,\n 'conversion': 28,\n 'non-conversion': 29, // alternate: 235?\n 'spacebar': 32,\n 'pageup': 33,\n 'pagedown': 34,\n 'end': 35,\n 'home': 36, // alternate: 172?\n 'leftarrow': 37,\n 'uparrow': 38,\n 'rightarrow': 39,\n 'downarrow': 40,\n 'select': 41,\n 'print': 42,\n 'execute': 43,\n 'printscreen': 44,\n 'insert': 45,\n 'delete': 46, // alternate: 8\n 'help': 47,\n '0': 48,\n '1': 49,\n '2': 50,\n '3': 51,\n '4': 52,\n '5': 53,\n '6': 54,\n '7': 55,\n '8': 56,\n '9': 57,\n ':': 58,\n 'semicolon (firefox)': 59,\n 'equals': 59,\n '<': 60,\n 'equals (firefox)': 61,\n 'ß': 63,\n '@ (firefox)': 64,\n 'a': 65,\n 'b': 66,\n 'c': 67,\n 'd': 68,\n 'e': 69,\n 'f': 70,\n 'g': 71,\n 'h': 72,\n 'i': 73,\n 'j': 74,\n 'k': 75,\n 'l': 76,\n 'm': 77,\n 'n': 78,\n 'o': 79,\n 'p': 80,\n 'q': 81,\n 'r': 82,\n 's': 83,\n 't': 84,\n 'u': 85,\n 'v': 86,\n 'w': 87,\n 'x': 88,\n 'y': 89,\n 'z': 90,\n 'windows': 91,\n 'leftcommand': 91, // left ⌘\n 'chromebooksearch': 91,\n 'rightwindowkey': 92,\n 'windowsmenu': 93,\n 'rightcommant': 93, // right ⌘\n 'sleep': 95,\n 'numpad0': 96,\n 'numpad1': 97,\n 'numpad2': 98,\n 'numpad3': 99,\n 'numpad4': 100,\n 'numpad5': 101,\n 'numpad6': 102,\n 'numpad7': 103,\n 'numpad8': 104,\n 'numpad9': 105,\n 'multiply': 106,\n 'add': 107,\n 'numpadperiod': 108, // firefox, 194 on chrome\n 'subtract': 109,\n 'decimalpoint': 110,\n 'divide': 111,\n 'f1': 112,\n 'f2': 113,\n 'f3': 114,\n 'f4': 115,\n 'f5': 116,\n 'f6': 117,\n 'f7': 118,\n 'f8': 119,\n 'f9': 120,\n 'f10': 121,\n 'f11': 122,\n 'f12': 123,\n 'f13': 124,\n 'f14': 125,\n 'f15': 126,\n 'f16': 127,\n 'f17': 128,\n 'f18': 129,\n 'f19': 130,\n 'f20': 131,\n 'f21': 132,\n 'f22': 133,\n 'f23': 134,\n 'f24': 135,\n 'numlock': 144,\n 'scrolllock': 145,\n '^': 160,\n '!': 161,\n // '؛' \t : 162 // (arabic semicolon)\n '#': 163,\n '$': 164,\n 'ù': 165,\n 'pagebackward': 166,\n 'pageforward': 167,\n 'refresh': 168,\n 'closingparen': 169, // (AZERTY)\n '*': 170,\n '~+*': 171,\n // 'home'\t : 172,\n 'minus': 173, // firefox\n // 'mute' : 173,\n // 'unmute'\t : 173,\n 'decreasevolumelevel': 174,\n 'increasevolumelevel': 175,\n 'next': 176,\n 'previous': 177,\n 'stop': 178,\n 'play/pause': 179,\n 'email': 180,\n 'mute': 181, // firefox, alternate: 173\n 'unmute': 181, // alternate: 173?\n //'decreasevolumelevel'\t182 // firefox\n //'increasevolumelevel'\t183 // firefox\n 'semicolon': 186,\n 'ñ': 186,\n 'equal': 187,\n 'comma': 188,\n 'dash': 189,\n 'period': 190,\n 'forwardslash': 191,\n 'ç': 191, // 231 alternate?\n 'grave accent': 192,\n //'ñ' 192,\n 'æ': 192,\n 'ö': 192,\n '?': 193,\n '/': 193,\n '°': 193,\n // 'numpadperiod'\t : 194, // chrome\n 'openbracket': 219,\n 'backslash': 220,\n 'closebracket': 221,\n 'å': 221,\n 'singlequote': 222,\n 'ø': 222,\n 'ä': 222,\n '`': 223,\n // 'left or right ⌘ key (firefox)'\t224\n 'altgr': 225,\n // '< /git >, left back slash'\t226\n 'GNOME Compose Key': 230,\n 'XF86Forward': 233,\n 'XF86Back': 234,\n 'alphanumeric': 240,\n 'hiragana': 242,\n 'katakana': 242,\n 'half-width': 243,\n 'full-width': 243,\n 'kanji': 244,\n 'unlocktrackpad': 251, // Chrome/Edge\n 'toggletouchpad': 255\n};\n//# sourceMappingURL=KeyHandler.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-03-19\n * @modified 2018-04-28 Added the param 'wasDragged'.\n * @modified 2018-08-16 Added the param 'dragAmount'.\n * @modified 2018-08-27 Added the param 'element'.\n * @modified 2018-11-11 Changed the scope from a simple global var to a member of window/_context.\n * @modified 2018-11-19 Renamed the 'mousedown' function to 'down' and the 'mouseup' function to 'up'.\n * @modified 2018-11-28 Added the 'wheel' listener.\n * @modified 2018-12-09 Cleaned up some code.\n * @modified 2019-02-10 Cleaned up some more code.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-04-08 Fixed the click event (internally fired a 'mouseup' event) (1.0.10)\n * @modified 2020-04-08 Added the optional 'name' property. (1.0.11)\n * @modified 2020-04-08 The new version always installs internal listenrs to track drag events even\n * if there is no external drag listener installed (1.1.0).\n * @modified 2020-10-04 Added extended JSDoc comments.\n * @modified 2020-11-25 Added the `isTouchEvent` param.\n * @modified 2021-01-10 The mouse handler is now also working with SVGElements.\n * @modified 2022-08-16 Fixed a bug in the mouse button detection.\n * @version 1.2.1\n *\n * @file MouseHandler\n * @public\n **/\nexport class XMouseEvent extends MouseEvent {\n}\nexport class XWheelEvent extends WheelEvent {\n}\n/**\n * @classdesc A simple mouse handler for demos.\n * Use to avoid load massive libraries like jQuery.\n *\n * @requires XYCoords\n */\nexport class MouseHandler {\n /**\n * The constructor.\n *\n * Pass the DOM element you want to receive mouse events from.\n *\n * Usage\n * =====\n * @example\n * // Javascript\n * new MouseHandler( document.getElementById('mycanvas') )\n *\t .drag( function(e) {\n *\t\tconsole.log( 'Mouse dragged: ' + JSON.stringify(e) );\n *\t\tif( e.params.leftMouse ) ;\n *\t\telse if( e.params.rightMouse ) ;\n *\t } )\n *\t .move( function(e) {\n *\t\tconsole.log( 'Mouse moved: ' + JSON.stringify(e.params) );\n *\t } )\n * .up( function(e) {\n * console.log( 'Mouse up. Was dragged?', e.params.wasDragged );\n * } )\n * .down( function(e) {\n * console.log( 'Mouse down.' );\n * } )\n * .click( function(e) {\n * console.log( 'Click.' );\n * } )\n * .wheel( function(e) {\n * console.log( 'Wheel. delta='+e.deltaY );\n * } )\n *\n * @example\n * // Typescript\n * new MouseHandler( document.getElementById('mycanvas') )\n *\t .drag( (e:XMouseEvent) => {\n *\t\tconsole.log( 'Mouse dragged: ' + JSON.stringify(e) );\n *\t\tif( e.params.leftMouse ) ;\n *\t\telse if( e.params.rightMouse ) ;\n *\t } )\n *\t .move( (e:XMouseEvent) => {\n *\t\tconsole.log( 'Mouse moved: ' + JSON.stringify(e.params) );\n *\t } )\n * .up( (e:XMouseEvent) => {\n * console.log( 'Mouse up. Was dragged?', e.params.wasDragged );\n * } )\n * .down( (e:XMouseEvent) => {\n * console.log( 'Mouse down.' );\n * } )\n * .click( (e:XMouseEvent) => {\n * console.log( 'Click.' );\n * } )\n * .wheel( (e:XWheelEvent) => {\n * console.log( 'Wheel. delta='+e.deltaY );\n * } )\n *\n * @constructor\n * @instance\n * @memberof MouseHandler\n * @param {HTMLElement} element\n **/\n constructor(element, name) {\n this.mouseDownPos = undefined;\n this.mouseDragPos = undefined;\n // TODO: cc\n // private mousePos : { x:number, y:number }|undefined = undefined;\n this.mouseButton = -1;\n this.listeners = {};\n this.installed = {};\n this.handlers = {};\n // +----------------------------------------------------------------------\n // | Some private vars to store the current mouse/position/button state.\n // +-------------------------------------------------\n this.name = name;\n this.element = element;\n this.mouseDownPos = undefined;\n this.mouseDragPos = undefined;\n // this.mousePos = null;\n this.mouseButton = -1;\n this.listeners = {};\n this.installed = {};\n this.handlers = {};\n // +----------------------------------------------------------------------\n // | Define the internal event handlers.\n // |\n // | They will dispatch the modified event (relative mouse position,\n // | drag offset, ...) to the callbacks.\n // +-------------------------------------------------\n const _self = this;\n this.handlers[\"mousemove\"] = (e) => {\n if (_self.listeners.mousemove)\n _self.listeners.mousemove(_self.mkParams(e, \"mousemove\"));\n if (_self.mouseDragPos && _self.listeners.drag)\n _self.listeners.drag(_self.mkParams(e, \"drag\"));\n if (_self.mouseDownPos)\n _self.mouseDragPos = _self.relPos(e);\n };\n this.handlers[\"mouseup\"] = (e) => {\n if (_self.listeners.mouseup)\n _self.listeners.mouseup(_self.mkParams(e, \"mouseup\"));\n _self.mouseDragPos = undefined;\n _self.mouseDownPos = undefined;\n _self.mouseButton = -1;\n };\n this.handlers[\"mousedown\"] = (e) => {\n _self.mouseDragPos = _self.relPos(e);\n _self.mouseDownPos = _self.relPos(e);\n _self.mouseButton = e.button;\n if (_self.listeners.mousedown)\n _self.listeners.mousedown(_self.mkParams(e, \"mousedown\"));\n };\n this.handlers[\"click\"] = (e) => {\n if (_self.listeners.click)\n _self.listeners.click(_self.mkParams(e, \"click\"));\n };\n this.handlers[\"wheel\"] = (e) => {\n if (_self.listeners.wheel)\n _self.listeners.wheel(_self.mkParams(e, \"wheel\"));\n };\n this.element.addEventListener(\"mousemove\", this.handlers[\"mousemove\"]);\n this.element.addEventListener(\"mouseup\", this.handlers[\"mouseup\"]);\n this.element.addEventListener(\"mousedown\", this.handlers[\"mousedown\"]);\n this.element.addEventListener(\"click\", this.handlers[\"click\"]);\n this.element.addEventListener(\"wheel\", this.handlers[\"wheel\"]);\n }\n /**\n * Get relative position from the given MouseEvent.\n *\n * @name relPos\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {MouseEvent} e - The mouse event to get the relative position for.\n * @return {XYCoords} The relative mouse coordinates.\n */\n relPos(e) {\n return { x: e.offsetX, y: e.offsetY };\n }\n /**\n * Build the extended event params.\n *\n * @name mkParams\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {MouseEvent} event - The mouse event to get the relative position for.\n * @param {string} eventName - The name of the firing event.\n * @return {XMouseEvent}\n */\n mkParams(event, eventName) {\n var _a, _b;\n const rel = this.relPos(event);\n const xEvent = event;\n xEvent.params = {\n element: this.element,\n name: eventName,\n isTouchEvent: false,\n pos: rel,\n button: event.button, // this.mouseButton,\n leftButton: event.button === 0, // this.mouseButton === 0,\n middleButton: event.button === 1, // this.mouseButton === 1,\n rightButton: event.button === 2, // this.mouseButton === 2,\n mouseDownPos: (_a = this.mouseDownPos) !== null && _a !== void 0 ? _a : { x: NaN, y: NaN },\n draggedFrom: (_b = this.mouseDragPos) !== null && _b !== void 0 ? _b : { x: NaN, y: NaN },\n wasDragged: this.mouseDownPos != null && (this.mouseDownPos.x != rel.x || this.mouseDownPos.y != rel.y),\n dragAmount: this.mouseDragPos != null ? { x: rel.x - this.mouseDragPos.x, y: rel.y - this.mouseDragPos.y } : { x: 0, y: 0 }\n };\n return xEvent;\n }\n /**\n * Install a new listener.\n * Please note that this mouse handler can only handle one listener per event type.\n *\n * @name listenFor\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {string} eventName - The name of the firing event to listen for.\n * @return {void}\n */\n listenFor(eventName) {\n if (this.installed[eventName])\n return;\n // In the new version 1.1.0 has all internal listeners installed by default.\n this.installed[eventName] = true;\n }\n /**\n * Un-install a new listener.\n *\n * @name listenFor\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {string} eventName - The name of the firing event to unlisten for.\n * @return {void}\n */\n unlistenFor(eventName) {\n if (!this.installed[eventName])\n return;\n // In the new version 1.1.0 has all internal listeners installed by default.\n delete this.installed[eventName];\n }\n /**\n * Installer function to listen for a specific event: mouse-drag.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name drag\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The drag-callback to listen for.\n * @return {MouseHandler} this\n */\n drag(callback) {\n if (this.listeners.drag)\n this.throwAlreadyInstalled(\"drag\");\n this.listeners.drag = callback;\n this.listenFor(\"mousedown\");\n this.listenFor(\"mousemove\");\n this.listenFor(\"mouseup\");\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-move.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name move\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The move-callback to listen for.\n * @return {MouseHandler} this\n */\n move(callback) {\n if (this.listeners.mousemove)\n this.throwAlreadyInstalled(\"mousemove\");\n this.listenFor(\"mousemove\");\n this.listeners.mousemove = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-up.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name up\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The up-callback to listen for.\n * @return {MouseHandler} this\n */\n up(callback) {\n if (this.listeners.mouseup)\n this.throwAlreadyInstalled(\"mouseup\");\n this.listenFor(\"mouseup\");\n this.listeners.mouseup = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-down.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name down\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The down-callback to listen for.\n * @return {MouseHandler} this\n */\n down(callback) {\n if (this.listeners.mousedown)\n this.throwAlreadyInstalled(\"mousedown\");\n this.listenFor(\"mousedown\");\n this.listeners.mousedown = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-click.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name click\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The click-callback to listen for.\n * @return {MouseHandler} this\n */\n click(callback) {\n if (this.listeners.click)\n this.throwAlreadyInstalled(\"click\");\n this.listenFor(\"click\");\n this.listeners.click = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-wheel.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name wheel\n * @memberof MouseHandler\n * @instance\n * @param {XWheelCallback} callback - The wheel-callback to listen for.\n * @return {MouseHandler} this\n */\n wheel(callback) {\n if (this.listeners.wheel)\n this.throwAlreadyInstalled(\"wheel\");\n this.listenFor(\"wheel\");\n this.listeners.wheel = callback;\n return this;\n }\n /**\n * An internal function to throw events.\n *\n * @name throwAlreadyInstalled\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {string} name - The name of the event.\n * @return {void}\n */\n throwAlreadyInstalled(name) {\n throw `This MouseHandler already has a '${name}' callback. To keep the code simple there is only room for one.`;\n }\n /**\n * Call this when your work is done.\n *\n * The function will un-install all event listeners.\n *\n * @name destroy\n * @memberof MouseHandler\n * @instance\n * @private\n * @return {void}\n */\n destroy() {\n this.unlistenFor(\"mousedown\");\n this.unlistenFor(\"mousemove\");\n this.unlistenFor(\"moseup\");\n this.unlistenFor(\"click\");\n this.unlistenFor(\"wheel\");\n this.element.removeEventListener(\"mousemove\", this.handlers[\"mousemove\"]);\n this.element.removeEventListener(\"mouseup\", this.handlers[\"mousedown\"]);\n this.element.removeEventListener(\"mousedown\", this.handlers[\"mousedown\"]);\n this.element.removeEventListener(\"click\", this.handlers[\"click\"]);\n this.element.removeEventListener(\"wheel\", this.handlers[\"wheel\"]);\n }\n}\n//# sourceMappingURL=MouseHandler.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-01-30\n * @modified 2019-03-23 Added JSDoc tags.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `PBImage.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @version 1.2.0\n *\n * @file PBImage\n * @fileoverview As native Image objects have only a position and with\n * and height thei are not suitable for UI dragging interfaces.\n * @public\n **/\nimport { UIDGenerator } from \"./UIDGenerator\";\n/**\n * @classdesc A wrapper for image objects. Has an upper left and a lower right corner point.\n *\n * @requires Vertex\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n */\nexport class PBImage {\n /**\n * The constructor.\n *\n * @constructor\n * @name PBImage\n * @param {Image} image - The actual image.\n * @param {Vertex} upperLeft - The upper left corner.\n * @param {Vertex} lowerRight - The lower right corner.\n **/\n constructor(image, upperLeft, lowerRight) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"PBImage\";\n this.uid = UIDGenerator.next();\n this.image = image;\n this.upperLeft = upperLeft;\n this.lowerRight = lowerRight;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.upperLeft.destroy();\n this.lowerRight.destroy();\n this.isDestroyed = true;\n }\n}\n//# sourceMappingURL=PBImage.js.map","/**\n * @author Ikaros Kappler\n * @date 2021-11-16\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2023-09-25 Fixed a type error in the constructor. Nothing vital.\n * @version 1.1.1\n **/\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A simple text element: position, fontSize, fontFamily, color, textAlign, lineHeight and rotation.\n *\n * @requires FontOptions\n * @requires FontSize\n * @requires FontStyle\n * @requires FontWeight\n * @requires Vertex\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class PBText {\n /**\n * Create a new circle with given center point and radius.\n *\n * @constructor\n * @name Circle\n * @param {Vertex} center - The center point of the circle.\n * @param {number} radius - The radius of the circle.\n */\n constructor(text, anchor, options) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"PBText\";\n this.uid = UIDGenerator.next();\n this.text = text;\n this.anchor = anchor !== null && anchor !== void 0 ? anchor : new Vertex();\n this.color = options === null || options === void 0 ? void 0 : options.color;\n this.fontFamily = options === null || options === void 0 ? void 0 : options.fontFamily;\n this.fontSize = options === null || options === void 0 ? void 0 : options.fontSize;\n this.fontStyle = options === null || options === void 0 ? void 0 : options.fontStyle;\n this.fontWeight = options === null || options === void 0 ? void 0 : options.fontWeight;\n this.lineHeight = options === null || options === void 0 ? void 0 : options.lineHeight;\n this.textAlign = options === null || options === void 0 ? void 0 : options.textAlign;\n this.rotation = options === null || options === void 0 ? void 0 : options.rotation;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.anchor.destroy();\n this.isDestroyed = true;\n }\n} // END class\n//# sourceMappingURL=PBText.js.map","/* Port from AlloyFinger v0.1.15\n * Original by dntzhang\n * Typescript port by Ikaros Kappler\n * Github: https://github.com/IkarosKappler/AlloyFinger-Typescript\n *\n * @date 2021-02-10 (Typescript port)\n * @version 0.1.18\n */\n;\n/**\n * Tiny math function to calculate the length of a vector in euclidean space.\n *\n * @param {XYCoords} v - The vector in {x,y} notation.\n * @return {number} The length of the vector.\n */\nconst getLen = (v) => {\n return Math.sqrt(v.x * v.x + v.y * v.y);\n};\n/**\n * Tiny math function to calculate the dot product of two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The dot product of both vectors.\n */\nconst dot = (v1, v2) => {\n return v1.x * v2.x + v1.y * v2.y;\n};\n/**\n * Tiny math function to calculate the angle between two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The angle (in radians) between the two vectors.\n */\nconst getAngle = (v1, v2) => {\n const mr = getLen(v1) * getLen(v2);\n if (mr === 0)\n return 0;\n var r = dot(v1, v2) / mr;\n if (r > 1)\n r = 1;\n return Math.acos(r);\n};\n/**\n * Tiny math function to calculate the cross product of two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The cross product of both vectors.\n */\nconst cross = (v1, v2) => {\n return v1.x * v2.y - v2.x * v1.y;\n};\n/**\n * Tiny math function to calculate the rotate-angle (in degrees) for two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The rotate-angle in degrees for the two vectors.\n */\nconst getRotateAngle = (v1, v2) => {\n var angle = getAngle(v1, v2);\n if (cross(v1, v2) > 0) {\n angle *= -1;\n }\n return angle * 180 / Math.PI;\n};\n/**\n * A HandlerAdmin holds all the added event handlers for one kind of event type.\n */\nclass HandlerAdmin {\n constructor(el) {\n this.handlers = [];\n this.el = el;\n }\n ;\n add(handler) {\n this.handlers.push(handler);\n }\n ;\n del(handler) {\n if (!handler)\n this.handlers = [];\n for (var i = this.handlers.length; i >= 0; i--) {\n if (this.handlers[i] === handler) {\n this.handlers.splice(i, 1);\n }\n }\n }\n ;\n dispatch(..._args) {\n for (var i = 0, len = this.handlers.length; i < len; i++) {\n const handler = this.handlers[i];\n if (typeof handler === 'function') {\n handler.apply(this.el, arguments);\n }\n }\n }\n ;\n} // END class HandlerAdmin\n/**\n * A wrapper for handler functions; converts the passed handler function into a HadlerAdmin instance..\n */\nconst wrapFunc = (el, handler) => {\n const handlerAdmin = new HandlerAdmin(el);\n handlerAdmin.add(handler);\n return handlerAdmin;\n};\n/**\n * @classdesc The AlloyFinger main class. Use this to add handler functions for\n * touch events to any HTML- or SVG-Element.\n **/\nexport class AlloyFinger {\n constructor(el, option) {\n this.element = typeof el == 'string' ? document.querySelector(el) : el;\n // Fancy stuff: change `this` from the start-, move-, end- and cancel-function.\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind\n this.start = this.start.bind(this);\n this.move = this.move.bind(this);\n this.end = this.end.bind(this);\n this.cancel = this.cancel.bind(this);\n this.element.addEventListener(\"touchstart\", this.start, false);\n this.element.addEventListener(\"touchmove\", this.move, false);\n this.element.addEventListener(\"touchend\", this.end, false);\n this.element.addEventListener(\"touchcancel\", this.cancel, false);\n this.preV = { x: null, y: null };\n this.pinchStartLen = null;\n this.zoom = 1;\n this.isDoubleTap = false;\n const noop = () => { };\n this.rotate = wrapFunc(this.element, option.rotate || noop);\n this.touchStart = wrapFunc(this.element, option.touchStart || noop);\n this.multipointStart = wrapFunc(this.element, option.multipointStart || noop);\n this.multipointEnd = wrapFunc(this.element, option.multipointEnd || noop);\n this.pinch = wrapFunc(this.element, option.pinch || noop);\n this.swipe = wrapFunc(this.element, option.swipe || noop);\n this.tap = wrapFunc(this.element, option.tap || noop);\n this.doubleTap = wrapFunc(this.element, option.doubleTap || noop);\n this.longTap = wrapFunc(this.element, option.longTap || noop);\n this.singleTap = wrapFunc(this.element, option.singleTap || noop);\n this.pressMove = wrapFunc(this.element, option.pressMove || noop);\n this.twoFingerPressMove = wrapFunc(this.element, option.twoFingerPressMove || noop);\n this.touchMove = wrapFunc(this.element, option.touchMove || noop);\n this.touchEnd = wrapFunc(this.element, option.touchEnd || noop);\n this.touchCancel = wrapFunc(this.element, option.touchCancel || noop);\n this._cancelAllHandler = this.cancelAll.bind(this);\n if (globalThis && typeof globalThis.addEventListener === \"function\") {\n globalThis.addEventListener('scroll', this._cancelAllHandler);\n }\n this.delta = null;\n this.last = null;\n this.now = null;\n this.tapTimeout = null;\n this.singleTapTimeout = null;\n this.longTapTimeout = null;\n this.swipeTimeout = null;\n this.x1 = this.x2 = this.y1 = this.y2 = null;\n this.preTapPosition = { x: null, y: null };\n }\n ;\n start(evt) {\n if (!evt.touches)\n return;\n const _self = this;\n this.now = Date.now();\n this.x1 = evt.touches[0].pageX;\n this.y1 = evt.touches[0].pageY;\n this.delta = this.now - (this.last || this.now);\n this.touchStart.dispatch(evt, this.element);\n if (this.preTapPosition.x !== null) {\n this.isDoubleTap = (this.delta > 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30);\n if (this.isDoubleTap)\n clearTimeout(this.singleTapTimeout);\n }\n this.preTapPosition.x = this.x1;\n this.preTapPosition.y = this.y1;\n this.last = this.now;\n const preV = this.preV;\n const len = evt.touches.length;\n if (len > 1) {\n this._cancelLongTap();\n this._cancelSingleTap();\n const v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 };\n preV.x = v.x;\n preV.y = v.y;\n this.pinchStartLen = getLen(preV);\n this.multipointStart.dispatch(evt, this.element);\n }\n this._preventTap = false;\n this.longTapTimeout = setTimeout((() => {\n _self.longTap.dispatch(evt, _self.element);\n _self._preventTap = true;\n }).bind(_self), 750);\n }\n ;\n move(event) {\n if (!event.touches)\n return;\n const afEvent = event;\n const preV = this.preV;\n const len = event.touches.length;\n const currentX = event.touches[0].pageX;\n const currentY = event.touches[0].pageY;\n this.isDoubleTap = false;\n if (len > 1) {\n const sCurrentX = afEvent.touches[1].pageX;\n const sCurrentY = afEvent.touches[1].pageY;\n const v = { x: afEvent.touches[1].pageX - currentX, y: afEvent.touches[1].pageY - currentY };\n if (preV.x !== null) {\n if (this.pinchStartLen > 0) {\n afEvent.zoom = getLen(v) / this.pinchStartLen;\n this.pinch.dispatch(afEvent, this.element);\n }\n afEvent.angle = getRotateAngle(v, preV);\n this.rotate.dispatch(afEvent, this.element);\n }\n preV.x = v.x;\n preV.y = v.y;\n if (this.x2 !== null && this.sx2 !== null) {\n afEvent.deltaX = (currentX - this.x2 + sCurrentX - this.sx2) / 2;\n afEvent.deltaY = (currentY - this.y2 + sCurrentY - this.sy2) / 2;\n }\n else {\n afEvent.deltaX = 0;\n afEvent.deltaY = 0;\n }\n this.twoFingerPressMove.dispatch(afEvent, this.element);\n this.sx2 = sCurrentX;\n this.sy2 = sCurrentY;\n }\n else {\n if (this.x2 !== null) {\n afEvent.deltaX = currentX - this.x2;\n afEvent.deltaY = currentY - this.y2;\n //move事件中添加对当前触摸点到初始触摸点的判断,\n //如果曾经大于过某个距离(比如10),就认为是移动到某个地方又移回来,应该不再触发tap事件才对。\n //\n // translation:\n // Add the judgment of the current touch point to the initial touch point in the event,\n // If it has been greater than a certain distance (such as 10), it is considered to be\n // moved to a certain place and then moved back, and the tap event should no longer be triggered.\n const movedX = Math.abs(this.x1 - this.x2);\n const movedY = Math.abs(this.y1 - this.y2);\n if (movedX > 10 || movedY > 10) {\n this._preventTap = true;\n }\n }\n else {\n afEvent.deltaX = 0;\n afEvent.deltaY = 0;\n }\n this.pressMove.dispatch(afEvent, this.element);\n }\n this.touchMove.dispatch(afEvent, this.element);\n this._cancelLongTap();\n this.x2 = currentX;\n this.y2 = currentY;\n if (len > 1) {\n event.preventDefault();\n }\n }\n ; // END move\n end(event) {\n if (!event.changedTouches)\n return;\n const afEvent = event;\n this._cancelLongTap();\n const self = this;\n if (afEvent.touches.length < 2) {\n this.multipointEnd.dispatch(afEvent, this.element);\n this.sx2 = this.sy2 = null;\n }\n //swipe\n if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) ||\n (this.y2 && Math.abs(this.y1 - this.y2) > 30)) {\n afEvent.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2);\n this.swipeTimeout = setTimeout(function () {\n self.swipe.dispatch(afEvent, self.element);\n }, 0);\n }\n else {\n this.tapTimeout = setTimeout(function () {\n if (!self._preventTap) {\n self.tap.dispatch(afEvent, self.element);\n }\n // trigger double tap immediately\n if (self.isDoubleTap) {\n self.doubleTap.dispatch(afEvent, self.element);\n self.isDoubleTap = false;\n }\n }, 0);\n if (!self.isDoubleTap) {\n self.singleTapTimeout = setTimeout(function () {\n self.singleTap.dispatch(afEvent, self.element);\n }, 250);\n }\n }\n this.touchEnd.dispatch(afEvent, this.element);\n this.preV.x = 0;\n this.preV.y = 0;\n this.zoom = 1;\n this.pinchStartLen = null;\n this.x1 = this.x2 = this.y1 = this.y2 = null;\n }\n ; // END end\n cancelAll() {\n this._preventTap = true;\n clearTimeout(this.singleTapTimeout);\n clearTimeout(this.tapTimeout);\n clearTimeout(this.longTapTimeout);\n clearTimeout(this.swipeTimeout);\n }\n ;\n cancel(evt) {\n this.cancelAll();\n this.touchCancel.dispatch(evt, this.element);\n }\n ;\n _cancelLongTap() {\n clearTimeout(this.longTapTimeout);\n }\n ;\n _cancelSingleTap() {\n clearTimeout(this.singleTapTimeout);\n }\n ;\n _swipeDirection(x1, x2, y1, y2) {\n return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down');\n }\n ;\n on(evt, handler) {\n if (this[evt]) {\n // Force the generic parameter into it's expected candidate here ;)\n const admin = this[evt];\n admin.add(handler);\n }\n }\n ;\n off(evt, handler) {\n if (this[evt]) {\n // Force the generic parameter into it's expected candidate here ;)\n const admin = this[evt];\n admin.del(handler);\n }\n }\n ;\n destroy() {\n if (this.singleTapTimeout) {\n clearTimeout(this.singleTapTimeout);\n }\n if (this.tapTimeout) {\n clearTimeout(this.tapTimeout);\n }\n if (this.longTapTimeout) {\n clearTimeout(this.longTapTimeout);\n }\n if (this.swipeTimeout) {\n clearTimeout(this.swipeTimeout);\n }\n this.element.removeEventListener(\"touchstart\", this.start);\n this.element.removeEventListener(\"touchmove\", this.move);\n this.element.removeEventListener(\"touchend\", this.end);\n this.element.removeEventListener(\"touchcancel\", this.cancel);\n this.rotate.del();\n this.touchStart.del();\n this.multipointStart.del();\n this.multipointEnd.del();\n this.pinch.del();\n this.swipe.del();\n this.tap.del();\n this.doubleTap.del();\n this.longTap.del();\n this.singleTap.del();\n this.pressMove.del();\n this.twoFingerPressMove.del();\n this.touchMove.del();\n this.touchEnd.del();\n this.touchCancel.del();\n this.preV = this.pinchStartLen = this.zoom = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = this.twoFingerPressMove = null;\n if (globalThis && typeof globalThis.removeEventListener === \"function\") {\n globalThis.removeEventListener('scroll', this._cancelAllHandler);\n }\n }\n ; // END destroy\n}\n;\nexport default AlloyFinger;\n//# sourceMappingURL=alloy_finger.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-11-28\n * @modified 2018-12-04 Added the toSVGString function.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2021-01-20 Added UID.\n * @modified 2021-02-14 Added functions `radiusH` and `radiusV`.\n * @modified 2021-02-26 Added helper function `decribeSVGArc(...)`.\n * @modified 2021-03-01 Added attribute `rotation` to allow rotation of ellipses.\n * @modified 2021-03-03 Added the `vertAt` and `perimeter` methods.\n * @modified 2021-03-05 Added the `getFoci`, `normalAt` and `tangentAt` methods.\n * @modified 2021-03-09 Added the `clone` and `rotate` methods.\n * @modified 2021-03-10 Added the `toCubicBezier` method.\n * @modified 2021-03-15 Added `VEllipse.quarterSegmentCount` and `VEllipse.scale` functions.\n * @modified 2021-03-19 Added the `VEllipse.rotate` function.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `VEllipse.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2025-03-31 ATTENTION: modified the winding direction of the `tangentAt` method to match with the Circle method. This is a breaking change!\n * @modified 2025-03-31 Adding the `VEllipse.move(amount: XYCoords)` method.\n * @modified 2025-04-19 Adding the `VEllipse.getBounds()` method.\n * @modified 2025-04-24 Adding the `VEllipse.getExtremePoints()` method for calculating minima and maxima.\n * @version 1.4.0\n *\n * @file VEllipse\n * @fileoverview Ellipses with a center and an x- and a y-axis (stored as a vertex).\n **/\nimport { Line } from \"./Line\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { Circle } from \"./Circle\";\nimport { Bounds } from \"./Bounds\";\n/**\n * @classdesc An ellipse class based on two vertices [centerX,centerY] and [radiusX,radiusY].\n *\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n * @requires Vertex\n */\nexport class VEllipse {\n /**\n * The constructor.\n *\n * @constructor\n * @param {Vertex} center - The ellipses center.\n * @param {Vertex} axis - The x- and y-axis (the two radii encoded in a control point).\n * @param {Vertex} rotation - [optional, default=0] The rotation of this ellipse.\n * @name VEllipse\n **/\n constructor(center, axis, rotation) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"VEllipse\";\n this.uid = UIDGenerator.next();\n this.center = center;\n this.axis = axis;\n this.rotation = rotation || 0.0;\n }\n /**\n * Clone this ellipse (deep clone).\n *\n * @return {VEllipse} A copy of this ellipse.s\n */\n clone() {\n return new VEllipse(this.center.clone(), this.axis.clone(), this.rotation);\n }\n /**\n * Get the non-negative horizonal radius of this ellipse.\n *\n * @method radiusH\n * @instance\n * @memberof VEllipse\n * @return {number} The unsigned horizontal radius of this ellipse.\n */\n radiusH() {\n return Math.abs(this.signedRadiusH());\n }\n /**\n * Get the signed horizonal radius of this ellipse.\n *\n * @method signedRadiusH\n * @instance\n * @memberof VEllipse\n * @return {number} The signed horizontal radius of this ellipse.\n */\n signedRadiusH() {\n // return Math.abs(this.axis.x - this.center.x);\n // Rotate axis back to origin before calculating radius\n // return Math.abs(new Vertex(this.axis).rotate(-this.rotation,this.center).x - this.center.x);\n return new Vertex(this.axis).rotate(-this.rotation, this.center).x - this.center.x;\n }\n /**\n * Get the non-negative vertical radius of this ellipse.\n *\n * @method radiusV\n * @instance\n * @memberof VEllipse\n * @return {number} The unsigned vertical radius of this ellipse.\n */\n radiusV() {\n return Math.abs(this.signedRadiusV());\n }\n /**\n * Get the signed vertical radius of this ellipse.\n *\n * @method radiusV\n * @instance\n * @memberof VEllipse\n * @return {number} The signed vertical radius of this ellipse.\n */\n signedRadiusV() {\n // Rotate axis back to origin before calculating radius\n return new Vertex(this.axis).rotate(-this.rotation, this.center).y - this.center.y;\n }\n /**\n * Get the the minima and maxima (points) of this (rotated) ellipse.\n *\n * @method getExtremePoints\n * @instance\n * @memberof VEllipse\n * @return {[Vertex, Vertex, Vertex, Vertex]} Get the the minima and maxima (points) of this (rotated) ellipse.\n */\n getExtremePoints() {\n const a = this.radiusH();\n const b = this.radiusV();\n // Calculate t_x values\n const t_x1 = Math.atan2(-b * Math.sin(this.rotation), a * Math.cos(this.rotation));\n const t_x2 = t_x1 + Math.PI;\n // Calculate x values at t_x\n const x_x1 = this.center.x + a * Math.cos(t_x1) * Math.cos(this.rotation) - b * Math.sin(t_x1) * Math.sin(this.rotation);\n const y_x1 = this.center.y + a * Math.cos(t_x1) * Math.sin(this.rotation) + b * Math.sin(t_x1) * Math.cos(this.rotation);\n const x_x2 = this.center.x + a * Math.cos(t_x2) * Math.cos(this.rotation) - b * Math.sin(t_x2) * Math.sin(this.rotation);\n const y_x2 = this.center.y + a * Math.cos(t_x2) * Math.sin(this.rotation) + b * Math.sin(t_x2) * Math.cos(this.rotation);\n let x_max, x_min;\n if (x_x1 > x_x2) {\n x_max = new Vertex(x_x1, y_x1);\n x_min = new Vertex(x_x2, y_x2);\n }\n else {\n x_max = new Vertex(x_x2, y_x2);\n x_min = new Vertex(x_x1, y_x1);\n }\n // Calculate t_y values\n const t_y1 = Math.atan2(b * Math.cos(this.rotation), a * Math.sin(this.rotation));\n const t_y2 = t_y1 + Math.PI;\n // Calculate y values at t_y\n const x_y1 = this.center.x + a * Math.cos(t_y1) * Math.cos(this.rotation) - b * Math.sin(t_y1) * Math.sin(this.rotation);\n const y_y1 = this.center.y + a * Math.cos(t_y1) * Math.sin(this.rotation) + b * Math.sin(t_y1) * Math.cos(this.rotation);\n const x_y2 = this.center.x + a * Math.cos(t_y2) * Math.cos(this.rotation) - b * Math.sin(t_y2) * Math.sin(this.rotation);\n const y_y2 = this.center.y + a * Math.cos(t_y2) * Math.sin(this.rotation) + b * Math.sin(t_y2) * Math.cos(this.rotation);\n let y_max, y_min;\n if (y_y1 > y_y2) {\n y_max = new Vertex(x_y1, y_y1);\n y_min = new Vertex(x_y2, y_y2);\n }\n else {\n y_max = new Vertex(x_y2, y_y2);\n y_min = new Vertex(x_y1, y_y1);\n }\n return [x_max, x_min, y_max, y_min];\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this ellipse.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getBounds\n * @instance\n * @memberof VEllipse\n * @return {Bounds} The bounds of this ellipse.\n **/\n getBounds() {\n // Thanks to Cuixiping\n // https://stackoverflow.com/questions/87734/how-do-you-calculate-the-axis-aligned-bounding-box-of-an-ellipse\n const r1 = this.radiusH();\n const r2 = this.radiusV();\n const ux = r1 * Math.cos(this.rotation);\n const uy = r1 * Math.sin(this.rotation);\n const vx = r2 * Math.cos(this.rotation + Math.PI / 2);\n const vy = r2 * Math.sin(this.rotation + Math.PI / 2);\n const bbox_halfwidth = Math.sqrt(ux * ux + vx * vx);\n const bbox_halfheight = Math.sqrt(uy * uy + vy * vy);\n return new 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 });\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Move the ellipse by the given amount. This is equivalent by moving the `center` and `axis` points.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof VEllipse\n * @return {VEllipse} this for chaining\n **/\n move(amount) {\n this.center.add(amount);\n this.axis.add(amount);\n return this;\n }\n /**\n * Scale this ellipse by the given factor from the center point. The factor will be applied to both radii.\n *\n * @method scale\n * @instance\n * @memberof VEllipse\n * @param {number} factor - The factor to scale by.\n * @return {VEllipse} this for chaining.\n */\n scale(factor) {\n this.axis.scale(factor, this.center);\n return this;\n }\n /**\n * Rotate this ellipse around its center.\n *\n * @method rotate\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to rotate by.\n * @returns {VEllipse} this for chaining.\n */\n rotate(angle) {\n this.axis.rotate(angle, this.center);\n this.rotation += angle;\n return this;\n }\n /**\n * Get the vertex on the ellipse's outline at the given angle.\n *\n * @method vertAt\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to determine the vertex at.\n * @return {Vertex} The vertex on the outline at the given angle.\n */\n vertAt(angle) {\n // Tanks to Narasinham for the vertex-on-ellipse equations\n // https://math.stackexchange.com/questions/22064/calculating-a-point-that-lies-on-an-ellipse-given-an-angle\n const a = this.radiusH();\n const b = this.radiusV();\n return new Vertex(VEllipse.utils.polarToCartesian(this.center.x, this.center.y, a, b, angle)).rotate(this.rotation, this.center);\n }\n /**\n * Get the normal vector at the given angle.\n * The normal vector is the vector that intersects the ellipse in a 90 degree angle\n * at the given point (speicified by the given angle).\n *\n * Length of desired normal vector can be specified, default is 1.0.\n *\n * @method normalAt\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to get the normal vector at.\n * @param {number=1.0} length - [optional, default=1] The length of the returned vector.\n */\n normalAt(angle, length) {\n const point = this.vertAt(angle - this.rotation); // HERE IS THE CORRECT BEHAVIOR!\n const foci = this.getFoci();\n // Calculate the angle between [point,focusA] and [point,focusB]\n const angleA = new Line(point, foci[0]).angle();\n const angleB = new Line(point, foci[1]).angle();\n const centerAngle = angleA + (angleB - angleA) / 2.0;\n const endPointA = point.clone().addX(50).clone().rotate(centerAngle, point);\n const endPointB = point\n .clone()\n .addX(50)\n .clone()\n .rotate(Math.PI + centerAngle, point);\n const resultVector = this.center.distance(endPointA) < this.center.distance(endPointB)\n ? new Vector(point, endPointB)\n : new Vector(point, endPointA);\n if (typeof length === \"number\") {\n resultVector.setLength(length);\n }\n return resultVector;\n }\n /**\n * Get the tangent vector at the given angle.\n * The tangent vector is the vector that touches the ellipse exactly at the given given\n * point (speicified by the given angle).\n *\n * Note that the tangent is just 90 degree rotated normal vector.\n *\n * Length of desired tangent vector can be specified, default is 1.0.\n *\n * @method tangentAt\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to get the tangent vector at.\n * @param {number=1.0} length - [optional, default=1] The length of the returned vector.\n */\n tangentAt(angle, length) {\n const normal = this.normalAt(angle, length);\n return normal.inv().perp();\n }\n /**\n * Get the perimeter of this ellipse.\n *\n * @method perimeter\n * @instance\n * @memberof VEllipse\n * @return {number}\n */\n perimeter() {\n // This method does not use an iterative approximation to determine the perimeter, but it uses\n // a wonderful closed approximation found by Srinivasa Ramanujan.\n // Matt Parker made a neat video about it:\n // https://www.youtube.com/watch?v=5nW3nJhBHL0\n const a = this.radiusH();\n const b = this.radiusV();\n return Math.PI * (3 * (a + b) - Math.sqrt((3 * a + b) * (a + 3 * b)));\n }\n /**\n * Get the two foci of this ellipse.\n *\n * @method getFoci\n * @instance\n * @memberof VEllipse\n * @return {Array<Vertex>} An array with two elements, the two focal points of the ellipse (foci).\n */\n getFoci() {\n // https://www.mathopenref.com/ellipsefoci.html\n const rh = this.radiusH();\n const rv = this.radiusV();\n const sdiff = rh * rh - rv * rv;\n // f is the distance of each focs to the center.\n const f = Math.sqrt(Math.abs(sdiff));\n // Foci on x- or y-axis?\n if (sdiff < 0) {\n return [\n this.center.clone().addY(f).rotate(this.rotation, this.center),\n this.center.clone().addY(-f).rotate(this.rotation, this.center)\n ];\n }\n else {\n return [\n this.center.clone().addX(f).rotate(this.rotation, this.center),\n this.center.clone().addX(-f).rotate(this.rotation, this.center)\n ];\n }\n }\n /**\n * Get equally distributed points on the outline of this ellipse.\n *\n * @method getEquidistantVertices\n * @instance\n * @param {number} pointCount - The number of points.\n * @returns {Array<Vertex>}\n */\n getEquidistantVertices(pointCount) {\n const angles = VEllipse.utils.equidistantVertAngles(this.radiusH(), this.radiusV(), pointCount);\n const result = [];\n for (var i = 0; i < angles.length; i++) {\n result.push(this.vertAt(angles[i]));\n }\n return result;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the line intersections as vectors with this ellipse.\n *\n * @method lineIntersections\n * @instance\n * @param {VertTuple<Vector> ray - The line/ray to intersect this ellipse with.\n * @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.\n * @returns\n */\n lineIntersections(ray, inVectorBoundsOnly = false) {\n // Question: what happens to extreme versions when ellipse is a line (width or height is zero)?\n // This would result in a Division_by_Zero exception!\n // Step A: create clones for operations (keep originals unchanged)\n const ellipseCopy = this.clone(); // VEllipse\n const rayCopy = ray.clone(); // Vector\n // Step B: move both so ellipse's center is located at (0,0)\n const moveAmount = ellipseCopy.center.clone().inv();\n ellipseCopy.move(moveAmount);\n rayCopy.add(moveAmount);\n // Step C: rotate eclipse backwards it's rotation, so that rotation is zero (0.0).\n // Rotate together with ray!\n const rotationAmount = -ellipseCopy.rotation;\n ellipseCopy.rotate(rotationAmount); // Rotation around (0,0) = center of translated ellipse\n rayCopy.a.rotate(rotationAmount, ellipseCopy.center);\n rayCopy.b.rotate(rotationAmount, ellipseCopy.center);\n // Step D: find x/y factors to use for scaling to transform the ellipse to a circle.\n // Scale together with vector ray.\n const radiusH = ellipseCopy.radiusH();\n const radiusV = ellipseCopy.radiusV();\n const scalingFactors = radiusH > radiusV ? { x: radiusV / radiusH, y: 1.0 } : { x: 1.0, y: radiusH / radiusV };\n // Step E: scale ellipse AND ray by calculated factors.\n ellipseCopy.axis.scaleXY(scalingFactors);\n rayCopy.a.scaleXY(scalingFactors);\n rayCopy.b.scaleXY(scalingFactors);\n // Intermediate result: now the ellipse is transformed to a circle and we can calculate intersections :)\n // Step F: calculate circle+line intersecions\n const tmpCircle = new Circle(new Vertex(), ellipseCopy.radiusH()); // radiusH() === radiusV()\n const intersections = tmpCircle.lineIntersections(rayCopy, inVectorBoundsOnly);\n // Step G: transform intersecions back to original configuration\n intersections.forEach(function (intersectionPoint) {\n // Reverse transformation from above.\n intersectionPoint.scaleXY({ x: 1 / scalingFactors.x, y: 1 / scalingFactors.y }, ellipseCopy.center);\n intersectionPoint.rotate(-rotationAmount, ellipseCopy.center);\n intersectionPoint.sub(moveAmount);\n });\n return intersections;\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.center, vert);\n const angle = lineFromCenter.angle();\n // Calculate tangent at angle\n return this.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Convert this ellipse into cubic Bézier curves.\n *\n * @param {number=3} quarterSegmentCount - The number of segments per base elliptic quarter (default is 3, min is 1).\n * @param {number=0.666666} threshold - The Bézier threshold (default value 0.666666 approximates the ellipse with best results\n * but you might wish to use other values)\n * @return {Array<CubicBezierCurve>} An array of cubic Bézier curves representing this ellipse.\n */\n toCubicBezier(quarterSegmentCount, threshold) {\n // Math by Luc Maisonobe\n // http://www.spaceroots.org/documents/ellipse/node22.html\n // Note that ellipses with radiusH=0 or radiusV=0 cannot be represented as Bézier curves.\n // Return a single line here (as a Bézier curve)?\n // if (Math.abs(this.radiusV()) < 0.00001) {\n // const radiusH = this.radiusH();\n // return [\n // new CubicBezierCurve(\n // this.center.clone().addX(radiusH),\n // this.center.clone().addX(-radiusH),\n // this.center.clone(),\n // this.center.clone()\n // )\n // ]; // TODO: test horizontal line ellipse\n // }\n // if (Math.abs(this.radiusH()) < 0.00001) {\n // const radiusV = this.radiusV();\n // return [\n // new CubicBezierCurve(\n // this.center.clone().addY(radiusV),\n // this.center.clone().addY(-radiusV),\n // this.center.clone(),\n // this.center.clone()\n // )\n // ]; // TODO: test vertical line ellipse\n // }\n // At least 4, but 16 seems to be a good value.\n const segmentCount = Math.max(1, quarterSegmentCount || 3) * 4;\n threshold = typeof threshold === \"undefined\" ? 0.666666 : threshold;\n const radiusH = this.radiusH();\n const radiusV = this.radiusV();\n const curves = [];\n const angles = VEllipse.utils.equidistantVertAngles(radiusH, radiusV, segmentCount);\n let curAngle = angles[0] + this.rotation;\n let startPoint = this.vertAt(curAngle);\n for (var i = 0; i < angles.length; i++) {\n let nextAngle = angles[(i + 1) % angles.length] + this.rotation;\n let endPoint = this.vertAt(nextAngle);\n if (Math.abs(radiusV) < 0.0001 || Math.abs(radiusH) < 0.0001) {\n // Distorted ellipses can only be approximated by linear Bézier segments\n let diff = startPoint.difference(endPoint);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().addXY(diff.x * 0.333, diff.y * 0.333), endPoint.clone().addXY(-diff.x * 0.333, -diff.y * 0.333));\n curves.push(curve);\n }\n else {\n let startTangent = this.tangentAt(curAngle + this.rotation);\n let endTangent = this.tangentAt(nextAngle + this.rotation);\n // Find intersection (ignore that the result might be null in some extreme cases)\n let intersection = startTangent.intersection(endTangent);\n // What if intersection is undefined?\n // --> This *can* not happen if segmentCount > 2 and height and width of the ellipse are not zero.\n let startDiff = startPoint.difference(intersection);\n let endDiff = endPoint.difference(intersection);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().add(startDiff.scale(threshold)), endPoint.clone().add(endDiff.scale(threshold)));\n curves.push(curve);\n }\n startPoint = endPoint;\n curAngle = nextAngle;\n }\n return curves;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.center.destroy();\n this.axis.destroy();\n this.isDestroyed = true;\n }\n}\n/**\n * A static collection of ellipse-related helper functions.\n * @static\n */\nVEllipse.utils = {\n /**\n * Calculate a particular point on the outline of the given ellipse (center plus two radii plus angle).\n *\n * @name polarToCartesian\n * @param {number} centerX - The x coordinate of the elliptic center.\n * @param {number} centerY - The y coordinate of the elliptic center.\n * @param {number} radiusH - The horizontal radius of the ellipse.\n * @param {number} radiusV - The vertical radius of the ellipse.\n * @param {number} angle - The angle (in radians) to get the desired outline point for.\n * @reutn {XYCoords} The outlont point in absolute x-y-coordinates.\n */\n polarToCartesian: (centerX, centerY, radiusH, radiusV, angle) => {\n // Tanks to Narasinham for the vertex-on-ellipse equations\n // https://math.stackexchange.com/questions/22064/calculating-a-point-that-lies-on-an-ellipse-given-an-angle\n var s = Math.sin(Math.PI / 2 - angle);\n var c = Math.cos(Math.PI / 2 - angle);\n return {\n x: centerX + (radiusH * radiusV * s) / Math.sqrt(Math.pow(radiusH * c, 2) + Math.pow(radiusV * s, 2)),\n y: centerY + (radiusH * radiusV * c) / Math.sqrt(Math.pow(radiusH * c, 2) + Math.pow(radiusV * s, 2))\n };\n },\n /**\n * Get the `theta` for a given `phi` (used to determine equidistant points on ellipse).\n *\n * @param radiusH\n * @param radiusV\n * @param phi\n * @returns {number} theta\n */\n phiToTheta: (radiusH, radiusV, phi) => {\n // See https://math.stackexchange.com/questions/172766/calculating-equidistant-points-around-an-ellipse-arc\n var tanPhi = Math.tan(phi);\n var tanPhi2 = tanPhi * tanPhi;\n var theta = -Math.PI / 2 + phi + Math.atan(((radiusH - radiusV) * tanPhi) / (radiusV + radiusH * tanPhi2));\n return theta;\n },\n /**\n * Get n equidistant points on the elliptic arc.\n *\n * @param pointCount\n * @returns\n */\n equidistantVertAngles: (radiusH, radiusV, pointCount) => {\n const angles = [];\n for (var i = 0; i < pointCount; i++) {\n var phi = Math.PI / 2.0 + ((Math.PI * 2) / pointCount) * i;\n let theta = VEllipse.utils.phiToTheta(radiusH, radiusV, phi);\n angles[i] = theta;\n }\n return angles;\n }\n}; // END utils\n//# sourceMappingURL=VEllipse.js.map","/**\n * Implementation of elliptic sectors.\n * Note that sectors are constructed in clockwise direction.\n *\n * @author Ikaros Kappler\n * @date 2021-02-26\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-11-01 Tweaked the `endpointToCenterParameters` function to handle negative values, too, without errors.\n * @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).\n * @modified 2025-04-02 Adding `VEllipseSector.containsAngle` method.\n * @modified 2025-04-02 Adding `VEllipseSector.lineIntersections` and `VEllipseSector.lineIntersectionTangents` and implementing `Intersectable`.\n * @modified 2025-04-07 Adding value wrapping (0 to TWO_PI) to the `VEllipseSector.containsAngle` method.\n * @modified 2025-04-09 Adding the `VEllipseSector.move` method.\n * @modified 2025-04-19 Added the `VEllipseSector.getStartPoint` and `getEndPoint` methods.\n * @modified 2025-04-23 Added the `VEllipseSector.getBounds` method.\n * @version 1.2.0\n */\nimport { Bounds } from \"./Bounds\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { geomutils } from \"./geomutils\";\nimport { Line } from \"./Line\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { VEllipse } from \"./VEllipse\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A class for elliptic sectors.\n *\n * @requires Line\n * @requires Vector\n * @requires VertTuple\n * @requires Vertex\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class VEllipseSector {\n /**\n * Create a new elliptic sector from the given ellipse and two angles.\n *\n * Note that the direction from start to end goes clockwise, and that start and end angle\n * will be wrapped to [0,PI*2).\n *\n * @constructor\n * @name VEllipseSector\n * @param {VEllipse} - The underlying ellipse to use.\n * @param {number} startAngle - The start angle of the sector.\n * @param {numner} endAngle - The end angle of the sector.\n */\n constructor(ellipse, startAngle, endAngle) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"VEllipseSector\";\n this.uid = UIDGenerator.next();\n this.ellipse = ellipse;\n this.startAngle = geomutils.wrapMinMax(startAngle, 0, Math.PI * 2);\n this.endAngle = geomutils.wrapMinMax(endAngle, 0, Math.PI * 2);\n }\n /**\n * Move the ellipse sector by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof VEllipseSector\n * @return {VEllipseSector} this for chaining\n **/\n move(amount) {\n this.ellipse.move(amount);\n return this;\n }\n /**\n * Checks wether the given angle (must be inside 0 and PI*2) is contained inside this sector.\n *\n * @param {number} angle - The numeric angle to check.\n * @method containsAngle\n * @instance\n * @memberof VEllipseSectpr\n * @return {boolean} True if (and only if) this sector contains the given angle.\n */\n containsAngle(angle) {\n angle = geomutils.mapAngleTo2PI(angle); // wrapMinMax(angle, 0, Math.PI * 2);\n const sAngle = geomutils.mapAngleTo2PI(this.startAngle);\n const eAngle = geomutils.mapAngleTo2PI(this.endAngle);\n // TODO: cleanup\n // if (this.startAngle <= this.endAngle) {\n // return angle >= this.startAngle && angle < this.endAngle;\n // } else {\n // // startAngle > endAngle\n // return angle >= this.startAngle || angle < this.endAngle;\n // }\n if (sAngle <= eAngle) {\n return angle >= sAngle && angle < eAngle;\n }\n else {\n // startAngle > endAngle\n return angle >= sAngle || angle < eAngle;\n }\n }\n /**\n * Get the sectors starting point (on the underlying ellipse, located at the start angle).\n *\n * @method getStartPoint\n * @instance\n * @memberof VEllipseSector\n * @return {Vertex} The sector's stating point.\n */\n getStartPoint() {\n return this.ellipse.vertAt(this.startAngle);\n }\n /**\n * Get the sectors ending point (on the underlying ellipse, located at the end angle).\n *\n * @method getEndPoint\n * @instance\n * @memberof VEllipseSector\n * @return {Vertex} The sector's ending point.\n */\n getEndPoint() {\n return this.ellipse.vertAt(this.endAngle);\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this elliptic sector.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getBounds\n * @instance\n * @memberof VEllipse\n * @return {Bounds} The bounds of this elliptic sector.\n **/\n getBounds() {\n // Calculage angles from east, west, north and south box points and check if they are inside\n const extremes = this.ellipse.getExtremePoints();\n const candidates = extremes.filter(point => {\n const angle = new Line(this.ellipse.center, point).angle() - this.ellipse.rotation;\n return this.containsAngle(angle);\n });\n return Bounds.computeFromVertices([this.getStartPoint(), this.getEndPoint()].concat(candidates));\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the line intersections as vectors with this ellipse.\n *\n * @method lineIntersections\n * @instance\n * @memberof VEllipseSectpr\n * @param {VertTuple<Vector>} ray - The line/ray to intersect this ellipse with.\n * @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.\n * @returns\n */\n lineIntersections(ray, inVectorBoundsOnly = false) {\n // First get all line intersections from underlying ellipse.\n const ellipseIntersections = this.ellipse.lineIntersections(ray, inVectorBoundsOnly);\n // Drop all intersection points that are not contained in the circle sectors bounds.\n const tmpLine = new Line(this.ellipse.center, new Vertex());\n return ellipseIntersections.filter((intersectionPoint) => {\n tmpLine.b.set(intersectionPoint);\n const lineAngle = tmpLine.angle();\n return this.containsAngle(lineAngle - this.ellipse.rotation);\n });\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @method lineIntersections\n * @memberof VEllipseSectpr\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.ellipse.center, vert);\n const angle = lineFromCenter.angle();\n // console.log(\"angle\", (angle / Math.PI) * 180.0);\n // const angle = Math.random() * Math.PI * 2; // TODO\n // Calculate tangent at angle\n return this.ellipse.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Convert this elliptic sector into cubic Bézier curves.\n *\n * @param {number=3} quarterSegmentCount - The number of segments per base elliptic quarter (default is 3, min is 1).\n * @param {number=0.666666} threshold - The Bézier threshold (default value 0.666666 approximates the ellipse with best results\n * but you might wish to use other values)\n * @return {Array<CubicBezierCurve>} An array of cubic Bézier curves representing the elliptic sector.\n */\n toCubicBezier(quarterSegmentCount, threshold) {\n // There are at least 4 segments required (dour quarters) to approximate a whole\n // ellipse with Bézier curves.\n // A visually 'good' approximation should have 12; this seems to be a good value (anything multiple of 4).\n const segmentCount = Math.max(1, quarterSegmentCount || 3) * 4;\n threshold = typeof threshold === \"undefined\" ? 0.666666 : threshold;\n const radiusH = this.ellipse.radiusH();\n const radiusV = this.ellipse.radiusV();\n var startAngle = VEllipseSector.ellipseSectorUtils.normalizeAngle(this.startAngle);\n var endAngle = VEllipseSector.ellipseSectorUtils.normalizeAngle(this.endAngle);\n // Find all angles inside start and end\n var angles = VEllipseSector.ellipseSectorUtils.equidistantVertAngles(radiusH, radiusV, startAngle, endAngle, segmentCount);\n angles = [startAngle].concat(angles).concat([endAngle]);\n const curves = [];\n let curAngle = angles[0];\n let startPoint = this.ellipse.vertAt(curAngle);\n for (var i = 0; i + 1 < angles.length; i++) {\n let nextAngle = angles[(i + 1) % angles.length];\n let endPoint = this.ellipse.vertAt(nextAngle);\n let startTangent = this.ellipse.tangentAt(curAngle + this.ellipse.rotation);\n let endTangent = this.ellipse.tangentAt(nextAngle + this.ellipse.rotation);\n // Distorted ellipses can only be approximated by linear Bézier segments\n if (Math.abs(radiusV) < 0.0001 || Math.abs(radiusH) < 0.0001) {\n let diff = startPoint.difference(endPoint);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().addXY(diff.x * 0.333, diff.y * 0.333), endPoint.clone().addXY(-diff.x * 0.333, -diff.y * 0.333));\n curves.push(curve);\n }\n else {\n // Find intersection\n let intersection = startTangent.intersection(endTangent);\n // What if intersection is undefined?\n // --> This *can* not happen if segmentCount > 2 and height and width of the ellipse are not zero.\n if (intersection) {\n // It's VERY LIKELY hat this ALWAYS happens; it's just a typesave variant.\n // Intersection cannot be null.\n let startDiff = startPoint.difference(intersection);\n let endDiff = endPoint.difference(intersection);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().add(startDiff.scale(threshold)), endPoint.clone().add(endDiff.scale(threshold)));\n curves.push(curve);\n }\n }\n startPoint = endPoint;\n curAngle = nextAngle;\n }\n return curves;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.ellipse.destroy();\n this.isDestroyed = true;\n }\n}\nVEllipseSector.ellipseSectorUtils = {\n /**\n * Helper function to convert an elliptic section to SVG arc params (for the `d` attribute).\n * Inspiration found at:\n * https://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle\n *\n * @param {boolean} options.moveToStart - If false (default=true) the initial 'Move' command will not be used.\n * @return [ 'A', radiusH, radiusV, rotation, largeArcFlag=1|0, sweepFlag=0, endx, endy ]\n */\n describeSVGArc: (x, y, radiusH, radiusV, startAngle, endAngle, rotation, options) => {\n if (typeof options === \"undefined\")\n options = { moveToStart: true };\n if (typeof rotation === \"undefined\")\n rotation = 0.0;\n // Important note: this function only works if start- and end-angle are within\n // one whole circle [x,x+2*PI].\n // Revelations of more than 2*PI might result in unexpected arcs.\n // -> Use the geomutils.wrapMax( angle, 2*PI )\n startAngle = geomutils.wrapMax(startAngle, Math.PI * 2);\n endAngle = geomutils.wrapMax(endAngle, Math.PI * 2);\n // Find the start- and end-point on the rotated ellipse\n // XYCoords to Vertex (for rotation)\n var end = new Vertex(VEllipse.utils.polarToCartesian(x, y, radiusH, radiusV, endAngle));\n var start = new Vertex(VEllipse.utils.polarToCartesian(x, y, radiusH, radiusV, startAngle));\n end.rotate(rotation, { x: x, y: y });\n start.rotate(rotation, { x: x, y: y });\n // Boolean stored as integers (0|1).\n var diff = endAngle - startAngle;\n var largeArcFlag;\n if (diff < 0) {\n largeArcFlag = Math.abs(diff) < Math.PI ? 1 : 0;\n }\n else {\n largeArcFlag = Math.abs(diff) > Math.PI ? 1 : 0;\n }\n const sweepFlag = 1;\n const pathData = [];\n if (options.moveToStart) {\n pathData.push(\"M\", start.x, start.y);\n }\n // Arc rotation in degrees, not radians.\n const r2d = 180 / Math.PI;\n pathData.push(\"A\", radiusH, radiusV, rotation * r2d, largeArcFlag, sweepFlag, end.x, end.y);\n return pathData;\n }, // END function describeSVGArc\n /**\n * Helper function to find second-kind elliptic angles, so that the euclidean distance along the the\n * elliptic sector is the same for all.\n *\n * Note that this is based on the full ellipse calculuation and start and end will be cropped; so the\n * distance from the start angle to the first angle and/or the distance from the last angle to\n * the end angle may be different to the others.\n *\n * Furthermore the computation is only possible on un-rotated ellipses; if your source ellipse has\n * a rotation on the plane please 'rotate' the result angles afterwards to find matching angles.\n *\n * Returned angles are normalized to the interval `[ 0, PI*2 ]`.\n *\n * @param {number} radiusH - The first (horizonal) radius of the ellipse.\n * @param {number} radiusV - The second (vertical) radius of the ellipse.\n * @param {number} startAngle - The opening angle of your elliptic sector (please use normalized angles).\n * @param {number} endAngle - The closing angle of your elliptic sector (please use normalized angles).\n * @param {number} fullEllipsePointCount - The number of base segments to use from the source ellipse (12 or 16 are good numbers).\n * @return {Array<number>} An array of n angles inside startAngle and endAngle (where n <= fullEllipsePointCount).\n */\n equidistantVertAngles: (radiusH, radiusV, startAngle, endAngle, fullEllipsePointCount) => {\n var ellipseAngles = VEllipse.utils.equidistantVertAngles(radiusH, radiusV, fullEllipsePointCount);\n ellipseAngles = ellipseAngles.map((angle) => VEllipseSector.ellipseSectorUtils.normalizeAngle(angle));\n const angleIsInRange = (angle) => {\n if (startAngle < endAngle)\n return angle >= startAngle && angle <= endAngle;\n else\n return angle >= startAngle || (angle <= endAngle && angle >= 0);\n };\n // Drop all angles outside the sector\n ellipseAngles = ellipseAngles.filter(angleIsInRange);\n // Now we need to sort the angles to the first one in the array is the closest to startAngle.\n // --> find the angle that is closest to the start angle\n const startIndex = VEllipseSector.ellipseSectorUtils.findClosestToStartAngle(startAngle, endAngle, ellipseAngles);\n // Bring all angles into the correct order\n // Idea: use splice or slice here?\n const angles = [];\n for (var i = 0; i < ellipseAngles.length; i++) {\n angles.push(ellipseAngles[(startIndex + i) % ellipseAngles.length]);\n }\n return angles;\n },\n findClosestToStartAngle: (startAngle, endAngle, ellipseAngles) => {\n // Note: endAngle > 0 && startAngle > 0\n if (startAngle > endAngle) {\n const n = ellipseAngles.length;\n for (var i = 0; i < n; i++) {\n const ea = geomutils.wrapMinMax(ellipseAngles[i], 0, Math.PI * 2);\n if (ea >= startAngle && ea >= endAngle) {\n return i;\n }\n }\n }\n return 0;\n },\n normalizeAngle: (angle) => (angle < 0 ? Math.PI * 2 + angle : angle),\n /**\n * Convert the elliptic arc from endpoint parameters to center parameters as described\n * in the w3c svg arc implementation note.\n *\n * https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter\n *\n * @param {number} x1 - The x component of the start point (end of last SVG command).\n * @param {number} y1 - The y component of the start point (end of last SVG command).\n * @param {number} rx - The first (horizontal) radius of the ellipse.\n * @param {number} ry - The second (vertical) radius of the ellipse.\n * @param {number} phi - The ellipse's rotational angle (angle of axis rotation) in radians (not in degrees as the SVG command uses!)\n * @param {boolean} fa - The large-arc-flag (boolean, not 0 or 1).\n * @param {boolean} fs - The sweep-flag (boolean, not 0 or 1).\n * @param {number} x2 - The x component of the end point (end of last SVG command).\n * @param {number} y2 - The y component of the end point (end of last SVG command).\n * @returns\n */\n endpointToCenterParameters(x1, y1, rx, ry, phi, fa, fs, x2, y2) {\n // console.log(\"endpointToCenterParameters\", x1, y1, phi, rx, ry, fa, fs, x2, y2);\n // Thanks to\n // https://observablehq.com/@toja/ellipse-and-elliptical-arc-conversion\n const abs = Math.abs;\n const sin = Math.sin;\n const cos = Math.cos;\n const sqrt = Math.sqrt;\n const pow = (n) => {\n return n * n;\n };\n const sinphi = sin(phi);\n const cosphi = cos(phi);\n // Step 1: simplify through translation/rotation\n const x = (cosphi * (x1 - x2)) / 2 + (sinphi * (y1 - y2)) / 2;\n const y = (-sinphi * (x1 - x2)) / 2 + (cosphi * (y1 - y2)) / 2;\n const px = pow(x), py = pow(y), prx = pow(rx), pry = pow(ry);\n // correct of out-of-range radii\n const L = px / prx + py / pry;\n if (L > 1) {\n rx = sqrt(L) * abs(rx);\n ry = sqrt(L) * abs(ry);\n }\n else {\n rx = abs(rx);\n ry = abs(ry);\n }\n // Step 2 + 3: compute center\n const sign = fa === fs ? -1 : 1;\n // const M: number = sqrt((prx * pry - prx * py - pry * px) / (prx * py + pry * px)) * sign;\n const M = sqrt(Math.abs((prx * pry - prx * py - pry * px) / (prx * py + pry * px))) * sign;\n const _cx = (M * (rx * y)) / ry;\n const _cy = (M * (-ry * x)) / rx;\n const cx = cosphi * _cx - sinphi * _cy + (x1 + x2) / 2;\n const cy = sinphi * _cx + cosphi * _cy + (y1 + y2) / 2;\n // Step 4: Compute start and end angle\n const center = new Vertex(cx, cy);\n const axis = center.clone().addXY(rx, ry);\n const ellipse = new VEllipse(center, axis, 0);\n // console.log(\"VELLIPSE::::::\", ellipse);\n ellipse.rotate(phi);\n const startAngle = new Line(ellipse.center, new Vertex(x1, y1)).angle();\n const endAngle = new Line(ellipse.center, new Vertex(x2, y2)).angle();\n return new VEllipseSector(ellipse, startAngle - phi, endAngle - phi);\n }\n}; // END ellipseSectorUtils\n//# sourceMappingURL=VEllipseSector.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-10-23\n * @modified 2018-11-19 Added multi-select and multi-drag.\n * @modified 2018-12-04 Added basic SVG export.\n * @modified 2018-12-09 Extended the constructor (canvas).\n * @modified 2018-12-18 Added the config.redrawOnResize param.\n * @modified 2018-12-18 Added the config.defaultCanvas{Width,Height} params.\n * @modified 2018-12-19 Added CSS scaling.\n * @modified 2018-12-28 Removed the unused 'drawLabel' param. Added the 'enableMouse' and 'enableKeys' params.\n * @modified 2018-12-29 Added the 'drawOrigin' param.\n * @modified 2018-12-29 Renamed the 'autoCenterOffset' param to 'autoAdjustOffset'. Added the params 'offsetAdjustXPercent' and 'offsetAdjustYPercent'.\n * @modified 2019-01-14 Added params 'drawBezierHandleLines' and 'drawBezierHandlePoints'. Added the 'redraw' praam to the add() function.\n * @modified 2019-01-16 Added params 'drawHandleLines' and 'drawHandlePoints'. Added the new params to the dat.gui interface.\n * @modified 2019-01-30 Added the 'Vector' type (extending the Line class).\n * @modified 2019-01-30 Added the 'PBImage' type (a wrapper for images).\n * @modified 2019-02-02 Added the 'canvasWidthFactor' and 'canvasHeightFactor' params.\n * @modified 2019-02-03 Removed the drawBackgroundImage() function, with had no purpose at all. Just add an image to the drawables-list.\n * @modified 2019-02-06 Vertices (instace of Vertex) can now be added. Added the 'draggable' attribute to the vertex attributes.\n * @modified 2019-02-10 Fixed a draggable-bug in PBImage handling (scaling was not possible).\n * @modified 2019-02-10 Added the 'enableTouch' option (default is true).\n * @modified 2019-02-14 Added the console for debugging (setConsole(object)).\n * @modified 2019-02-19 Added two new constants: DEFAULT_CLICK_TOLERANCE and DEFAULT_TOUCH_TOLERANCE.\n * @modified 2019-02-19 Added the second param to the locatePointNear(Vertex,Number) function.\n * @modified 2019-02-20 Removed the 'loadFile' entry from the GUI as it was experimental and never in use.\n * @modified 2019-02-23 Removed the 'rebuild' function as it had no purpose.\n * @modified 2019-02-23 Added scaling of the click-/touch-tolerance with the CSS scale.\n * @modified 2019-03-23 Added JSDoc tags. Changed the default value of config.drawOrigin to false.\n * @modified 2019-04-03 Fixed the touch-drag position detection for canvas elements that are not located at document position (0,0).\n * @modified 2019-04-03 Tweaked the fit-to-parent function to work with paddings and borders.\n * @modified 2019-04-28 Added the preClear callback param (called before the canvas was cleared on redraw and before any elements are drawn).\n * @modified 2019-09-18 Added basics for WebGL support (strictly experimental).\n * @modified 2019-10-03 Added the .beginDrawCycle call in the redraw function.\n * @modified 2019-11-06 Added fetch.num, fetch.val, fetch.bool, fetch.func functions.\n * @modified 2019-11-13 Fixed an issue with the mouse-sensitive area around vertices (were affected by zoom).\n * @modified 2019-11-13 Added the 'enableMouseWheel' param.\n * @modified 2019-11-18 Added the Triangle class as a regular drawable element.\n * @modified 2019-11-18 The add function now works with arrays, too.\n * @modified 2019-11-18 Added the _handleColor helper function to determine the render color of non-draggable vertices.\n * @modified 2019-11-19 Fixed a bug in the resizeCanvas function; retina resolution was not possible.\n * @modified 2019-12-04 Added relative positioned zooming.\n * @modified 2019-12-04 Added offsetX and offsetY params.\n * @modified 2019-12-04 Added an 'Set to fullsize retina' button to the GUI config.\n * @modified 2019-12-07 Added the drawConfig for lines, polygons, ellipse, triangles, bezier curves and image control lines.\n * @modified 2019-12-08 Fixed a css scale bug in the viewport() function.\n * @modified 2019-12-08 Added the drawconfig UI panel (line colors and line widths).\n * @modified 2020-02-06 Added handling for the end- and end-control-points of non-cirular Bézier paths (was still missing).\n * @modified 2020-02-06 Fixed a drag-amount bug in the move handling of end points of Bezier paths (control points was not properly moved when non circular).\n * @modified 2020-03-28 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-03-29 Fixed the enableSVGExport flag (read enableEport before).\n * @modified 2020-05-09 Included the Cirlcle class.\n * @modified 2020-06-22 Added the rasterScaleX and rasterScaleY config params.\n * @modified 2020-06-03 Fixed the selectedVerticesOnPolyon(Polygon) function: non-selectable vertices were selected too, before.\n * @modified 2020-07-06 Replacing Touchy.js by AlloyFinger.js\n * @modified 2020-07-27 Added the getVertexNear(XYCoords,number) function\n * @modified 2020-07-27 Extended the remove(Drawable) function: vertices are now removed, too.\n * @modified 2020-07-28 Added PlotBoilerplate.revertMousePosition(number,number) – the inverse function of transformMousePosition(...).\n * @modified 2020-07-31 Added PlotBoilerplate.getDraggedElementCount() to check wether any elements are currently being dragged.\n * @modified 2020-08-19 Added the VertexAttributes.visible attribute to make vertices invisible.\n * @modified 2020-11-17 Added pure click handling (no dragEnd and !wasMoved jiggliny any more) to the PlotBoilerplate.\n * @modified 2020-12-11 Added the `removeAll(boolean)` function.\n * @modified 2020-12-17 Added the `CircleSector` drawable.\n * @modified 2021-01-04 Avoiding multiple redraw call on adding multiple Drawables (array).\n * @modified 2021-01-08 Added param `draw:DraLib<void>` to the methods `drawVertices`, `drawGrid` and `drawSelectPolygon`.\n * @modified 2021-01-08 Added the customizable `drawAll(...)` function.\n * @modified 2021-01-09 Added the `drawDrawable(...)` function.\n * @modified 2021-01-10 Added the `eventCatcher` element (used to track mouse events on SVGs).\n * @modified 2021-01-26 Fixed SVG resizing.\n * @modified 2021-01-26 Replaced the old SVGBuilder by the new `drawutilssvg` library.\n * @modified 2021-02-08 Fixed a lot of es2015 compatibility issues.\n * @modified 2021-02-18 Adding `adjustOffset(boolean)` function.\n * @modified 2021-03-01 Updated the `PlotBoilerplate.draw(...)` function: ellipses are now rotate-able.\n * @modified 2021-03-03 Added the `VEllipseSector` drawable.\n * @modified 2021-03-29 Clearing `currentClassName` and `currentId` after drawing each drawable.\n * @modified 2021-04-25 Extending `remove` to accept arrays of drawables.\n * @modified 2021-11-16 Adding the `PBText` drawable.\n * @modified 2022-08-01 Added `title` to the params.\n * @modified 2022-10-25 Added the `origin` to the default draw config.\n * @modified 2022-11-06 Adding an XML declaration to the SVG export routine.\n * @modified 2022-11-23 Added the `drawRaster` (default=true) option to the config/drawconfig.\n * @modified 2023-02-04 Fixed a bug in the `drawDrawable` function; fill's current classname was not set.\n * @modified 2023-02-10 Fixing an issue of the `style.position` setting when `fitToParent=true` from `absolute` to `static` (default).\n * @modified 2023-02-10 Cleaning up most type errors in the main class (mostly null checks).\n * @modified 2023-02-10 Adding `enableZoom` and `enablePan` (both default true) to have the option to disable these functions.\n * @modified 2023-09-29 Adding proper dicionary key and value types to the params of `PlotBoilerplate.utils.safeMergeByKeys` (was `object` before).\n * @modified 2024-07-08 Adding `PlotBoilerplate.getGUI()` to retrieve the GUI instance.\n * @modified 2024-08-25 Extending main class `PlotBoilerplate` optional param `isBackdropFiltersEnabled`.\n * @modified 2024-12-02 Adding the `triggerRedraw` to the `removeAll` method.\n * @modified 2025-05-07 Changing the return type of `removeVertex` from `void` to `boolean`.\n * @modified 2025-05-07 Handling content changes now with `contentChangeListeners`.\n * @modified 2025-05-07 Added `PlogBoilerplate.addContentChangeListener` and `.removeContentChangeListener`.\n * @modified 2025-05-07 Moving full vectors now by default when vector point a is moved.\n * @modified 2025-05-20 Applying `lineWith` parameter in the draw routine for vectors (had been missing).\n *\n * @version 1.21.1\n *\n * @file PlotBoilerplate\n * @fileoverview The main class.\n * @public\n **/\nvar __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\nvar _a;\nimport AlloyFinger from \"alloyfinger-typescript\";\nimport { drawutils } from \"./draw\";\nimport { drawutilsgl } from \"./drawgl\";\nimport { drawutilssvg } from \"./drawutilssvg\";\nimport { BezierPath } from \"./BezierPath\";\nimport { Bounds } from \"./Bounds\";\nimport { Circle } from \"./Circle\";\nimport { CircleSector } from \"./CircleSector\";\nimport { Grid } from \"./Grid\";\nimport { KeyHandler } from \"./KeyHandler\";\nimport { Line } from \"./Line\";\nimport { MouseHandler } from \"./MouseHandler\";\nimport { PBImage } from \"./PBImage\";\nimport { Polygon } from \"./Polygon\";\nimport { Triangle } from \"./Triangle\";\nimport { VEllipse } from \"./VEllipse\";\nimport { VEllipseSector } from \"./VEllipseSector\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { VertexAttr } from \"./VertexAttr\";\nimport { PBText } from \"./PBText\";\n/**\n * @classdesc The main class of the PlotBoilerplate.\n *\n * @requires Vertex\n * @requires Line\n * @requires Vector\n * @requires Polygon\n * @requires PBImage\n * @requires VEllipse\n * @requires Circle\n * @requires MouseHandler\n * @requires KeyHandler\n * @requires VertexAttr\n * @requires CubicBezierCurve\n * @requires BezierPath\n * @requires Drawable\n * @requires DrawConfig\n * @requires IHooks\n * @requires PBParams\n * @requires Triangle\n * @requires drawutils\n * @requires drawutilsgl\n * @requires SVGSerializable\n * @requires XYCoords\n * @requires XYDimension\n */\nexport class PlotBoilerplate {\n /**\n * The constructor.\n *\n * @constructor\n * @name PlotBoilerplate\n * @public\n * @param {object} config={} - The configuration.\n * @param {HTMLCanvasElement} config.canvas - Your canvas element in the DOM (required).\n * @param {boolean=} [config.fullSize=true] - If set to true the canvas will gain full window size.\n * @param {boolean=} [config.fitToParent=true] - If set to true the canvas will gain the size of its parent container (overrides fullSize).\n * @param {number=} [config.scaleX=1.0] - The initial x-zoom. Default is 1.0.\n * @param {number=} [config.scaleY=1.0] - The initial y-zoom. Default is 1.0.\n * @param {number=} [config.offsetX=1.0] - The initial x-offset. Default is 0.0. Note that autoAdjustOffset=true overrides these values.\n * @param {number=} [config.offsetY=1.0] - The initial y-offset. Default is 0.0. Note that autoAdjustOffset=true overrides these values.\n * @param {boolean=} [config.rasterGrid=true] - If set to true the background grid will be drawn rastered.\n * @param {boolean=} [config.rasterScaleX=1.0] - Define the default horizontal raster scale (default=1.0).\n * @param {boolean=} [config.rasterScaleY=1.0] - Define the default vertical raster scale (default=1.0).\n * @param {number=} [config.rasterAdjustFactor=1.0] - The exponential limit for wrapping down the grid. (2.0 means: halve the grid each 2.0*n zoom step).\n * @param {boolean=} [config.drawOrigin=false] - Draw a crosshair at (0,0).\n * @param {boolean=} [config.autoAdjustOffset=true] - When set to true then the origin of the XY plane will\n * be re-adjusted automatically (see the params\n * offsetAdjust{X,Y}Percent for more).\n * @param {number=} [config.offsetAdjustXPercent=50] - The x-fallback position for the origin after\n * resizing the canvas.\n * @param {number=} [config.offsetAdjustYPercent=50] - The y-fallback position for the origin after\n * resizing the canvas.\n * @param {number=} [config.defaultCanvasWidth=1024] - The canvas size fallback (width) if no automatic resizing\n * is switched on.\n * @param {number=} [config.defaultCanvasHeight=768] - The canvas size fallback (height) if no automatic resizing\n * is switched on.\n * @param {number=} [config.canvasWidthFactor=1.0] - Scaling factor (width) upon the canvas size.\n * In combination with cssScale{X,Y} this can be used to obtain\n * sub pixel resolutions for retina displays.\n * @param {number=} [config.canvasHeightFactor=1.0] - Scaling factor (height) upon the canvas size.\n * In combination with cssScale{X,Y} this can be used to obtain\n * sub pixel resolutions for retina displays.\n * @param {number=} [config.cssScaleX=1.0] - Visually resize the canvas (horizontally) using CSS transforms (scale).\n * @param {number=} [config.cssScaleY=1.0] - Visually resize the canvas (vertically) using CSS transforms (scale).\n * @param {boolan=} [config.cssUniformScale=true] - CSS scale x and y obtaining aspect ratio.\n * @param {boolean=} [config.autoDetectRetina=true] - When set to true (default) the canvas will try to use the display's pixel ratio.\n * @param {string=} [config.backgroundColor=#ffffff] - The backround color.\n * @param {boolean=} [config.redrawOnResize=true] - Switch auto-redrawing on resize on/off (some applications\n * might want to prevent automatic redrawing to avoid data loss from the draw buffer).\n * @param {boolean=} [config.drawBezierHandleLines=true] - Indicates if Bézier curve handles should be drawn (used for\n * editors, no required in pure visualizations).\n * @param {boolean=} [config.drawBezierHandlePoints=true] - Indicates if Bézier curve handle points should be drawn.\n * @param {function=} [config.preClear=null] - A callback function that will be triggered just before the\n * draw function clears the canvas (before anything else was drawn).\n * @param {function=} [config.preDraw=null] - A callback function that will be triggered just before the draw\n * function starts.\n * @param {function=} [config.postDraw=null] - A callback function that will be triggered right after the drawing\n * process finished.\n * @param {boolean=} [config.enableMouse=true] - Indicates if the application should handle mouse events for you.\n * @param {boolean=} [config.enableTouch=true] - Indicates if the application should handle touch events for you.\n * @param {boolean=} [config.enableKeys=true] - Indicates if the application should handle key events for you.\n * @param {boolean=} [config.enableMouseWheel=true] - Indicates if the application should handle mouse wheel events for you.\n * @param {boolean=} [config.enablePan=true] - (default true) Set to false if you want to disable panning completely.\n * @param {boolean=} [config.enableZoom=true] - (default true) Set to false if you want to disable zooming completely.\n * @param {boolean=} [config.enableGL=false] - Indicates if the application should use the experimental WebGL features (not recommended).\n * @param {boolean=} [config.enableSVGExport=true] - Indicates if the SVG export should be enabled (default is true).\n * Note that changes from the postDraw hook might not be visible in the export.\n * @param {string=} [config.title=null] - Specify any hover tile here. It will be attached as a `title` attribute to the most elevated element.\n */\n constructor(config, drawConfig) {\n var _b, _c;\n /**\n * A list of content change listeners.\n */\n this.contentChangeListeners = [];\n /**\n * A discrete timestamp to identify single render cycles.\n * Note that using system time milliseconds is not a safe way to identify render frames, as on modern powerful machines\n * multiple frames might be rendered within each millisecond.\n * @member {number}\n * @memberof plotboilerplate\n * @instance\n * @private\n */\n this.renderTime = 0;\n /**\n * A storage variable for retrieving the GUI instance once it was created.\n */\n this._gui = null;\n // This should be in some static block ...\n VertexAttr.model = {\n bezierAutoAdjust: false,\n renderTime: 0,\n selectable: true,\n isSelected: false,\n draggable: true,\n visible: true\n };\n if (typeof config.canvas === \"undefined\") {\n throw \"No canvas specified.\";\n }\n /**\n * A global config that's attached to the dat.gui control interface.\n *\n * @member {Object}\n * @memberof PlotBoilerplate\n * @instance\n */\n const f = PlotBoilerplate.utils.fetch;\n this.config = {\n canvas: config.canvas,\n fullSize: f.val(config, \"fullSize\", true),\n fitToParent: f.bool(config, \"fitToParent\", true),\n scaleX: f.num(config, \"scaleX\", 1.0),\n scaleY: f.num(config, \"scaleY\", 1.0),\n offsetX: f.num(config, \"offsetX\", 0.0),\n offsetY: f.num(config, \"offsetY\", 0.0),\n rasterGrid: f.bool(config, \"rasterGrid\", true),\n drawRaster: f.bool(config, \"drawRaster\", true),\n rasterScaleX: f.num(config, \"rasterScaleX\", 1.0),\n rasterScaleY: f.num(config, \"rasterScaleY\", 1.0),\n rasterAdjustFactor: f.num(config, \"rasterAdjustdFactror\", 2.0),\n drawOrigin: f.bool(config, \"drawOrigin\", false),\n autoAdjustOffset: f.val(config, \"autoAdjustOffset\", true),\n offsetAdjustXPercent: f.num(config, \"offsetAdjustXPercent\", 50),\n offsetAdjustYPercent: f.num(config, \"offsetAdjustYPercent\", 50),\n backgroundColor: config.backgroundColor || \"#ffffff\",\n redrawOnResize: f.bool(config, \"redrawOnResize\", true),\n defaultCanvasWidth: f.num(config, \"defaultCanvasWidth\", PlotBoilerplate.DEFAULT_CANVAS_WIDTH),\n defaultCanvasHeight: f.num(config, \"defaultCanvasHeight\", PlotBoilerplate.DEFAULT_CANVAS_HEIGHT),\n canvasWidthFactor: f.num(config, \"canvasWidthFactor\", 1.0),\n canvasHeightFactor: f.num(config, \"canvasHeightFactor\", 1.0),\n cssScaleX: f.num(config, \"cssScaleX\", 1.0),\n cssScaleY: f.num(config, \"cssScaleY\", 1.0),\n cssUniformScale: f.bool(config, \"cssUniformScale\", true),\n saveFile: () => {\n _self.hooks.saveFile(_self);\n },\n setToRetina: () => {\n _self._setToRetina();\n },\n autoDetectRetina: f.bool(config, \"autoDetectRetina\", true),\n enableSVGExport: f.bool(config, \"enableSVGExport\", true),\n // Listeners/observers\n preClear: f.func(config, \"preClear\", null),\n preDraw: f.func(config, \"preDraw\", null),\n postDraw: f.func(config, \"postDraw\", null),\n // Interaction\n enableMouse: f.bool(config, \"enableMouse\", true),\n enableTouch: f.bool(config, \"enableTouch\", true),\n enableKeys: f.bool(config, \"enableKeys\", true),\n enableMouseWheel: f.bool(config, \"enableMouseWheel\", true),\n enableZoom: f.bool(config, \"enableZoom\", true), // default=true\n enablePan: f.bool(config, \"enablePan\", true), // default=true\n // Experimental (and unfinished)\n enableGL: f.bool(config, \"enableGL\", false),\n isBackdropFiltersEnabled: f.bool(config, \"isBackdropFiltersEnabled\", true)\n }; // END confog\n /**\n * Configuration for drawing things.\n *\n * @member {Object}\n * @memberof PlotBoilerplate\n * @instance\n */\n this.drawConfig = {\n drawVertices: true,\n drawBezierHandleLines: f.bool(config, \"drawBezierHandleLines\", true),\n drawBezierHandlePoints: f.bool(config, \"drawBezierHandlePoints\", true),\n drawHandleLines: f.bool(config, \"drawHandleLines\", true),\n drawHandlePoints: f.bool(config, \"drawHandlePoints\", true),\n drawGrid: f.bool(config, \"drawGrid\", true),\n drawRaster: f.bool(config, \"drawRaster\", true),\n bezier: {\n color: \"#00a822\",\n lineWidth: 2,\n handleLine: {\n color: \"rgba(180,180,180,0.5)\",\n lineWidth: 1\n },\n pathVertex: {\n color: \"#B400FF\",\n lineWidth: 1,\n fill: true\n },\n controlVertex: {\n color: \"#B8D438\",\n lineWidth: 1,\n fill: true\n }\n },\n // bezierPath: {\n // color: \"#0022a8\",\n // lineWidth: 1\n // },\n polygon: {\n color: \"#0022a8\",\n lineWidth: 1\n },\n triangle: {\n color: \"#6600ff\",\n lineWidth: 1\n },\n ellipse: {\n color: \"#2222a8\",\n lineWidth: 1\n },\n ellipseSector: {\n color: \"#a822a8\",\n lineWidth: 2\n },\n circle: {\n color: \"#22a8a8\",\n lineWidth: 2\n },\n circleSector: {\n color: \"#2280a8\",\n lineWidth: 1\n },\n vertex: {\n color: \"#a8a8a8\",\n lineWidth: 1\n },\n selectedVertex: {\n color: \"#c08000\",\n lineWidth: 2\n },\n line: {\n color: \"#a844a8\",\n lineWidth: 1\n },\n vector: {\n color: \"#ff44a8\",\n lineWidth: 1\n },\n image: {\n color: \"#a8a8a8\",\n lineWidth: 1\n },\n text: {\n color: \"rgba(192,0,128,0.5)\",\n lineWidth: 1,\n fill: true,\n anchor: true\n },\n origin: {\n color: \"#000000\"\n }\n }; // END drawConfig\n // +---------------------------------------------------------------------------------\n // | Object members.\n // +-------------------------------\n this.grid = new Grid(new Vertex(0, 0), new Vertex(50, 50));\n this.canvasSize = { width: PlotBoilerplate.DEFAULT_CANVAS_WIDTH, height: PlotBoilerplate.DEFAULT_CANVAS_HEIGHT };\n const canvasElement = typeof config.canvas === \"string\" ? document.querySelector(config.canvas) : config.canvas;\n if (typeof canvasElement === \"undefined\") {\n throw `Cannot initialize PlotBoilerplate with a null canvas (element \"${config.canvas} not found).`;\n }\n // Which renderer to use: Canvas2D, WebGL (experimental) or SVG?\n if (canvasElement.tagName.toLowerCase() === \"canvas\") {\n this.canvas = canvasElement;\n this.eventCatcher = this.canvas;\n if (this.config.enableGL && typeof drawutilsgl === \"undefined\") {\n console.warn(`Cannot use webgl. Package was compiled without experimental gl support. Please use plotboilerplate-glsupport.min.js instead.`);\n console.warn(`Disabling GL and falling back to Canvas2D.`);\n this.config.enableGL = false;\n }\n if (this.config.enableGL) {\n // Override the case 'null' here. If GL is not supported, well then nothing works.\n const ctx = this.canvas.getContext(\"webgl\"); // webgl-experimental?\n this.draw = new drawutilsgl(ctx, false);\n // PROBLEM: same instance of fill and draw when using WebGL.\n // Shader program cannot be duplicated on the same context.\n this.fill = this.draw.copyInstance(true);\n console.warn(\"Initialized with experimental mode enableGL=true. Note that this is not yet fully implemented.\");\n }\n else {\n // Override the case 'null' here. If context creation is not supported, well then nothing works.\n const ctx = this.canvas.getContext(\"2d\");\n this.draw = new drawutils(ctx, false);\n this.fill = new drawutils(ctx, true);\n }\n }\n else if (canvasElement.tagName.toLowerCase() === \"svg\") {\n if (typeof drawutilssvg === \"undefined\")\n throw `The svg draw library is not yet integrated part of PlotBoilerplate. Please include ./src/js/utils/helpers/drawutils.svg into your document.`;\n this.canvas = canvasElement;\n this.draw = new drawutilssvg(this.canvas, new Vertex(), // offset\n new Vertex(), // scale\n this.canvasSize, false, // fillShapes=false\n this.drawConfig, false // isSecondary=false\n );\n this.fill = this.draw.copyInstance(true); // fillShapes=true\n if (this.canvas.parentElement) {\n this.eventCatcher = document.createElement(\"div\");\n this.eventCatcher.style.position = \"absolute\";\n this.eventCatcher.style.left = \"0\";\n this.eventCatcher.style.top = \"0\";\n this.eventCatcher.style.cursor = \"pointer\";\n this.canvas.parentElement.style.position = \"relative\";\n this.canvas.parentElement.appendChild(this.eventCatcher);\n }\n else {\n this.eventCatcher = document.body;\n }\n }\n else {\n throw \"Element is neither a canvas nor an svg element.\";\n }\n // At this point the event cacher element is deinfed and located at highest elevation.\n // Set `title` attribut?\n if (config.title) {\n this.eventCatcher.setAttribute(\"title\", config.title);\n }\n this.draw.scale.set((_b = this.config.scaleX) !== null && _b !== void 0 ? _b : 1.0, this.config.scaleY);\n this.fill.scale.set((_c = this.config.scaleX) !== null && _c !== void 0 ? _c : 1.0, this.config.scaleY);\n this.vertices = [];\n this.selectPolygon = null;\n this.draggedElements = [];\n this.drawables = [];\n this.console = console;\n this.hooks = {\n // This is changable from the outside\n saveFile: PlotBoilerplate._saveFile\n };\n var _self = this;\n globalThis.addEventListener(\"resize\", () => _self.resizeCanvas());\n this.resizeCanvas();\n if (config.autoDetectRetina) {\n this._setToRetina();\n }\n this.installInputListeners();\n // Apply the configured CSS scale.\n this.updateCSSscale();\n // Init\n this.redraw();\n // Gain focus\n this.canvas.focus();\n } // END constructor\n /**\n * This function opens a save-as file dialog and – once an output file is\n * selected – stores the current canvas contents as an SVG image.\n *\n * It is the default hook for saving files and can be overwritten.\n *\n * @method _saveFile\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n * @private\n **/\n static _saveFile(pb) {\n // Create fake SVG node\n const svgNode = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n // Draw everything to fake node.\n var tosvgDraw = new drawutilssvg(svgNode, pb.draw.offset, pb.draw.scale, pb.canvasSize, false, // fillShapes=false\n pb.drawConfig);\n var tosvgFill = tosvgDraw.copyInstance(true); // fillShapes=true\n tosvgDraw.beginDrawCycle(0);\n tosvgFill.beginDrawCycle(0);\n if (pb.config.preClear) {\n pb.config.preClear();\n }\n tosvgDraw.clear(pb.config.backgroundColor || \"white\");\n if (pb.config.preDraw) {\n pb.config.preDraw(tosvgDraw, tosvgFill);\n }\n pb.drawAll(0, tosvgDraw, tosvgFill);\n pb.drawVertices(0, tosvgDraw);\n if (pb.config.postDraw)\n pb.config.postDraw(tosvgDraw, tosvgFill);\n tosvgDraw.endDrawCycle(0);\n tosvgFill.endDrawCycle(0);\n // Full support in all browsers \\o/\n // https://caniuse.com/xml-serializer\n var serializer = new XMLSerializer();\n var svgCode = serializer.serializeToString(svgNode);\n // Add: '<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' ?\n var blob = new Blob(['<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' + svgCode], { type: \"image/svg;charset=utf-8\" });\n // See documentation for FileSaver.js for usage.\n // https://github.com/eligrey/FileSaver.js\n if (typeof globalThis[\"saveAs\"] !== \"function\") {\n throw \"Cannot save file; did you load the ./utils/savefile helper function and the eligrey/SaveFile library?\";\n }\n var _saveAs = globalThis[\"saveAs\"];\n _saveAs(blob, \"plotboilerplate.svg\");\n }\n /**\n * This function sets the canvas resolution to factor 2.0 (or the preferred pixel ratio of your device) for retina displays.\n * Please not that in non-GL mode this might result in very slow rendering as the canvas buffer size may increase.\n *\n * @method _setToRetina\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n * @private\n **/\n _setToRetina() {\n this.config.autoDetectRetina = true;\n const pixelRatio = globalThis.devicePixelRatio || 1;\n this.config.cssScaleX = this.config.cssScaleY = 1.0 / pixelRatio;\n this.config.canvasWidthFactor = this.config.canvasHeightFactor = pixelRatio;\n this.resizeCanvas();\n this.updateCSSscale();\n }\n /**\n * Set the current zoom and draw offset to fit the given bounds.\n *\n * This method currently restores the aspect zoom ratio.\n *\n **/\n fitToView(bounds) {\n const canvasCenter = new Vertex(this.canvasSize.width / 2.0, this.canvasSize.height / 2.0);\n const canvasRatio = this.canvasSize.width / this.canvasSize.height;\n const ratio = bounds.width / bounds.height;\n // Find the new draw offset\n const center = new Vertex(bounds.max.x - bounds.width / 2.0, bounds.max.y - bounds.height / 2.0)\n .inv()\n .addXY(this.canvasSize.width / 2.0, this.canvasSize.height / 2.0);\n this.setOffset(center);\n if (canvasRatio < ratio) {\n const newUniformZoom = this.canvasSize.width / bounds.width;\n this.setZoom(newUniformZoom, newUniformZoom, canvasCenter);\n }\n else {\n const newUniformZoom = this.canvasSize.height / bounds.height;\n this.setZoom(newUniformZoom, newUniformZoom, canvasCenter);\n }\n this.redraw();\n }\n /**\n * Set the console for this instance.\n *\n * @method setConsole\n * @param {Console} con - The new console object (default is globalThis.console).\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n setConsole(con) {\n this.console = con;\n }\n /**\n * Update the CSS scale for the canvas depending onf the cssScale{X,Y} settings.<br>\n * <br>\n * This function is usually only used inernally.\n *\n * @method updateCSSscale\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n * @private\n **/\n updateCSSscale() {\n var _b, _c, _d, _e;\n if (this.config.cssUniformScale) {\n PlotBoilerplate.utils.setCSSscale(this.canvas, (_b = this.config.cssScaleX) !== null && _b !== void 0 ? _b : 1.0, (_c = this.config.cssScaleX) !== null && _c !== void 0 ? _c : 1.0);\n }\n else {\n PlotBoilerplate.utils.setCSSscale(this.canvas, (_d = this.config.cssScaleX) !== null && _d !== void 0 ? _d : 1.0, (_e = this.config.cssScaleY) !== null && _e !== void 0 ? _e : 1.0);\n }\n }\n /**\n * Adds a new content change listener to this instance. Adding duplicates is not possible.\n *\n * @param {PBContentChangeListener} listener - The listenre to add.\n * @method addContentChangeListener\n * @instance\n * @memberof PlotBoilerplate\n * @returns {void}\n */\n addContentChangeListener(listener) {\n for (var i in this.contentChangeListeners) {\n if (this.contentChangeListeners[i] === listener) {\n return;\n }\n }\n this.contentChangeListeners.push(listener);\n }\n /**\n * Removes an existing content change listener from this instance.\n *\n * @param {PBContentChangeListener} listener - The listenre to add.\n * @method removeContentChangeListener\n * @instance\n * @memberof PlotBoilerplate\n * @returns {void}\n */\n removeContentChangeListener(listener) {\n for (var i = 0; i < this.contentChangeListeners.length; i++) {\n if (this.contentChangeListeners[i] === listener) {\n this.contentChangeListeners.splice(i, 1);\n return;\n }\n }\n }\n _fireContentChanged(addedDrawables, removedDrawables) {\n for (var i in this.contentChangeListeners) {\n const listener = this.contentChangeListeners[i];\n if (listener && typeof listener === \"function\") {\n listener({\n type: addedDrawables.length > 0 ? \"DRAWABLES_ADDED\" : \"DRAWABLES_REMOVED\",\n addedDrawables: addedDrawables,\n removedDrawables: removedDrawables\n });\n }\n }\n }\n /**\n * Add a drawable object.<br>\n * <br>\n * This must be either:<br>\n * <pre>\n * * a Vertex\n * * a Line\n * * a Vector\n * * a VEllipse\n * * a VEllipseSector\n * * a Circle\n * * a Polygon\n * * a Triangle\n * * a BezierPath\n * * a BPImage\n * </pre>\n *\n * @param {Drawable|Drawable[]} drawable - The drawable (of one of the allowed class instance) to add.\n * @param {boolean} [redraw=true] - If true the function will trigger redraw after the drawable(s) was/were added.\n * @method add\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n add(drawable, redraw, doNotFireEvent) {\n if (Array.isArray(drawable)) {\n const arr = drawable;\n for (var i = 0; i < arr.length; i++) {\n this.add(arr[i], false, doNotFireEvent);\n }\n // !doNotFireEvent && this._fireContentChanged(arr, []);\n }\n else {\n const addedDrawables = [drawable];\n if (drawable instanceof Vertex) {\n this.drawables.push(drawable);\n this.vertices.push(drawable);\n }\n else if (drawable instanceof Line) {\n // Add some lines\n this.drawables.push(drawable);\n this.vertices.push(drawable.a);\n this.vertices.push(drawable.b);\n addedDrawables.push(drawable.a, drawable.b);\n }\n else if (drawable instanceof Vector) {\n this.drawables.push(drawable);\n this.vertices.push(drawable.a);\n this.vertices.push(drawable.b);\n addedDrawables.push(drawable.a, drawable.b);\n drawable.a.listeners.addDragListener((event) => {\n drawable.b.add(event.params.dragAmount);\n });\n }\n else if (drawable instanceof VEllipse) {\n this.vertices.push(drawable.center);\n this.vertices.push(drawable.axis);\n addedDrawables.push(drawable.center, drawable.axis);\n this.drawables.push(drawable);\n drawable.center.listeners.addDragListener((event) => {\n drawable.axis.add(event.params.dragAmount);\n });\n }\n else if (drawable instanceof VEllipseSector) {\n this.vertices.push(drawable.ellipse.center);\n this.vertices.push(drawable.ellipse.axis);\n addedDrawables.push(drawable.ellipse.center, drawable.ellipse.axis);\n this.drawables.push(drawable);\n drawable.ellipse.center.listeners.addDragListener((event) => {\n drawable.ellipse.axis.add(event.params.dragAmount);\n });\n }\n else if (drawable instanceof Circle) {\n this.vertices.push(drawable.center);\n addedDrawables.push(drawable.center);\n this.drawables.push(drawable);\n }\n else if (drawable instanceof CircleSector) {\n this.vertices.push(drawable.circle.center);\n addedDrawables.push(drawable.circle.center);\n this.drawables.push(drawable);\n }\n else if (drawable instanceof Polygon) {\n this.drawables.push(drawable);\n for (var i = 0; i < drawable.vertices.length; i++) {\n this.vertices.push(drawable.vertices[i]);\n addedDrawables.push(drawable.vertices[i]);\n }\n }\n else if (drawable instanceof Triangle) {\n this.drawables.push(drawable);\n this.vertices.push(drawable.a);\n this.vertices.push(drawable.b);\n this.vertices.push(drawable.c);\n addedDrawables.push(drawable.a, drawable.b, drawable.c);\n }\n else if (drawable instanceof BezierPath) {\n this.drawables.push(drawable);\n const bezierPath = drawable;\n for (var i = 0; i < bezierPath.bezierCurves.length; i++) {\n if (!drawable.adjustCircular && i == 0) {\n this.vertices.push(bezierPath.bezierCurves[i].startPoint);\n addedDrawables.push(bezierPath.bezierCurves[i].startPoint);\n }\n this.vertices.push(bezierPath.bezierCurves[i].endPoint);\n this.vertices.push(bezierPath.bezierCurves[i].startControlPoint);\n this.vertices.push(bezierPath.bezierCurves[i].endControlPoint);\n addedDrawables.push(bezierPath.bezierCurves[i].endPoint, bezierPath.bezierCurves[i].startControlPoint, bezierPath.bezierCurves[i].endControlPoint);\n bezierPath.bezierCurves[i].startControlPoint.attr.selectable = false;\n bezierPath.bezierCurves[i].endControlPoint.attr.selectable = false;\n }\n PlotBoilerplate.utils.enableBezierPathAutoAdjust(drawable);\n }\n else if (drawable instanceof PBImage) {\n this.vertices.push(drawable.upperLeft);\n this.vertices.push(drawable.lowerRight);\n addedDrawables.push(drawable.upperLeft, drawable.lowerRight);\n this.drawables.push(drawable);\n // Todo: think about a IDragEvent interface\n drawable.upperLeft.listeners.addDragListener((e) => {\n drawable.lowerRight.add(e.params.dragAmount);\n });\n drawable.lowerRight.attr.selectable = false;\n }\n else if (drawable instanceof PBText) {\n this.vertices.push(drawable.anchor);\n addedDrawables.push(drawable.anchor);\n this.drawables.push(drawable);\n drawable.anchor.attr.selectable = false;\n }\n else {\n throw \"Cannot add drawable of unrecognized type: \" + typeof drawable + \".\";\n }\n !doNotFireEvent && this._fireContentChanged(addedDrawables, []);\n }\n // This is a workaround for backwards compatibility when the 'redraw' param was not yet present.\n if (redraw || typeof redraw == \"undefined\") {\n this.redraw();\n }\n }\n /**\n * Remove a drawable object.<br>\n * <br>\n * This must be either:<br>\n * <pre>\n * * a Vertex\n * * a Line\n * * a Vector\n * * a VEllipse\n * * a Circle\n * * a Polygon\n * * a BezierPath\n * * a BPImage\n * * a Triangle\n * </pre>\n *\n * @param {Drawable|Array<Drawable>} drawable - The drawable (of one of the allowed class instance) to remove.\n * @param {boolean} [redraw=false]\n * @param {removeWidth}\n * @method remove\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n remove(drawable, redraw, removeWithVertices, doNotFireEvent) {\n if (Array.isArray(drawable)) {\n const removedDrawables = [];\n for (var i = 0; i < drawable.length; i++) {\n if (this.remove(drawable[i], false, removeWithVertices, true)) {\n removedDrawables.push(drawable[i]);\n }\n }\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], removedDrawables);\n return removedDrawables.length > 0;\n }\n if (drawable instanceof Vertex) {\n const wasRemoved = this.removeVertex(drawable, false, false);\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], [drawable]);\n return wasRemoved;\n }\n let wasRemoved = false;\n const removedDrawables = [];\n for (var i = 0; i < this.drawables.length; i++) {\n if (this.drawables[i] === drawable || this.drawables[i].uid === drawable.uid) {\n this.drawables.splice(i, 1);\n removedDrawables.push(drawable);\n if (removeWithVertices) {\n // Check if some listeners need to be removed\n if (drawable instanceof Line) {\n // Add some lines\n this.removeVertex(drawable.a, false, true);\n this.removeVertex(drawable.b, false, true);\n removedDrawables.push(drawable.a, drawable.b);\n }\n else if (drawable instanceof Vector) {\n this.removeVertex(drawable.a, false, true);\n this.removeVertex(drawable.b, false, true);\n removedDrawables.push(drawable.a, drawable.b);\n }\n else if (drawable instanceof VEllipse) {\n this.removeVertex(drawable.center, false, true);\n this.removeVertex(drawable.axis, false, true);\n removedDrawables.push(drawable.center, drawable.axis);\n }\n else if (drawable instanceof VEllipseSector) {\n this.removeVertex(drawable.ellipse.center, false, true);\n this.removeVertex(drawable.ellipse.axis, false, true);\n removedDrawables.push(drawable.ellipse.center, drawable.ellipse.axis);\n }\n else if (drawable instanceof Circle) {\n this.removeVertex(drawable.center, false, true);\n }\n else if (drawable instanceof CircleSector) {\n this.removeVertex(drawable.circle.center, false, true);\n removedDrawables.push(drawable.circle.center);\n }\n else if (drawable instanceof Polygon) {\n // for( var i in drawable.vertices )\n for (var i = 0; i < drawable.vertices.length; i++) {\n this.removeVertex(drawable.vertices[i], false, true);\n removedDrawables.push(drawable.vertices[i]);\n }\n }\n else if (drawable instanceof Triangle) {\n this.removeVertex(drawable.a, false, true);\n this.removeVertex(drawable.b, false, true);\n this.removeVertex(drawable.c, false, true);\n removedDrawables.push(drawable.a, drawable.b, drawable.c);\n }\n else if (drawable instanceof BezierPath) {\n for (var i = 0; i < drawable.bezierCurves.length; i++) {\n this.removeVertex(drawable.bezierCurves[i].startPoint, false, true);\n this.removeVertex(drawable.bezierCurves[i].startControlPoint, false, true);\n this.removeVertex(drawable.bezierCurves[i].endControlPoint, false, true);\n removedDrawables.push(drawable.bezierCurves[i].startPoint, drawable.bezierCurves[i].startControlPoint, drawable.bezierCurves[i].endControlPoint);\n if (i + 1 == drawable.bezierCurves.length) {\n this.removeVertex(drawable.bezierCurves[i].endPoint, false, true);\n removedDrawables.push(drawable.bezierCurves[i].endPoint);\n }\n }\n }\n else if (drawable instanceof PBImage) {\n this.removeVertex(drawable.upperLeft, false, true);\n this.removeVertex(drawable.lowerRight, false, true);\n removedDrawables.push(drawable.upperLeft, drawable.lowerRight);\n }\n else if (drawable instanceof PBText) {\n this.removeVertex(drawable.anchor, false, true);\n removedDrawables.push(drawable.anchor);\n }\n } // END removeWithVertices\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], removedDrawables);\n wasRemoved = true;\n } // END if\n } // END for\n return wasRemoved;\n }\n /**\n * Remove a vertex from the vertex list.<br>\n *\n * @param {Vertex} vert - The vertex to remove.\n * @param {boolean} [redraw=false]\n * @method removeVertex\n * @instance\n * @memberof PlotBoilerplate\n * @return {boolean}\n **/\n removeVertex(vert, redraw, doNotFireEvent) {\n for (var i = 0; i < this.vertices.length; i++) {\n if (this.vertices[i] === vert) {\n this.vertices.splice(i, 1);\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], [vert]);\n return true;\n }\n }\n return false;\n }\n /**\n * Remove all elements.\n *\n * If you want to keep the vertices, pass `true`.\n *\n * @method removeAll\n * @param {boolean=false} keepVertices\n * @param {boolean=true} triggerRedraw - By default this method triggers the redraw routine; passing `false` will suppress redrawing.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n */\n removeAll(keepVertices, triggerRedraw) {\n let removedDrawables = this.drawables;\n this.drawables = [];\n if (!Boolean(keepVertices)) {\n removedDrawables = removedDrawables.concat(this.vertices);\n this.vertices = [];\n }\n if (triggerRedraw || typeof triggerRedraw === \"undefined\") {\n this.redraw();\n }\n removedDrawables.length > 0 && this._fireContentChanged([], removedDrawables);\n }\n /**\n * Find the vertex near the given position.\n *\n * The position is the absolute vertex position, not the x-y-coordinates on the canvas.\n *\n * @param {XYCoords} position - The position of the vertex to search for.\n * @param {number} pixelTolerance - A radius around the position to include into the search.\n * Note that the tolerance will be scaled up/down when zoomed.\n * @return The vertex near the given position or undefined if none was found there.\n **/\n getVertexNear(pixelPosition, pixelTolerance) {\n var _b, _c;\n const p = this.locatePointNear(this.transformMousePosition(pixelPosition.x, pixelPosition.y), pixelTolerance / Math.min((_b = this.config.cssScaleX) !== null && _b !== void 0 ? _b : 1.0, (_c = this.config.cssScaleY) !== null && _c !== void 0 ? _c : 1.0));\n if (p && p.typeName == \"vertex\") {\n return this.vertices[p.vindex];\n }\n return undefined;\n }\n /**\n * Draw the grid with the current config settings.<br>\n *\n * This function is usually only used internally.\n *\n * @method drawGrid\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawGrid(draw) {\n if (typeof draw === \"undefined\") {\n draw = this.draw;\n }\n const gScale = {\n x: (Grid.utils.mapRasterScale(this.config.rasterAdjustFactor, this.draw.scale.x) * this.config.rasterScaleX) /\n this.config.cssScaleX,\n y: (Grid.utils.mapRasterScale(this.config.rasterAdjustFactor, this.draw.scale.y) * this.config.rasterScaleY) /\n this.config.cssScaleY\n };\n var gSize = { width: this.grid.size.x * gScale.x, height: this.grid.size.y * gScale.y };\n var cs = { width: this.canvasSize.width / 2, height: this.canvasSize.height / 2 };\n var offset = this.draw.offset.clone().inv();\n // console.log( \"drawGrid\", gScale, gSize, cs, offset );\n offset.x =\n ((Math.round(offset.x + cs.width) / Math.round(gSize.width)) * gSize.width) / this.draw.scale.x +\n (((this.draw.offset.x - cs.width) / this.draw.scale.x) % gSize.width);\n offset.y =\n ((Math.round(offset.y + cs.height) / Math.round(gSize.height)) * gSize.height) / this.draw.scale.y +\n (((this.draw.offset.y - cs.height) / this.draw.scale.x) % gSize.height);\n if (this.drawConfig.drawGrid) {\n draw.setCurrentClassName(null);\n if (this.config.rasterGrid) {\n // TODO: move config member to drawConfig\n draw.setCurrentId(\"raster\");\n draw.raster(offset, this.canvasSize.width / this.draw.scale.x, this.canvasSize.height / this.draw.scale.y, gSize.width, gSize.height, \"rgba(0,128,255,0.125)\");\n }\n else {\n draw.setCurrentId(\"grid\");\n draw.grid(offset, this.canvasSize.width / this.draw.scale.x, this.canvasSize.height / this.draw.scale.y, gSize.width, gSize.height, \"rgba(0,128,255,0.095)\");\n }\n }\n }\n /**\n * Draw the origin with the current config settings.<br>\n *\n * This function is usually only used internally.\n *\n * @method drawOrigin\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawOrigin(draw) {\n // Add a crosshair to mark the origin\n draw.setCurrentId(\"origin\");\n draw.crosshair({ x: 0, y: 0 }, 10, this.drawConfig.origin.color);\n }\n /**\n * This is just a tiny helper function to determine the render color of vertices.\n **/\n _handleColor(h, color) {\n return h.attr.isSelected ? this.drawConfig.selectedVertex.color : h.attr.draggable ? color : \"rgba(128,128,128,0.5)\";\n }\n /**\n * Draw all drawables.\n *\n * This function is usually only used internally.\n *\n * @method drawDrawables\n * @param {number} renderTime - The current render time. It will be used to distinct\n * already draw vertices from non-draw-yet vertices.\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @param {DrawLib} fill - The drawing library to use to fill areas.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawDrawables(renderTime, draw, fill) {\n for (var i in this.drawables) {\n var d = this.drawables[i];\n this.draw.setCurrentId(d.uid);\n this.fill.setCurrentId(d.uid);\n this.draw.setCurrentClassName(d.className);\n this.fill.setCurrentClassName(d.className);\n this.drawDrawable(d, renderTime, draw, fill);\n }\n }\n /**\n * Draw the given drawable.\n *\n * This function is usually only used internally.\n *\n * @method drawDrawable\n * @param {Drawable} d - The drawable to draw.\n * @param {number} renderTime - The current render time. It will be used to distinct\n * already draw vertices from non-draw-yet vertices.\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @param {DrawLib} fill - The drawing library to use to fill areas.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawDrawable(d, renderTime, draw, fill) {\n if (d instanceof BezierPath) {\n var curveIndex = 0;\n for (var c in d.bezierCurves) {\n // Restore these settings again in each loop (will be overwritten)\n this.draw.setCurrentId(`${d.uid}-${curveIndex}`);\n this.fill.setCurrentId(`${d.uid}-${curveIndex}`);\n this.draw.setCurrentClassName(d.className);\n this.fill.setCurrentClassName(d.className);\n draw.cubicBezier(d.bezierCurves[c].startPoint, d.bezierCurves[c].endPoint, d.bezierCurves[c].startControlPoint, d.bezierCurves[c].endControlPoint, this.drawConfig.bezier.color, this.drawConfig.bezier.lineWidth);\n if (this.drawConfig.drawBezierHandlePoints && this.drawConfig.drawHandlePoints) {\n if (d.bezierCurves[c].startPoint.attr.visible) {\n const df = this.drawConfig.bezier.pathVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h0`);\n df.setCurrentClassName(`${d.className}-start-handle`);\n if (d.bezierCurves[c].startPoint.attr.bezierAutoAdjust) {\n df.squareHandle(d.bezierCurves[c].startPoint, 5, this._handleColor(d.bezierCurves[c].startPoint, this.drawConfig.bezier.pathVertex.color));\n }\n else {\n df.diamondHandle(d.bezierCurves[c].startPoint, 7, this._handleColor(d.bezierCurves[c].startPoint, this.drawConfig.bezier.pathVertex.color));\n }\n }\n d.bezierCurves[c].startPoint.attr.renderTime = renderTime;\n if (d.bezierCurves[c].endPoint.attr.visible) {\n const df = this.drawConfig.bezier.pathVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h0`);\n df.setCurrentClassName(`${d.className}-start-handle`);\n if (d.bezierCurves[c].endPoint.attr.bezierAutoAdjust) {\n df.squareHandle(d.bezierCurves[c].endPoint, 5, this._handleColor(d.bezierCurves[c].endPoint, this.drawConfig.bezier.pathVertex.color));\n }\n else {\n df.diamondHandle(d.bezierCurves[c].endPoint, 7, this._handleColor(d.bezierCurves[c].endPoint, this.drawConfig.bezier.pathVertex.color));\n }\n }\n if (d.bezierCurves[c].startControlPoint.attr.visible) {\n const df = this.drawConfig.bezier.controlVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h2`);\n df.setCurrentClassName(`${d.className}-start-control-handle`);\n df.circleHandle(d.bezierCurves[c].startControlPoint, 3, this._handleColor(d.bezierCurves[c].startControlPoint, this.drawConfig.bezier.controlVertex.color));\n }\n if (d.bezierCurves[c].endControlPoint.attr.visible) {\n const df = this.drawConfig.bezier.controlVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h3`);\n df.setCurrentClassName(`${d.className}-end-control-handle`);\n df.circleHandle(d.bezierCurves[c].endControlPoint, 3, this._handleColor(d.bezierCurves[c].endControlPoint, this.drawConfig.bezier.controlVertex.color));\n }\n d.bezierCurves[c].startPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].startControlPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endControlPoint.attr.renderTime = renderTime;\n }\n else {\n d.bezierCurves[c].startPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].startControlPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endControlPoint.attr.renderTime = renderTime;\n }\n if (this.drawConfig.drawBezierHandleLines && this.drawConfig.drawHandleLines) {\n draw.setCurrentId(`${d.uid}_l0`);\n draw.setCurrentClassName(`${d.className}-start-line`);\n draw.handleLine(d.bezierCurves[c].startPoint, d.bezierCurves[c].startControlPoint);\n draw.setCurrentId(`${d.uid}_l1`);\n draw.setCurrentClassName(`${d.className}-end-line`);\n draw.handleLine(d.bezierCurves[c].endPoint, d.bezierCurves[c].endControlPoint);\n }\n curveIndex++;\n } // END for\n }\n else if (d instanceof Polygon) {\n draw.polygon(d, this.drawConfig.polygon.color, this.drawConfig.polygon.lineWidth);\n if (!this.drawConfig.drawHandlePoints) {\n for (var i in d.vertices) {\n d.vertices[i].attr.renderTime = renderTime;\n }\n }\n }\n else if (d instanceof Triangle) {\n draw.polyline([d.a, d.b, d.c], false, this.drawConfig.triangle.color, this.drawConfig.triangle.lineWidth);\n if (!this.drawConfig.drawHandlePoints) {\n d.a.attr.renderTime = d.b.attr.renderTime = d.c.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof VEllipse) {\n if (this.drawConfig.drawHandleLines) {\n draw.setCurrentId(`${d.uid}_e0`);\n draw.setCurrentClassName(`${d.className}-v-line`);\n draw.handleLine(d.center.clone().add(0, d.signedRadiusV()).rotate(d.rotation, d.center), d.axis); // , \"#c8c8c8\");\n draw.setCurrentId(`${d.uid}_e1`);\n draw.setCurrentClassName(`${d.className}-h-line`);\n draw.handleLine(d.center.clone().add(d.signedRadiusH(), 0).rotate(d.rotation, d.center), d.axis); // , \"#c8c8c8\");\n }\n draw.setCurrentId(d.uid);\n draw.setCurrentClassName(`${d.className}`);\n draw.ellipse(d.center, \n // Math.abs(d.axis.x-d.center.x), Math.abs(d.axis.y-d.center.y),\n d.radiusH(), d.radiusV(), this.drawConfig.ellipse.color, this.drawConfig.ellipse.lineWidth, d.rotation);\n if (!this.drawConfig.drawHandlePoints) {\n d.center.attr.renderTime = renderTime;\n d.axis.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof VEllipseSector) {\n draw.setCurrentId(d.uid);\n draw.setCurrentClassName(`${d.className}`);\n const data = 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 });\n draw.path(data, this.drawConfig.ellipseSector.color, this.drawConfig.ellipseSector.lineWidth);\n }\n else if (d instanceof Circle) {\n draw.circle(d.center, d.radius, this.drawConfig.circle.color, this.drawConfig.circle.lineWidth);\n }\n else if (d instanceof CircleSector) {\n draw.circleArc(d.circle.center, d.circle.radius, d.startAngle, d.endAngle, this.drawConfig.circleSector.color, this.drawConfig.circleSector.lineWidth);\n }\n else if (d instanceof Vertex) {\n if (this.drawConfig.drawVertices && (!d.attr.selectable || !d.attr.draggable) && d.attr.visible) {\n // Draw as special point (grey)\n draw.circleHandle(d, 7, this.drawConfig.vertex.color);\n d.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof Line) {\n draw.line(d.a, d.b, this.drawConfig.line.color, this.drawConfig.line.lineWidth);\n if (!this.drawConfig.drawHandlePoints || !d.a.attr.selectable)\n d.a.attr.renderTime = renderTime;\n if (!this.drawConfig.drawHandlePoints || !d.b.attr.selectable)\n d.b.attr.renderTime = renderTime;\n }\n else if (d instanceof Vector) {\n draw.arrow(d.a, d.b, this.drawConfig.vector.color, this.drawConfig.vector.lineWidth);\n if (this.drawConfig.drawHandlePoints && d.b.attr.selectable && d.b.attr.visible) {\n draw.setCurrentId(`${d.uid}_h0`);\n draw.setCurrentClassName(`${d.className}-handle`);\n draw.circleHandle(d.b, 3, \"#a8a8a8\");\n }\n else {\n d.b.attr.renderTime = renderTime;\n }\n if (!this.drawConfig.drawHandlePoints || !d.a.attr.selectable)\n d.a.attr.renderTime = renderTime;\n if (!this.drawConfig.drawHandlePoints || !d.b.attr.selectable)\n d.b.attr.renderTime = renderTime;\n }\n else if (d instanceof PBImage) {\n if (this.drawConfig.drawHandleLines) {\n draw.setCurrentId(`${d.uid}_l0`);\n draw.setCurrentClassName(`${d.className}-line`);\n draw.line(d.upperLeft, d.lowerRight, this.drawConfig.image.color, this.drawConfig.image.lineWidth);\n }\n fill.setCurrentId(d.uid);\n fill.image(d.image, d.upperLeft, d.lowerRight.clone().sub(d.upperLeft));\n if (this.drawConfig.drawHandlePoints) {\n draw.setCurrentId(`${d.uid}_h0`);\n draw.setCurrentClassName(`${d.className}-lower-right`);\n draw.circleHandle(d.lowerRight, 3, this.drawConfig.image.color);\n d.lowerRight.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof PBText) {\n fill.setCurrentId(d.uid);\n fill.text(d.text, d.anchor.x, d.anchor.y, d);\n if (this.drawConfig.text.anchor) {\n draw.setCurrentId(`${d.uid}_a0`);\n draw.setCurrentClassName(`${d.className}-anchor`);\n (this.drawConfig.text.fill ? fill : draw).point(d.anchor, this.drawConfig.text.color);\n }\n d.anchor.attr.renderTime = renderTime;\n }\n else {\n console.error(\"Cannot draw object. Unknown class.\");\n }\n draw.setCurrentClassName(null);\n draw.setCurrentId(null);\n fill.setCurrentClassName(null);\n fill.setCurrentId(null);\n }\n /**\n * Draw the select-polygon (if there is one).\n *\n * This function is usually only used internally.\n *\n * @method drawSelectPolygon\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawSelectPolygon(draw) {\n // Draw select polygon?\n if (this.selectPolygon != null && this.selectPolygon.vertices.length > 0) {\n draw.setCurrentId(this.selectPolygon.uid);\n draw.polygon(this.selectPolygon, \"#888888\");\n draw.crosshair(this.selectPolygon.vertices[0], 3, \"#008888\");\n }\n }\n /**\n * Draw all vertices that were not yet drawn with the given render time.<br>\n * <br>\n * This function is usually only used internally.\n *\n * @method drawVertices\n * @private\n * @param {number} renderTime - The current render time. It is used to distinct\n * already draw vertices from non-draw-yet vertices.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawVertices(renderTime, draw) {\n // Draw all vertices as small squares if they were not already drawn by other objects\n for (var i in this.vertices) {\n if (this.drawConfig.drawVertices && this.vertices[i].attr.renderTime != renderTime && this.vertices[i].attr.visible) {\n draw.setCurrentId(this.vertices[i].uid);\n draw.squareHandle(this.vertices[i], 5, this._handleColor(this.vertices[i], \"rgb(0,128,192)\"));\n this.vertices[i].attr.renderTime = renderTime;\n }\n }\n }\n /**\n * Trigger redrawing of all objects.<br>\n * <br>\n * Usually this function is automatically called when objects change.\n *\n * @method redraw\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n redraw() {\n const renderTime = this.renderTime++;\n // Tell the drawing library that a new drawing cycle begins (required for the GL lib).\n this.draw.beginDrawCycle(renderTime);\n this.fill.beginDrawCycle(renderTime);\n if (this.config.preClear)\n this.config.preClear();\n this.clear();\n if (this.config.preDraw)\n this.config.preDraw(this.draw, this.fill);\n this.drawAll(renderTime, this.draw, this.fill);\n if (this.config.postDraw)\n this.config.postDraw(this.draw, this.fill);\n this.draw.endDrawCycle(renderTime);\n this.fill.endDrawCycle(renderTime);\n }\n /**\n * Draw all: drawables, grid, select-polygon and vertices.\n *\n * @method drawAll\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawAll(renderTime, draw, fill) {\n if (this.config.drawRaster) {\n this.drawGrid(draw);\n }\n if (this.config.drawOrigin) {\n this.drawOrigin(draw);\n }\n this.drawDrawables(renderTime, draw, fill);\n this.drawVertices(renderTime, draw);\n this.drawSelectPolygon(draw);\n // Clear IDs and classnames (postDraw hook might draw somthing and the do not want\n // to interfered with that).\n draw.setCurrentId(null);\n draw.setCurrentClassName(null);\n } // END redraw\n /**\n * This function clears the canvas with the configured background color.<br>\n * <br>\n * This function is usually only used internally.\n *\n * @method clear\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n clear() {\n // Note that elements might have an alpha channel. Clear the scene first.\n this.draw.clear(this.config.backgroundColor || \"white\");\n }\n /**\n * Clear the selection.<br>\n * <br>\n * This function is usually only used internally.\n *\n * @method clearSelection\n * @private\n * @param {boolean=} [redraw=false] - Indicates if the redraw function should be triggered.\n * @instance\n * @memberof PlotBoilerplate\n * @return {PlotBoilerplate} this\n **/\n clearSelection(redraw) {\n for (var i in this.vertices)\n this.vertices[i].attr.isSelected = false;\n if (redraw)\n this.redraw();\n return this;\n }\n /**\n * Get the current view port.\n *\n * @method viewport\n * @instance\n * @memberof PlotBoilerplate\n * @return {Bounds} The current viewport.\n **/\n viewport() {\n var _b, _c;\n return new Bounds(this.transformMousePosition(0, 0), this.transformMousePosition(this.canvasSize.width * ((_b = this.config.cssScaleX) !== null && _b !== void 0 ? _b : 1.0), this.canvasSize.height * ((_c = this.config.cssScaleY) !== null && _c !== void 0 ? _c : 1.0)));\n }\n /**\n * Trigger the saveFile.hook.\n *\n * @method saveFile\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n saveFile() {\n this.hooks.saveFile(this);\n }\n /**\n * Internal helper function used to get 'float' properties from elements.\n * Used to determine border withs and paddings that were defined using CSS.\n */\n // TODO: this was moved to the DOM utils\n getFProp(elem, propName) {\n return parseFloat(globalThis.getComputedStyle(elem, null).getPropertyValue(propName));\n }\n /**\n * Get the available inner space of the given container.\n *\n * Size minus padding minus border.\n **/\n // TODO: this was moved to the DOM utils\n getAvailableContainerSpace() {\n const _self = this;\n const container = _self.canvas.parentNode; // Element | Document | DocumentFragment;\n _self.canvas.style.display = \"none\";\n var padding = this.getFProp(container, \"padding\") || 0, border = this.getFProp(_self.canvas, \"border-width\") || 0, pl = this.getFProp(container, \"padding-left\") || padding, pr = this.getFProp(container, \"padding-right\") || padding, pt = this.getFProp(container, \"padding-top\") || padding, pb = this.getFProp(container, \"padding-bottom\") || padding, bl = this.getFProp(_self.canvas, \"border-left-width\") || border, br = this.getFProp(_self.canvas, \"border-right-width\") || border, bt = this.getFProp(_self.canvas, \"border-top-width\") || border, bb = this.getFProp(_self.canvas, \"border-bottom-width\") || border;\n var w = container.clientWidth;\n var h = container.clientHeight;\n _self.canvas.style.display = \"block\";\n return { width: w - pl - pr - bl - br, height: h - pt - pb - bt - bb };\n }\n /**\n * This function resizes the canvas to the required settings (toggles fullscreen).<br>\n * <br>\n * This function is usually only used internally but feel free to call it if resizing required.\n *\n * @method resizeCanvas\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n resizeCanvas() {\n var _b, _c, _d, _e, _f, _g;\n const _self = this;\n const _setSize = (w, h) => {\n var _b, _c;\n w *= (_b = _self.config.canvasWidthFactor) !== null && _b !== void 0 ? _b : 1.0;\n h *= (_c = _self.config.canvasHeightFactor) !== null && _c !== void 0 ? _c : 1.0;\n _self.canvasSize.width = w;\n _self.canvasSize.height = h;\n if (_self.canvas instanceof HTMLCanvasElement) {\n _self.canvas.width = w;\n _self.canvas.height = h;\n }\n else if (_self.canvas instanceof SVGElement) {\n this.canvas.setAttribute(\"viewBox\", `0 0 ${w} ${h}`);\n this.canvas.setAttribute(\"width\", `${w}`);\n this.canvas.setAttribute(\"height\", `${h}`);\n this.draw.setSize(_self.canvasSize); // No need to set size to this.fill (instance copy)\n this.eventCatcher.style.width = `${w}px`;\n this.eventCatcher.style.height = `${h}px`;\n }\n else {\n console.error(\"Error: cannot resize canvas element because it seems neither be a HTMLCanvasElement nor an SVGElement.\");\n }\n if (_self.config.autoAdjustOffset) {\n // _self.draw.offset.x = _self.fill.offset.x = _self.config.offsetX = w*(_self.config.offsetAdjustXPercent/100);\n // _self.draw.offset.y = _self.fill.offset.y = _self.config.offsetY = h*(_self.config.offsetAdjustYPercent/100);\n _self.adjustOffset(false);\n }\n };\n if (_self.config.fullSize && !_self.config.fitToParent) {\n // Set editor size\n var width = globalThis.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;\n var height = globalThis.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;\n _self.canvas.style.position = \"absolute\";\n _self.canvas.style.width = ((_b = _self.config.canvasWidthFactor) !== null && _b !== void 0 ? _b : 1.0) * width + \"px\";\n _self.canvas.style.height = ((_c = _self.config.canvasWidthFactor) !== null && _c !== void 0 ? _c : 1.0) * height + \"px\";\n _self.canvas.style.top = \"0px\";\n _self.canvas.style.left = \"0px\";\n _setSize(width, height);\n }\n else if (_self.config.fitToParent) {\n // Set editor size\n _self.canvas.style.position = \"static\";\n const space = this.getAvailableContainerSpace();\n _self.canvas.style.width = ((_d = _self.config.canvasWidthFactor) !== null && _d !== void 0 ? _d : 1.0) * space.width + \"px\";\n _self.canvas.style.height = ((_e = _self.config.canvasHeightFactor) !== null && _e !== void 0 ? _e : 1.0) * space.height + \"px\";\n _self.canvas.style.top = \"\";\n _self.canvas.style.left = \"\";\n _setSize(space.width, space.height);\n }\n else {\n _self.canvas.style.width = \"\";\n _self.canvas.style.height = \"\";\n _setSize((_f = _self.config.defaultCanvasWidth) !== null && _f !== void 0 ? _f : 1024, (_g = _self.config.defaultCanvasHeight) !== null && _g !== void 0 ? _g : 768);\n }\n if (_self.config.redrawOnResize)\n _self.redraw();\n }\n /**\n * Add all vertices inside the polygon to the current selection.<br>\n *\n * @method selectVerticesInPolygon\n * @param {Polygon} polygon - The polygonal selection area.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n selectVerticesInPolygon(polygon) {\n for (var i in this.vertices) {\n if (this.vertices[i].attr.selectable && polygon.containsVert(this.vertices[i]))\n this.vertices[i].attr.isSelected = true;\n }\n }\n /**\n * (Helper) Locates the point (index) at the passed position. Using an internal tolerance of 7 pixels.\n *\n * The result is an object { type : 'bpath', pindex, cindex, pid }\n *\n * Returns false if no point is near the passed position.\n *\n * @method locatePointNear\n * @param {Vertex} point - The polygonal selection area.\n * @param {number=} [tolerance=7] - The tolerance to use identtifying vertices.\n * @private\n * @return {IDraggable} Or false if none found.\n **/\n locatePointNear(point, tolerance) {\n const _self = this;\n if (typeof tolerance == \"undefined\")\n tolerance = 7;\n // Apply the zoom (the tolerant area should not shrink or grow when zooming)\n tolerance /= _self.draw.scale.x;\n // Search in vertices\n for (var vindex = 0; vindex < _self.vertices.length; vindex++) {\n var vert = _self.vertices[vindex];\n if ((vert.attr.draggable || vert.attr.selectable) && vert.distance(point) < tolerance) {\n // { type : 'vertex', vindex : vindex };\n return new PlotBoilerplate.Draggable(vert, PlotBoilerplate.Draggable.VERTEX).setVIndex(vindex);\n }\n }\n return null;\n }\n /**\n * Handle left-click event.<br>\n *\n * @method handleClick\n * @param {number} x - The click X position on the canvas.\n * @param {number} y - The click Y position on the canvas.\n * @private\n * @return {void}\n **/\n handleClick(e) {\n const _self = this;\n var point = this.locatePointNear(_self.transformMousePosition(e.params.pos.x, e.params.pos.y), PlotBoilerplate.DEFAULT_CLICK_TOLERANCE / Math.min(_self.config.cssScaleX || 1.0, _self.config.cssScaleY || 1.0));\n if (point) {\n _self.vertices[point.vindex].listeners.fireClickEvent(e);\n if (this.keyHandler && this.keyHandler.isDown(\"shift\")) {\n if (point.typeName == \"bpath\") {\n let vert = _self.paths[point.pindex].bezierCurves[point.cindex].getPointByID(point.pid);\n if (vert.attr.selectable)\n vert.attr.isSelected = !vert.attr.isSelected;\n }\n else if (point.typeName == \"vertex\") {\n let vert = _self.vertices[point.vindex];\n if (vert.attr.selectable)\n vert.attr.isSelected = !vert.attr.isSelected;\n }\n _self.redraw();\n }\n else if (this.keyHandler && this.keyHandler.isDown(\"y\")) {\n _self.vertices[point.vindex].attr.bezierAutoAdjust = !_self.vertices[point.vindex].attr.bezierAutoAdjust;\n _self.redraw();\n }\n }\n else if (_self.selectPolygon != null) {\n const vert = _self.transformMousePosition(e.params.pos.x, e.params.pos.y);\n _self.selectPolygon.vertices.push(new Vertex(vert.x, vert.y));\n _self.redraw();\n }\n }\n /**\n * Transforms the given x-y-(mouse-)point to coordinates respecting the view offset\n * and the zoom settings.\n *\n * @method transformMousePosition\n * @param {number} x - The x position relative to the canvas.\n * @param {number} y - The y position relative to the canvas.\n * @instance\n * @memberof PlotBoilerplate\n * @return {XYCoords} A simple object <pre>{ x : Number, y : Number }</pre> with the transformed coordinates.\n **/\n transformMousePosition(x, y) {\n return {\n x: (x / this.config.cssScaleX - this.config.offsetX) / this.config.scaleX,\n y: (y / this.config.cssScaleY - this.config.offsetY) / this.config.scaleY\n };\n }\n /**\n * Revert a transformed mouse position back to canvas coordinates.\n *\n * This is the inverse function of `transformMousePosition`.\n *\n * @method revertMousePosition\n * @param {number} x - The x component of the position to revert.\n * @param {number} y - The y component of the position to revert.\n * @instance\n * @memberof PlotBoilerplate\n * @return {XYCoords} The canvas coordinates for the given position.\n **/\n revertMousePosition(x, y) {\n return { x: x / this.config.cssScaleX + this.config.offsetX, y: y / this.config.cssScaleY + this.config.offsetY };\n }\n /**\n * Determine if any elements are currently being dragged (on mouse move or touch move).\n *\n * @method getDraggedElementCount\n * @instance\n * @memberof PlotBoilerplate\n * @return {number} The number of elements that are currently being dragged.\n **/\n getDraggedElementCount() {\n return this.draggedElements.length;\n }\n /**\n * (Helper) The mouse-down handler.\n *\n * It selects vertices for dragging.\n *\n * @method mouseDownHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseDownHandler(e) {\n const _self = this;\n if (e.button != 0)\n return; // Only react on left mouse or touch events\n var draggablePoint = _self.locatePointNear(_self.transformMousePosition(e.params.pos.x, e.params.pos.y), PlotBoilerplate.DEFAULT_CLICK_TOLERANCE / Math.min(_self.config.cssScaleX, _self.config.cssScaleY));\n if (!draggablePoint)\n return;\n // Drag all selected elements?\n if (draggablePoint.typeName == \"vertex\" && _self.vertices[draggablePoint.vindex].attr.isSelected) {\n // Multi drag\n // for( var i in _self.vertices ) {\n for (var i = 0; i < _self.vertices.length; i++) {\n if (_self.vertices[i].attr.isSelected) {\n _self.draggedElements.push(new PlotBoilerplate.Draggable(_self.vertices[i], PlotBoilerplate.Draggable.VERTEX).setVIndex(i));\n _self.vertices[i].listeners.fireDragStartEvent(e);\n }\n }\n }\n else {\n // Single drag\n if (!_self.vertices[draggablePoint.vindex].attr.draggable)\n return;\n _self.draggedElements.push(draggablePoint);\n if (draggablePoint.typeName == \"bpath\")\n _self.paths[draggablePoint.pindex].bezierCurves[draggablePoint.cindex]\n .getPointByID(draggablePoint.pid)\n .listeners.fireDragStartEvent(e);\n else if (draggablePoint.typeName == \"vertex\")\n _self.vertices[draggablePoint.vindex].listeners.fireDragStartEvent(e);\n }\n _self.redraw();\n }\n /**\n * The mouse-drag handler.\n *\n * It moves selected elements around or performs the panning if the ctrl-key if\n * hold down.\n *\n * @method mouseDragHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseDragHandler(e) {\n const _self = this;\n const oldDragAmount = { x: e.params.dragAmount.x, y: e.params.dragAmount.y };\n e.params.dragAmount.x /= _self.config.cssScaleX;\n e.params.dragAmount.y /= _self.config.cssScaleY;\n // Important note to: this.keyHandler.isDown('ctrl')\n // We should not use this for any input.\n // Reason: most browsers use [Ctrl]+[t] to create new browser tabs.\n // If so, the key-up event for [Ctrl] will be fired in the _new tab_,\n // not this one. So this tab will never receive any [Ctrl-down] events\n // until next keypress; the implication is, that [Ctrl] would still\n // considered to be pressed which is not true.\n if (this.keyHandler && (this.keyHandler.isDown(\"alt\") || this.keyHandler.isDown(\"spacebar\"))) {\n if (!this.config.enablePan) {\n return;\n }\n _self.setOffset(_self.draw.offset.clone().add(e.params.dragAmount));\n _self.redraw();\n }\n else {\n // Convert drag amount by scaling\n // Warning: this possibly invalidates the dragEvent for other listeners!\n // Rethink the solution when other features are added.\n e.params.dragAmount.x /= _self.draw.scale.x;\n e.params.dragAmount.y /= _self.draw.scale.y;\n for (var i in _self.draggedElements) {\n var p = _self.draggedElements[i];\n if (p.typeName == \"bpath\") {\n _self.paths[p.pindex].moveCurvePoint(p.cindex, p.pid, new Vertex(e.params.dragAmount.x, e.params.dragAmount.y));\n _self.paths[p.pindex].bezierCurves[p.cindex].getPointByID(p.pid).listeners.fireDragEvent(e);\n }\n else if (p.typeName == \"vertex\") {\n if (!_self.vertices[p.vindex].attr.draggable)\n continue;\n _self.vertices[p.vindex].add(e.params.dragAmount);\n _self.vertices[p.vindex].listeners.fireDragEvent(e);\n }\n }\n }\n // Restore old event values!\n e.params.dragAmount.x = oldDragAmount.x;\n e.params.dragAmount.y = oldDragAmount.y;\n _self.redraw();\n }\n /**\n * The mouse-up handler.\n *\n * It clears the dragging-selection.\n *\n * @method mouseUpHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseUpHandler(e) {\n const _self = this;\n if (e.button != 0)\n return; // Only react on left mouse;\n if (!e.params.wasDragged) {\n _self.handleClick(e); // e.params.pos.x, e.params.pos.y );\n }\n for (var i in _self.draggedElements) {\n var p = _self.draggedElements[i];\n if (p.typeName == \"bpath\") {\n _self.paths[p.pindex].bezierCurves[p.cindex].getPointByID(p.pid).listeners.fireDragEndEvent(e);\n }\n else if (p.typeName == \"vertex\") {\n _self.vertices[p.vindex].listeners.fireDragEndEvent(e);\n }\n }\n _self.draggedElements = [];\n _self.redraw();\n }\n /**\n * The mouse-wheel handler.\n *\n * It performs the zooming.\n *\n * @method mouseWheelHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseWheelHandler(e) {\n if (!this.config.enableZoom) {\n return;\n }\n var zoomStep = 1.25; // Make configurable?\n // CHANGED replaced _self by this\n const _self = this;\n const we = e;\n if (we.deltaY < 0) {\n _self.setZoom(_self.config.scaleX * zoomStep, _self.config.scaleY * zoomStep, new Vertex(e.params.pos.x, e.params.pos.y));\n }\n else if (we.deltaY > 0) {\n _self.setZoom(_self.config.scaleX / zoomStep, _self.config.scaleY / zoomStep, new Vertex(e.params.pos.x, e.params.pos.y));\n }\n e.preventDefault();\n _self.redraw();\n }\n /**\n * Re-adjust the configured offset depending on the current canvas size and zoom (scaleX and scaleY).\n *\n * @method adjustOffset\n * @param {boolean=false} redraw - [optional] If set the canvas will redraw with the new offset (default=false).\n * @return {void}\n **/\n adjustOffset(redraw) {\n this.draw.offset.x =\n this.fill.offset.x =\n this.config.offsetX =\n this.canvasSize.width * (this.config.offsetAdjustXPercent / 100);\n this.draw.offset.y =\n this.fill.offset.y =\n this.config.offsetY =\n this.canvasSize.height * (this.config.offsetAdjustYPercent / 100);\n if (redraw) {\n this.redraw();\n }\n }\n /**\n * Set the new draw offset.\n *\n * Note: the function will not trigger any redraws.\n *\n * @param {Vertex} newOffset - The new draw offset to use.\n **/\n setOffset(newOffset) {\n this.draw.offset.set(newOffset);\n this.fill.offset.set(newOffset);\n this.config.offsetX = newOffset.x;\n this.config.offsetY = newOffset.y;\n }\n /**\n * Set a new zoom value (and re-adjust the draw offset).\n *\n * Note: the function will not trigger any redraws.\n *\n * @param {number} zoomFactorX - The new horizontal zoom value.\n * @param {number} zoomFactorY - The new vertical zoom value.\n * @param {Vertex} interactionPos - The position of mouse/touch interaction.\n **/\n setZoom(zoomFactorX, zoomFactorY, interactionPos) {\n let oldPos = this.transformMousePosition(interactionPos.x, interactionPos.y);\n this.draw.scale.x = this.fill.scale.x = this.config.scaleX = Math.max(zoomFactorX, 0.01);\n this.draw.scale.y = this.fill.scale.y = this.config.scaleY = Math.max(zoomFactorY, 0.01);\n let newPos = this.transformMousePosition(interactionPos.x, interactionPos.y);\n let newOffsetX = this.draw.offset.x + (newPos.x - oldPos.x) * this.draw.scale.x;\n let newOffsetY = this.draw.offset.y + (newPos.y - oldPos.y) * this.draw.scale.y;\n this.setOffset({ x: newOffsetX, y: newOffsetY });\n }\n installInputListeners() {\n var _self = this;\n if (this.config.enableMouse) {\n // Install a mouse handler on the canvas.\n new MouseHandler(this.eventCatcher ? this.eventCatcher : this.canvas)\n .down((e) => {\n _self.mouseDownHandler(e);\n })\n .drag((e) => {\n _self.mouseDragHandler(e);\n })\n .up((e) => {\n _self.mouseUpHandler(e);\n });\n }\n else {\n _self.console.log(\"Mouse interaction disabled.\");\n }\n if (this.config.enableMouseWheel) {\n // Install a mouse handler on the canvas.\n new MouseHandler(this.eventCatcher ? this.eventCatcher : this.canvas).wheel((e) => {\n _self.mouseWheelHandler(e);\n });\n }\n else {\n _self.console.log(\"Mouse wheel interaction disabled.\");\n }\n if (this.config.enableTouch) {\n // Install a touch handler on the canvas.\n const relPos = (pos) => {\n const bounds = _self.canvas.getBoundingClientRect();\n return { x: pos.x - bounds.left, y: pos.y - bounds.top };\n };\n // Make PB work together with both, AlloyFinger as a esm module or a commonjs function.\n if (typeof globalThis[\"AlloyFinger\"] === \"function\" ||\n typeof globalThis[\"createAlloyFinger\"] === \"function\") {\n try {\n var touchMovePos = null;\n var touchDownPos = null;\n var draggedElement = null;\n var multiTouchStartScale = null;\n const clearTouch = () => {\n touchMovePos = null;\n touchDownPos = null;\n draggedElement = null;\n multiTouchStartScale = null;\n _self.draggedElements = [];\n };\n const afProps = {\n // touchStart: (evt: TouchEvent) => {\n touchStart: (evt) => {\n if (evt.touches.length == 1) {\n touchMovePos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));\n touchDownPos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));\n draggedElement = _self.locatePointNear(_self.transformMousePosition(touchMovePos.x, touchMovePos.y), PlotBoilerplate.DEFAULT_TOUCH_TOLERANCE / Math.min(_self.config.cssScaleX, _self.config.cssScaleY));\n if (draggedElement && draggedElement.typeName == \"vertex\") {\n var draggingVertex = _self.vertices[draggedElement.vindex];\n var fakeEvent = {\n params: {\n isTouchEvent: true,\n dragAmount: { x: 0, y: 0 },\n wasDragged: false,\n mouseDownPos: touchDownPos.clone(),\n mouseDragPos: touchDownPos.clone(),\n vertex: draggingVertex\n }\n };\n _self.draggedElements = [draggedElement];\n draggingVertex.listeners.fireDragStartEvent(fakeEvent);\n }\n }\n },\n touchMove: (evt) => {\n if (evt.touches.length == 1 && draggedElement) {\n evt.preventDefault();\n evt.stopPropagation();\n if (!touchDownPos || !touchMovePos) {\n return;\n }\n var rel = relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY });\n var trans = _self.transformMousePosition(rel.x, rel.y);\n var diff = new Vertex(_self.transformMousePosition(touchMovePos.x, touchMovePos.y)).difference(trans);\n if (draggedElement.typeName == \"vertex\") {\n if (!_self.vertices[draggedElement.vindex].attr.draggable)\n return;\n _self.vertices[draggedElement.vindex].add(diff);\n var draggingVertex = _self.vertices[draggedElement.vindex];\n var fakeEvent = {\n isTouchEvent: true,\n params: {\n dragAmount: diff.clone(),\n wasDragged: true,\n mouseDownPos: touchDownPos.clone(),\n mouseDragPos: touchDownPos.clone().add(diff),\n vertex: draggingVertex\n }\n };\n draggingVertex.listeners.fireDragEvent(fakeEvent);\n _self.redraw();\n }\n touchMovePos = new Vertex(rel);\n }\n else if (evt.touches.length == 2) {\n if (!this.config.enablePan) {\n return;\n }\n // If at least two fingers touch and move, then change the draw offset (panning).\n evt.preventDefault();\n evt.stopPropagation();\n _self.setOffset(_self.draw.offset\n .clone()\n .addXY(evt.deltaX, evt.deltaY)); // Apply zoom?\n _self.redraw();\n }\n },\n touchEnd: (evt) => {\n // Note: e.touches.length is 0 here\n if (draggedElement && draggedElement.typeName == \"vertex\") {\n if (!touchDownPos) {\n return;\n }\n var draggingVertex = _self.vertices[draggedElement.vindex];\n var fakeEvent = {\n isTouchEvent: true,\n params: {\n dragAmount: { x: 0, y: 0 },\n wasDragged: false,\n mouseDownPos: touchDownPos.clone(),\n mouseDragPos: touchDownPos.clone(),\n vertex: draggingVertex\n }\n };\n // Check if vertex was moved\n if (touchMovePos && touchDownPos && touchDownPos.distance(touchMovePos) < 0.001) {\n // if( e.touches.length == 1 && diff.x == 0 && diff.y == 0 ) {\n draggingVertex.listeners.fireClickEvent(fakeEvent);\n }\n else {\n draggingVertex.listeners.fireDragEndEvent(fakeEvent);\n }\n }\n clearTouch();\n },\n touchCancel: (evt) => {\n clearTouch();\n },\n multipointStart: (evt) => {\n multiTouchStartScale = _self.draw.scale.clone();\n },\n multipointEnd: (evt) => {\n multiTouchStartScale = null;\n },\n pinch: (evt) => {\n if (!this.config.enableZoom) {\n return;\n }\n const touchItem0 = evt.touches.item(0);\n const touchItem1 = evt.touches.item(1);\n if (!evt.touches || !multiTouchStartScale || !touchItem0 || !touchItem1) {\n return;\n }\n // For pinching there must be at least two touch items\n const fingerA = new Vertex(touchItem0.clientX, touchItem0.clientY);\n const fingerB = new Vertex(touchItem1.clientX, touchItem1.clientY);\n const center = new Line(fingerA, fingerB).vertAt(0.5);\n _self.setZoom(multiTouchStartScale.x * evt.zoom, multiTouchStartScale.y * evt.zoom, center);\n _self.redraw();\n }\n }; // END afProps\n if (window[\"createAlloyFinger\"]) {\n // window[\"createAlloyFinger\"](this.eventCatcher ? this.eventCatcher : this.canvas, afProps);\n const createAlloyFinger = window[\"createAlloyFinger\"];\n createAlloyFinger(this.eventCatcher ? this.eventCatcher : this.canvas, afProps);\n }\n else {\n /* tslint:disable-next-line */\n new AlloyFinger(this.eventCatcher ? this.eventCatcher : this.canvas, afProps);\n }\n }\n catch (e) {\n console.error(\"Failed to initialize AlloyFinger!\");\n console.error(e);\n }\n }\n else if (globalThis[\"Touchy\"] && typeof globalThis[\"Touchy\"] == \"function\") {\n console.error(\"[Deprecation] Found Touchy which is not supported any more. Please use AlloyFinger instead.\");\n // Convert absolute touch positions to relative DOM element position (relative to canvas)\n }\n else {\n console.warn(\"Cannot initialize the touch handler. AlloyFinger is missig. Did you include it?\");\n }\n }\n else {\n _self.console.log(\"Touch interaction disabled.\");\n }\n if (this.config.enableKeys) {\n // Install key handler\n this.keyHandler = new KeyHandler({ trackAll: true })\n .down(\"escape\", function () {\n _self.clearSelection(true);\n })\n .down(\"shift\", function () {\n _self.selectPolygon = new Polygon();\n _self.redraw();\n })\n .up(\"shift\", function () {\n // Find and select vertices in the drawn area\n if (_self.selectPolygon == null)\n return;\n _self.selectVerticesInPolygon(_self.selectPolygon);\n _self.selectPolygon = null;\n _self.redraw();\n });\n } // END IF enableKeys?\n else {\n _self.console.log(\"Keyboard interaction disabled.\");\n }\n }\n /**\n * Creates a control GUI (a dat.gui instance) for this\n * plot boilerplate instance.\n *\n * @method createGUI\n * @instance\n * @memberof PlotBoilerplate\n * @return {dat.gui.GUI}\n **/\n createGUI(props) {\n // This function moved to the helper utils.\n // We do not want to include the whole dat.GUI package.\n const utils = globalThis[\"utils\"];\n // if (globalThis[\"utils\"] && typeof globalThis[\"utils\"].createGUI == \"function\") {\n // return (globalThis[\"utils\" as keyof Object] as any as ({createGUI : (pb:PlotBoilerplate,props:DatGuiProps|undefined)=>GUI })).createGUI(this, props);\n if (utils && typeof utils.createGUI === \"function\") {\n return (this._gui = utils.createGUI(this, props));\n }\n else {\n throw \"Cannot create dat.GUI or lil-gui instance; did you load the ./utils/creategui helper function an the dat.GUI/lil-gui library?\";\n }\n }\n /**\n * Retriebe the GUI once it was created. If the `createGUI` method was not called or failed to create any\n * GUI then null is returned.\n * @returns {GUI | null}\n */\n getGUI() {\n return this._gui;\n }\n} // END class PlotBoilerplate\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_CANVAS_WIDTH = 1024;\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_CANVAS_HEIGHT = 768;\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_CLICK_TOLERANCE = 8;\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_TOUCH_TOLERANCE = 32;\n/**\n * A wrapper class for draggable items (mostly vertices).\n * @private\n **/\nPlotBoilerplate.Draggable = (_a = class {\n constructor(item, typeName) {\n this.item = item;\n this.typeName = typeName;\n }\n isVertex() {\n return this.typeName == PlotBoilerplate.Draggable.VERTEX;\n }\n setVIndex(vindex) {\n this.vindex = vindex;\n return this;\n }\n },\n __setFunctionName(_a, \"Draggable\"),\n _a.VERTEX = \"vertex\",\n _a);\n/**\n * A set of helper functions.\n **/\nPlotBoilerplate.utils = {\n /**\n * Merge the elements in the 'extension' object into the 'base' object based on\n * the keys of 'base'.\n *\n * @param {Object} base\n * @param {Object} extension\n * @return {Object} base extended by the new attributes.\n **/\n safeMergeByKeys: (base, extension) => {\n for (var k in extension) {\n if (!extension.hasOwnProperty(k)) {\n continue;\n }\n if (base.hasOwnProperty(k)) {\n const typ = typeof base[k];\n const extVal = extension[k];\n try {\n if (typ == \"boolean\") {\n if (typeof extVal === \"string\")\n base[k] = Boolean(!!JSON.parse(extVal));\n else\n base[k] = extVal;\n }\n else if (typ == \"number\") {\n if (typeof extVal === \"string\")\n base[k] = Number(JSON.parse(extVal) * 1);\n else\n base[k] = extension[k];\n }\n else if (typ == \"function\" && typeof extVal == \"function\") {\n base[k] = extension[k];\n }\n else {\n // Probably a sting\n base[k] = extension[k];\n }\n }\n catch (e) {\n console.error(\"error in key \", k, extVal, e);\n }\n }\n else {\n base[k] = extension[k];\n }\n }\n return base;\n },\n /*\n __safeMergeByKeys: <KeyType extends string | number | symbol, ValueType extends boolean | number | string | Function>(\n base: Record<KeyType, ValueType>,\n extension: Record<KeyType, string>\n ): Record<KeyType, ValueType> => {\n for (var k in extension) {\n if (!extension.hasOwnProperty(k)) continue;\n if (base.hasOwnProperty(k)) {\n var typ = typeof base[k];\n try {\n if (typ == \"boolean\") base[k] = !!JSON.parse(extension[k]);\n else if (typ == \"number\") base[k] = JSON.parse(extension[k]) * 1;\n else if (typ == \"function\" && typeof extension[k] == \"function\") base[k] = extension[k];\n else base[k] = extension[k];\n } catch (e) {\n console.error(\"error in key \", k, extension[k], e);\n }\n } else {\n base[k] = extension[k];\n }\n }\n return base;\n },\n *()\n\n /**\n * A helper function to scale elements (usually the canvas) using CSS.\n *\n * transform-origin is at (0,0).\n *\n * @param {HTMLElement} element - The DOM element to scale.\n * @param {number} scaleX The - X scale factor.\n * @param {number} scaleY The - Y scale factor.\n * @return {void}\n **/\n setCSSscale: (element, scaleX, scaleY) => {\n // element.style[\"transform-origin\"] = \"0 0\";\n element.style.transformOrigin = \"0 0\";\n if (scaleX == 1.0 && scaleY == 1.0) {\n // element.style.transform = null;\n element.style.removeProperty(\"transform\");\n }\n else\n element.style.transform = \"scale(\" + scaleX + \",\" + scaleY + \")\";\n },\n // A helper for fetching data from objects.\n fetch: {\n /**\n * A helper function to the the object property value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {any} fallback - A default value if the key does not exist.\n **/\n val: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] == \"undefined\")\n return fallback;\n return obj[key];\n },\n /**\n * A helper function to the the object property numeric value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {number} fallback - A default value if the key does not exist.\n * @return {number}\n **/\n num: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] === \"number\")\n return obj[key];\n else {\n try {\n return JSON.parse(obj[key]) * 1;\n }\n catch (e) {\n return fallback;\n }\n }\n },\n /**\n * A helper function to the the object property boolean value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {boolean} fallback - A default value if the key does not exist.\n * @return {boolean}\n **/\n bool: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] == \"boolean\")\n return obj[key];\n else {\n try {\n return !!JSON.parse(obj[key]);\n }\n catch (e) {\n return fallback;\n }\n }\n },\n /**\n * A helper function to the the object property function-value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {function} fallback - A default value if the key does not exist.\n * @return {function}\n **/\n func: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] !== \"function\")\n return fallback;\n return obj[key];\n }\n }, // END fetch\n /**\n * Installs vertex listeners to the path's vertices so that controlpoints\n * move with their path points when dragged.\n *\n * Bézier path points with attr.bezierAutoAdjust==true will have their\n * two control points audo-updated if moved, too (keep path connections smooth).\n *\n * @param {BezierPath} bezierPath - The path to use auto-adjustment for.\n **/\n enableBezierPathAutoAdjust: (bezierPath) => {\n for (var i = 0; i < bezierPath.bezierCurves.length; i++) {\n // This should be wrapped into the BezierPath implementation.\n bezierPath.bezierCurves[i].startPoint.listeners.addDragListener(function (e) {\n var cindex = bezierPath.locateCurveByStartPoint(e.params.vertex);\n bezierPath.bezierCurves[cindex].startPoint.addXY(-e.params.dragAmount.x, -e.params.dragAmount.y);\n bezierPath.moveCurvePoint(cindex * 1, bezierPath.START_POINT, e.params.dragAmount);\n bezierPath.updateArcLengths();\n });\n bezierPath.bezierCurves[i].startControlPoint.listeners.addDragListener(function (e) {\n var cindex = bezierPath.locateCurveByStartControlPoint(e.params.vertex);\n if (!bezierPath.bezierCurves[cindex].startPoint.attr.bezierAutoAdjust)\n return;\n bezierPath.adjustPredecessorControlPoint(cindex * 1, true, // obtain handle length?\n false // update arc lengths\n );\n bezierPath.updateArcLengths();\n });\n bezierPath.bezierCurves[i].endControlPoint.listeners.addDragListener(function (e) {\n var cindex = bezierPath.locateCurveByEndControlPoint(e.params.vertex);\n if (!bezierPath.bezierCurves[cindex % bezierPath.bezierCurves.length].endPoint.attr.bezierAutoAdjust)\n return;\n bezierPath.adjustSuccessorControlPoint(cindex * 1, true, // obtain handle length?\n false // update arc lengths\n );\n bezierPath.updateArcLengths();\n });\n if (i + 1 == bezierPath.bezierCurves.length) {\n // && !bezierPath.adjustCircular ) {\n // Move last control point with the end point (if not circular)\n bezierPath.bezierCurves[bezierPath.bezierCurves.length - 1].endPoint.listeners.addDragListener(function (e) {\n if (!bezierPath.adjustCircular) {\n var cindex = bezierPath.locateCurveByEndPoint(e.params.vertex);\n bezierPath.moveCurvePoint(cindex * 1, bezierPath.END_CONTROL_POINT, new Vertex({ x: e.params.dragAmount.x, y: e.params.dragAmount.y }));\n }\n bezierPath.updateArcLengths();\n });\n }\n } // END for\n }\n}; // END utils\nexport default PlotBoilerplate;\n//# sourceMappingURL=PlotBoilerplate.js.map"],"names":["VertexAttr","constructor","key","this","draggable","selectable","isSelected","visible","model","UIDGenerator","next","current","VertexListeners","vertex","click","drag","dragStart","dragEnd","addClickListener","listener","_addListener","removeClickListener","_removeListener","addDragListener","removeDragListener","addDragStartListener","removeDragStartListener","addDragEndListener","removeDragEndListener","fireClickEvent","e","_fireEvent","fireDragEvent","fireDragStartEvent","fireDragEndEvent","removeAllListeners","_self","listeners","ve","i","params","newListener","push","oldListener","length","splice","Circle","center","radius","className","uid","move","amount","add","containsPoint","point","distance","containsCircle","circle","lineDistance","line","getClosestPoint","vertAt","angle","circleUtils","tangentAt","pointA","Vector","Vertex","perp","getBounds","Bounds","clone","subXY","Math","abs","addXY","circleIntersection","p0","p1","d","a","h","sqrt","p2","scale","x3","x","y","y3","x4","y4","Line","lineIntersection","b","interA","interB","transA","sub","transB","diff","difference","dist","det","distSquared","belowSqrt","sign","lineIntersections","inVectorBoundsOnly","intersectioLine","filter","vert","hasPoint","lineIntersectionTangents","map","closestPoint","destroy","isDestroyed","cos","sin","Triangle","c","calcCircumcircle","fromArray","arr","getArea","utils","signedArea","getCentroid","scaleToCentroid","factor","centroid","bounds","getCircumcircle","isAdjacent","tri","equals","getThirdVertex","vert1","vert2","A","B","C","D","E","F","G","dx","dy","EPSILON","min","max","cx","cy","radius_squared","inCircumcircle","v","min3","max3","Polygon","locateLineIntersecion","intersectionTuple","intersection","polyLine","getEdgeAt","edgeIndex","moveTo","modIndex","toPolygon","determinant","p","pointIsInTriangle","getIncircularTriangle","lineA","lineB","lineC","bisector1","geomutils","nsectAngle","bisector2","circleIntersA","circleIntersB","circleIntersC","getIncircle","getIncenter","toString","p0x","p0y","p1x","p1y","p2x","p2y","px","py","area","s","t","mapAngleTo2PI","new_angle","asin","PI","dist4","x1","y1","x2","y2","pow","dotProduct","vertA","vertB","pA","pB","pC","n","triangle","lineAB","lineAC","insideAngle","clockwise","scaleFactor","result","rotate","wrapMax","wrapMinMax","tuple","NaN","attr","set","setX","setY","invX","invY","amountX","amountY","addX","addY","subX","subY","eqX","eqY","origin","atan2","scaleXY","lerp","target","lerpAbs","u","step","factors","len","ZERO","multiplyScalar","scalar","round","inv","computeFromVertices","precision","toFixed","randomVertex","viewPort","random","buildArrowHead","zA","zB","headlen","scaleX","scaleY","console","warn","vertices","arrayToJSON","JSON","stringify","undefined","Number","VertTuple","factory","setLength","revert","tmp","normalize","newA","v0","v1","denominator","colinear","epsilon","getClosestT","l2","vtutils","dist2","insideBoundsOnly","pointDistance","w","super","inverse","numerator1","numerator2","getOrthogonal","linePoint","startPoint","isNaN","getStartPoint","getEndPoint","getStartTangent","getEndTangent","reverse","intersections","intrsctn","isOpen","addVertex","addVertexAt","index","vertIndex","getVertexAt","getEdges","lines","getInnerAngleAt","p3","isAcute","isAngleAcute","zero","p2mp1","p3mp2","p2mp1_len","p3mp2_len","lengthProduct","acos","containsVert","inside","j","xi","yi","xj","yj","containsVerts","verts","every","containsPolygon","polygon","lineSegment","isClockwise","perimeter","log","getMeanCenter","cur","lineIntersectionTangentsIndices","closestLineIntersection","closestInterSectionIndex","closestLineIntersectionIndex","allIntersections","closestIntersection","MAX_VALUE","curDist","curVert","getInterpolationPolygon","interpolationCount","nextVert","lerpAmount","getEvenDistributionPolygon","pointCount","Error","polygonPoint","stepSize","polygonIndex","nextPolygonPoint","segmentLength","loopMax","curSegmentU","newPoint","elimitateColinearEdges","tolerance","eps","slice","areColinear","vertC","toQuadraticBezierData","qbezier","cc0","cc1","edgeCenter","limit","toQuadraticBezierSVGString","qdata","buffer","join","toCubicBezierData","threshold","cbezier","aCenter","bCenter","a2","b0","toCubicBezierSVGString","toCubicBezierPath","pathdata","BezierPath","total","l","sum","intersectionPoints","width","height","getWidth","getHeight","getScaled","getCenter","newMin","newMax","getMoved","moveAmount","getNorthPoint","getSouthPoint","getWestPoint","getEastPoint","getNorthWestPoint","getNorthEastPoint","getSouthEastPoint","getSouthWestPoint","getMinDimension","getMaxDimension","randomPoint","horizontalSafeArea","verticalSafeArea","absHorizontalSafeArea","absVerticalSafeArea","xMin","xMax","yMin","yMax","computeFromBoundsSet","boundingBoxes","fromDimension","CubicBezierCurve","endPoint","startControlPoint","endControlPoint","START_POINT","START_CONTROL_POINT","END_CONTROL_POINT","END_POINT","curveIntervals","segmentCache","segmentLengths","updateArcLengths","moveCurvePoint","pointID","moveControlPoint","getStartControlPoint","getEndControlPoint","translate","getLength","arcLength","pointB","curveStep","newLength","tmpLength","getPointAt","tPrev","tNext","iteration","locateIntervalByDistance","tStart","tEnd","stepCount","minIndex","minDist","tDiff","xMinMax","cubicPolyMinMax","xl","xh","yMinMax","yl","yh","getPointByID","id","evaluateT","getPoint","getTangentAt","t2","nt2","tX","tY","trimStart","uValue","trimStartAt","convertU2T","subCurbePoints","getSubCurvePointsAt","trimEnd","trimEndAt","getSubCurve","uStart","uEnd","getSubCurveAt","getTangent","getPerpendicular","getPerpendicularAt","tangentVector","lineIntersectionTs","intersectionTangents","vec","bx","bezierCoeffs","by","poly","Array","cubicRoots","root","curve","isInstance","obj","toJSON","prettyFormat","fromJSON","jsonString","parse","fromObject","isArray","polyX","cubicPoly","disc","t1","startVec","endVec","S","T","Q","R","ts","sgn","th","sort","coeffs","totalArcLength","adjustCircular","bezierCurves","addCurve","adjustSuccessorControlPoint","locateCurveByStartPoint","locateCurveByEndPoint","locateCurveByStartControlPoint","locateCurveByEndControlPoint","getCurveCount","getCurveAt","curveIndex","anchor","scaleFactors","curveT","uMin","uTemp","relativeU","uResult","_locateUIndex","bCurve","uPart","reduce","accu","curCurve","concat","path","uBefore","getSubPathAt","startT","endT","startU","endU","uStartResult","uEndResult","firstT","lastT","firstCurve","curves","adjustPredecessorControlPoint","obtainHandleLength","mainCurve","neighbourCurve","adjustNeighbourControlPoint","_mainCurve","mainPoint","mainControlPoint","neighbourPoint","neighbourControlPoint","obtainHandleLengths","_updateArcLengths","mainHandleBounds","neighbourHandleBounds","mainHandleLength","neighbourHandleLength","POSITIVE_INFINITY","NEGATIVE_INFINITY","getEvenDistributionVertices","toPathPoints","fromCurve","bPath","lastCurve","toReducedListRepresentation","digits","fromReducedListRepresentation","listJSON","pointArray","fromReducedList","bezierPath","CircleSector","startAngle","endAngle","circleBounds","candidates","containsAngle","wrappedAngle","wrappedStart","wrappedEnd","angleAt","circleSectorIntersection","sector","radicalLine","thisIntersectionAngleA","thisIntersectionAngleB","thatIntersectionAngleA","thatIntersectionAngleB","centerOfOriginalGap","resultSector","ray","ellipseIntersections","tmpLine","intersectionPoint","lineAngle","describeSVGPath","options","circleSectorUtils","describeSVGArc","polarToCartesian","centerX","centerY","moveToStart","end","start","firstHalf","secondHalf","largeArcFlag","sweepFlag","pathData","RAD_TO_DEG","drawutilssvg","svgNode","offset","canvasSize","fillShapes","drawConfig","isSecondary","gNode","bufferGNode","nodeDefs","bufferNodeDefs","nodeStyle","Boolean","drawlibConfiguration","cache","Map","setSize","bufferedNodeDefs","addStyleDefs","addDefsNode","createSVGNode","appendChild","rebuildStyleDefs","keys","bezier","ellipse","ellipseSector","circleSector","vector","image","text","rules","k","drawSettings","color","lineWidth","customStyleDefs","forEach","value","innerHTML","addCustomStyleDefs","defs","findElement","nodeName","node","get","toUpperCase","delete","document","createElementNS","makeNode","curId","blendMode","style","_bindFillDraw","strokeOptions","_configureNode","_bindNode","bindingParent","parentNode","_addCSSClasses","curClassName","setAttribute","fillMode","applyStrokeOpts","copyInstance","setConfiguration","configuration","setCurrentId","setCurrentClassName","beginDrawCycle","renderTime","clear","childNodes","child","getAttribute","removeAllChildNodes","endDrawCycle","replaceChild","tmpGNode","tmpDefsNode","dashArray","nodeSupportsLineDash","tagName","dashArayElem","dashOffset","_x","_y","makeLineNode","arrow","headLength","group","arrowHeadBasePosition","arrowHead","makeArrowHeadNode","cubicBezierArrow","makeCubicBezierNode","position","size","alpha","setImageSize","naturalWidth","ratioX","ratioY","naturalHeight","addEventListener","event","src","texturedPoly","textureImage","textureSize","polygonPosition","rotation","rotatedScalingOrigin","clipPathNode","clipPathId","imageNode","pathNode","clipNode","cubicBezier","cubicBezierPath","handle","square","handleLine","dot","circleArc","arcData","radiusX","radiusY","rect","grid","sizeX","sizeY","ceil","raster","diamondHandle","squareHandle","circleHandle","crosshair","cross","polyline","_a","_b","_c","lineHeight","fontSize","textAlign","transformOrigin","textNode","fontFamily","fontStyle","fontWeight","label","inplace","copyPathData","transformPathData","lastChild","removeChild","createSvg","data","copy","_stx","_sty","_sx","_sy","_slp","includes","classNameOverride","makePathNode","pathString","arrowHeadBasePositionBuffer","HEAD_XML","drawutils","context","ctx","setLineDash","dashArrayElem","lineDashOffset","_fillOrDraw","fillStyle","fill","strokeStyle","stroke","globalCompositeOperation","save","beginPath","lineTo","restore","complete","globalAlpha","drawImage","basePolygonBounds","targetTextureSize","targetTextureOffset","helpers","clipPoly","closePath","bezierCurveTo","quadraticBezier","controlPoint","quadraticCurveTo","arc","asSegment","relX","relY","font","indexOf","fillText","strokeText","Path2D","clearRect","canvas","fillRect","clip","drawutilsgl","gl","_zindex","glutils","GLU","_vertShader","compileShader","vertCode","VERTEX_SHADER","_fragShader","fragCode","FRAGMENT_SHADER","_program","makeProgram","vertex_buffer","createBuffer","_x2rel","_y2rel","Float32Array","bindBuffer","ARRAY_BUFFER","bufferData","STATIC_DRAW","coord","getAttribLocation","vertexAttribPointer","FLOAT","enableVertexAttribArray","viewport","uRotationVector","getUniformLocation","uniform2fv","drawArrays","LINES","TRIANGLE_FAN","clearColor","enable","DEPTH_TEST","COLOR_BUFFER_BIT","DEPTH_BUFFER_BIT","vbuffer","shaderCode","shaderType","shader","createShader","shaderSource","getShaderParameter","COMPILE_STATUS","getShaderInfoLog","deleteShader","vertShader","fragShader","program","createProgram","attachShader","linkProgram","useProgram","detachShader","Grid","baseLog","base","num","mapRasterScale","adjustFactor","gf","floor","KeyHandler","downListeners","pressListeners","upListeners","keyStates","element","globalThis","trackAllKeys","trackAll","installListeners","fireEvent","hasListener","lis","keyCode","fireDownEvent","handler","firePressEvent","fireUpEvent","key2code","KEY_CODES","_keyDownListener","_keyPressListener","_keyUpListener","releaseListeners","removeEventListener","down","press","up","isDown","break","backspace","tab","enter","shift","ctrl","alt","pause","capslock","hangul","hanja","escape","conversion","spacebar","pageup","pagedown","home","leftarrow","uparrow","rightarrow","downarrow","select","print","execute","printscreen","insert","help","f","g","m","o","q","r","z","windows","leftcommand","chromebooksearch","rightwindowkey","windowsmenu","rightcommant","sleep","numpad0","numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9","multiply","numpadperiod","subtract","decimalpoint","divide","f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","f12","f13","f14","f15","f16","f17","f18","f19","f20","f21","f22","f23","f24","numlock","scrolllock","$","pagebackward","pageforward","refresh","closingparen","minus","decreasevolumelevel","increasevolumelevel","previous","stop","email","mute","unmute","semicolon","equal","comma","dash","period","forwardslash","openbracket","backslash","closebracket","singlequote","altgr","XF86Forward","XF86Back","alphanumeric","hiragana","katakana","kanji","unlocktrackpad","toggletouchpad","XMouseEvent","MouseEvent","XWheelEvent","WheelEvent","MouseHandler","name","mouseDownPos","mouseDragPos","mouseButton","installed","handlers","mousemove","mkParams","relPos","mouseup","button","mousedown","wheel","offsetX","offsetY","eventName","rel","xEvent","isTouchEvent","pos","leftButton","middleButton","rightButton","draggedFrom","wasDragged","dragAmount","listenFor","unlistenFor","callback","throwAlreadyInstalled","PBImage","upperLeft","lowerRight","PBText","getLen","getRotateAngle","v2","mr","getAngle","HandlerAdmin","el","del","dispatch","_args","apply","arguments","wrapFunc","handlerAdmin","AlloyFinger","option","querySelector","bind","cancel","preV","pinchStartLen","zoom","isDoubleTap","noop","touchStart","multipointStart","multipointEnd","pinch","swipe","tap","doubleTap","longTap","singleTap","pressMove","twoFingerPressMove","touchMove","touchEnd","touchCancel","_cancelAllHandler","cancelAll","delta","last","now","tapTimeout","singleTapTimeout","longTapTimeout","swipeTimeout","preTapPosition","evt","touches","Date","pageX","pageY","clearTimeout","_cancelLongTap","_cancelSingleTap","_preventTap","setTimeout","afEvent","currentX","currentY","sCurrentX","sCurrentY","sx2","deltaX","deltaY","sy2","movedX","movedY","preventDefault","changedTouches","self","direction","_swipeDirection","on","off","VEllipse","axis","radiusH","signedRadiusH","radiusV","signedRadiusV","getExtremePoints","t_x1","t_x2","x_x1","y_x1","x_x2","y_x2","x_max","x_min","t_y1","t_y2","x_y1","y_y1","x_y2","y_y2","y_max","y_min","r1","r2","ux","uy","vx","vy","bbox_halfwidth","bbox_halfheight","normalAt","foci","getFoci","angleA","centerAngle","endPointA","endPointB","resultVector","rh","rv","sdiff","getEquidistantVertices","angles","equidistantVertAngles","ellipseCopy","rayCopy","rotationAmount","scalingFactors","toCubicBezier","quarterSegmentCount","segmentCount","curAngle","nextAngle","startTangent","endTangent","startDiff","endDiff","phiToTheta","phi","tanPhi","tan","tanPhi2","atan","theta","VEllipseSector","sAngle","eAngle","ellipseSectorUtils","normalizeAngle","r2d","fullEllipsePointCount","ellipseAngles","startIndex","findClosestToStartAngle","ea","endpointToCenterParameters","rx","ry","fa","fs","sinphi","cosphi","prx","pry","L","M","_cx","_cy","__setFunctionName","prefix","description","Object","defineProperty","configurable","PlotBoilerplate","config","contentChangeListeners","_gui","bezierAutoAdjust","fetch","fullSize","val","fitToParent","bool","rasterGrid","drawRaster","rasterScaleX","rasterScaleY","rasterAdjustFactor","drawOrigin","autoAdjustOffset","offsetAdjustXPercent","offsetAdjustYPercent","backgroundColor","redrawOnResize","defaultCanvasWidth","DEFAULT_CANVAS_WIDTH","defaultCanvasHeight","DEFAULT_CANVAS_HEIGHT","canvasWidthFactor","canvasHeightFactor","cssScaleX","cssScaleY","cssUniformScale","saveFile","hooks","setToRetina","_setToRetina","autoDetectRetina","enableSVGExport","preClear","func","preDraw","postDraw","enableMouse","enableTouch","enableKeys","enableMouseWheel","enableZoom","enablePan","enableGL","isBackdropFiltersEnabled","drawVertices","drawBezierHandleLines","drawBezierHandlePoints","drawHandleLines","drawHandlePoints","drawGrid","pathVertex","controlVertex","selectedVertex","canvasElement","toLowerCase","eventCatcher","getContext","draw","parentElement","createElement","left","top","cursor","body","title","selectPolygon","draggedElements","drawables","_saveFile","resizeCanvas","installInputListeners","updateCSSscale","redraw","focus","pb","tosvgDraw","tosvgFill","drawAll","svgCode","XMLSerializer","serializeToString","blob","Blob","type","_saveAs","pixelRatio","devicePixelRatio","fitToView","canvasCenter","canvasRatio","ratio","setOffset","newUniformZoom","setZoom","setConsole","con","_d","_e","setCSSscale","addContentChangeListener","removeContentChangeListener","_fireContentChanged","addedDrawables","removedDrawables","drawable","doNotFireEvent","enableBezierPathAutoAdjust","remove","removeWithVertices","wasRemoved","removeVertex","removeAll","keepVertices","triggerRedraw","getVertexNear","pixelPosition","pixelTolerance","locatePointNear","transformMousePosition","typeName","vindex","gScale","gSize","cs","_handleColor","drawDrawables","drawDrawable","df","error","drawSelectPolygon","clearSelection","getFProp","elem","propName","parseFloat","getComputedStyle","getPropertyValue","getAvailableContainerSpace","container","display","padding","border","pl","pr","pt","bl","br","bt","bb","clientWidth","clientHeight","_f","_g","_setSize","HTMLCanvasElement","SVGElement","adjustOffset","innerWidth","documentElement","innerHeight","space","selectVerticesInPolygon","Draggable","VERTEX","setVIndex","handleClick","DEFAULT_CLICK_TOLERANCE","keyHandler","paths","pindex","cindex","pid","revertMousePosition","getDraggedElementCount","mouseDownHandler","draggablePoint","mouseDragHandler","oldDragAmount","mouseUpHandler","mouseWheelHandler","zoomStep","we","newOffset","zoomFactorX","zoomFactorY","interactionPos","oldPos","newPos","newOffsetX","newOffsetY","getBoundingClientRect","touchMovePos","touchDownPos","draggedElement","multiTouchStartScale","clearTouch","afProps","clientX","clientY","DEFAULT_TOUCH_TOLERANCE","draggingVertex","fakeEvent","stopPropagation","trans","touchItem0","item","touchItem1","fingerA","fingerB","window","createAlloyFinger","createGUI","props","getGUI","isVertex","safeMergeByKeys","extension","hasOwnProperty","typ","extVal","removeProperty","transform","fallback"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.min.js","sources":["../src/esm/VertexAttr.js","../src/esm/UIDGenerator.js","../src/esm/VertexListeners.js","../src/esm/Circle.js","../src/esm/Triangle.js","../src/esm/geomutils.js","../src/esm/Vertex.js","../src/esm/VertTuple.js","../src/esm/Vector.js","../src/esm/Line.js","../src/esm/Polygon.js","../src/esm/Bounds.js","../src/esm/CubicBezierCurve.js","../src/esm/BezierPath.js","../src/esm/CircleSector.js","../src/esm/drawutilssvg.js","../src/esm/draw.js","../src/esm/drawgl.js","../src/esm/Grid.js","../src/esm/KeyHandler.js","../src/esm/MouseHandler.js","../src/esm/PBImage.js","../src/esm/PBText.js","../node_modules/alloyfinger-typescript/src/esm/alloy_finger.js","../src/esm/VEllipse.js","../src/esm/VEllipseSector.js","../src/esm/PlotBoilerplate.js"],"sourcesContent":["/**\n * @author Ikaros Kappler\n * @date 2018-08-26\n * @modified 2018-11-17 Added the 'isSelected' attribute.\n * @modified 2018-11-27 Added the global model for instantiating with custom attributes.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2020-02-29 Added the 'selectable' attribute.\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2024-03-10 Fixed some types for Typescript 5 compatibility.\n * @version 1.1.2\n *\n * @file VertexAttr\n * @public\n **/\n/**\n * @classdesc The VertexAttr is a helper class to wrap together additional attributes\n * to vertices that do not belong to the 'standard canonical' vertex implementation.<br>\n * <br>\n * This is some sort of 'userData' object, but the constructor uses a global model\n * to obtain a (configurable) default attribute set to all instances.<br>\n */\nexport class VertexAttr {\n /**\n * The constructor.\n *\n * Attributes will be initialized as defined in the model object\n * which serves as a singleton.\n *\n * @constructor\n * @name VertexAttr\n **/\n constructor() {\n this.draggable = true;\n this.selectable = true;\n this.isSelected = false;\n this.visible = true;\n for (var key in VertexAttr.model)\n this[key] = VertexAttr.model[key];\n }\n ;\n}\n/**\n * This is the global attribute model. Set these object on the initialization\n * of your app to gain all VertexAttr instances have these attributes.\n *\n * @type {object}\n **/\nVertexAttr.model = {\n draggable: true,\n selectable: true,\n isSelected: false,\n visible: true\n};\n//# sourceMappingURL=VertexAttr.js.map","/**\n * @classdesc A static UIDGenerator.\n *\n * @author Ikaros Kappler\n * @date 2021-01-20\n * @version 1.0.0\n */\nexport class UIDGenerator {\n static next() {\n return `${UIDGenerator.current++}`;\n }\n}\nUIDGenerator.current = 0;\n//# sourceMappingURL=UIDGenerator.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-08-27\n * @modified 2018-11-28 Added the vertex-param to the constructor and extended the event. Vertex events now have a 'params' attribute object.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2020-02-22 Added 'return this' to the add* functions (for chanining).\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2020-11-17 Added the `click` handler.\n * @version 1.1.0\n *\n * @file VertexListeners\n * @public\n **/\n/**\n * @classdesc An event listeners wrapper. This is just a set of three listener\n * queues (drag, dragStart, dragEnd) and their respective firing\n * functions.\n *\n */\nexport class VertexListeners {\n /**\n * The constructor.\n *\n * @constructor\n * @name VertexListeners\n * @param {Vertex} vertex - The vertex to use these listeners on (just a backward reference).\n **/\n constructor(vertex) {\n this.click = [];\n this.drag = [];\n this.dragStart = [];\n this.dragEnd = [];\n this.vertex = vertex;\n }\n /**\n * Add a click listener.\n *\n * @method addClickListener\n * @param {VertexListeners~dragListener} listener - The click listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addClickListener(listener) {\n VertexListeners._addListener(this.click, listener);\n return this;\n }\n /**\n * The click listener is a function with a single drag event param.\n * @callback VertexListeners~clickListener\n * @param {Event} e - The (extended) click event.\n */\n /**\n * Remove a drag listener.\n *\n * @method removeDragListener\n * @param {VertexListeners~dragListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeClickListener(listener) {\n this.click = VertexListeners._removeListener(this.click, listener);\n return this;\n }\n /**\n * The click listener is a function with a single drag event param.\n * @callback VertexListeners~clickListener\n * @param {Event} e - The (extended) click event.\n */\n /**\n * Add a drag listener.\n *\n * @method addDragListener\n * @param {VertexListeners~dragListener} listener - The drag listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addDragListener(listener) {\n VertexListeners._addListener(this.drag, listener);\n return this;\n }\n /**\n * The drag listener is a function with a single drag event param.\n * @callback VertexListeners~dragListener\n * @param {Event} e - The (extended) drag event.\n */\n /**\n * Remove a drag listener.\n *\n * @method removeDragListener\n * @param {VertexListeners~dragListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeDragListener(listener) {\n this.drag = VertexListeners._removeListener(this.drag, listener);\n return this;\n }\n /**\n * Add a dragStart listener.\n *\n * @method addDragListener\n * @param {VertexListeners~dragStartListener} listener - The drag-start listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addDragStartListener(listener) {\n VertexListeners._addListener(this.dragStart, listener);\n return this;\n }\n /**\n * The drag-start listener is a function with a single drag event param.\n * @callback VertexListeners~dragStartListener\n * @param {Event} e - The (extended) drag event.\n */\n /**\n * Remove a dragStart listener.\n *\n * @method addDragStartListener\n * @param {VertexListeners~dragListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeDragStartListener(listener) {\n this.dragStart = VertexListeners._removeListener(this.dragStart, listener);\n return this;\n }\n /**\n * Add a dragEnd listener.\n *\n * @method addDragListener\n * @param {VertexListeners~dragEndListener} listener - The drag-end listener to add (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n addDragEndListener(listener) {\n // this.dragEnd.push( listener );\n VertexListeners._addListener(this.dragEnd, listener);\n return this;\n }\n /**\n * The drag-end listener is a function with a single drag event param.\n * @callback VertexListeners~dragEndListener\n * @param {Event} e - The (extended) drag event.\n */\n /**\n * Remove a drag listener.\n *\n * @method removeDragEndListener\n * @param {VertexListeners~clickListener} listener - The drag listener to remove (a callback).\n * @return {VertexListeners} this (for chaining)\n * @instance\n * @memberof VertexListeners\n **/\n removeDragEndListener(listener) {\n // this.drag.push( listener );\n this.dragEnd = VertexListeners._removeListener(this.dragEnd, listener);\n return this;\n }\n /**\n * Fire a click event with the given event instance to all\n * installed click listeners.\n *\n * @method fireClickEvent\n * @param {VertEvent|XMouseEvent} e - The click event itself to be fired to all installed drag listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireClickEvent(e) {\n VertexListeners._fireEvent(this, this.click, e);\n }\n /**\n * Fire a drag event with the given event instance to all\n * installed drag listeners.\n *\n * @method fireDragEvent\n * @param {VertEvent|XMouseEvent} e - The drag event itself to be fired to all installed drag listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireDragEvent(e) {\n VertexListeners._fireEvent(this, this.drag, e);\n }\n /**\n * Fire a dragStart event with the given event instance to all\n * installed drag-start listeners.\n *\n * @method fireDragStartEvent\n * @param {VertEvent|XMouseEvent} e - The drag-start event itself to be fired to all installed dragStart listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireDragStartEvent(e) {\n VertexListeners._fireEvent(this, this.dragStart, e);\n }\n /**\n * Fire a dragEnd event with the given event instance to all\n * installed drag-end listeners.\n *\n * @method fireDragEndEvent\n * @param {VertEvent|XMouseEvent} e - The drag-end event itself to be fired to all installed dragEnd listeners.\n * @return {void}\n * @instance\n * @memberof VertexListeners\n **/\n fireDragEndEvent(e) {\n VertexListeners._fireEvent(this, this.dragEnd, e);\n }\n /**\n * Removes all listeners from this listeners object.\n */\n removeAllListeners() {\n this.click = [];\n this.drag = [];\n this.dragStart = [];\n this.dragEnd = [];\n }\n /**\n * @private\n **/\n static _fireEvent(_self, listeners, e) {\n const ve = e;\n if (typeof ve.params == \"undefined\")\n ve.params = { vertex: _self.vertex };\n else\n ve.params.vertex = _self.vertex;\n for (var i in listeners) {\n listeners[i](ve);\n }\n }\n /**\n * @private\n */\n static _addListener(listeners, newListener) {\n for (var i in listeners) {\n if (listeners[i] == newListener)\n return false;\n }\n listeners.push(newListener);\n return true;\n }\n /**\n * @private\n */\n static _removeListener(listeners, oldListener) {\n for (var i = 0; i < listeners.length; i++) {\n if (listeners[i] == oldListener)\n return listeners.splice(i, 1);\n }\n return listeners;\n }\n}\n//# sourceMappingURL=VertexListeners.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-05-04\n * @modified 2020-05-09 Ported to typescript.\n * @modified 2020-05-25 Added the vertAt and tangentAt functions.\n * @mofidied 2020-09-07 Added the circleIntersection(Circle) function.\n * @modified 2020-09-07 Changed the vertAt function by switching sin and cos! The old version did not return the correct vertex (by angle) accoring to the assumed circle math.\n * @modified 2020-10-16 Added the containsCircle(...) function.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-08-15 Added the `containsPoint` function.\n * @modified 2022-08-23 Added the `lineIntersection` function.\n * @modified 2022-08-23 Added the `closestPoint` function.\n * @modified 2025-04-09 Added the `Circle.move(amount: XYCoords)` method.\n * @modified 2025-04-16 Class `Circle` now implements interface `Intersectable`.\n * @version 1.5.0\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Line } from \"./Line\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A simple circle: center point and radius.\n *\n * @requires Line\n * @requires Vector\n * @requires VertTuple\n * @requires Vertex\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class Circle {\n /**\n * Create a new circle with given center point and radius.\n *\n * @constructor\n * @name Circle\n * @param {Vertex} center - The center point of the circle.\n * @param {number} radius - The radius of the circle.\n */\n constructor(center, radius) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Circle\";\n this.uid = UIDGenerator.next();\n this.center = center;\n this.radius = radius;\n }\n /**\n * Move the circle by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof Circle\n * @return {Circle} this for chaining\n **/\n move(amount) {\n this.center.add(amount);\n return this;\n }\n /**\n * Check if the given circle is fully contained inside this circle.\n *\n * @method containsPoint\n * @param {XYCoords} point - The point to check if it is contained in this circle.\n * @instance\n * @memberof Circle\n * @return {boolean} `true` if the given point is inside this circle.\n */\n containsPoint(point) {\n return this.center.distance(point) < this.radius;\n }\n /**\n * Check if the given circle is fully contained inside this circle.\n *\n * @method containsCircle\n * @param {Circle} circle - The circle to check if it is contained in this circle.\n * @instance\n * @memberof Circle\n * @return {boolean} `true` if any only if the given circle is completely inside this circle.\n */\n containsCircle(circle) {\n return this.center.distance(circle.center) + circle.radius < this.radius;\n }\n /**\n * Calculate the distance from this circle to the given line.\n *\n * * If the line does not intersect this ciecle then the returned\n * value will be the minimal distance.\n * * If the line goes through this circle then the returned value\n * will be max inner distance and it will be negative.\n *\n * @method lineDistance\n * @param {Line} line - The line to measure the distance to.\n * @return {number} The minimal distance from the outline of this circle to the given line.\n * @instance\n * @memberof Circle\n */\n lineDistance(line) {\n const closestPointOnLine = line.getClosestPoint(this.center);\n return closestPointOnLine.distance(this.center) - this.radius;\n }\n /**\n * Get the vertex on the this circle for the given angle.\n *\n * @method vertAt\n * @param {number} angle - The angle (in radians) to use.\n * @return {Vertex} The vertex (point) at the given angle.\n * @instance\n * @memberof Circle\n **/\n vertAt(angle) {\n // Find the point on the circle respective the angle. Then move relative to center.\n return Circle.circleUtils.vertAt(angle, this.radius).add(this.center);\n }\n /**\n * Get a tangent line of this circle for a given angle.\n *\n * Point a of the returned line is located on the circle, the length equals the radius.\n *\n * @method tangentAt\n * @instance\n * @param {number} angle - The angle (in radians) to use.\n * @return {Line} The tangent line.\n * @memberof Circle\n **/\n tangentAt(angle) {\n const pointA = Circle.circleUtils.vertAt(angle, this.radius);\n // Construct the perpendicular of the line in point a. Then move relative to center.\n return new Vector(pointA, new Vertex(0, 0)).add(this.center).perp();\n // return (new Vector(this.center.clone(), pointA).add(pointA) as Vector).perp() as Vector;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the bounding box (bounds) of this Circle.\n *\n * @method getBounds\n * @instance\n * @memberof Circle\n * @return {Bounds} The rectangular bounds of this Circle.\n **/\n getBounds() {\n return new 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)));\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Calculate the intersection points (if exists) with the given circle.\n *\n * @method circleIntersection\n * @instance\n * @memberof Circle\n * @param {Circle} circle\n * @return {Line|null} The intersection points (as a line) or null if the two circles do not intersect.\n **/\n circleIntersection(circle) {\n // Circles do not intersect at all?\n if (this.center.distance(circle.center) > this.radius + circle.radius) {\n return null;\n }\n // One circle is fully inside the other?\n if (this.center.distance(circle.center) < Math.abs(this.radius - circle.radius)) {\n return null;\n }\n // Based on the C++ implementation by Robert King\n // https://stackoverflow.com/questions/3349125/circle-circle-intersection-points\n // and the 'Circles and spheres' article by Paul Bourke.\n // http://paulbourke.net/geometry/circlesphere/\n //\n // This is the original C++ implementation:\n //\n // pair<Point, Point> intersections(Circle c) {\n // Point P0(x, y);\n // Point P1(c.x, c.y);\n // float d, a, h;\n // d = P0.distance(P1);\n // a = (r*r - c.r*c.r + d*d)/(2*d);\n // h = sqrt(r*r - a*a);\n // Point P2 = P1.sub(P0).scale(a/d).add(P0);\n // float x3, y3, x4, y4;\n // x3 = P2.x + h*(P1.y - P0.y)/d;\n // y3 = P2.y - h*(P1.x - P0.x)/d;\n // x4 = P2.x - h*(P1.y - P0.y)/d;\n // y4 = P2.y + h*(P1.x - P0.x)/d;\n // return pair<Point, Point>(Point(x3, y3), Point(x4, y4));\n // }\n var p0 = this.center;\n var p1 = circle.center;\n var d = p0.distance(p1);\n var a = (this.radius * this.radius - circle.radius * circle.radius + d * d) / (2 * d);\n var h = Math.sqrt(this.radius * this.radius - a * a);\n var p2 = p1.clone().scale(a / d, p0);\n var x3 = p2.x + (h * (p1.y - p0.y)) / d;\n var y3 = p2.y - (h * (p1.x - p0.x)) / d;\n var x4 = p2.x - (h * (p1.y - p0.y)) / d;\n var y4 = p2.y + (h * (p1.x - p0.x)) / d;\n return new Line(new Vertex(x3, y3), new Vertex(x4, y4));\n }\n /**\n * Calculate the intersection points (if exists) with the given infinite line (defined by two points).\n *\n * @method lineIntersection\n * @instance\n * @memberof Circle\n * @param {Vertex} a- The first of the two points defining the line.\n * @param {XYCoords} b - The second of the two points defining the line.\n * @return {Line|null} The intersection points (as a line) or null if this circle does not intersect the line given.\n **/\n lineIntersection(a, b) {\n // Based on the math from\n // https://mathworld.wolfram.com/Circle-LineIntersection.html\n const interA = new Vertex();\n const interB = new Vertex();\n // First do a transformation, because the calculation is based on a cicle at (0,0)\n const transA = new Vertex(a).sub(this.center);\n const transB = new Vertex(b).sub(this.center);\n const diff = transA.difference(transB);\n // There is a special case if diff.y=0, where the intersection is not calcuatable.\n // Use an non-zero epsilon here to approximate this case.\n // TODO for the future: find a better solution\n if (Math.abs(diff.y) === 0) {\n diff.y = 0.000001;\n }\n const dist = transA.distance(transB);\n const det = transA.x * transB.y - transA.y * transB.x;\n const distSquared = dist * dist;\n const radiusSquared = this.radius * this.radius;\n // Check if circle and line have an intersection at all\n if (radiusSquared * distSquared - det * det < 0) {\n return null;\n }\n const belowSqrt = this.radius * this.radius * dist * dist - det * det;\n const sqrt = Math.sqrt(belowSqrt);\n interA.x = (det * diff.y + Math.sign(diff.y) * diff.x * sqrt) / distSquared;\n interB.x = (det * diff.y - Math.sign(diff.y) * diff.x * sqrt) / distSquared;\n interA.y = (-det * diff.x + Math.abs(diff.y) * sqrt) / distSquared;\n interB.y = (-det * diff.x - Math.abs(diff.y) * sqrt) / distSquared;\n return new Line(interA.add(this.center), interB.add(this.center));\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this circle.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections with the circle outline.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n const intersectioLine = this.lineIntersection(line.a, line.b);\n if (!intersectioLine) {\n return [];\n }\n if (inVectorBoundsOnly) {\n // const maxDist = line.length();\n return [intersectioLine.a, intersectioLine.b].filter((vert) => line.hasPoint(vert, true));\n }\n else {\n return [intersectioLine.a, intersectioLine.b];\n }\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.center, vert);\n const angle = lineFromCenter.angle();\n // console.log(\"angle\", (angle / Math.PI) * 180.0);\n // const angle = Math.random() * Math.PI * 2; // TODO\n // Calculate tangent at angle\n return this.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Calculate the closest point on the outline of this circle to the given point.\n *\n * @method closestPoint\n * @instance\n * @memberof Circle\n * @param {XYCoords} vert - The point to find the closest circle point for.\n * @return {Vertex} The closest point on this circle.\n **/\n closestPoint(vert) {\n const lineIntersection = this.lineIntersection(this.center, vert);\n if (!lineIntersection) {\n // Note: this case should not happen as a radial from the center always intersect this circle.\n return new Vertex();\n }\n // Return closed of both\n if (lineIntersection.a.distance(vert) < lineIntersection.b.distance(vert)) {\n return lineIntersection.a;\n }\n else {\n return lineIntersection.b;\n }\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.center.destroy();\n this.isDestroyed = true;\n }\n} // END class\nCircle.circleUtils = {\n vertAt: (angle, radius) => {\n /* return new Vertex( Math.sin(angle) * radius,\n Math.cos(angle) * radius ); */\n return new Vertex(Math.cos(angle) * radius, Math.sin(angle) * radius);\n }\n};\n//# sourceMappingURL=Circle.js.map","/**\n * @author Ikaros Kappler\n * @date_init 2012-10-17 (Wrote a first version of this in that year).\n * @date 2018-04-03 (Refactored the code into a new class).\n * @modified 2018-04-28 Added some documentation.\n * @modified 2019-09-11 Added the scaleToCentroid(Number) function (used by the walking triangle demo).\n * @modified 2019-09-12 Added beautiful JSDoc compliable comments.\n * @modified 2019-11-07 Added to toSVG(options) function to make Triangles renderable as SVG.\n * @modified 2019-12-09 Fixed the determinant() function. The calculation was just wrong.\n * @modified 2020-03-16 (Corona times) Added the 'fromArray' function.\n * @modified 2020-03-17 Added the Triangle.toPolygon() function.\n * @modified 2020-03-17 Added proper JSDoc comments.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-05-09 Added the new Circle class (ported to Typescript from the demos).\n * @modified 2020-05-12 Added getIncircularTriangle() function.\n * @modified 2020-05-12 Added getIncircle() function.\n * @modified 2020-05-12 Fixed the signature of getCircumcirle(). Was still a generic object.\n * @modified 2020-06-18 Added the `getIncenter` function.\n * @modified 2020-12-28 Added the `getArea` function.\n * @modified 2021-01-20 Added UID.\n * @modified 2021-01-22 Always updating circumcircle when retieving it.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Triangle.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2024-11-22 Added static utility function Triangle.utils.determinant; adapted method `determinant`.\n * @modified 2024-11-22 Changing visibility of `Triangle.utils` from `private` to `public`.\n * @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.\n * @modified 2025-14-16 Class `Triangle` now implements interface `IBounded`.\n * @modified 2025-14-16 Class `Triangle` now implements interface `Intersectable`.\n * @modified 2025-14-16 Added method `Triangle.move`.\n * @version 2.10.0\n *\n * @file Triangle\n * @fileoverview A simple triangle class: three vertices.\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Circle } from \"./Circle\";\nimport { Line } from \"./Line\";\nimport { Polygon } from \"./Polygon\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { geomutils } from \"./geomutils\";\n/**\n * @classdesc A triangle class for triangulations.\n *\n * The class was written for a Delaunay trinagulation demo so it might\n * contain some strange and unexpected functions.\n *\n * @requires Bounds\n * @requires Circle\n * @requires Line\n * @requires Vertex\n * @requires Polygon\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n * @requires geomutils\n *\n */\nexport class Triangle {\n /**\n * The constructor.\n *\n * @constructor\n * @name Triangle\n * @param {Vertex} a - The first vertex of the triangle.\n * @param {Vertex} b - The second vertex of the triangle.\n * @param {Vertex} c - The third vertex of the triangle.\n **/\n constructor(a, b, c) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Triangle\";\n this.uid = UIDGenerator.next();\n this.a = a;\n this.b = b;\n this.c = c;\n this.calcCircumcircle();\n }\n /**\n * Create a new triangle from the given array of vertices.\n *\n * The array must have at least three vertices, otherwise an error will be raised.\n * This function will not create copies of the vertices.\n *\n * @method fromArray\n * @static\n * @param {Array<Vertex>} arr - The required array with at least three vertices.\n * @memberof Vertex\n * @return {Triangle}\n **/\n static fromArray(arr) {\n if (arr.length < 3)\n throw `Cannot create triangle from array with less than three vertices (${arr.length})`;\n return new Triangle(arr[0], arr[1], arr[2]);\n }\n /**\n * Get the area of this triangle. The returned area is never negative.\n *\n * If you are interested in the signed area, please consider using the\n * `Triangle.utils.signedArea` helper function. This method just returns\n * the absolute value of the signed area.\n *\n * @method getArea\n * @instance\n * @memberof Triangle\n * @return {number} The non-negative area of this triangle.\n */\n getArea() {\n return Math.abs(Triangle.utils.signedArea(this.a.x, this.a.y, this.b.x, this.b.y, this.c.x, this.c.y));\n }\n /**\n * Get the centroid of this triangle.\n *\n * The centroid is the average midpoint for each side.\n *\n * @method getCentroid\n * @return {Vertex} The centroid\n * @instance\n * @memberof Triangle\n **/\n getCentroid() {\n return new Vertex((this.a.x + this.b.x + this.c.x) / 3, (this.a.y + this.b.y + this.c.y) / 3);\n }\n /**\n * Scale the triangle towards its centroid.\n *\n * @method scaleToCentroid\n * @param {number} - The scale factor to use. That can be any scalar.\n * @return {Triangle} this (for chaining)\n * @instance\n * @memberof Triangle\n */\n scaleToCentroid(factor) {\n let centroid = this.getCentroid();\n this.a.scale(factor, centroid);\n this.b.scale(factor, centroid);\n this.c.scale(factor, centroid);\n return this;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this Triangle.\n *\n * @method getBounds\n * @instance\n * @memberof Triangle\n * @return {Bounds} The rectangular bounds of this Triangle.\n **/\n getBounds() {\n // return Bounds.computeFromVertices([this.a, this.b, this.c]);\n return this.bounds();\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Move the Triangle's vertices by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof Triangle\n * @return {Triangle} this for chaining\n **/\n move(amount) {\n this.a.add(amount);\n this.b.add(amount);\n this.c.add(amount);\n return this;\n }\n /**\n * Get the circumcircle of this triangle.\n *\n * The circumcircle is that unique circle on which all three\n * vertices of this triangle are located on.\n *\n * Please note that for performance reasons any changes to vertices will not reflect in changes\n * of the circumcircle (center or radius). Please call the calcCirumcircle() function\n * after triangle vertex changes.\n *\n * @method getCircumcircle\n * @return {Object} - { center:Vertex, radius:float }\n * @instance\n * @memberof Triangle\n */\n getCircumcircle() {\n // if( !this.center || !this.radius )\n this.calcCircumcircle();\n return new Circle(this.center.clone(), this.radius);\n }\n /**\n * Check if this triangle and the passed triangle share an\n * adjacent edge.\n *\n * For edge-checking Vertex.equals is used which uses an\n * an epsilon for comparison.\n *\n * @method isAdjacent\n * @param {Triangle} tri - The second triangle to check adjacency with.\n * @return {boolean} - True if this and the passed triangle have at least one common edge.\n * @instance\n * @memberof Triangle\n */\n isAdjacent(tri) {\n var a = this.a.equals(tri.a) || this.a.equals(tri.b) || this.a.equals(tri.c);\n var b = this.b.equals(tri.a) || this.b.equals(tri.b) || this.b.equals(tri.c);\n var c = this.c.equals(tri.a) || this.c.equals(tri.b) || this.c.equals(tri.c);\n return (a && b) || (a && c) || (b && c);\n }\n /**\n * Get that vertex of this triangle (a,b,c) that is not vert1 nor vert2 of\n * the passed two.\n *\n * @method getThirdVertex\n * @param {Vertex} vert1 - The first vertex.\n * @param {Vertex} vert2 - The second vertex.\n * @return {Vertex} - The third vertex of this triangle that makes up the whole triangle with vert1 and vert2.\n * @instance\n * @memberof Triangle\n */\n getThirdVertex(vert1, vert2) {\n if ((this.a.equals(vert1) && this.b.equals(vert2)) || (this.a.equals(vert2) && this.b.equals(vert1)))\n return this.c;\n if ((this.b.equals(vert1) && this.c.equals(vert2)) || (this.b.equals(vert2) && this.c.equals(vert1)))\n return this.a;\n //if( this.c.equals(vert1) && this.a.equals(vert2) || this.c.equals(vert2) && this.a.equals(vert1) )\n return this.b;\n }\n /**\n * Re-compute the circumcircle of this triangle (if the vertices\n * have changed).\n *\n * The circumcenter and radius are stored in this.center and\n * this.radius. There is a third result: radius_squared (for internal computations).\n *\n * @method calcCircumcircle\n * @return void\n * @instance\n * @memberof Triangle\n */\n calcCircumcircle() {\n // From\n // http://www.exaflop.org/docs/cgafaq/cga1.html\n const A = this.b.x - this.a.x;\n const B = this.b.y - this.a.y;\n const C = this.c.x - this.a.x;\n const D = this.c.y - this.a.y;\n const E = A * (this.a.x + this.b.x) + B * (this.a.y + this.b.y);\n const F = C * (this.a.x + this.c.x) + D * (this.a.y + this.c.y);\n const G = 2.0 * (A * (this.c.y - this.b.y) - B * (this.c.x - this.b.x));\n let dx, dy;\n if (Math.abs(G) < Triangle.EPSILON) {\n // Collinear - find extremes and use the midpoint\n const bounds = this.bounds();\n this.center = new Vertex((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2);\n dx = this.center.x - bounds.min.x;\n dy = this.center.y - bounds.min.y;\n }\n else {\n const cx = (D * E - B * F) / G;\n const cy = (A * F - C * E) / G;\n this.center = new Vertex(cx, cy);\n dx = this.center.x - this.a.x;\n dy = this.center.y - this.a.y;\n }\n this.radius_squared = dx * dx + dy * dy;\n this.radius = Math.sqrt(this.radius_squared);\n } // END calcCircumcircle\n /**\n * Check if the passed vertex is inside this triangle's\n * circumcircle.\n *\n * @method inCircumcircle\n * @param {Vertex} v - The vertex to check.\n * @return {boolean}\n * @instance\n * @memberof Triangle\n */\n inCircumcircle(v) {\n const dx = this.center.x - v.x;\n const dy = this.center.y - v.y;\n const dist_squared = dx * dx + dy * dy;\n return dist_squared <= this.radius_squared;\n }\n /**\n * Get the rectangular bounds for this triangle.\n *\n * @method bounds\n * @return {Bounds} - The min/max bounds of this triangle.\n * @instance\n * @memberof Triangle\n */\n bounds() {\n return new Bounds(new Vertex(Triangle.utils.min3(this.a.x, this.b.x, this.c.x), Triangle.utils.min3(this.a.y, this.b.y, this.c.y)), new Vertex(Triangle.utils.max3(this.a.x, this.b.x, this.c.x), Triangle.utils.max3(this.a.y, this.b.y, this.c.y)));\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this polygon.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n return Polygon.utils\n .locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)\n .map(intersectionTuple => intersectionTuple.intersection);\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n return Polygon.utils\n .locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)\n .map(intersectionTuple => {\n // const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection);\n });\n }\n //--- END --- Implement interface `Intersectable`\n getEdgeAt(edgeIndex) {\n var modIndex = edgeIndex % 3;\n return modIndex === 0 ? new Line(this.a, this.b) : modIndex === 1 ? new Line(this.b, this.c) : new Line(this.c, this.a);\n }\n /**\n * Convert this triangle to a polygon instance.\n *\n * Plase note that this conversion does not perform a deep clone.\n *\n * @method toPolygon\n * @return {Polygon} A new polygon representing this triangle.\n * @instance\n * @memberof Triangle\n **/\n toPolygon() {\n return new Polygon([this.a, this.b, this.c]);\n }\n /**\n * Get the determinant of this triangle.\n *\n * @method determinant\n * @return {number} - The determinant (float).\n * @instance\n * @memberof Triangle\n */\n determinant() {\n // (b.y - a.y)*(c.x - b.x) - (c.y - b.y)*(b.x - a.x);\n // 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);\n return Triangle.utils.determinant(this.a, this.b, this.c);\n }\n /**\n * Checks if the passed vertex (p) is inside this triangle.\n *\n * Note: matrix determinants rock.\n *\n * @method containsPoint\n * @param {Vertex} p - The vertex to check.\n * @return {boolean}\n * @instance\n * @memberof Triangle\n */\n containsPoint(p) {\n return Triangle.utils.pointIsInTriangle(p.x, p.y, this.a.x, this.a.y, this.b.x, this.b.y, this.c.x, this.c.y);\n }\n /**\n * Get that inner triangle which defines the maximal incircle.\n *\n * @return {Triangle} The triangle of those points in this triangle that define the incircle.\n */\n getIncircularTriangle() {\n const lineA = new Line(this.a, this.b);\n const lineB = new Line(this.b, this.c);\n const lineC = new Line(this.c, this.a);\n const bisector1 = geomutils.nsectAngle(this.b, this.a, this.c, 2)[0]; // bisector of first angle (in b)\n const bisector2 = geomutils.nsectAngle(this.c, this.b, this.a, 2)[0]; // bisector of second angle (in c)\n // Cast to non-null here because we know there _is_ an intersection\n const intersection = bisector1.intersection(bisector2);\n // Find the closest points on one of the polygon lines (all have same distance by construction)\n const circleIntersA = lineA.getClosestPoint(intersection);\n const circleIntersB = lineB.getClosestPoint(intersection);\n const circleIntersC = lineC.getClosestPoint(intersection);\n return new Triangle(circleIntersA, circleIntersB, circleIntersC);\n }\n /**\n * Get the incircle of this triangle. That is the circle that touches each side\n * of this triangle in exactly one point.\n *\n * Note this just calls getIncircularTriangle().getCircumcircle()\n *\n * @return {Circle} The incircle of this triangle.\n */\n getIncircle() {\n return this.getIncircularTriangle().getCircumcircle();\n }\n /**\n * Get the incenter of this triangle (which is the center of the circumcircle).\n *\n * Note: due to performance reasonst the incenter is buffered inside the triangle because\n * computing it is relatively expensive. If a, b or c have changed you should call the\n * calcCircumcircle() function first, otherwise you might get wrong results.\n * @return Vertex The incenter of this triangle.\n **/\n getIncenter() {\n if (!this.center || !this.radius)\n this.calcCircumcircle();\n return this.center.clone();\n }\n /**\n * Converts this triangle into a human-readable string.\n *\n * @method toString\n * @return {string}\n * @instance\n * @memberof Triangle\n */\n toString() {\n return \"{ a : \" + this.a.toString() + \", b : \" + this.b.toString() + \", c : \" + this.c.toString() + \"}\";\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.a.destroy();\n this.b.destroy();\n this.c.destroy();\n this.isDestroyed = true;\n }\n}\n/**\n * An epsilon for comparison.\n * This should be the same epsilon as in Vertex.\n *\n * @private\n **/\nTriangle.EPSILON = 1.0e-6;\nTriangle.utils = {\n // Used in the bounds() function.\n max3(a, b, c) {\n return a >= b && a >= c ? a : b >= a && b >= c ? b : c;\n },\n min3(a, b, c) {\n return a <= b && a <= c ? a : b <= a && b <= c ? b : c;\n },\n signedArea(p0x, p0y, p1x, p1y, p2x, p2y) {\n return 0.5 * (-p1y * p2x + p0y * (-p1x + p2x) + p0x * (p1y - p2y) + p1x * p2y);\n },\n /**\n * Used by the containsPoint() function.\n *\n * @private\n **/\n pointIsInTriangle(px, py, p0x, p0y, p1x, p1y, p2x, p2y) {\n //\n // Point-in-Triangle test found at\n // http://stackoverflow.com/questions/2049582/how-to-determine-a-point-in-a-2d-triangle\n // var area : number = 1/2*(-p1y*p2x + p0y*(-p1x + p2x) + p0x*(p1y - p2y) + p1x*p2y);\n var area = Triangle.utils.signedArea(p0x, p0y, p1x, p1y, p2x, p2y);\n var s = (1 / (2 * area)) * (p0y * p2x - p0x * p2y + (p2y - p0y) * px + (p0x - p2x) * py);\n var t = (1 / (2 * area)) * (p0x * p1y - p0y * p1x + (p0y - p1y) * px + (p1x - p0x) * py);\n return s > 0 && t > 0 && 1 - s - t > 0;\n },\n /**\n * Calculate the determinant of the three vertices a, b and c (in this order).\n * @param {XYCords} a - The first vertex.\n * @param {XYCords} b - The first vertex.\n * @param {XYCords} c - The first vertex.\n * @returns {nmber}\n */\n determinant(a, b, c) {\n return (b.y - a.y) * (c.x - b.x) - (c.y - b.y) * (b.x - a.x);\n }\n};\n//# sourceMappingURL=Triangle.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-02-03\n * @modified 2021-03-01 Added `wrapMax` function.\n * @modified 2024-11-15 Adding helper function `geomutils.mapAngleTo2PI(number)` for mapping any value into the interval [0,2*PI).\n * @modified 2024-11-22 Adding helper function `geomutils.dotProduct(number)` for calculating the dot product of two vertices (as vectors).\n *\n * @version 1.2.0\n **/\nimport { Line } from \"./Line\";\nimport { Triangle } from \"./Triangle\";\n/**\n * A collection of usefull geometry utilities.\n *\n * @global\n **/\nexport const geomutils = {\n /**\n * Map any angle (any numeric value) to [0, Math.PI).\n *\n * @param {number} angle - The numeric value to map.\n * @return {number} The mapped angle inside [0,PI*2].\n **/\n mapAngleTo2PI(angle) {\n // Source: https://forums.codeguru.com/showthread.php?384172-get-angle-into-range-0-2*pi\n const new_angle = Math.asin(Math.sin(angle));\n if (Math.cos(angle) < 0) {\n return Math.PI - new_angle;\n }\n else if (new_angle < 0) {\n return new_angle + 2 * Math.PI;\n }\n else {\n return new_angle;\n }\n },\n /**\n * Calculate the euclidean distance between two points given by four coordinates (two coordinates each).\n *\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @returns {number}\n */\n dist4(x1, y1, x2, y2) {\n return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y1 - y2, 2));\n },\n /**\n * Map any angle (any numeric value) to [0, Math.PI).\n *\n * A × B := (A.x * B.x) + (A.y * B.y)\n *\n * @param {XYCoords} vertA - The first vertex.\n * @param {XYCoords} vertB - The second vertex.\n * @return {number} The dot product of the two vertices.\n **/\n dotProduct(vertA, vertB) {\n return vertA.x * vertB.x + vertA.y * vertB.y;\n },\n /**\n * Compute the n-section of the angle – described as a triangle (A,B,C) – in point A.\n *\n * @param {Vertex} pA - The first triangle point.\n * @param {Vertex} pB - The second triangle point.\n * @param {Vertex} pC - The third triangle point.\n * @param {number} n - The number of desired angle sections (example: 2 means the angle will be divided into two sections,\n * means an returned array with length 1, the middle line).\n *\n * @return {Line[]} An array of n-1 lines secting the given angle in point A into n equal sized angle sections. The lines' first vertex is A.\n */\n nsectAngle(pA, pB, pC, n) {\n const triangle = new Triangle(pA, pB, pC);\n const lineAB = new Line(pA, pB);\n const lineAC = new Line(pA, pC);\n // Compute the difference; this is the angle between AB and AC\n var insideAngle = lineAB.angle(lineAC);\n // We want the inner angles of the triangle, not the outer angle;\n // which one is which depends on the triangle 'direction'\n const clockwise = triangle.determinant() > 0;\n // For convenience convert the angle [-PI,PI] to [0,2*PI]\n if (insideAngle < 0)\n insideAngle = 2 * Math.PI + insideAngle;\n if (!clockwise)\n insideAngle = (2 * Math.PI - insideAngle) * -1;\n // Scale the rotated lines to the max leg length (looks better)\n const lineLength = Math.max(lineAB.length(), lineAC.length());\n const scaleFactor = lineLength / lineAB.length();\n var result = [];\n for (var i = 1; i < n; i++) {\n // Compute the i-th inner sector line\n result.push(new Line(pA, pB.clone().rotate(-i * (insideAngle / n), pA)).scale(scaleFactor));\n }\n return result;\n },\n /**\n * Wrap the value (e.g. an angle) into the given range of [0,max).\n *\n * @name wrapMax\n * @param {number} x - The value to wrap.\n * @param {number} max - The max bound to use for the range.\n * @return {number} The wrapped value inside the range [0,max).\n */\n wrapMax(x, max) {\n // Found at\n // https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi\n return (max + (x % max)) % max;\n },\n /**\n * Wrap the value (e.g. an angle) into the given range of [min,max).\n *\n * @name wrapMinMax\n * @param {number} x - The value to wrap.\n * @param {number} min - The min bound to use for the range.\n * @param {number} max - The max bound to use for the range.\n * @return {number} The wrapped value inside the range [min,max).\n */\n // Currently un-used\n wrapMinMax(x, min, max) {\n return min + geomutils.wrapMax(x - min, max - min);\n }\n};\n//# sourceMappingURL=geomutils.js.map","/**\n * @author Ikaros Kappler\n * @date 2012-10-17\n * @modified 2018-04-03 Refactored the code of october 2012 into a new class.\n * @modified 2018-04-28 Added some documentation.\n * @modified 2018-08-16 Added the set() function.\n * @modified 2018-08-26 Added VertexAttr.\n * @modified 2018-10-31 Extended the constructor by object{x,y}.\n * @modified 2018-11-19 Extended the set(number,number) function to set(Vertex).\n * @modified 2018-11-28 Added 'this' to the VertexAttr constructor.\n * @modified 2018-12-05 Added the sub(...) function. Changed the signature of the add() function! add(Vertex) and add(number,number) are now possible.\n * @modified 2018-12-21 (It's winter solstice) Added the inv()-function.\n * @modified 2019-01-30 Added the setX(Number) and setY(Number) functions.\n * @modified 2019-02-19 Added the difference(Vertex) function.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-04-24 Added the randomVertex(ViewPort) function.\n * @modified 2019-11-07 Added toSVGString(object) function.\n * @modified 2019-11-18 Added the rotate(number,Vertex) function.\n * @modified 2019-11-21 Fixed a bug in the rotate(...) function (elements were moved).\n * @modified 2020-03-06 Added functions invX() and invY().\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2020-05-26 Added functions addX(number) and addY(number).\n * @modified 2020-10-30 Changed the warnings in `sub(...)` and `add(...)` into real errors.\n * @modified 2021-03-01 Changed the second param `center` in the `rotate` function from Vertex to XYCoords.\n * @modified 2021-12-01 Changed the type of param of `scale` to XYCoords.\n * @modified 2021-12-01 Added function `scaleXY` for non uniform scaling.\n * @modified 2021-12-17 Added the functions `lerp` and `lerpAbs` for linear interpolations.\n * @modified 2022-01-31 Added `Vertex.utils.arrayToJSON`.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Vertex.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-11-28 Added the `subXY`, `subX` and `subY` methods to the `Vertex` class.\n * @modified 2023-09-29 Downgraded types for the `Vertex.utils.buildArrowHead` function (replacing Vertex params by more generic XYCoords type).\n * @modified 2023-09-29 Added the `Vertex.abs()` method as it seems useful.\n * @modified 2024-03-08 Added the optional `precision` param to the `toString` method.\n * @modified 2024-12-17 Outsourced the euclidean distance calculation of `Vertex.distance` to `geomutils.dist4`.\n * @modified 2025-03-24 Making the second parameter `center` of the `Vertex.rotate` method optional.\n * @modified 2025-04-13 Adding the `Vertex.move(amount: XYCoords)` method (does the same as `add`, added by naming convention).\n * @modified 2025-05-07 Class `Vertex` is now implementing interface `IBounded` (to meet convention).\n * @version 2.11.0\n *\n * @file Vertex\n * @public\n **/\nimport { VertexAttr } from \"./VertexAttr\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { VertexListeners } from \"./VertexListeners\";\nimport { geomutils } from \"./geomutils\";\nimport { Bounds } from \"./Bounds\";\n/**\n * @classdesc A vertex is a pair of two numbers.<br>\n * <br>\n * It is used to identify a 2-dimensional point on the x-y-plane.\n *\n * @requires IVertexAttr\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n * @requires VertexAttr\n * @requires VertexListeners\n * @requires XYCoords\n *\n */\nexport class Vertex {\n /**\n * The constructor for the vertex class.\n *\n * @constructor\n * @name Vertex\n * @param {number} x - The x-coordinate of the new vertex.\n * @param {number} y - The y-coordinate of the new vertex.\n **/\n constructor(x, y) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Vertex\";\n this.uid = UIDGenerator.next();\n if (typeof x == \"undefined\") {\n this.x = 0;\n this.y = 0;\n }\n else if (typeof x == \"number\" && typeof y == \"number\") {\n this.x = x;\n this.y = y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x = tuple.x;\n this.y = tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x = x;\n else if (typeof x == \"undefined\")\n this.x = 0;\n else\n this.x = NaN;\n if (typeof y == \"number\")\n this.y = y;\n else if (typeof y == \"undefined\")\n this.y = 0;\n else\n this.y = NaN;\n }\n }\n this.attr = new VertexAttr();\n this.listeners = new VertexListeners(this);\n }\n /**\n * Set the x- and y- component of this vertex.\n *\n * @method set\n * @param {number} x - The new x-component.\n * @param {number} y - The new y-component.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n set(x, y) {\n if (typeof x == \"number\" && typeof y == \"number\") {\n this.x = x;\n this.y = y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x = tuple.x;\n this.y = tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x = x;\n else if (typeof x == \"undefined\")\n this.x = 0;\n else\n this.x = NaN;\n if (typeof y == \"number\")\n this.y = y;\n else if (typeof y == \"undefined\")\n this.y = 0;\n else\n this.y = NaN;\n }\n }\n return this;\n }\n /**\n * Set the x-component of this vertex.\n *\n * @method setX\n * @param {number} x - The new x-component.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n setX(x) {\n this.x = x;\n return this;\n }\n /**\n * Set the y-component of this vertex.\n *\n * @method setY\n * @param {number} y - The new y-component.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n setY(y) {\n this.y = y;\n return this;\n }\n /**\n * Set the x-component if this vertex to the inverse of its value.\n *\n * @method invX\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n invX() {\n this.x = -this.x;\n return this;\n }\n /**\n * Set the y-component if this vertex to the inverse of its value.\n *\n * @method invY\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n invY() {\n this.y = -this.y;\n return this;\n }\n /**\n * Add the passed amount to x- and y- component of this vertex.<br>\n * <br>\n * This function works with add( {number}, {number} ) and\n * add( {Vertex} ), as well.\n *\n * @method add\n * @param {(number|Vertex)} x - The amount to add to x (or a vertex itself).\n * @param {number=} y - The amount to add to y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n add(x, y) {\n if (typeof x == \"number\" && typeof y == \"number\") {\n this.x += x;\n this.y += y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x += tuple.x;\n this.y += tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x += x;\n else\n throw `Cannot add ${typeof x} to numeric x component!`;\n if (typeof y == \"number\")\n this.y += y;\n else\n throw `Cannot add ${typeof y} to numeric y component!`;\n }\n }\n return this;\n }\n /**\n * Move this point by the given amount.\n *\n * This method just calls `add(amount).\n *\n *\n * @method move\n * @param {Vertex} amount - The amount to move this vertex.\n * @return {Vertex} this - For chaining.\n * @instance\n * @memberof Vertex\n */\n move(amount) {\n return this.add(amount);\n }\n /**\n * Add the passed amounts to the x- and y- components of this vertex.\n *\n * @method addXY\n * @param {number} x - The amount to add to x.\n * @param {number} y - The amount to add to y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n addXY(amountX, amountY) {\n this.x += amountX;\n this.y += amountY;\n return this;\n }\n /**\n * Add the passed amounts to the x-component of this vertex.\n *\n * @method addX\n * @param {number} x - The amount to add to x.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n addX(amountX) {\n this.x += amountX;\n return this;\n }\n /**\n * Add the passed amounts to the y-component of this vertex.\n *\n * @method addY\n * @param {number} y - The amount to add to y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n addY(amountY) {\n this.y += amountY;\n return this;\n }\n /**\n * Substract the passed amount from x- and y- component of this vertex.<br>\n * <br>\n * This function works with sub( {number}, {number} ) and\n * sub( {Vertex} ), as well.\n *\n * @method sub\n * @param {(number|Vertex)} x - The amount to substract from x (or a vertex itself).\n * @param {number=} y - The amount to substract from y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n sub(x, y) {\n if (typeof x == \"number\" && typeof y == \"number\") {\n this.x -= x;\n this.y -= y;\n }\n else {\n const tuple = x;\n if (typeof tuple.x == \"number\" && typeof tuple.y == \"number\") {\n this.x -= tuple.x;\n this.y -= tuple.y;\n }\n else {\n if (typeof x == \"number\")\n this.x -= x;\n else\n throw `Cannot add ${typeof x} to numeric x component!`;\n if (typeof y == \"number\")\n this.y -= y;\n else\n throw `Cannot add ${typeof y} to numeric y component!`;\n }\n }\n return this;\n }\n /**\n * Substract the passed amounts from the x- and y- components of this vertex.\n *\n * @method subXY\n * @param {number} x - The amount to substract from x.\n * @param {number} y - The amount to substract from y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n subXY(amountX, amountY) {\n this.x -= amountX;\n this.y -= amountY;\n return this;\n }\n /**\n * Substract the passed amounts from the x-component of this vertex.\n *\n * @method addX\n * @param {number} x - The amount to substract from x.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n subX(amountX) {\n this.x -= amountX;\n return this;\n }\n /**\n * Substract the passed amounts from the y-component of this vertex.\n *\n * @method subY\n * @param {number} y - The amount to substract from y.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n subY(amountY) {\n this.y -= amountY;\n return this;\n }\n /**\n * Check if this vertex equals the passed one.\n * <br>\n * This function uses an internal epsilon as tolerance.\n *\n * @method equals\n * @param {Vertex} vertex - The vertex to compare this with.\n * @return {boolean}\n * @instance\n * @memberof Vertex\n **/\n equals(vertex) {\n var eqX = Math.abs(this.x - vertex.x) < Vertex.EPSILON;\n var eqY = Math.abs(this.y - vertex.y) < Vertex.EPSILON;\n var result = eqX && eqY;\n return result;\n }\n /**\n * Create a copy of this vertex.\n *\n * @method clone\n * @return {Vertex} A new vertex, an exact copy of this.\n * @instance\n * @memberof Vertex\n **/\n clone() {\n return new Vertex(this.x, this.y);\n }\n /**\n * Get the distance to the passed point (in euclidean metric)\n *\n * @method distance\n * @param {XYCoords} vert - The vertex to measure the distance to.\n * @return {number}\n * @instance\n * @memberof Vertex\n **/\n distance(vert) {\n // return Math.sqrt(Math.pow(vert.x - this.x, 2) + Math.pow(vert.y - this.y, 2));\n return geomutils.dist4(this.x, this.y, vert.x, vert.y);\n }\n /**\n * Get the angle of this point (relative to (0,0) or to the given other origin point).\n *\n * @method angle\n * @param {XYCoords} origin - The vertex to measure the angle from.\n * @return {number}\n * @instance\n * @memberof Vertex\n **/\n angle(origin) {\n const a = typeof origin === \"undefined\"\n ? Math.PI / 2 - Math.atan2(this.x, this.y)\n : Math.PI / 2 - Math.atan2(origin.x - this.x, origin.y - this.y);\n // Map to positive value\n return a < 0 ? Math.PI * 2 + a : a;\n }\n /**\n * Get the difference to the passed point.<br>\n * <br>\n * The difference is (vert.x-this.x, vert.y-this.y).\n *\n * @method difference\n * @param {Vertex} vert - The vertex to measure the x-y-difference to.\n * @return {Vertex} A new vertex.\n * @instance\n * @memberof Vertex\n **/\n difference(vert) {\n return new Vertex(vert.x - this.x, vert.y - this.y);\n }\n /**\n * This is a vector-like behavior and 'scales' this vertex\n * towards/from a given center by one uniform scale factor.\n *\n * @method scale\n * @param {number} factor - The factor to 'scale' this vertex; 1.0 means no change.\n * @param {XYCoords=} center - The origin of scaling; default is (0,0).\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n scale(factor, center) {\n return this.scaleXY({ x: factor, y: factor }, center);\n }\n /**\n * Perform a linear interpolation towards the given target vertex.\n * The amount value `t` is relative, `t=0.0` means no change, `t=1.0`\n * means this point will be moved to the exact target position.\n *\n * `t=0.5` will move this point to the middle of the connecting\n * linear segment.\n *\n * @param {XYCoords} target - The target position to lerp this vertex to.\n * @param {number} t - The relative amount, usually in [0..1], but other values will work, too.\n * @returns\n */\n lerp(target, t) {\n var diff = this.difference(target);\n // return new Vertex(this.x + diff.x * t, this.y + diff.y * t);\n this.x += diff.x * t;\n this.y += diff.y * t;\n return this;\n }\n /**\n * Perform a linear interpolation towards the given target vertex (absolute variant).\n * The amount value `t` is absolute, which means the lerp amount is a direct distance\n * value. This point will have move the amount of the passed distance `u`.\n *\n * @param {XYCoords} target - The target position to lerp this vertex to.\n * @param {number} t - The absolute move amount to use to lerping.\n * @returns\n */\n lerpAbs(target, u) {\n var dist = this.distance(target);\n var diff = this.difference(target);\n var step = { x: diff.x / dist, y: diff.y / dist };\n // return new Vertex(this.x + step.x * u, this.y + step.y * u);\n this.x += step.x * u;\n this.y += step.y * u;\n return this;\n }\n /**\n * This is a vector-like behavior and 'scales' this vertex\n * towards/from a given center by two independent x- and y- scale factors.\n *\n * @method scale\n * @param {number} factor - The factor to 'scale' this vertex; 1.0 means no change.\n * @param {XYCoords=} center - The origin of scaling; default is (0,0).\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n scaleXY(factors, center) {\n if (!center || typeof center === \"undefined\") {\n center = { x: 0, y: 0 };\n }\n this.x = center.x + (this.x - center.x) * factors.x;\n this.y = center.y + (this.y - center.y) * factors.y;\n return this;\n }\n /**\n * This is a vector-like behavior and 'rotates' this vertex\n * around given center.\n *\n * @method rotate\n * @param {number} angle - The angle to 'rotate' this vertex; 0.0 means no change.\n * @param {XYCoords=} center - The center of rotation; default is (0,0).\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n rotate(angle, center) {\n if (!center || typeof center === \"undefined\") {\n center = { x: 0, y: 0 };\n }\n this.sub(center);\n angle += Math.atan2(this.y, this.x);\n let len = this.distance(Vertex.ZERO); // {x:0,y:0});\n this.x = len * Math.cos(angle);\n this.y = len * Math.sin(angle);\n this.add(center);\n return this;\n }\n /**\n * Multiply both components of this vertex with the given scalar.<br>\n * <br>\n * Note: as in<br>\n * https://threejs.org/docs/#api/math/Vector2.multiplyScalar\n *\n * @method multiplyScalar\n * @param {number} scalar - The scale factor; 1.0 means no change.\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n multiplyScalar(scalar) {\n this.x *= scalar;\n this.y *= scalar;\n return this;\n }\n /**\n * Round the two components x and y of this vertex.\n *\n * @method round\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n round() {\n this.x = Math.round(this.x);\n this.y = Math.round(this.y);\n return this;\n }\n /**\n * Change this vertex (x,y) to its inverse (-x,-y).\n *\n * @method inv\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n **/\n inv() {\n this.x = -this.x;\n this.y = -this.y;\n return this;\n }\n /**\n * Set both coordinates of this vertex to their absolute value (abs(x), abs(y)).\n *\n * @method abs\n * @return {Vertex} this\n * @instance\n * @memberof Vertex\n */\n abs() {\n this.x = Math.abs(this.x);\n this.y = Math.abs(this.y);\n return this;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this Vertex.\n * This is just by convention – any vertex is just a position without any useful with or height (0).\n *\n * @method getBounds\n * @instance\n * @memberof Vertex\n * @return {Bounds} The rectangular bounds of this Vertex (width and height are zero).\n **/\n getBounds() {\n // return Bounds.computeFromVertices([this.a, this.b, this.c]);\n return Bounds.computeFromVertices([this]);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Get a string representation of this vertex.\n *\n * @method toString\n * @return {string} The string representation of this vertex.\n * @instance\n * @memberof Vertex\n **/\n toString(precision) {\n if (typeof precision === \"undefined\") {\n return \"(\" + this.x + \",\" + this.y + \")\";\n }\n else {\n return \"(\" + this.x.toFixed(precision) + \",\" + this.y.toFixed(precision) + \")\";\n }\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.listeners.removeAllListeners();\n this.isDestroyed = true;\n }\n /**\n * Create a new random vertex inside the given viewport.\n *\n * @param {ViewPort} viewPort - A {min:Vertex, max:Vertex} viewport specifying the bounds.\n * @return A new vertex with a random position.\n **/\n static randomVertex(viewPort) {\n return new Vertex(viewPort.min.x + Math.random() * (viewPort.max.x - viewPort.min.x), viewPort.min.y + Math.random() * (viewPort.max.y - viewPort.min.y));\n }\n}\nVertex.ZERO = new Vertex(0, 0);\n/**\n * An epsilon for comparison\n *\n * @private\n * @readonly\n **/\nVertex.EPSILON = 1.0e-6;\nVertex.utils = {\n /**\n * Generate a four-point arrow head, starting at the vector end minus the\n * arrow head length.\n *\n * The first vertex in the returned array is guaranteed to be the located\n * at the vector line end minus the arrow head length.\n *\n *\n * Due to performance all params are required.\n *\n * The params scaleX and scaleY are required for the case that the scaling is not uniform (x and y\n * scaling different). Arrow heads should not look distored on non-uniform scaling.\n *\n * If unsure use 1.0 for scaleX and scaleY (=no distortion).\n * For headlen use 8, it's a good arrow head size.\n *\n * Example:\n * buildArrowHead( new Vertex(0,0), new Vertex(50,100), 8, 1.0, 1.0 )\n *\n * @param {XYCoords} zA - The start vertex of the vector to calculate the arrow head for.\n * @param {XYCoords} zB - The end vertex of the vector.\n * @param {number} headlen - The length of the arrow head (along the vector direction. A good value is 12).\n * @param {number} scaleX - The horizontal scaling during draw.\n * @param {number} scaleY - the vertical scaling during draw.\n **/\n // @DEPRECATED: use Vector.utils.buildArrowHead instead!!!\n buildArrowHead: (zA, zB, headlen, scaleX, scaleY) => {\n console.warn(\"[DEPRECATION] Vertex.utils.buildArrowHead is deprecated. Please use Vector.utils.buildArrowHead instead.\");\n var angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);\n var vertices = [];\n vertices.push(new Vertex(zB.x * scaleX - headlen * Math.cos(angle), zB.y * scaleY - headlen * Math.sin(angle)));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle - Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle - Math.PI / 8)));\n vertices.push(new Vertex(zB.x * scaleX, zB.y * scaleY));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle + Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle + Math.PI / 8)));\n return vertices;\n },\n /**\n * Convert the given vertices (array) to a JSON string.\n *\n * @param {number?} precision - (optional) The numeric precision to be used (number of precision digits).\n * @returns {string}\n */\n arrayToJSON(vertices, precision) {\n return JSON.stringify(vertices.map(function (vert) {\n return typeof precision === undefined\n ? { x: vert.x, y: vert.y }\n : { x: Number(vert.x.toFixed(precision)), y: Number(vert.y.toFixed(precision)) };\n }));\n }\n};\n//# sourceMappingURL=Vertex.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-03-24\n * @modified 2020-05-04 Fixed a serious bug in the pointDistance function.\n * @modified 2020-05-12 The angle(line) param was still not optional. Changed that.\n * @modified 2020-11-11 Generalized the `add` and `sub` param from `Vertex` to `XYCoords`.\n * @modified 2020-12-04 Changed`vtutils.dist2` params from `Vertex` to `XYCoords` (generalized).\n * @modified 2020-12-04 Changed `getClosestT` param from `Vertex` to `XYCoords` (generalized).\n * @modified 2020-12-04 Added the `hasPoint(XYCoords)` function.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2023-09-29 Fixed a calculation error in the VertTuple.hasPoint() function; distance measure was broken!\n * @modified 2024-09-10 Chaging the first param of `pointDistance` from `Vertex` to less strict type `XYCoords`. This should not break anything.\n * @modified 2024-09-10 Adding the optional `epsilon` param to the `hasPoint` method.\n * @modified 2024-12-02 Added the `epsilon` param to the `colinear` method. Default is 1.0e-6.\n * @modified 2025-03-31 Added the `VertTuple.revert` method.\n * @modified 2025-04-15 Changed param of `VertTuple.moveTo` method from `Vertex` to `XYCoords`.\n * @modified 2025-04-15 Added method `VertTuple.move` method.\n * @version 1.4.0\n */\nimport { Vertex } from \"./Vertex\";\nimport { UIDGenerator } from \"./UIDGenerator\";\n/**\n * @classdesc An abstract base classes for vertex tuple constructs, like Lines or Vectors.\n * @abstract\n * @requires UID\n * @requires Vertex\n * @requires XYCoords\n */\nexport class VertTuple {\n /**\n * Creates an instance.\n *\n * @constructor\n * @name VertTuple\n * @param {Vertex} a The tuple's first point.\n * @param {Vertex} b The tuple's second point.\n **/\n constructor(a, b, factory) {\n this.uid = UIDGenerator.next();\n this.a = a;\n this.b = b;\n this.factory = factory;\n }\n /**\n * Get the length of this line.\n *\n * @method length\n * @instance\n * @memberof VertTuple\n **/\n length() {\n return Math.sqrt(Math.pow(this.b.x - this.a.x, 2) + Math.pow(this.b.y - this.a.y, 2));\n }\n /**\n * Set the length of this vector to the given amount. This only works if this\n * vector is not a null vector.\n *\n * @method setLength\n * @param {number} length - The desired length.\n * @memberof VertTuple\n * @return {T} this (for chaining)\n **/\n setLength(length) {\n return this.scale(length / this.length());\n }\n /**\n * Substract the given vertex from this line's end points.\n *\n * @method sub\n * @param {XYCoords} amount The amount (x,y) to substract.\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n sub(amount) {\n this.a.sub(amount);\n this.b.sub(amount);\n return this;\n }\n /**\n * Add the given vertex to this line's end points.\n *\n * @method add\n * @param {XYCoords} amount The amount (x,y) to add.\n * @instance\n * @memberof VertTuple\n * @return {VertTuple<T>} this\n **/\n add(amount) {\n this.a.add(amount);\n this.b.add(amount);\n return this;\n }\n /**\n * Reverse this vertex tuple: a becomes b, and b becomes a.\n * This operation is in-place.\n *\n * @method add\n * @param {XYCoords} amount The amount (x,y) to add.\n * @instance\n * @memberof VertTuple\n * @return {VertTuple<T>} this\n */\n revert() {\n const tmp = this.a;\n this.a = this.b;\n this.b = tmp;\n return this;\n }\n /**\n * Normalize this line (set to length 1).\n *\n * @method normalize\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n normalize() {\n this.b.set(this.a.x + (this.b.x - this.a.x) / this.length(), this.a.y + (this.b.y - this.a.y) / this.length());\n return this;\n }\n /**\n * Scale this line by the given factor.\n *\n * @method scale\n * @param {number} factor The factor for scaling (1.0 means no scale).\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n scale(factor) {\n this.b.set(this.a.x + (this.b.x - this.a.x) * factor, this.a.y + (this.b.y - this.a.y) * factor);\n return this;\n }\n /**\n * Move this line to a new location.\n *\n * @method moveTo\n * @param {XYCoords} newA - The new desired location of 'a'. Vertex 'b' will be moved, too.\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n moveTo(newA) {\n let diff = this.a.difference(newA);\n this.a.add(diff);\n this.b.add(diff);\n return this;\n }\n /**\n * Move this line by the given amount\n *\n * @method move\n * @param {XYCoords} amount - The amount to move both point of this tuple.\n * @return {VertTuple} this\n * @instance\n * @memberof VertTuple\n **/\n move(amount) {\n this.a.add(amount);\n this.b.add(amount);\n return this;\n }\n /**\n * Get the angle between this and the passed line (in radians).\n *\n * @method angle\n * @param {VertTuple} line - (optional) The line to calculate the angle to. If null the baseline (x-axis) will be used.\n * @return {number} this\n * @instance\n * @memberof VertTuple\n **/\n angle(line) {\n if (line == null || typeof line == \"undefined\") {\n line = this.factory(new Vertex(0, 0), new Vertex(100, 0));\n }\n // Compute the angle from x axis and the return the difference :)\n const v0 = this.b.clone().sub(this.a);\n const v1 = line.b.clone().sub(line.a);\n // Thank you, Javascript, for this second atan function. No additional math is needed here!\n // The result might be negative, but isn't it usually nicer to determine angles in positive values only?\n return Math.atan2(v1.x, v1.y) - Math.atan2(v0.x, v0.y);\n }\n /**\n * Get line point at position t in [0 ... 1]:<br>\n * <pre>[P(0)]=[A]--------------------[P(t)]------[B]=[P(1)]</pre><br>\n * <br>\n * The counterpart of this function is Line.getClosestT(Vertex).\n *\n * @method vertAt\n * @param {number} t The position scalar.\n * @return {Vertex} The vertex a position t.\n * @instance\n * @memberof VertTuple\n **/\n vertAt(t) {\n return new Vertex(this.a.x + (this.b.x - this.a.x) * t, this.a.y + (this.b.y - this.a.y) * t);\n }\n /**\n * Get the denominator of this and the given line.\n *\n * If the denominator is zero (or close to zero) both line are co-linear.\n *\n * @method denominator\n * @param {VertTuple} line\n * @instance\n * @memberof VertTuple\n * @return {Number}\n **/\n denominator(line) {\n // http://jsfiddle.net/justin_c_rounds/Gd2S2/\n return (line.b.y - line.a.y) * (this.b.x - this.a.x) - (line.b.x - line.a.x) * (this.b.y - this.a.y);\n }\n /**\n * Checks if this and the given line are co-linear.\n *\n * The constant Vertex.EPSILON is used for tolerance.\n *\n * @method colinear\n * @param {VertTuple} line\n * @param {epsilon?=1.0e-6} epsilon - The epsilon to use (default is 1.0e-6).\n * @instance\n * @memberof VertTuple\n * @return true if both lines are co-linear.\n */\n colinear(line, epsilon) {\n return Math.abs(this.denominator(line)) < (typeof epsilon === \"undefined\" ? Vertex.EPSILON : epsilon);\n }\n /**\n * Get the closest position T from this line to the specified point.\n *\n * The counterpart for this function is Line.vertAt(Number).\n *\n * @name getClosetT\n * @method getClosestT\n * @param {XYCoords} p The point (vertex) to measure the distance to.\n * @return {number} The line position t of minimal distance to p.\n * @instance\n * @memberof VertTuple\n **/\n getClosestT(p) {\n var l2 = VertTuple.vtutils.dist2(this.a, this.b);\n if (l2 === 0)\n return 0;\n var t = ((p.x - this.a.x) * (this.b.x - this.a.x) + (p.y - this.a.y) * (this.b.y - this.a.y)) / l2;\n // Do not wrap to [0,1] here.\n // Other results are of interest, too.\n // t = Math.max(0, Math.min(1, t));\n return t;\n }\n /**\n * Check if the given point is located on this line. Optionally also check if\n * that point is located between point `a` and `b`.\n *\n * @method hasPoint\n * @param {Vertex} point - The point to check.\n * @param {boolean=} insideBoundsOnly - [optional] If set to to true (default=false) the point must be between start and end point of the line.\n * @param {number=Vertex.EPSILON} epsilon - [optional] A tolerance.\n * @return {boolean} True if the given point is on this line.\n * @instance\n * @memberof VertTuple\n */\n hasPoint(point, insideBoundsOnly, epsilon) {\n const t = this.getClosestT(point);\n // Compare to pointDistance?\n const distance = Math.sqrt(VertTuple.vtutils.dist2(point, this.vertAt(t)));\n if (typeof insideBoundsOnly !== \"undefined\" && insideBoundsOnly) {\n return distance < (epsilon !== null && epsilon !== void 0 ? epsilon : Vertex.EPSILON) && t >= 0 && t <= 1;\n }\n else {\n return distance < (epsilon !== null && epsilon !== void 0 ? epsilon : Vertex.EPSILON); // t >= 0 && t <= 1;\n }\n }\n /**\n * Get the closest point on this line to the specified point.\n *\n * @method getClosestPoint\n * @param {Vertex} p The point (vertex) to measre the distance to.\n * @return {Vertex} The point on the line that is closest to p.\n * @instance\n * @memberof VertTuple\n **/\n getClosestPoint(p) {\n var t = this.getClosestT(p);\n return this.vertAt(t);\n }\n /**\n * The the minimal distance between this line and the specified point.\n *\n * @method pointDistance\n * @param {XYCoords} p The point (vertex) to measre the distance to.\n * @return {number} The absolute minimal distance.\n * @instance\n * @memberof VertTuple\n **/\n pointDistance(p) {\n // Taken From:\n // https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment\n return Math.sqrt(VertTuple.vtutils.dist2(p, this.vertAt(this.getClosestT(p))));\n }\n /**\n * Create a deep clone of this instance.\n *\n * @method cloneLine\n * @return {T} A type safe clone if this instance.\n * @instance\n * @memberof VertTuple\n **/\n clone() {\n return this.factory(this.a.clone(), this.b.clone());\n }\n /**\n * Create a string representation of this line.\n *\n * @method totring\n * @return {string} The string representing this line.\n * @instance\n * @memberof VertTuple\n **/\n toString() {\n return \"{ a : \" + this.a.toString() + \", b : \" + this.b.toString() + \" }\";\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.a.destroy();\n this.b.destroy();\n this.isDestroyed = true;\n }\n}\n/**\n * @private\n **/\nVertTuple.vtutils = {\n dist2: (v, w) => {\n return (v.x - w.x) * (v.x - w.x) + (v.y - w.y) * (v.y - w.y);\n }\n};\n//# sourceMappingURL=VertTuple.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-01-30\n * @modified 2019-02-23 Added the toSVGString function, overriding Line.toSVGString.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-04-19 Added the clone function (overriding Line.clone()).\n * @modified 2019-09-02 Added the Vector.perp() function.\n * @modified 2019-09-02 Added the Vector.inverse() function.\n * @modified 2019-12-04 Added the Vector.inv() function.\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Vector.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-10-25 Added the `getOrthogonal` method.\n * @modified 2025-04-14 Added the `Vector.rotate(number)` method.\n * @version 1.6.0\n *\n * @file Vector\n * @public\n **/\nimport { VertTuple } from \"./VertTuple\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A vector (Vertex,Vertex) is a line with a visible direction.<br>\n * <br>\n * Vectors are drawn with an arrow at their end point.<br>\n * <b>The Vector class extends the Line class.</b>\n *\n * @requires VertTuple\n * @requires Vertex\n **/\nexport class Vector extends VertTuple {\n /**\n * The constructor.\n *\n * @constructor\n * @name Vector\n * @extends Line\n * @param {Vertex} vertA - The start vertex of the vector.\n * @param {Vertex} vertB - The end vertex of the vector.\n **/\n constructor(vertA, vertB) {\n super(vertA, vertB, (a, b) => new Vector(a, b));\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Vector\";\n }\n /**\n * Get the perpendicular of this vector which is located at a.\n *\n * @return {Vector} A new vector being the perpendicular of this vector sitting on a.\n **/\n perp() {\n var v = this.clone();\n v.sub(this.a);\n v = new Vector(new Vertex(), new Vertex(-v.b.y, v.b.x));\n v.a.add(this.a);\n v.b.add(this.a);\n return v;\n }\n /**\n * The inverse of a vector is a vector with the same magnitude but oppose direction.\n *\n * Please not that the origin of this vector changes here: a->b becomes b->a.\n *\n * @return {Vector}\n **/\n inverse() {\n var tmp = this.a;\n this.a = this.b;\n this.b = tmp;\n return this;\n }\n /**\n * This function computes the inverse of the vector, which means 'a' stays untouched.\n *\n * @return {Vector} this for chaining.\n **/\n inv() {\n this.b.x = this.a.x - (this.b.x - this.a.x);\n this.b.y = this.a.y - (this.b.y - this.a.y);\n return this;\n }\n /**\n * Get the intersection if this vector and the specified vector.\n *\n * @method intersection\n * @param {Vector} line The second vector.\n * @return {Vertex} The intersection (may lie outside the end-points).\n * @instance\n * @memberof Line\n **/\n intersection(line) {\n var denominator = this.denominator(line);\n if (denominator == 0)\n return null;\n var a = this.a.y - line.a.y;\n var b = this.a.x - line.a.x;\n var numerator1 = (line.b.x - line.a.x) * a - (line.b.y - line.a.y) * b;\n var numerator2 = (this.b.x - this.a.x) * a - (this.b.y - this.a.y) * b;\n a = numerator1 / denominator; // NaN if parallel lines\n b = numerator2 / denominator;\n // TODO:\n // FOR A VECTOR THE LINE-INTERSECTION MUST BE ON BOTH VECTORS\n // if we cast these lines infinitely in both directions, they intersect here:\n return new Vertex(this.a.x + a * (this.b.x - this.a.x), this.a.y + a * (this.b.y - this.a.y));\n }\n /**\n * Get the orthogonal \"vector\" of this vector (rotated by 90° clockwise).\n *\n * @name getOrthogonal\n * @method getOrthogonal\n * @return {Vector} A new vector with the same length that stands on this vector's point a.\n * @instance\n * @memberof Vector\n **/\n getOrthogonal() {\n // Orthogonal of vector (0,0)->(x,y) is (0,0)->(-y,x)\n const linePoint = this.a.clone();\n const startPoint = this.b.clone().sub(this.a);\n const tmp = startPoint.x;\n startPoint.x = -startPoint.y;\n startPoint.y = tmp;\n return new Vector(linePoint, startPoint.add(this.a));\n }\n /**\n * Rotate this vector by the given angle around the first point `a`.\n *\n * @name rotate\n * @method rotate\n * @return {Vector} this - for chaining.\n * @instance\n * @memberof Vector\n */\n rotate(angle) {\n this.b.rotate(angle, this.a);\n return this;\n }\n}\nVector.utils = {\n /**\n * Generate a four-point arrow head, starting at the vector end minus the\n * arrow head length.\n *\n * The first vertex in the returned array is guaranteed to be the located\n * at the vector line end minus the arrow head length.\n *\n *\n * Due to performance all params are required.\n *\n * The params scaleX and scaleY are required for the case that the scaling is not uniform (x and y\n * scaling different). Arrow heads should not look distored on non-uniform scaling.\n *\n * If unsure use 1.0 for scaleX and scaleY (=no distortion).\n * For headlen use 8, it's a good arrow head size.\n *\n * Example:\n * buildArrowHead( new Vertex(0,0), new Vertex(50,100), 8, 1.0, 1.0 )\n *\n * @param {XYCoords} zA - The start vertex of the vector to calculate the arrow head for.\n * @param {XYCoords} zB - The end vertex of the vector.\n * @param {number} headlen - The length of the arrow head (along the vector direction. A good value is 12).\n * @param {number} scaleX - The horizontal scaling during draw.\n * @param {number} scaleY - the vertical scaling during draw.\n **/\n buildArrowHead: (zA, zB, headlen, scaleX, scaleY) => {\n const angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);\n const vertices = [];\n vertices.push(new Vertex(zB.x * scaleX - headlen * Math.cos(angle), zB.y * scaleY - headlen * Math.sin(angle)));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle - Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle - Math.PI / 8)));\n vertices.push(new Vertex(zB.x * scaleX, zB.y * scaleY));\n vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle + Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle + Math.PI / 8)));\n return vertices;\n }\n};\n//# sourceMappingURL=Vector.js.map","/**\n * @author Ikaros Kappler\n * @date 2016-03-12\n * @modified 2018-12-05 Refactored the code from the morley-triangle script.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-04-28 Fixed a bug in the Line.sub( Vertex ) function (was not working).\n * @modified 2019-09-02 Added the Line.add( Vertex ) function.\n * @modified 2019-09-02 Added the Line.denominator( Line ) function.\n * @modified 2019-09-02 Added the Line.colinear( Line ) function.\n * @modified 2019-09-02 Fixed an error in the Line.intersection( Line ) function (class Point was renamed to Vertex).\n * @modified 2019-12-15 Added the Line.moveTo(Vertex) function.\n * @modified 2020-03-16 The Line.angle(Line) parameter is now optional. The baseline (x-axis) will be used if not defined.\n * @modified 2020-03-23 Ported to Typescript from JS.\n * @modified 2020-12-04 The `intersection` function returns undefined if both lines are parallel.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-10-09 Changed the actual return value of the `intersection` function to null (was undefined before).\n * @modified 2022-10-17 Adding these methods from the `PathSegment` interface: getStartPoint, getEndPoint, revert.\n * @modified 2023-09-25 Changed param type of `intersection()` from Line to VertTuple.\n * @modified 2025-04-15 Class `Line` now implements interface `Intersectable`.\n * @modified 2025-04-16 Class `Line` now implements interface `IBounded`.\n * @version 2.4.0\n *\n * @file Line\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Vector } from \"./Vector\";\nimport { VertTuple } from \"./VertTuple\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A line consists of two vertices a and b.<br>\n * <br>\n * This is some refactored code from my 'Morley Triangle' test<br>\n * https://github.com/IkarosKappler/morleys-trisector-theorem\n *\n * @requires Vertex\n */\nexport class Line extends VertTuple {\n /**\n * Creates an instance of Line.\n *\n * @constructor\n * @name Line\n * @param {Vertex} a The line's first point.\n * @param {Vertex} b The line's second point.\n **/\n constructor(a, b) {\n super(a, b, (a, b) => new Line(a, b));\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Line\";\n }\n /**\n * Get the intersection if this line and the specified line.\n *\n * @method intersection\n * @param {Line} line The second line.\n * @return {Vertex|undefined} The intersection (may lie outside the end-points) or `undefined` if both lines are parallel.\n * @instance\n * @memberof Line\n **/\n // !!! DO NOT MOVE TO VertTuple\n intersection(line) {\n const denominator = this.denominator(line);\n if (denominator == 0) {\n return null;\n }\n let a = this.a.y - line.a.y;\n let b = this.a.x - line.a.x;\n const numerator1 = (line.b.x - line.a.x) * a - (line.b.y - line.a.y) * b;\n const numerator2 = (this.b.x - this.a.x) * a - (this.b.y - this.a.y) * b;\n a = numerator1 / denominator; // NaN if parallel lines\n b = numerator2 / denominator;\n // Catch NaN?\n const x = this.a.x + a * (this.b.x - this.a.x);\n const y = this.a.y + a * (this.b.y - this.a.y);\n if (isNaN(a) || isNaN(x) || isNaN(y)) {\n return null;\n }\n // if we cast these lines infinitely in both directions, they intersect here:\n return new Vertex(x, y);\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this Line.\n *\n * @method getBounds\n * @instance\n * @memberof Line\n * @return {Bounds} The rectangular bounds of this Line.\n **/\n getBounds() {\n return Bounds.computeFromVertices([this.a, this.b]);\n }\n //--- END --- Implement interface `IBounded`\n //--- Implement PathSegment ---\n /**\n * Get the start point of this path segment.\n *\n * @method getStartPoint\n * @memberof PathSegment\n * @return {Vertex} The start point of this path segment.\n */\n getStartPoint() {\n return this.a;\n }\n /**\n * Get the end point of this path segment.\n *\n * @method getEndPoint\n * @memberof PathSegment\n * @return {Vertex} The end point of this path segment.\n */\n getEndPoint() {\n return this.b;\n }\n /**\n * Get the tangent's end point at the start point of this segment.\n *\n * @method getStartTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the starting point's tangent.\n */\n getStartTangent() {\n return this.b;\n }\n /**\n * Get the tangent's end point at the end point of this segment.\n *\n * @method getEndTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the ending point's tangent.\n */\n getEndTangent() {\n return this.a;\n }\n /**\n * Inverse this path segment (in-place) and return this same instance (useful for chaining).\n *\n * @method reverse\n * @memberof PathSegment\n * @return {PathSegment} This path segment instance (for chaining).\n */\n reverse() {\n var tmp = this.a;\n this.a = this.b;\n this.b = tmp;\n return this;\n }\n //--- END Implement PathSegment ---\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this polygon.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n const intersection = this.intersection(line);\n if (!intersection) {\n return []; // Both lines parallel\n }\n if (this.hasPoint(intersection, true) && (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {\n return [intersection];\n }\n else {\n return [];\n }\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n const intersections = this.lineIntersections(line, inVectorBoundsOnly);\n if (intersections.length === 0) {\n return [];\n }\n const intrsctn = intersections[0];\n return [new Vector(this.a.clone(), this.b.clone()).moveTo(intrsctn)];\n }\n}\n//# sourceMappingURL=Line.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-04-14\n * @modified 2018-11-17 Added the containsVert function.\n * @modified 2018-12-04 Added the toSVGString function.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-10-25 Added the scale function.\n * @modified 2019-11-06 JSDoc update.\n * @modified 2019-11-07 Added toCubicBezierPath(number) function.\n * @modified 2019-11-22 Added the rotate(number,Vertex) function.\n * @modified 2020-03-24 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-10-30 Added the `addVertex` function.\n * @modified 2020-10-31 Added the `getVertexAt` function.\n * @modified 2020-11-06 Added the `move` function.\n * @modified 2020-11-10 Added the `getBounds` function.\n * @modified 2020-11-11 Generalized `move(Vertex)` to `move(XYCoords)`.\n * @modified 2021-01-20 Added UID.\n * @modified 2021-01-29 Added the `signedArea` function (was global function in the demos before).\n * @modified 2021-01-29 Added the `isClockwise` function.\n * @modified 2021-01-29 Added the `area` function.\n * @modified 2021-01-29 Changed the param type for `containsVert` from Vertex to XYCoords.\n * @modified 2021-12-14 Added the `perimeter()` function.\n * @modified 2021-12-16 Added the `getEvenDistributionPolygon()` function.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `Polygon.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-03-08 Added the `Polygon.clone()` function.\n * @modified 2023-09-25 Added the `Polygon.getInterpolationPolygon(number)` function.\n * @modified 2023-09-25 Added the `Polygon.lineIntersections(Line,boolean)` function.\n * @modified 2023-09-29 Added the `Polygon.closestLineIntersection(Line,boolean)` function.\n * @modified 2023-11-24 Added the `Polygon.containsPolygon(Polygon)' function.\n * @modified 2024-10-12 Added the `getEdgeAt` method.\n * @modified 2024-10-30 Added the `getEdges` method.\n * @modified 2024-12-02 Added the `elimitateColinearEdges` method.\n * @modified 2025-02-12 Added the `containsVerts` method to test multiple vertices for containment.\n * @modified 2025-03-28 Added the `Polygon.utils.locateLineIntersecion` static helper method.\n * @modified 2025-03-28 Added the `Polygon.lineIntersectionTangents` method.\n * @modified 2025-04-09 Added the `Polygon.getCentroid` method.\n * @modified 2025-05-16 Class `Polygon` now implements `IBounded`.\n * @modified 2025-05-20 Tweaking `Polygon.getInnerAngleAt` and `Polygo.isAngleAcute` to handle indices out of array bounds as well.\n * @modified 2025-06-07 Adding `Polygon.closestLineIntersectionIndex` to determine line intersections plus detected edge index.\n * @version 1.16.0\n *\n * @file Polygon\n * @public\n **/\nimport { BezierPath } from \"./BezierPath\";\nimport { Bounds } from \"./Bounds\";\nimport { Line } from \"./Line\";\nimport { Triangle } from \"./Triangle\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { geomutils } from \"./geomutils\";\n/**\n * @classdesc A polygon class. Any polygon consists of an array of vertices; polygons can be open or closed.\n *\n * @requires BezierPath\n * @requires Bounds\n * @requires SVGSerializabe\n * @requires UID\n * @requires UIDGenerator\n * @requires Vertex\n * @requires XYCoords\n */\nexport class Polygon {\n /**\n * The constructor.\n *\n * @constructor\n * @name Polygon\n * @param {Vertex[]} vertices - An array of 2d vertices that shape the polygon.\n * @param {boolean} isOpen - Indicates if the polygon should be rendered as an open or closed shape.\n **/\n constructor(vertices, isOpen) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"Polygon\";\n this.uid = UIDGenerator.next();\n if (typeof vertices == \"undefined\") {\n vertices = [];\n }\n this.vertices = vertices;\n this.isOpen = isOpen || false;\n }\n /**\n * Add a vertex to the end of the `vertices` array.\n *\n * @method addVertex\n * @param {Vertex} vert - The vertex to add.\n * @instance\n * @memberof Polygon\n **/\n addVertex(vert) {\n this.vertices.push(vert);\n }\n /**\n * Add a vertex at a particular position of the `vertices` array.\n *\n * @method addVertexAt\n * @param {Vertex} vert - The vertex to add.\n * @param {number} index - The position to add the vertex at. Will be handled modulo.\n * @instance\n * @memberof Polygon\n **/\n addVertexAt(vert, index) {\n // var moduloIndex = index % (this.vertices.length + 1);\n this.vertices.splice(index, 0, vert);\n }\n /**\n * Get a new instance of the line at the given start index. The returned line will consist\n * of the vertex at `vertIndex` and `vertIndex+1` (will be handled modulo).\n *\n * @method getEdgeAt\n * @param {number} vertIndex - The vertex index of the line to start.\n * @instance\n * @memberof Polygon\n * @return {Line}\n **/\n getEdgeAt(vertIndex) {\n return new Line(this.getVertexAt(vertIndex), this.getVertexAt(vertIndex + 1));\n }\n /**\n * Converts this polygon into a sequence of lines. Please note that each time\n * this method is called new lines are created. The underlying line vertices are no clones\n * (instances).\n *\n * @method getEdges\n * @instance\n * @memberof Polygon\n * @return {Array<Line>}\n */\n getEdges() {\n const lines = [];\n for (var i = 0; i + 1 < this.vertices.length; i++) {\n // var line = this.getLineAt(i).clone();\n lines.push(this.getEdgeAt(i));\n }\n if (!this.isOpen && this.vertices.length > 0) {\n lines.push(this.getEdgeAt(this.vertices.length - 1));\n }\n return lines;\n }\n /**\n * Checks if the angle at the given polygon vertex (index) is acute. Please not that this is\n * only working for clockwise polygons. If this polygon is not clockwise please use the\n * `isClockwise` method and reverse polygon vertices if needed.\n *\n * @method isAngleAcute\n * @instance\n * @memberof Polygon\n * @param {number} vertIndex - The index of the polygon vertex to check.\n * @returns {boolean} `true` is angle is acute, `false` is obtuse.\n */\n getInnerAngleAt(vertIndex) {\n const p2 = this.vertices[vertIndex % this.vertices.length];\n const p1 = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();\n const p3 = this.vertices[(vertIndex + 1) % this.vertices.length].clone();\n // See\n // https://math.stackexchange.com/questions/149959/how-to-find-the-interior-angle-of-an-irregular-pentagon-or-polygon\n // π−arccos((P2−P1)⋅(P3−P2)|P2−P1||P3−P2|)\n // Check if triangle is acute (will be used later)\n // Acute angles and obtuse angles need to be handled differently.\n const isAcute = this.isAngleAcute(vertIndex);\n // Differences\n const zero = new Vertex(0, 0);\n const p2mp1 = new Vertex(p2.x - p1.x, p2.y - p1.y);\n const p3mp2 = new Vertex(p3.x - p2.x, p3.y - p2.y);\n const p2mp1_len = zero.distance(p2mp1);\n const p3mp2_len = zero.distance(p3mp2);\n // Dot products\n const dotProduct = geomutils.dotProduct(p2mp1, p3mp2);\n const lengthProduct = p2mp1_len * p3mp2_len;\n if (isAcute) {\n return Math.PI - Math.acos(dotProduct / lengthProduct);\n }\n else {\n return Math.PI + Math.acos(dotProduct / lengthProduct);\n }\n }\n /**\n * Checks if the angle at the given polygon vertex (index) is acute.\n *\n * @method isAngleAcute\n * @instance\n * @memberof Polygon\n * @param {number} vertIndex - The index of the polygon vertex to check.\n * @returns {boolean} `true` is angle is acute, `false` is obtuse.\n */\n isAngleAcute(vertIndex) {\n const A = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();\n const B = this.vertices[vertIndex % this.vertices.length];\n const C = this.vertices[(vertIndex + 1) % this.vertices.length].clone();\n // Find local winding number for triangle A B C\n const windingNumber = Triangle.utils.determinant(A, B, C);\n // console.log(\"vertIndex\", vertIndex, \"windingNumber\", windingNumber);\n return windingNumber < 0;\n }\n /**\n * Get the polygon vertex at the given position (index).\n *\n * The index may exceed the total vertex count, and will be wrapped around then (modulo).\n *\n * For k >= 0:\n * - getVertexAt( vertices.length ) == getVertexAt( 0 )\n * - getVertexAt( vertices.length + k ) == getVertexAt( k )\n * - getVertexAt( -k ) == getVertexAt( vertices.length -k )\n *\n * @method getVertexAt\n * @param {number} index - The index of the desired vertex.\n * @instance\n * @memberof Polygon\n * @return {Vertex} At the given index.\n **/\n getVertexAt(index) {\n if (index < 0) {\n return this.vertices[this.vertices.length - (Math.abs(index) % this.vertices.length)];\n }\n else {\n return this.vertices[index % this.vertices.length];\n }\n }\n /**\n * Move the polygon's vertices by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof Polygon\n * @return {Polygon} this for chaining\n **/\n move(amount) {\n for (var i in this.vertices) {\n this.vertices[i].add(amount);\n }\n return this;\n }\n /**\n * Check if the given vertex is inside this polygon.<br>\n * <br>\n * Ray-casting algorithm found at<br>\n * https://stackoverflow.com/questions/22521982/check-if-point-inside-a-polygon\n *\n * @method containsVert\n * @param {XYCoords} vert - The vertex to check.\n * @return {boolean} True if the passed vertex is inside this polygon. The polygon is considered closed.\n * @instance\n * @memberof Polygon\n **/\n containsVert(vert) {\n // ray-casting algorithm based on\n // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\n var inside = false;\n for (var i = 0, j = this.vertices.length - 1; i < this.vertices.length; j = i++) {\n let xi = this.vertices[i].x, yi = this.vertices[i].y;\n let xj = this.vertices[j].x, yj = this.vertices[j].y;\n var intersect = yi > vert.y != yj > vert.y && vert.x < ((xj - xi) * (vert.y - yi)) / (yj - yi) + xi;\n if (intersect) {\n inside = !inside;\n }\n }\n return inside;\n }\n /**\n * Check if all given vertices are inside this polygon.<br>\n * <br>\n * This method just uses the `Polygon.containsVert` method.\n *\n * @method containsVerts\n * @param {XYCoords[]} verts - The vertices to check.\n * @return {boolean} True if all passed vertices are inside this polygon. The polygon is considered closed.\n * @instance\n * @memberof Polygon\n **/\n containsVerts(verts) {\n return verts.every((vert) => this.containsVert(vert));\n }\n /**\n * Check if the passed polygon is completly contained inside this polygon.\n *\n * This means:\n * - all polygon's vertices must be inside this polygon.\n * - the polygon has no edge intersections with this polygon.\n *\n * @param {Polygon} polygon - The polygon to check if contained.\n * @return {boolean}\n */\n containsPolygon(polygon) {\n for (var i = 0; i < polygon.vertices.length; i++) {\n if (!this.containsVert(polygon.vertices[i])) {\n return false;\n }\n }\n // All vertices are inside; check for intersections\n const lineSegment = new Line(new Vertex(), new Vertex());\n for (var i = 0; i < polygon.vertices.length; i++) {\n lineSegment.a.set(polygon.vertices[i]);\n lineSegment.b.set(polygon.vertices[(i + 1) % polygon.vertices.length]);\n if (this.lineIntersections(lineSegment, true).length > 0) {\n // Current segment has intersection(s) with this polygon.\n return false;\n }\n }\n return true;\n }\n /**\n * Calculate the area of the given polygon (unsigned).\n *\n * Note that this does not work for self-intersecting polygons.\n *\n * @method area\n * @instance\n * @memberof Polygon\n * @return {number}\n */\n area() {\n return Polygon.utils.area(this.vertices);\n }\n /**\n * Calulate the signed polyon area by interpreting the polygon as a matrix\n * and calculating its determinant.\n *\n * @method signedArea\n * @instance\n * @memberof Polygon\n * @return {number}\n */\n signedArea() {\n return Polygon.utils.signedArea(this.vertices);\n }\n /**\n * Get the winding order of this polgon: clockwise or counterclockwise.\n *\n * @method isClockwise\n * @instance\n * @memberof Polygon\n * @return {boolean}\n */\n isClockwise() {\n // return Polygon.utils.signedArea(this.vertices) < 0;\n return Polygon.utils.isClockwise(this.vertices);\n }\n /**\n * Get the perimeter of this polygon.\n * The perimeter is the absolute length of the outline.\n *\n * If this polygon is open then the last segment (connecting the first and the\n * last vertex) will be skipped.\n *\n * @method perimeter\n * @instance\n * @memberof Polygon\n * @return {number}\n */\n perimeter() {\n let length = 0;\n for (var i = 1; i < this.vertices.length; i++) {\n length += this.vertices[i - 1].distance(this.vertices[i]);\n }\n if (!this.isOpen && this.vertices.length > 1) {\n length += this.vertices[0].distance(this.vertices[this.vertices.length - 1]);\n }\n return length;\n }\n /**\n * Scale the polygon relative to the given center.\n *\n * @method scale\n * @param {number} factor - The scale factor.\n * @param {Vertex} center - The center of scaling.\n * @return {Polygon} this, for chaining.\n * @instance\n * @memberof Polygon\n **/\n scale(factor, center) {\n for (var i in this.vertices) {\n if (typeof this.vertices[i].scale == \"function\")\n this.vertices[i].scale(factor, center);\n else\n console.log(\"There seems to be a null vertex!\", this.vertices[i]);\n }\n return this;\n }\n /**\n * Rotate the polygon around the given center.\n *\n * @method rotate\n * @param {number} angle - The rotation angle.\n * @param {Vertex} center - The center of rotation.\n * @instance\n * @memberof Polygon\n * @return {Polygon} this, for chaining.\n **/\n rotate(angle, center) {\n for (var i in this.vertices) {\n this.vertices[i].rotate(angle, center);\n }\n return this;\n }\n /**\n * Get the mean `center` of this polygon by calculating the mean value of all vertices.\n *\n * Mean: (v[0] + v[1] + ... v[n-1]) / n\n *\n * @method getMeanCenter\n * @instance\n * @memberof Polygon\n * @return {Vertex|null} `null` is no vertices are available.\n */\n getMeanCenter() {\n if (this.vertices.length === 0) {\n return null;\n }\n const center = this.vertices[0].clone();\n for (var i = 1; i < this.vertices.length; i++) {\n center.add(this.vertices[i]);\n }\n center.x /= this.vertices.length;\n center.y /= this.vertices.length;\n return center;\n }\n /**\n * Get centroid.\n * Centroids define the barycenter of any non self-intersecting convex polygon.\n *\n * If the polygon is self intersecting or non konvex then the barycenter is not well defined.\n *\n * https://mathworld.wolfram.com/PolygonCentroid.html\n *\n * @method getCentroid\n * @instance\n * @memberof Polygon\n * @returns {Vertex|null}\n */\n getCentroid() {\n if (this.vertices.length === 0) {\n return null;\n }\n const center = new Vertex(0.0, 0.0);\n const n = this.vertices.length;\n for (var i = 0; i < n; i++) {\n // center.add(this.vertices[i]);\n const cur = this.vertices[i];\n const next = this.vertices[(i + 1) % n];\n var factor = cur.x * next.y - next.x * cur.y;\n center.x += (cur.x + next.x) * factor;\n center.y += (cur.y + next.y) * factor;\n }\n const area = this.area();\n center.x *= 1 / (6 * area);\n center.y *= 1 / (6 * area);\n return center;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this polygon.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines inside the edge bounds\n return Polygon.utils\n .locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly)\n .map(intersectionTuple => intersectionTuple.intersection);\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {\n const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param inVectorBoundsOnly\n * @returns\n */\n lineIntersectionTangentsIndices(line, inVectorBoundsOnly = false) {\n // Find the intersection tangents of all lines inside the edge bounds\n return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {\n const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);\n return {\n intersection: new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection),\n edgeIndex: intersectionTuple.edgeIndex\n };\n });\n }\n /**\n * Get the closest line-polygon-intersection point (closest the line point A).\n *\n * See demo `47-closest-vector-projection-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).\n * @returns {Vertex | null} - The intersection point within the polygon bounds.\n */\n closestLineIntersection(line, inVectorBoundsOnly = false) {\n var closestInterSectionIndex = this.closestLineIntersectionIndex(line, inVectorBoundsOnly);\n if (closestInterSectionIndex) {\n return closestInterSectionIndex.intersection;\n }\n else {\n return null;\n }\n }\n /**\n * Get the closest line-polygon-intersection point (closest the line point A) plus the edge index..\n *\n * See demo `63-measure-angles-on-polygon` for how it works.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).\n * @returns {PolygonIntersectionTuple| null} - A pair containing the intersection point and the affected polygon edge index.\n */\n closestLineIntersectionIndex(line, inVectorBoundsOnly = false) {\n const allIntersections = this.lineIntersections(line, inVectorBoundsOnly);\n if (allIntersections.length <= 0) {\n // Empty polygon -> no intersections\n return null;\n }\n // Find the closest intersection\n let closestIntersection = new Vertex(Number.MAX_VALUE, Number.MAX_VALUE);\n let closestInterSectionIndex = -1;\n let curDist = Number.MAX_VALUE;\n for (var i = 0; i < allIntersections.length; i++) {\n const curVert = allIntersections[i];\n const dist = curVert.distance(line.a);\n if (dist < curDist) {\n // && line.hasPoint(curVert)) {\n curDist = dist;\n closestIntersection = curVert;\n closestInterSectionIndex = i;\n }\n }\n // return [closestIntersection, closestInterSectionIndex];\n return { edgeIndex: closestInterSectionIndex, intersection: closestIntersection };\n }\n /**\n * Construct a new polygon from this polygon with more vertices on each edge. The\n * interpolation count determines the number of additional vertices on each edge.\n * An interpolation count of `0` will return a polygon that equals the source\n * polygon.\n *\n * @param {number} interpolationCount\n * @returns {Polygon} A polygon with `interpolationCount` more vertices (as as factor).\n */\n getInterpolationPolygon(interpolationCount) {\n const verts = [];\n for (var i = 0; i < this.vertices.length; i++) {\n const curVert = this.vertices[i];\n const nextVert = this.vertices[(i + 1) % this.vertices.length];\n verts.push(curVert.clone());\n // Add interpolation points\n if (!this.isOpen || i + 1 !== this.vertices.length) {\n const lerpAmount = 1.0 / (interpolationCount + 1);\n for (var j = 1; j <= interpolationCount; j++) {\n verts.push(curVert.clone().lerp(nextVert, lerpAmount * j));\n }\n }\n }\n return new Polygon(verts, this.isOpen);\n }\n /**\n * Convert this polygon into a new polygon with n evenly distributed vertices.\n *\n * @param {number} pointCount - Must not be negative.\n */\n getEvenDistributionPolygon(pointCount) {\n if (pointCount <= 0) {\n throw new Error(\"pointCount must be larger than zero; is \" + pointCount + \".\");\n }\n const result = new Polygon([], this.isOpen);\n if (this.vertices.length === 0) {\n return result;\n }\n // Fetch and add the start point from the source polygon\n let polygonPoint = new Vertex(this.vertices[0]);\n result.vertices.push(polygonPoint);\n if (this.vertices.length === 1) {\n return result;\n }\n const perimeter = this.perimeter();\n const stepSize = perimeter / pointCount;\n const n = this.vertices.length;\n let polygonIndex = 1;\n let nextPolygonPoint = new Vertex(this.vertices[1]);\n let segmentLength = polygonPoint.distance(nextPolygonPoint);\n let loopMax = this.isOpen ? n : n + 1;\n let curSegmentU = stepSize;\n var i = 1;\n while (i < pointCount && polygonIndex < loopMax) {\n // Check if next eq point is inside this segment\n if (curSegmentU < segmentLength) {\n let newPoint = polygonPoint.clone().lerpAbs(nextPolygonPoint, curSegmentU);\n result.vertices.push(newPoint);\n curSegmentU += stepSize;\n i++;\n }\n else {\n polygonIndex++;\n polygonPoint = nextPolygonPoint;\n nextPolygonPoint = new Vertex(this.vertices[polygonIndex % n]);\n curSegmentU = curSegmentU - segmentLength;\n segmentLength = polygonPoint.distance(nextPolygonPoint);\n }\n }\n return result;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounding box (bounds) of this polygon.\n *\n * @method getBounds\n * @instance\n * @memberof Polygon\n * @return {Bounds} The rectangular bounds of this polygon.\n **/\n getBounds() {\n return Bounds.computeFromVertices(this.vertices);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Create a deep copy of this polygon.\n *\n * @method clone\n * @instance\n * @memberof Polygon\n * @return {Polygon} The cloned polygon.\n */\n clone() {\n return new Polygon(this.vertices.map(vert => vert.clone()), this.isOpen);\n }\n /**\n * Create a new polygon without colinear adjacent edges. This method does not midify the current polygon\n * but creates a new one.\n *\n * Please note that this method does NOT create deep clones of the vertices. Use Polygon.clone() if you need to.\n *\n * Please also note that the `tolerance` may become really large here, as the denominator of two closely\n * parallel lines is usually pretty large. See the demo `57-eliminate-colinear-polygon-edges` to get\n * an impression of how denominators work.\n *\n * @method elimitateColinearEdges\n * @instance\n * @memberof Polygon\n * @param {number?} tolerance - (default is 1.0) The epsilon to detect co-linear edges.\n * @return {Polygon} A new polygon without co-linear adjacent edges – respective the given epsilon.\n */\n elimitateColinearEdges(tolerance) {\n const eps = typeof tolerance === \"undefined\" ? 1.0 : tolerance;\n const verts = this.vertices.slice(); // Creates a shallow copy\n let i = 0;\n var lineA = new Line(new Vertex(), new Vertex());\n var lineB = new Line(new Vertex(), new Vertex());\n while (i + 1 < verts.length && verts.length > 2) {\n const vertA = verts[i];\n const vertB = verts[(i + 1) % verts.length];\n lineA.a = vertA;\n lineA.b = vertB;\n lineB.a = vertB;\n let areColinear = false;\n let j = i + 2;\n do {\n let vertC = verts[j % verts.length];\n lineB.b = vertC;\n areColinear = lineA.colinear(lineB, eps);\n // console.log(\"are colinear?\", i, i + 1, j, areColinear);\n if (areColinear) {\n j++;\n }\n } while (areColinear);\n // Now j points to the first vertex that's NOT colinear to the current lineA\n // -> delete all vertices in between\n if (j - i > 2) {\n // Means: there have been 'colinear vertices' in between\n verts.splice(i + 1, j - i - 2);\n }\n i++;\n }\n return new Polygon(verts, this.isOpen);\n }\n /**\n * Convert this polygon to a sequence of quadratic Bézier curves.<br>\n * <br>\n * The first vertex in the returned array is the start point.<br>\n * The following sequence are pairs of control-point-and-end-point:\n * <pre>startPoint, controlPoint0, pathPoint1, controlPoint1, pathPoint2, controlPoint2, ..., endPoint</pre>\n *\n * @method toQuadraticBezierData\n * @return {Vertex[]} An array of 2d vertices that shape the quadratic Bézier curve.\n * @instance\n * @memberof Polygon\n **/\n toQuadraticBezierData() {\n if (this.vertices.length < 3)\n return [];\n var qbezier = [];\n var cc0 = this.vertices[0];\n var cc1 = this.vertices[1];\n var edgeCenter = new Vertex(cc0.x + (cc1.x - cc0.x) / 2, cc0.y + (cc1.y - cc0.y) / 2);\n qbezier.push(edgeCenter);\n var limit = this.isOpen ? this.vertices.length : this.vertices.length + 1;\n for (var t = 1; t < limit; t++) {\n cc0 = this.vertices[t % this.vertices.length];\n cc1 = this.vertices[(t + 1) % this.vertices.length];\n var edgeCenter = new Vertex(cc0.x + (cc1.x - cc0.x) / 2, cc0.y + (cc1.y - cc0.y) / 2);\n qbezier.push(cc0);\n qbezier.push(edgeCenter);\n cc0 = cc1;\n }\n return qbezier;\n }\n /**\n * Convert this polygon to a quadratic bezier curve, represented as an SVG data string.\n *\n * @method toQuadraticBezierSVGString\n * @return {string} The 'd' part for an SVG 'path' element.\n * @instance\n * @memberof Polygon\n **/\n toQuadraticBezierSVGString() {\n var qdata = this.toQuadraticBezierData();\n if (qdata.length == 0)\n return \"\";\n var buffer = [\"M \" + qdata[0].x + \" \" + qdata[0].y];\n for (var i = 1; i < qdata.length; i += 2) {\n buffer.push(\"Q \" + qdata[i].x + \" \" + qdata[i].y + \", \" + qdata[i + 1].x + \" \" + qdata[i + 1].y);\n }\n return buffer.join(\" \");\n }\n /**\n * Convert this polygon to a sequence of cubic Bézier curves.<br>\n * <br>\n * The first vertex in the returned array is the start point.<br>\n * The following sequence are triplets of (first-control-point, secnond-control-point, end-point):<br>\n * <pre>startPoint, controlPoint0_0, controlPoint1_1, pathPoint1, controlPoint1_0, controlPoint1_1, ..., endPoint</pre>\n *\n * @method toCubicBezierData\n * @param {number=} threshold - An optional threshold (default=1.0) how strong the curve segments\n * should over-/under-drive. Should be between 0.0 and 1.0 for best\n * results but other values are allowed.\n * @return {Vertex[]} An array of 2d vertices that shape the cubic Bézier curve.\n * @instance\n * @memberof Polygon\n **/\n toCubicBezierData(threshold) {\n if (typeof threshold == \"undefined\")\n threshold = 1.0;\n if (this.vertices.length < 3)\n return [];\n var cbezier = [];\n var a = this.vertices[0];\n var b = this.vertices[1];\n var edgeCenter = new Vertex(a.x + (b.x - a.x) / 2, a.y + (b.y - a.y) / 2);\n cbezier.push(edgeCenter);\n var limit = this.isOpen ? this.vertices.length - 1 : this.vertices.length;\n for (var t = 0; t < limit; t++) {\n var a = this.vertices[t % this.vertices.length];\n var b = this.vertices[(t + 1) % this.vertices.length];\n var c = this.vertices[(t + 2) % this.vertices.length];\n var aCenter = new Vertex(a.x + (b.x - a.x) / 2, a.y + (b.y - a.y) / 2);\n var bCenter = new Vertex(b.x + (c.x - b.x) / 2, b.y + (c.y - b.y) / 2);\n var a2 = new Vertex(aCenter.x + (b.x - aCenter.x) * threshold, aCenter.y + (b.y - aCenter.y) * threshold);\n var b0 = new Vertex(bCenter.x + (b.x - bCenter.x) * threshold, bCenter.y + (b.y - bCenter.y) * threshold);\n cbezier.push(a2);\n cbezier.push(b0);\n cbezier.push(bCenter);\n }\n return cbezier;\n }\n /**\n * Convert this polygon to a cubic bezier curve, represented as an SVG data string.\n *\n * @method toCubicBezierSVGString\n * @return {string} The 'd' part for an SVG 'path' element.\n * @instance\n * @memberof Polygon\n **/\n toCubicBezierSVGString(threshold) {\n var qdata = this.toCubicBezierData(threshold);\n if (qdata.length == 0) {\n return \"\";\n }\n var buffer = [\"M \" + qdata[0].x + \" \" + qdata[0].y];\n for (var i = 1; i < qdata.length; i += 3) {\n buffer.push(\"C \" +\n qdata[i].x +\n \" \" +\n qdata[i].y +\n \", \" +\n qdata[i + 1].x +\n \" \" +\n qdata[i + 1].y +\n \", \" +\n qdata[i + 2].x +\n \" \" +\n qdata[i + 2].y);\n }\n return buffer.join(\" \");\n }\n /**\n * Convert this polygon to a cubic bezier path instance.\n *\n * @method toCubicBezierPath\n * @param {number} threshold - The threshold, usually from 0.0 to 1.0.\n * @return {BezierPath} - A bezier path instance.\n * @instance\n * @memberof Polygon\n **/\n toCubicBezierPath(threshold) {\n var qdata = this.toCubicBezierData(threshold);\n // Conver the linear path vertices to a two-dimensional path array\n var pathdata = [];\n for (var i = 0; i + 3 < qdata.length; i += 3) {\n pathdata.push([qdata[i], qdata[i + 3], qdata[i + 1], qdata[i + 2]]);\n }\n return BezierPath.fromArray(pathdata);\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n for (var i = 0; i < this.vertices.length; i++) {\n this.vertices[i].destroy();\n }\n this.isDestroyed = true;\n }\n}\nPolygon.utils = {\n /**\n * Calculate the area of the given polygon (unsigned).\n *\n * Note that this does not work for self-intersecting polygons.\n *\n * @name area\n * @return {number}\n */\n area(vertices) {\n // Found at:\n // https://stackoverflow.com/questions/16285134/calculating-polygon-area\n let total = 0.0;\n for (var i = 0, l = vertices.length; i < l; i++) {\n const addX = vertices[i].x;\n const addY = vertices[(i + 1) % l].y;\n const subX = vertices[(i + 1) % l].x;\n const subY = vertices[i].y;\n total += addX * addY * 0.5;\n total -= subX * subY * 0.5;\n }\n return Math.abs(total);\n },\n isClockwise(vertices) {\n return Polygon.utils.signedArea(vertices) < 0;\n },\n /**\n * Calulate the signed polyon area by interpreting the polygon as a matrix\n * and calculating its determinant.\n *\n * @name signedArea\n * @return {number}\n */\n signedArea(vertices) {\n let sum = 0;\n const n = vertices.length;\n for (var i = 0; i < n; i++) {\n const j = (i + 1) % n;\n sum += (vertices[j].x - vertices[i].x) * (vertices[i].y + vertices[j].y);\n }\n return sum;\n },\n /**\n * Find intersections of a line with a polygon (vertices).\n *\n * @param {VertTuple<any>} line - The line to find intersections with.\n * @param {Array<Vertex>} vertices - The polygon's vertices.\n * @param {boolean} isOpen - True if the polygon is open, false otherwise.\n * @param {boolean} inVectorBoundsOnly - If only intersections in strict vector bounds should be returned.\n * @returns\n */\n locateLineIntersecion(line, vertices, isOpen, inVectorBoundsOnly) {\n // Find the intersections of all lines inside the edge bounds\n const intersectionPoints = [];\n var n = isOpen ? vertices.length - 1 : vertices.length;\n for (var i = 0; i < n; i++) {\n const polyLine = new Line(vertices[i % n], vertices[(i + 1) % n]);\n const intersection = polyLine.intersection(line);\n // true => only inside bounds\n // ignore last edge if open\n if (intersection !== null &&\n polyLine.hasPoint(intersection, true) &&\n (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {\n intersectionPoints.push({ edgeIndex: i, intersection: intersection });\n }\n }\n return intersectionPoints;\n }\n};\n//# sourceMappingURL=Polygon.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-05-11\n * @modified 2020-10-30 Added the static computeFromVertices function.\n * @modified 2020-11-19 Set min, max, width and height to private.\n * @modified 2021-02-02 Added the `toPolygon` method.\n * @modified 2021-06-21 (mid-summer) Added `getCenter` method.\n * @modified 2022-02-01 Added the `toString` function.\n * @modified 2022-10-09 Added the `fromDimension` function.\n * @modified 2022-11-28 Added the `clone` method.\n * @modified 2023-09-29 Added the `randomPoint` method.\n * @modified 2025-03-23 Added the `getMinDimension` and `getMaxDimension` methods.\n * @modified 2025-04-18 Change parameter type in `Bounds.computeFromVertices` from `Vertex` to more general `XYCoords`.\n * @modified 2025-04-19 Added methods to `Bounds` class: `getNorthPoint`, `getSouthPoint`, `getEastPoint` and `getWestPoint`.\n * @modified 2025-04-26 Added static method `Bounds.computeFromBoundsSet` to calculate containing bounds for a set of bounding boxes.\n * @modified 2025-10-17 Added the methods `Bounds.getSouthWestPoint`, `getNorthWestPoint`, `getNorthEastPoint` and `getSouthEastPoint`.\n * @modified 2025-10-18 Added method `Bounds.containsVert(XYCoords)`.\n * @modified 2025-10-28 Added the `Bounds.getWidth()` and `Bounds.getHeight()`.\n * @modified 2025-11-12 Added the `Bounds.getMoved()` method.\n * @version 1.11.0\n **/\nimport { Polygon } from \"./Polygon\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A bounds class with min and max values. Implementing IBounds.\n *\n * @requires XYCoords\n * @requires Vertex\n * @requires IBounds\n **/\nexport class Bounds {\n /**\n * The constructor.\n *\n * @constructor\n * @name Bounds\n * @param {XYCoords} min - The min values (x,y) as a XYCoords tuple.\n * @param {XYCoords} max - The max values (x,y) as a XYCoords tuple.\n **/\n constructor(min, max) {\n this.min = min;\n this.max = max;\n this.width = max.x - min.x;\n this.height = max.y - min.y;\n }\n /**\n * Check if the given vertex is inside this bounds.\n *\n * @method containsVert\n * @param {XYCoords} vert - The vertex to check.\n * @return {boolean} True if the passed vertex is inside this bounds.\n * @instance\n * @memberof Bounds\n **/\n containsVert(vert) {\n return this.min.x <= vert.x && vert.x < this.max.x && this.min.y <= vert.y && vert.y < this.max.y;\n }\n getWidth() {\n return this.max.x - this.min.x;\n }\n getHeight() {\n return this.max.y - this.min.y;\n }\n getScaled(scaleFactor) {\n const center = this.getCenter();\n const newMin = new Vertex(this.min).scale(scaleFactor, center);\n const newMax = new Vertex(this.max).scale(scaleFactor, center);\n return new Bounds(newMin, newMax);\n }\n getMoved(moveAmount) {\n const newMin = new Vertex(this.min).move(moveAmount);\n const newMax = new Vertex(this.max).move(moveAmount);\n return new Bounds(newMin, newMax);\n }\n /**\n * Get the center point of the north bound.\n *\n * @method getNorthPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"northmost\" centered point of this bounding box.\n */\n getNorthPoint() {\n return new Vertex(this.min.x + this.width / 2.0, this.min.y);\n }\n /**\n * Get the center point of the south bound.\n *\n * @method getNorthPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"southhmost\" centered point of this bounding box.\n */\n getSouthPoint() {\n return new Vertex(this.min.x + this.width / 2.0, this.max.y);\n }\n /**\n * Get the center point of the west bound.\n *\n * @method getWestPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"westhmost\" centered point of this bounding box.\n */\n getWestPoint() {\n return new Vertex(this.min.x, this.min.y + this.height / 2.0);\n }\n /**\n * Get the center point of the east bound.\n *\n * @method getEastPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"easthmost\" centered point of this bounding box.\n */\n getEastPoint() {\n return new Vertex(this.max.x, this.min.y + this.height / 2.0);\n }\n /**\n * Get the upper left corner point these bounds box.\n *\n * @method getNorthWestPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"northwestmost\" point of this bounding box.\n */\n getNorthWestPoint() {\n return new Vertex(this.min.x, this.min.y);\n }\n /**\n * Get the upper right corner point these bounds box.\n *\n * @method getNorthEastPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"northeastmost\" point of this bounding box.\n */\n getNorthEastPoint() {\n return new Vertex(this.max.x, this.min.y);\n }\n /**\n * Get the lower right corner point these bounds box.\n *\n * @method getSouthEastPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"southeastmost\" point of this bounding box.\n */\n getSouthEastPoint() {\n return new Vertex(this.max.x, this.max.y);\n }\n /**\n * Get the lower left corner point these bounds box.\n *\n * @method getSouthWestPoint\n * @instance\n * @memberof Bounds\n * @return {Vertex} The \"southwestmost\" point of this bounding box.\n */\n getSouthWestPoint() {\n return new Vertex(this.min.x, this.max.y);\n }\n /**\n * Convert this rectangular bounding box to a polygon with four vertices.\n *\n * @method toPolygon\n * @instance\n * @memberof Bounds\n * @return {Polygon} This bound rectangle as a polygon.\n */\n toPolygon() {\n return new Polygon([new Vertex(this.min), new Vertex(this.max.x, this.min.y), new Vertex(this.max), new Vertex(this.min.x, this.max.y)], false);\n }\n /**\n * Get the center of this boinding box.\n *\n * @method getCenter\n * @instance\n * @memberof Bounds\n * @returns {Vertex} The center of these bounds.\n */\n getCenter() {\n return new Vertex(this.min.x + (this.max.x - this.min.x) / 2.0, this.min.y + (this.max.y - this.min.y) / 2);\n }\n /**\n * Get the minimum of `width` and `height`.\n *\n * @returns {number} The value of Math.min( this.width, this.height )\n */\n getMinDimension() {\n return Math.min(this.width, this.height);\n }\n /**\n * Get the minimum of `width` and `height`.\n *\n * @returns {number} The value of Math.min( this.width, this.height )\n */\n getMaxDimension() {\n return Math.max(this.width, this.height);\n }\n /**\n * Generate a random point inside this bounds object. Safe areas at the border to avoid\n * included.\n *\n * @method randomPoint\n * @instance\n * @memberof Bounds\n * @param {horizontalSafeArea} - (optional) The horizonal (left and right) safe area. No vertex will be created here. Can be used as percent in (0.0 ... 0.1) interval.\n * @param {verticalSafeArea} - (optional) The vertical (top and bottom) safe area. No vertex will be created here. Can be used as percent in (0.0 ... 0.1) interval\n * @returns {Vertex} A pseudo random point inside these bounds.\n */\n randomPoint(horizontalSafeArea = 0, verticalSafeArea = 0) {\n // Check if the safe areas are meant as percent\n const absHorizontalSafeArea = horizontalSafeArea > 0 && horizontalSafeArea < 1 ? this.width * horizontalSafeArea : horizontalSafeArea;\n const absVerticalSafeArea = verticalSafeArea > 0 && verticalSafeArea < 1 ? this.height * verticalSafeArea : verticalSafeArea;\n return new Vertex(this.min.x + absHorizontalSafeArea + Math.random() * (this.width - 2 * absHorizontalSafeArea), this.min.y + absVerticalSafeArea + Math.random() * (this.height - 2 * absVerticalSafeArea));\n }\n /**\n * Convert these bounds to a human readable form.\n *\n * Note: the returned format might change in the future, so please do not\n * rely on the returned string format.\n *\n * @method toString\n * @instance\n * @memberof Bounds\n * @returns {string} Get these bounds in a human readable form.\n */\n toString() {\n return `{ min: ${this.min.toString()}, max : ${this.max.toString()}, width: ${this.width}, height : ${this.height} }`;\n }\n /**\n * Clone this bounds object (create a deep clone).\n *\n * @method clone\n * @instance\n * @memberof Bounds\n * @returns {Bounds} Creates a deep clone of this bounds object.\n */\n clone() {\n return new Bounds({ x: this.min.x, y: this.min.y }, { x: this.max.x, y: this.max.y });\n }\n /**\n * Compute the minimal bounding box for a given set of vertices.\n *\n * An empty vertex array will return an empty bounding box located at (0,0).\n *\n * @static\n * @method computeFromVertices\n * @memberof Bounds\n * @param {Array<XYCoords>} vertices - The set of vertices you want to get the bounding box for.\n * @return The minimal Bounds for the given vertices.\n **/\n static computeFromVertices(vertices) {\n if (vertices.length == 0) {\n return new Bounds(new Vertex(0, 0), new Vertex(0, 0));\n }\n let xMin = vertices[0].x;\n let xMax = vertices[0].x;\n let yMin = vertices[0].y;\n let yMax = vertices[0].y;\n let vert;\n for (var i in vertices) {\n vert = vertices[i];\n xMin = Math.min(xMin, vert.x);\n xMax = Math.max(xMax, vert.x);\n yMin = Math.min(yMin, vert.y);\n yMax = Math.max(yMax, vert.y);\n }\n return new Bounds(new Vertex(xMin, yMin), new Vertex(xMax, yMax));\n }\n /**\n * Compute the minimal bounding box for a given set of existing bounding boxes.\n *\n * An empty vertex array will return an empty bounding box located at (0,0).\n *\n * @static\n * @method computeFromBoundsSet\n * @memberof Bounds\n * @param {Array<IBounds>} boundingBoxes - The set of existing bounding boxes to get the containing bounding box for.\n * @return The minimal Bounds for the given bounds instances.\n **/\n static computeFromBoundsSet(boundingBoxes) {\n if (boundingBoxes.length == 0) {\n return new Bounds(new Vertex(0, 0), new Vertex(0, 0));\n }\n let xMin = boundingBoxes[0].min.x;\n let xMax = boundingBoxes[0].max.x;\n let yMin = boundingBoxes[0].min.y;\n let yMax = boundingBoxes[0].min.y;\n let bounds;\n for (var i in boundingBoxes) {\n bounds = boundingBoxes[i];\n xMin = Math.min(xMin, bounds.min.x);\n xMax = Math.max(xMax, bounds.max.x);\n yMin = Math.min(yMin, bounds.min.y);\n yMax = Math.max(yMax, bounds.min.y);\n }\n return new Bounds(new Vertex(xMin, yMin), new Vertex(xMax, yMax));\n }\n /**\n * Create a new `Bounds` instance just from `width` and `height`, located at (0,0) or the optionally given origin.\n *\n * @param {number} width - The width of the bounds\n * @param {number} height - The height of the bounds\n * @param {XYCoords={x:0,y:0}} origin - [optional] A origin to locate the new Bounds object at.\n * @returns {Bounds} A new `Bounds` instance width given width and height, located at (0,0) or the given origin..\n */\n static fromDimension(width, height, origin) {\n return new Bounds(origin !== null && origin !== void 0 ? origin : { x: 0, y: 0 }, { x: (origin ? origin.x : 0) + width, y: (origin ? origin.y : 0) + height });\n }\n} // END class bounds\n//# sourceMappingURL=Bounds.js.map","/**\n * @author Ikaros Kappler\n * @date 2013-08-15\n * @modified 2018-08-16 Added a closure. Removed the wrapper class 'IKRS'. Replaced class THREE.Vector2 by Vertex class.\n * @modified 2018-11-19 Added the fromArray(Array) function.\n * @modified 2018-11-28 Added the locateCurveByPoint(Vertex) function.\n * @modified 2018-12-04 Added the toSVGPathData() function.\n * @modified 2019-03-20 Added JSDoc tags.\n * @modified 2019-03-23 Changed the signatures of getPoint, getPointAt and getTangent (!version 2.0).\n * @modified 2019-12-02 Fixed the updateArcLength function. It used the wrong pointAt function (was renamed before).\n * @modified 2020-02-06 Added the getSubCurveAt(number,number) function.\n * @modified 2020-02-06 Fixed a serious bug in the arc lenght calculation (length was never reset, urgh).\n * @modified 2020-02-07 Added the isInstance(any) function.\n * @modified 2020-02-10 Added the reverse() function.\n * @modified 2020-02-10 Fixed the translate(...) function (returning 'this' was missing).\n * @modified 2020-03-24 Ported this class from vanilla JS to Typescript.\n * @modified 2020-06-03 Added the getBounds() function.\n * @modified 2020-07-14 Changed the moveCurvePoint(...,Vertex) to moveCurvePoint(...,XYCoords), which is more generic.\n * @modified 2020-07-24 Added the getClosestT function and the helper function locateIntervalByDistance(...).\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `toSVGPathData` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2022-10-17 The `CubicBezierCurve` class now implements the new `PathSegment` interface.\n * @modified 2023-09-30 Added the function `CubicbezierCurve.getSubCurve(number,number)` – similar to `getSubCurveAt(...)` but with absolute position parameters.\n * @modified 2023-10-07 Added the `trimEnd`, `trimEndAt`, `trimStart`, `trimStartAt` methods.\n * @modified 2025-04-09 Added the `CubicBezierCurve.move` method to match the convention – which just calls `translate`.\n * @modified 2025-04-09 Modified the `CubicBezierCurve.translate` method: chaning parameter `Vertex` to more generalized `XYCoords`.\n * @modified 2025-04-13 Changed visibility of `CubicBezierCurve.utils` from 'private' to 'public'.\n * @modified 2025-04-13 Added helper function `CubicBezierCurve.utils.bezierCoeffs`.\n * @modified 2025-04-13 Added helper functopn `CubicBezierCurve.utils.sgn(number)` for division safe sign calculation.\n * @modified 2025-03-13 Class `CubicBezierCurve` is now implementing interface `Intersectable`.\n * @modified 2025-04-18 Added evaluation method for cubic Bézier curves `CubicBezierCurve.utils.evaluateT`.\n * @modified 2025-04-18 Refactored method `CubicBezierCurve.getPointAt` to use `evaluateT`.\n * @modified 2025-04-18 Fixed the `CubicBezierCurve.getBounds` method: now returning the real bounding box. Before it was an approximated one.\n * @modified 2025-ß4-18 Added helper methods for bounding box calculation `CubucBezierCurve.util.cubicPolyMinMax` and `cubicPoly`.\n * @version 2.9.0\n *\n * @file CubicBezierCurve\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\nimport { Vector } from \"./Vector\";\n/**\n * @classdesc A refactored cubic bezier curve class.\n *\n * @requires Bounds\n * @requires Vertex\n * @requires Vector\n * @requires XYCoords\n * @requires UID\n * @requires UIDGenerator\n */\nexport class CubicBezierCurve {\n /**\n * The constructor.\n *\n * @constructor\n * @name CubicBezierCurve\n * @param {Vertex} startPoint - The Bézier curve's start point.\n * @param {Vertex} endPoint - The Bézier curve's end point.\n * @param {Vertex} startControlPoint - The Bézier curve's start control point.\n * @param {Vertex} endControlPoint - The Bézier curve's end control point.\n **/\n constructor(startPoint, endPoint, startControlPoint, endControlPoint) {\n /** @constant {number} */\n this.START_POINT = CubicBezierCurve.START_POINT;\n /** @constant {number} */\n this.START_CONTROL_POINT = CubicBezierCurve.START_CONTROL_POINT;\n /** @constant {number} */\n this.END_CONTROL_POINT = CubicBezierCurve.END_CONTROL_POINT;\n /** @constant {number} */\n this.END_POINT = CubicBezierCurve.END_POINT;\n this.uid = UIDGenerator.next();\n this.startPoint = startPoint;\n this.startControlPoint = startControlPoint;\n this.endPoint = endPoint;\n this.endControlPoint = endControlPoint;\n this.curveIntervals = 30;\n // An array of vertices\n this.segmentCache = [];\n // An array of floats\n this.segmentLengths = [];\n // float\n // this.arcLength = null;\n this.updateArcLengths();\n }\n /**\n * Move the given curve point (the start point, end point or one of the two\n * control points).\n *\n * @method moveCurvePoint\n * @param {number} pointID - The numeric identicator of the point to move. Use one of the four eBezierPoint constants.\n * @param {XYCoords} moveAmount - The amount to move the specified point by.\n * @param {boolean} moveControlPoint - Move the control points along with their path point (if specified point is a path point).\n * @param {boolean} updateArcLengths - Specifiy if the internal arc segment buffer should be updated.\n * @instance\n * @memberof CubicBezierCurve\n * @return {void}\n **/\n moveCurvePoint(pointID, moveAmount, moveControlPoint, updateArcLengths) {\n if (pointID == this.START_POINT) {\n this.getStartPoint().add(moveAmount);\n if (moveControlPoint)\n this.getStartControlPoint().add(moveAmount);\n }\n else if (pointID == this.START_CONTROL_POINT) {\n this.getStartControlPoint().add(moveAmount);\n }\n else if (pointID == this.END_CONTROL_POINT) {\n this.getEndControlPoint().add(moveAmount);\n }\n else if (pointID == this.END_POINT) {\n this.getEndPoint().add(moveAmount);\n if (moveControlPoint)\n this.getEndControlPoint().add(moveAmount);\n }\n else {\n console.log(`[CubicBezierCurve.moveCurvePoint] pointID '${pointID}' invalid.`);\n }\n if (updateArcLengths)\n this.updateArcLengths();\n }\n /**\n * Translate the whole curve by the given {x,y} amount: moves all four points.\n *\n * @method translate\n * @param {XYCoords} amount - The amount to translate this curve by.\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} this (for chaining).\n **/\n translate(amount) {\n this.startPoint.add(amount);\n this.startControlPoint.add(amount);\n this.endControlPoint.add(amount);\n this.endPoint.add(amount);\n return this;\n }\n /**\n * Translate the whole curve by the given {x,y} amount: moves all four points.\n *\n * @method translate\n * @param {XYCoords} amount - The amount to translate this curve by.\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} this (for chaining).\n **/\n move(amount) {\n return this.translate(amount);\n }\n /**\n * Reverse this curve, means swapping start- and end-point and swapping\n * start-control- and end-control-point.\n *\n * @method reverse\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} this (for chaining).\n **/\n reverse() {\n let tmp = this.startPoint;\n this.startPoint = this.endPoint;\n this.endPoint = tmp;\n tmp = this.startControlPoint;\n this.startControlPoint = this.endControlPoint;\n this.endControlPoint = tmp;\n return this;\n }\n /**\n * Get the total curve length.<br>\n * <br>\n * As not all Bézier curved have a closed formula to calculate their lengths, this\n * implementation uses a segment buffer (with a length of 30 segments). So the\n * returned length is taken from the arc segment buffer.<br>\n * <br>\n * Note that if the curve points were changed and the segment buffer was not\n * updated this function might return wrong (old) values.\n *\n * @method getLength\n * @instance\n * @memberof CubicBezierCurve\n * @return {number} >= 0\n **/\n getLength() {\n return this.arcLength;\n }\n /**\n * Uptate the internal arc segment buffer and their lengths.<br>\n * <br>\n * All class functions update the buffer automatically; if any\n * curve point is changed by other reasons you should call this\n * function to keep actual values in the buffer.\n *\n * @method updateArcLengths\n * @instance\n * @memberof CubicBezierCurve\n * @return {void}\n **/\n updateArcLengths() {\n let pointA = this.startPoint.clone();\n let pointB = new Vertex(0, 0);\n let curveStep = 1.0 / this.curveIntervals;\n // Clear segment cache\n this.segmentCache = [];\n // Push start point into buffer\n this.segmentCache.push(this.startPoint);\n this.segmentLengths = [];\n let newLength = 0.0;\n var t = 0.0;\n let tmpLength;\n while (t <= 1.0) {\n pointB = this.getPointAt(t);\n // Store point into cache\n this.segmentCache.push(pointB);\n // Calculate segment length\n tmpLength = pointA.distance(pointB);\n this.segmentLengths.push(tmpLength);\n newLength += tmpLength;\n pointA = pointB;\n t += curveStep;\n }\n this.arcLength = newLength;\n }\n /**\n * Get a 't' (relative position on curve) with the closest distance to point 'p'.\n *\n * The returned number is 0.0 <= t <= 1.0. Use the getPointAt(t) function to retrieve the actual curve point.\n *\n * This function uses a recursive approach by cutting the curve into several linear segments.\n *\n * @method getClosestT\n * @instance\n * @memberof CubicBezierCurve\n * @param {Vertex} p - The point to find the closest position ('t' on the curve).\n * @return {number}\n **/\n getClosestT(p) {\n // We would like to have an error that's not larger than 1.0.\n var desiredEpsilon = 1.0;\n var result = { t: 0, tPrev: 0.0, tNext: 1.0 };\n var iteration = 0;\n do {\n result = this.locateIntervalByDistance(p, result.tPrev, result.tNext, this.curveIntervals);\n iteration++;\n // Be sure: stop after 4 iterations\n } while (iteration < 4 && this.getPointAt(result.tPrev).distance(this.getPointAt(result.tNext)) > desiredEpsilon);\n return result.t;\n }\n /**\n * This helper function locates the 't' on a fixed step interval with the minimal distance\n * between the curve (at 't') and the given point.\n *\n * Furthermore you must specify a sub curve (start 't' and end 't') you want to search on.\n * Using tStart=0.0 and tEnd=1.0 will search on the full curve.\n *\n * @param {Vertex} p - The point to find the closest curve point for.\n * @param {number} tStart - The start position (start 't' of the sub curve). Should be >= 0.0.\n * @param {number} tEnd - The end position (end 't' of the sub curve). Should be <= 1.0.\n * @param {number} stepCount - The number of steps to check within the interval.\n *\n * @return {object} - An object with t, tPrev and tNext (numbers).\n **/\n locateIntervalByDistance(p, tStart, tEnd, stepCount) {\n var minIndex = -1;\n var minDist = 0;\n var t = 0.0;\n const tDiff = tEnd - tStart;\n for (var i = 0; i <= stepCount; i++) {\n t = tStart + tDiff * (i / stepCount);\n var vert = this.getPointAt(t);\n var dist = vert.distance(p);\n if (minIndex == -1 || dist < minDist) {\n minIndex = i;\n minDist = dist;\n }\n }\n return {\n t: tStart + tDiff * (minIndex / stepCount),\n tPrev: tStart + tDiff * (Math.max(0, minIndex - 1) / stepCount),\n tNext: tStart + tDiff * (Math.min(stepCount, minIndex + 1) / stepCount)\n };\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this bezier curve.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getClosestT\n * @instance\n * @memberof CubicBezierCurve\n * @return {Bounds} The bounds of this ellipse.\n **/\n getBounds() {\n // Thanks to Richard \"RM\" for the Bézier bounds calculatin\n // https://jsfiddle.net/SalixAlba/QQnvm/4/\n const xMinMax = CubicBezierCurve.utils.cubicPolyMinMax(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x);\n const xl = xMinMax.min;\n const xh = xMinMax.max;\n const yMinMax = CubicBezierCurve.utils.cubicPolyMinMax(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y);\n const yl = yMinMax.min;\n const yh = yMinMax.max;\n return Bounds.computeFromVertices([\n { x: xl, y: yl },\n { x: xl, y: yh },\n { x: xh, y: yh },\n { x: xh, y: yl }\n ]);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Get the start point of the curve.<br>\n * <br>\n * This function just returns this.startPoint.\n *\n * @method getStartPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.startPoint\n **/\n getStartPoint() {\n return this.startPoint;\n }\n /**\n * Get the end point of the curve.<br>\n * <br>\n * This function just returns this.endPoint.\n *\n * @method getEndPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.endPoint\n **/\n getEndPoint() {\n return this.endPoint;\n }\n /**\n * Get the start control point of the curve.<br>\n * <br>\n * This function just returns this.startControlPoint.\n *\n * @method getStartControlPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.startControlPoint\n **/\n getStartControlPoint() {\n return this.startControlPoint;\n }\n /**\n * Get the end control point of the curve.<br>\n * <br>\n * This function just returns this.endControlPoint.\n *\n * @method getEndControlPoint\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex} this.endControlPoint\n **/\n getEndControlPoint() {\n return this.endControlPoint;\n }\n /**\n * Get one of the four curve points specified by the passt point ID.\n *\n * @method getEndControlPoint\n * @param {number} id - One of START_POINT, START_CONTROL_POINT, END_CONTROL_POINT or END_POINT.\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPointByID(id) {\n if (id == this.START_POINT)\n return this.startPoint;\n if (id == this.END_POINT)\n return this.endPoint;\n if (id == this.START_CONTROL_POINT)\n return this.startControlPoint;\n if (id == this.END_CONTROL_POINT)\n return this.endControlPoint;\n throw new Error(`Invalid point ID '${id}'.`);\n }\n /**\n * Get the curve point at a given position t, where t is in [0,1].<br>\n * <br>\n * @see Line.pointAt\n *\n * @method getPointAt\n * @param {number} t - The position on the curve in [0,1] (0 means at\n * start point, 1 means at end point, other values address points in bertween).\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPointAt(t) {\n // Perform some powerful math magic\n // TODO: cleanup\n // const x: number =\n // this.startPoint.x * Math.pow(1.0 - t, 3) +\n // this.startControlPoint.x * 3 * t * Math.pow(1.0 - t, 2) +\n // this.endControlPoint.x * 3 * Math.pow(t, 2) * (1.0 - t) +\n // this.endPoint.x * Math.pow(t, 3);\n // const y: number =\n // this.startPoint.y * Math.pow(1.0 - t, 3) +\n // this.startControlPoint.y * 3 * t * Math.pow(1.0 - t, 2) +\n // this.endControlPoint.y * 3 * Math.pow(t, 2) * (1.0 - t) +\n // this.endPoint.y * Math.pow(t, 3);\n const x = CubicBezierCurve.utils.evaluateT(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x, t);\n const y = CubicBezierCurve.utils.evaluateT(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y, t);\n return new Vertex(x, y);\n }\n /**\n * Get the curve point at a given position u, where u is in [0,arcLength].<br>\n * <br>\n * @see CubicBezierCurve.getPointAt\n *\n * @method getPoint\n * @param {number} u - The position on the curve in [0,arcLength] (0 means at\n * start point, arcLength means at end point, other values address points in bertween).\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPoint(u) {\n return this.getPointAt(u / this.arcLength);\n }\n /**\n * Get the curve tangent vector at a given absolute curve position t in [0,1].<br>\n * <br>\n * Note that the returned tangent vector (end point) is not normalized and relative to (0,0).\n *\n * @method getTangent\n * @param {number} t - The position on the curve in [0,1].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getTangentAt(t) {\n const a = this.getStartPoint();\n const b = this.getStartControlPoint();\n const c = this.getEndControlPoint();\n const d = this.getEndPoint();\n // This is the shortened one\n const t2 = t * t;\n // (1 - t)^2 = (1-t)*(1-t) = 1 - t - t + t^2 = 1 - 2*t + t^2\n const nt2 = 1 - 2 * t + t2;\n const tX = -3 * a.x * nt2 + b.x * (3 * nt2 - 6 * (t - t2)) + c.x * (6 * (t - t2) - 3 * t2) + 3 * d.x * t2;\n const tY = -3 * a.y * nt2 + b.y * (3 * nt2 - 6 * (t - t2)) + c.y * (6 * (t - t2) - 3 * t2) + 3 * d.y * t2;\n // Note: my implementation does NOT normalize tangent vectors!\n return new Vertex(tX, tY);\n }\n /**\n * Trim off a start section of this curve. The position parameter `uValue` is the absolute position on the\n * curve in `[0...arcLength]`.\n * The remaining curve will be the one in the bounds `[uValue,1]` (so `[0.0,uValue]` is cut off).\n *\n * Note this function just converts the absolute parameter to a relative one and call `trimStartAt`.\n *\n * @method trimStart\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} uValue - The absolute position parameter where to cut off the head curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimStart(uValue) {\n return this.trimStartAt(this.convertU2T(uValue));\n }\n /**\n * Trim off a start section of this curve. The position parameter `t` is the relative position in [0..1].\n * The remaining curve will be the one in the bounds `[uValue,1]` (so `[0.0,uValue]` is cut off).\n *\n * @method trimStartAt\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} t - The relative position parameter where to cut off the head curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimStartAt(t) {\n const subCurbePoints = CubicBezierCurve.utils.getSubCurvePointsAt(this, t, 1.0);\n this.startPoint.set(subCurbePoints[0]);\n this.startControlPoint.set(subCurbePoints[2]);\n this.endPoint.set(subCurbePoints[1]);\n this.endControlPoint.set(subCurbePoints[3]);\n this.updateArcLengths();\n return this;\n }\n /**\n * Trim off the end of this curve. The position parameter `uValue` is the absolute position on the\n * curve in `[0...arcLength]`.\n * The remaining curve will be the one in the bounds `[0,uValue]` (so `[1.0-uValue,1.0]` is cut off).\n *\n * Note this function just converts the absolute parameter to a relative one and call `trimEndAt`.\n *\n * @method trimEnd\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} uValue - The absolute position parameter where to cut off the tail curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimEnd(uValue) {\n return this.trimEndAt(this.convertU2T(uValue));\n }\n /**\n * Trim off the end of this curve. The position parameter `t` is the relative position in [0..1].\n * The remaining curve will be the one in the bounds `[0,t]` (so `[1.0-t,1.0]` is cut off).\n *\n * @method trimEndAt\n * @instance\n * @memberof CubicBezierCurve\n * @param {number} t - The relative position parameter where to cut off the tail curve.\n * @returns {CubicBezierCurve} `this` for chanining.\n */\n trimEndAt(t) {\n const subCurbePoints = CubicBezierCurve.utils.getSubCurvePointsAt(this, 0.0, t);\n this.startPoint.set(subCurbePoints[0]);\n this.startControlPoint.set(subCurbePoints[2]);\n this.endPoint.set(subCurbePoints[1]);\n this.endControlPoint.set(subCurbePoints[3]);\n this.updateArcLengths();\n return this;\n }\n /**\n * Get a sub curve at the given start end end positions (values on the curve's length, between 0 and curve.arcLength).\n *\n * tStart >= tEnd is allowed, you will get a reversed sub curve then.\n *\n * @method getSubCurve\n * @param {number} tStart – The start position of the desired sub curve (must be in [0..arcLength]).\n * @param {number} tEnd – The end position if the desired cub curve (must be in [0..arcLength]).\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} The sub curve as a new curve.\n **/\n getSubCurve(uStart, uEnd) {\n return this.getSubCurveAt(this.convertU2T(uStart), this.convertU2T(uEnd));\n }\n /**\n * Get a sub curve at the given start end end offsets (values between 0.0 and 1.0).\n *\n * tStart >= tEnd is allowed, you will get a reversed sub curve then.\n *\n * @method getSubCurveAt\n * @param {number} tStart – The start offset of the desired sub curve (must be in [0..1]).\n * @param {number} tEnd – The end offset if the desired cub curve (must be in [0..1]).\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} The sub curve as a new curve.\n **/\n getSubCurveAt(tStart, tEnd) {\n // This 'splits' the curve at the given point at t.\n const subCurbePoints = CubicBezierCurve.utils.getSubCurvePointsAt(this, tStart, tEnd);\n return new CubicBezierCurve(subCurbePoints[0], subCurbePoints[1], subCurbePoints[2], subCurbePoints[3]);\n }\n /**\n * Convert a relative curve position u to the absolute curve position t.\n *\n * @method convertU2t\n * @param {number} u - The relative position on the curve in [0,arcLength].\n * @instance\n * @memberof CubicBezierCurve\n * @return {number}\n **/\n convertU2T(u) {\n return Math.max(0.0, Math.min(1.0, u / this.arcLength));\n }\n /**\n * Get the curve tangent vector at a given relative position u in [0,arcLength].<br>\n * <br>\n * Note that the returned tangent vector (end point) is not normalized.\n *\n * @method getTangent\n * @param {number} u - The position on the curve in [0,arcLength].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getTangent(u) {\n return this.getTangentAt(this.convertU2T(u));\n }\n /**\n * Get the curve perpendicular at a given relative position u in [0,arcLength] as a vector.<br>\n * <br>\n * Note that the returned vector (end point) is not normalized.\n *\n * @method getPerpendicular\n * @param {number} u - The relative position on the curve in [0,arcLength].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPerpendicular(u) {\n return this.getPerpendicularAt(this.convertU2T(u));\n }\n /**\n * Get the curve perpendicular at a given absolute position t in [0,1] as a vector.<br>\n * <br>\n * Note that the returned vector (end point) is not normalized.\n *\n * @method getPerpendicularAt\n * @param {number} u - The absolute position on the curve in [0,1].\n * @instance\n * @memberof CubicBezierCurve\n * @return {Vertex}\n **/\n getPerpendicularAt(t) {\n const tangentVector = this.getTangentAt(t);\n return new Vertex(tangentVector.y, -tangentVector.x);\n }\n /**\n * Clone this Bézier curve (deep clone).\n *\n * @method clone\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve}\n **/\n clone() {\n return new CubicBezierCurve(this.getStartPoint().clone(), this.getEndPoint().clone(), this.getStartControlPoint().clone(), this.getEndControlPoint().clone());\n }\n //---BEGIN PathSegment-------------------------\n /**\n * Get the tangent's end point at the start point of this segment.\n *\n * @method getStartTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the starting point's tangent.\n */\n getStartTangent() {\n return this.startControlPoint;\n }\n /**\n * Get the tangent's end point at the end point of this segment.\n *\n * @method getEndTangent\n * @memberof PathSegment\n * @return {Vertex} The end point of the ending point's tangent.\n */\n getEndTangent() {\n return this.endControlPoint;\n }\n //---END PathSegment-------------------------\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this shape.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections with the shape outline.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n const intersectionTs = this.lineIntersectionTs(line);\n const intersectionPoints = intersectionTs.map((t) => {\n return this.getPointAt(t);\n });\n if (inVectorBoundsOnly) {\n // const maxDist = line.length();\n return intersectionPoints.filter((vert) => line.hasPoint(vert, true));\n }\n else {\n return intersectionPoints;\n }\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n const intersectionTs = this.lineIntersectionTs(line);\n const intersectionTangents = intersectionTs.map((t) => {\n const startPoint = this.getPointAt(t);\n const endPoint = this.getTangentAt(t);\n return new Vector(startPoint, endPoint.add(startPoint));\n });\n if (inVectorBoundsOnly) {\n return intersectionTangents.filter((vec) => line.hasPoint(vec.a, true));\n }\n else {\n return intersectionTangents;\n }\n }\n //--- END --- Implement interface `Intersectable`\n lineIntersectionTs(line) {\n var A = line.b.y - line.a.y; // A=y2-y1\n var B = line.a.x - line.b.x; // B=x1-x2\n 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)\n // var bx = bezierCoeffs(px[0], px[1], px[2], px[3]);\n // var by = bezierCoeffs(py[0], py[1], py[2], py[3]);\n var bx = CubicBezierCurve.utils.bezierCoeffs(this.startPoint.x, this.startControlPoint.x, this.endControlPoint.x, this.endPoint.x);\n var by = CubicBezierCurve.utils.bezierCoeffs(this.startPoint.y, this.startControlPoint.y, this.endControlPoint.y, this.endPoint.y);\n const poly = Array(4);\n poly[0] = A * bx[0] + B * by[0]; /*t^3*/\n poly[1] = A * bx[1] + B * by[1]; /*t^2*/\n poly[2] = A * bx[2] + B * by[2]; /*t*/\n poly[3] = A * bx[3] + B * by[3] + C; /*1*/\n var roots = CubicBezierCurve.utils.cubicRoots(poly);\n return roots.filter((root) => root != -1);\n }\n /**\n * Check if this and the specified curve are equal.<br>\n * <br>\n * All four points need to be equal for this, the Vertex.equals function is used.<br>\n * <br>\n * Please note that this function is not type safe (comparison with any object will fail).\n *\n * @method clone\n * @param {CubicBezierCurve} curve - The curve to compare with.\n * @instance\n * @memberof CubicBezierCurve\n * @return {boolean}\n **/\n equals(curve) {\n // Note: in the earlier vanilla-JS version this was callable with plain objects.\n // Let's see if this restricted version works out.\n if (!curve)\n return false;\n if (!curve.startPoint || !curve.endPoint || !curve.startControlPoint || !curve.endControlPoint)\n return false;\n return (this.startPoint.equals(curve.startPoint) &&\n this.endPoint.equals(curve.endPoint) &&\n this.startControlPoint.equals(curve.startControlPoint) &&\n this.endControlPoint.equals(curve.endControlPoint));\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.startPoint.destroy();\n this.endPoint.destroy();\n this.startControlPoint.destroy();\n this.endControlPoint.destroy();\n this.isDestroyed = true;\n }\n /**\n * Quick check for class instance.\n * Is there a better way?\n *\n * @method isInstance\n * @param {any} obj - Check if the passed object/value is an instance of CubicBezierCurve.\n * @instance\n * @memberof CubicBezierCurve\n * @return {boolean}\n **/\n static isInstance(obj) {\n // Note: check this again\n /* OLD VANILLA JS IMPLEMENTATION */\n /* if( typeof obj != \"object\" )\n return false;\n function hasXY(v) {\n return typeof v != \"undefined\" && typeof v.x == \"number\" && typeof v.y == \"number\";\n }\n return typeof obj.startPoint == \"object\" && hasXY(obj.startPoint)\n && typeof obj.endPoint == \"object\" && hasXY(obj.endPoint)\n && typeof obj.startControlPoint == \"object\" && hasXY(obj.startControlPoint)\n && typeof obj.endControlPoint == \"object\" && hasXY(obj.endControlPoint);\n */\n return obj instanceof CubicBezierCurve;\n }\n /**\n * Convert this curve to a JSON string.\n *\n * @method toJSON\n * @param {boolean=} [prettyFormat=false] - If set to true the function will add line breaks.\n * @instance\n * @memberof CubicBezierCurve\n * @return {string} The JSON data.\n **/\n toJSON(prettyFormat) {\n var jsonString = \"{ \" + // begin object\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"startPoint\" : [' +\n this.getStartPoint().x +\n \",\" +\n this.getStartPoint().y +\n \"], \" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"endPoint\" : [' +\n this.getEndPoint().x +\n \",\" +\n this.getEndPoint().y +\n \"], \" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"startControlPoint\": [' +\n this.getStartControlPoint().x +\n \",\" +\n this.getStartControlPoint().y +\n \"], \" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n '\"endControlPoint\" : [' +\n this.getEndControlPoint().x +\n \",\" +\n this.getEndControlPoint().y +\n \"]\" +\n (prettyFormat ? \"\\n\\t\" : \"\") +\n \" }\"; // end object\n return jsonString;\n }\n /**\n * Parse a Bézier curve from the given JSON string.\n *\n * @method fromJSON\n * @param {string} jsonString - The JSON data to parse.\n * @memberof CubicBezierCurve\n * @static\n * @throws An exception if the JSON string is malformed.\n * @return {CubicBezierCurve}\n **/\n static fromJSON(jsonString) {\n var obj = JSON.parse(jsonString);\n return CubicBezierCurve.fromObject(obj);\n }\n /**\n * Try to convert the passed object to a CubicBezierCurve.\n *\n * @method fromObject\n * @param {object} obj - The object to convert.\n * @memberof CubicBezierCurve\n * @static\n * @throws An exception if the passed object is malformed.\n * @return {CubicBezierCurve}\n **/\n static fromObject(obj) {\n if (typeof obj !== \"object\")\n throw \"Can only build from object.\";\n if (!obj.startPoint)\n throw 'Object member \"startPoint\" missing.';\n if (!obj.endPoint)\n throw 'Object member \"endPoint\" missing.';\n if (!obj.startControlPoint)\n throw 'Object member \"startControlPoint\" missing.';\n if (!obj.endControlPoint)\n throw 'Object member \"endControlPoint\" missing.';\n return new CubicBezierCurve(new Vertex(obj.startPoint[0], obj.startPoint[1]), new Vertex(obj.endPoint[0], obj.endPoint[1]), new Vertex(obj.startControlPoint[0], obj.startControlPoint[1]), new Vertex(obj.endControlPoint[0], obj.endControlPoint[1]));\n }\n /**\n * Convert a 4-element array of vertices to a cubic bézier curve.\n *\n * @method fromArray\n * @param {Vertex[]} arr - [ startVertex, endVertex, startControlVertex, endControlVertex ]\n * @memberof CubicBezierCurve\n * @throws An exception if the passed array is malformed.\n * @return {CubicBezierCurve}\n **/\n static fromArray(arr) {\n if (!Array.isArray(arr))\n throw \"Can only build from object.\";\n if (arr.length != 4)\n throw \"Can only build from array with four elements.\";\n return new CubicBezierCurve(arr[0], arr[1], arr[2], arr[3]);\n }\n}\n/** @constant {number} */\nCubicBezierCurve.START_POINT = 0;\n/** @constant {number} */\nCubicBezierCurve.START_CONTROL_POINT = 1;\n/** @constant {number} */\nCubicBezierCurve.END_CONTROL_POINT = 2;\n/** @constant {number} */\nCubicBezierCurve.END_POINT = 3;\n/**\n * Helper utils.\n */\nCubicBezierCurve.utils = {\n evaluateT: (p0, p1, p2, p3, t) => {\n return p0 * Math.pow(1.0 - t, 3) +\n p1 * 3 * t * Math.pow(1.0 - t, 2) +\n p2 * 3 * Math.pow(t, 2) * (1.0 - t) +\n p3 * Math.pow(t, 3);\n },\n cubicPolyMinMax: (p0, p1, p2, p3) => {\n // var polyX = CubicBezierCurve.utils.cubicPoly2(\n // p0, // P[0].X, // bezierCurve.startPoint.x,\n // p1, // P[1].X, // bezierCurve.startControlPoint.x,\n // p2, // P[2].X, // bezierCurve.endControlPoint.x,\n // p3 // P[3].X // bezierCurve.endPoint.x\n // );\n // var a = polyX.a;\n // var b = polyX.b;\n // var c = polyX.c;\n // var disc = polyX.b * polyX.b - 4 * polyX.a * polyX.c;\n var polyX = CubicBezierCurve.utils.cubicPoly(p0, // P[0].X, // bezierCurve.startPoint.x,\n p1, // P[1].X, // bezierCurve.startControlPoint.x,\n p2, // P[2].X, // bezierCurve.endControlPoint.x,\n p3 // P[3].X // bezierCurve.endPoint.x\n );\n var a = polyX[0]; // .a;\n var b = polyX[1]; // .b;\n var c = polyX[2]; // .c;\n //alert(\"a \"+a+\" \"+b+\" \"+c);\n // var disc = b * b - 4 * a * c;\n var disc = polyX[1] * polyX[1] - 4 * polyX[0] * polyX[2];\n // var polyX = CubicBezierCurve.utils.bezierCoeffs(p3,p2,p1,p0);\n // var a = polyX[0]; //polyX.a;\n // var b = polyX[1]; // .b;\n // var c = polyX[2]; //.c;\n // var disc = polyX[1] * polyX[1] - 4 * polyX[0] * polyX[2];\n // var xl = Math.min(bCurve.endPoint.x, bCurve.startPoint.x); // P[0].X;\n // var xh = Math.max(bCurve.endPoint.x, bCurve.startPoint.x); // P[0].X;\n var xl = Math.min(p3, p0); // P[0].X;\n var xh = Math.max(p3, p0); // P[0].X;\n // if (P[3].X < xl) xl = P[3].X;\n // if (P[3].X > xh) xh = P[3].X;\n if (disc >= 0) {\n var t1 = (-b + Math.sqrt(disc)) / (2 * a);\n // alert(\"t1 \" + t1);\n if (t1 > 0 && t1 < 1) {\n // var x1 = evalBez(PX, t1);\n // var x1 = bCurve.getPointAt(t1).x;\n var x1 = CubicBezierCurve.utils.evaluateT(p0, p1, p2, p3, t1); // bCurve.getPointAt(t1).x;\n if (x1 < xl)\n xl = x1;\n if (x1 > xh)\n xh = x1;\n }\n var t2 = (-b - Math.sqrt(disc)) / (2 * a);\n // alert(\"t2 \" + t2);\n if (t2 > 0 && t2 < 1) {\n // var x2 = evalBez(PX, t2);\n // var x2 = bCurve.getPointAt(t2).x;\n var x2 = CubicBezierCurve.utils.evaluateT(p0, p1, p2, p3, t2); //\n if (x2 < xl)\n xl = x2;\n if (x2 > xh)\n xh = x2;\n }\n }\n return { min: xl, max: xh };\n },\n /**\n * Get the points of a sub curve at the given start end end offsets (values between 0.0 and 1.0).\n *\n * tStart >= tEnd is allowed, you will get a reversed sub curve then.\n *\n * @method getSubCurvePointsAt\n * @param {CubicBezierCurve} curve – The curve to get the sub curve points from.\n * @param {number} tStart – The start offset of the desired sub curve (must be in [0..1]).\n * @param {number} tEnd – The end offset if the desired cub curve (must be in [0..1]).\n * @instance\n * @memberof CubicBezierCurve\n * @return {CubicBezierCurve} The sub curve as a new curve.\n **/\n getSubCurvePointsAt: (curve, tStart, tEnd) => {\n const startVec = new Vector(curve.getPointAt(tStart), curve.getTangentAt(tStart));\n const endVec = new Vector(curve.getPointAt(tEnd), curve.getTangentAt(tEnd).inv());\n // Tangents are relative. Make absolute.\n startVec.b.add(startVec.a);\n endVec.b.add(endVec.a);\n // This 'splits' the curve at the given point at t.\n startVec.scale(0.33333333 * (tEnd - tStart));\n endVec.scale(0.33333333 * (tEnd - tStart));\n return [startVec.a, endVec.a, startVec.b, endVec.b];\n },\n /**\n * Compute the cubic roots for the given cubic polynomial coefficients.\n *\n * Based on\n * http://mysite.verizon.net/res148h4j/javascript/script_exact_cubic.html#the%20source%20code\n * Inspired by\n * https://www.particleincell.com/2013/cubic-line-intersection/\n * Thanks to Stephan Schmitt and Particle-In-Cell!\n *\n * @param poly\n * @returns\n */\n cubicRoots: (poly) => {\n const a = poly[0];\n const b = poly[1];\n const c = poly[2];\n const d = poly[3];\n const A = b / a;\n const B = c / a;\n const C = d / a;\n var S, T, Im;\n const Q = (3 * B - Math.pow(A, 2)) / 9;\n const R = (9 * A * B - 27 * C - 2 * Math.pow(A, 3)) / 54;\n const D = Math.pow(Q, 3) + Math.pow(R, 2); // polynomial discriminant\n const ts = []; // Array();\n if (D >= 0) {\n // complex or duplicate roots\n S = CubicBezierCurve.utils.sgn(R + Math.sqrt(D)) * Math.pow(Math.abs(R + Math.sqrt(D)), 1 / 3);\n T = CubicBezierCurve.utils.sgn(R - Math.sqrt(D)) * Math.pow(Math.abs(R - Math.sqrt(D)), 1 / 3);\n ts[0] = -A / 3 + (S + T); // real root\n ts[1] = -A / 3 - (S + T) / 2; // real part of complex root\n ts[2] = -A / 3 - (S + T) / 2; // real part of complex root\n Im = Math.abs((Math.sqrt(3) * (S - T)) / 2); // complex part of root pair\n // Mark complex roots to be discarded\n if (Im != 0) {\n ts[1] = -1;\n ts[2] = -1;\n }\n } // distinct real roots\n else {\n const th = Math.acos(R / Math.sqrt(-Math.pow(Q, 3)));\n ts[0] = 2 * Math.sqrt(-Q) * Math.cos(th / 3) - A / 3;\n ts[1] = 2 * Math.sqrt(-Q) * Math.cos((th + 2 * Math.PI) / 3) - A / 3;\n ts[2] = 2 * Math.sqrt(-Q) * Math.cos((th + 4 * Math.PI) / 3) - A / 3;\n Im = 0.0;\n }\n // Discard all t's out of spec and sort the rest\n return ts.filter((t) => t >= 0 && t <= 1.0).sort();\n },\n /**\n * Compute the Bézier coefficients from the given Bézier point coordinates.\n *\n * @param {number} p0 - The start point coordinate.\n * @param {number} p1 - The start control point coordinate.\n * @param {number} p2 - The end control point coordinate.\n * @param {number} p3 - The end point coordinate.\n * @returns {[number,number,number,number]}\n */\n bezierCoeffs: (p0, p1, p2, p3) => {\n const coeffs = [NaN, NaN, NaN, NaN]; //Array(4);\n coeffs[0] = -p0 + 3 * p1 + -3 * p2 + p3;\n coeffs[1] = 3 * p0 - 6 * p1 + 3 * p2;\n coeffs[2] = -3 * p0 + 3 * p1;\n coeffs[3] = p0;\n return coeffs;\n },\n /**\n * Calculate the cubic polynomial coefficients used to find the bounding box.\n *\n * @param {number} p0 - The start point coordinate.\n * @param {number} p1 - The start control point coordinate.\n * @param {number} p2 - The end control point coordinate.\n * @param {number} p3 - The end point coordinate.\n * @returns {[number,number,number]}\n */\n cubicPoly: (p0, p1, p2, p3) => {\n return [\n 3 * p3 - 9 * p2 + 9 * p1 - 3 * p0,\n 6 * p0 - 12 * p1 + 6 * p2,\n 3 * p1 - 3 * p0\n ];\n },\n /**\n * sign of number, but is division safe: no zero returned :)\n */\n sgn(x) {\n return x < 0.0 ? -1 : 1;\n }\n};\n//# sourceMappingURL=CubicBezierCurve.js.map","/**\n * @author Ikaros Kappler\n * @date 2013-08-19\n * @modified 2018-08-16 Added closure. Removed the 'IKRS' wrapper.\n * @modified 2018-11-20 Added circular auto-adjustment.\n * @modified 2018-11-25 Added the point constants to the BezierPath class itself.\n * @modified 2018-11-28 Added the locateCurveByStartPoint() function.\n * @modified 2018-12-04 Added the toSVGString() function.\n * @modified 2019-03-23 Added JSDoc tags.\n * @modified 2019-03-23 Changed the fuctions getPoint and getPointAt to match semantics in the Line class.\n * @modified 2019-11-18 Fixed the clone function: adjustCircular attribute was not cloned.\n * @modified 2019-12-02 Removed some excessive comments.\n * @modified 2019-12-04 Fixed the missing obtainHandleLengths behavior in the adjustNeightbourControlPoint function.\n * @modified 2020-02-06 Added function locateCurveByEndPoint( Vertex ).\n * @modified 2020-02-11 Added 'return this' to the scale(Vertex,number) and to the translate(Vertex) function.\n * @modified 2020-03-24 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-06-03 Made the private helper function _locateUIndex to a private function.\n * @modified 2020-06-03 Added the getBounds() function.\n * @modified 2020-07-14 Changed the moveCurvePoint(...,Vertex) to moveCurvePoint(...,XYCoords).\n * @modified 2020-07-24 Added the getClosestT(Vertex) function.\n * @modified 2020-12-29 Constructor is now private (no explicit use intended).\n * @modified 2021-05-25 Added BezierPath.fromReducedList( Array<number> ).\n * @modified 2022-01-31 Added `BezierPath.getEvenDistributionVertices(number)`.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2023-10-06 Adding the `BezierPath.toPathPoints()` method.\n * @modified 2023-10-07 Adding the `BezierPath.fromCurve(CubicBezierCurve)` static function.\n * @modified 2025-04-09 Added the `BezierPath.move` method to match the convention – which just calls `translate`.\n * @modified 2025-04-09 Modified the `BezierPath.translate` method: chaning parameter `Vertex` to more generalized `XYCoords`.\n * @modified 2025-04-14 Class `BezierPath` is now implementing interface `Intersectable`.\n * @version 2.7.0\n *\n * @file BezierPath\n * @public\n **/\nimport { Bounds } from \"./Bounds\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A BezierPath class.\n *\n * This was refactored from an older project.\n *\n * @requires Bounds\n * @requires Vertex\n * @requires CubicBezierCurve\n * @requires XYCoords\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class BezierPath {\n /**\n * The constructor.<br>\n * <br>\n * This constructor expects a sequence of path points and will approximate\n * the location of control points by picking some between the points.<br>\n * You should consider just constructing empty paths and then add more curves later using\n * the addCurve() function.\n *\n * @constructor\n * @name BezierPath\n * @param {Vertex[]} pathPoints - An array of path vertices (no control points).\n **/\n constructor() {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"BezierPath\";\n /** @constant {number} */\n this.START_POINT = 0;\n /** @constant {number} */\n this.START_CONTROL_POINT = 1;\n /** @constant {number} */\n this.END_CONTROL_POINT = 2;\n /** @constant {number} */\n this.END_POINT = 3;\n // pathPoints: Array<Vertex> | undefined | null) {\n this.uid = UIDGenerator.next();\n // if (!pathPoints) {\n // pathPoints = [];\n // }\n this.totalArcLength = 0.0;\n // Set this flag to true if you want the first point and\n // last point of the path to be auto adjusted, too.\n this.adjustCircular = false;\n this.bezierCurves = [];\n }\n /**\n * Add a cubic bezier curve to the end of this path.\n *\n * @method addCurve\n * @param {CubicBezierCurve} curve - The curve to be added to the end of the path.\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n addCurve(curve) {\n if (curve == null || typeof curve == \"undefined\")\n throw \"Cannot add null curve to bézier path.\";\n this.bezierCurves.push(curve);\n if (this.bezierCurves.length > 1) {\n curve.startPoint = this.bezierCurves[this.bezierCurves.length - 2].endPoint;\n this.adjustSuccessorControlPoint(this.bezierCurves.length - 2, // curveIndex,\n true, // obtainHandleLength,\n true // updateArcLengths\n );\n }\n else {\n this.totalArcLength += curve.getLength();\n }\n }\n /**\n * Locate the curve with the given start point (function returns the index).\n *\n * @method locateCurveByStartPoint\n * @param {Vertex} point - The (curve start-) point to look for.\n * @instance\n * @memberof BezierPath\n * @return {number} The curve index or -1 if curve (start-) point not found\n **/\n locateCurveByStartPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].startPoint.equals(point))\n return i;\n }\n return -1;\n }\n /**\n * Locate the curve with the given end point (function returns the index).\n *\n * @method locateCurveByEndPoint\n * @param {Vertex} point - The (curve end-) point to look for.\n * @instance\n * @memberof BezierPath\n * @return {number} The curve index or -1 if curve (end-) point not found\n **/\n locateCurveByEndPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].endPoint.equals(point))\n return i;\n }\n return -1;\n }\n /**\n * Locate the curve with the given start point (function returns the index).\n *\n * @method locateCurveByStartControlPoint\n * @param {Vertex} point - The (curve endt-) point to look for.\n * @instance\n * @memberof BezierPath\n * @return {number} The curve index or -1 if curve (end-) point not found\n **/\n locateCurveByStartControlPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].startControlPoint.equals(point))\n return i;\n }\n return -1;\n }\n // +---------------------------------------------------------------------------------\n // | Locate the curve with the given end control point.\n // |\n // | @param point:Vertex The point to look for.\n // | @return Number The index or -1 if not found.\n // +-------------------------------\n locateCurveByEndControlPoint(point) {\n // for( var i in this.bezierCurves ) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (this.bezierCurves[i].endControlPoint.equals(point))\n return i;\n }\n return -1;\n }\n /**\n * Get the total length of this path.<br>\n * <br>\n * Note that the returned value comes from the curve buffer. Unregistered changes\n * to the curve points will result in invalid path length values.\n *\n * @method getLength\n * @instance\n * @memberof BezierPath\n * @return {number} The (buffered) length of the path.\n **/\n getLength() {\n return this.totalArcLength;\n }\n /**\n * This function is internally called whenever the curve or path configuration\n * changed. It updates the attribute that stores the path length information.<br>\n * <br>\n * If you perform any unregistered changes to the curve points you should call\n * this function afterwards to update the curve buffer. Not updating may\n * result in unexpected behavior.\n *\n * @method updateArcLengths\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n updateArcLengths() {\n this.totalArcLength = 0.0;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n this.bezierCurves[i].updateArcLengths();\n this.totalArcLength += this.bezierCurves[i].getLength();\n }\n }\n /**\n * Get the number of curves in this path.\n *\n * @method getCurveCount\n * @instance\n * @memberof BezierPath\n * @return {number} The number of curves in this path.\n **/\n getCurveCount() {\n return this.bezierCurves.length;\n }\n /**\n * Get the cubic bezier curve at the given index.\n *\n * @method getCurveAt\n * @param {number} index - The curve index from 0 to getCurveCount()-1.\n * @instance\n * @memberof BezierPath\n * @return {CubicBezierCurve} The curve at the specified index.\n **/\n getCurveAt(curveIndex) {\n return this.bezierCurves[curveIndex];\n }\n /**\n * Move the whole bezier path by the given (x,y)-amount.\n *\n * @method translate\n * @param {XYCoords} amount - The amount to be added (amount.x and amount.y)\n * to each vertex of the curve.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining\n **/\n translate(amount) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n curve.getStartPoint().add(amount);\n curve.getStartControlPoint().add(amount);\n curve.getEndControlPoint().add(amount);\n }\n // Don't forget to translate the last curve's last point\n var curve = this.bezierCurves[this.bezierCurves.length - 1];\n curve.getEndPoint().add(amount);\n this.updateArcLengths();\n return this;\n }\n /**\n * Move the whole bezier path by the given (x,y)-amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to be added (amount.x and amount.y)\n * to each vertex of the curve.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining\n **/\n move(amount) {\n return this.translate(amount);\n }\n /**\n * Scale the whole bezier path by the given uniform factor.\n *\n * @method scale\n * @param {Vertex} anchor - The scale origin to scale from.\n * @param {number} scaleFactor - The scalar to be multiplied with.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining.\n **/\n scale(anchor, scaleFactor) {\n return this.scaleXY({ x: scaleFactor, y: scaleFactor }, anchor);\n }\n /**\n * Scale the whole bezier path by the given (x,y)-factors.\n *\n * @method scale\n * @param {Vertex} anchor - The scale origin to scale from.\n * @param {number} amount - The scalar to be multiplied with.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} this for chaining.\n **/\n scaleXY(scaleFactors, anchor) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n curve.getStartPoint().scaleXY(scaleFactors, anchor);\n curve.getStartControlPoint().scaleXY(scaleFactors, anchor);\n curve.getEndControlPoint().scaleXY(scaleFactors, anchor);\n // Do NOT scale the end point here!\n // Don't forget that the curves are connected and on curve's end point\n // the the successor's start point (same instance)!\n }\n // Finally move the last end point (was not scaled yet)\n if (this.bezierCurves.length > 0 && !this.adjustCircular) {\n this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().scaleXY(scaleFactors, anchor);\n }\n this.updateArcLengths();\n return this;\n }\n /**\n * Rotate the whole bezier path around a point..\n *\n * @method rotate\n * @param {Vertex} angle - The angle to rotate this path by.\n * @param {Vertex} center - The rotation center.\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n rotate(angle, center) {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n curve.getStartPoint().rotate(angle, center);\n curve.getStartControlPoint().rotate(angle, center);\n curve.getEndControlPoint().rotate(angle, center);\n // Do NOT rotate the end point here!\n // Don't forget that the curves are connected and on curve's end point\n // the the successor's start point (same instance)!\n }\n // Finally move the last end point (was not scaled yet)\n if (this.bezierCurves.length > 0 && !this.adjustCircular) {\n this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().rotate(angle, center);\n }\n }\n /**\n * Get the 't' position on this curve with the minimal distance to point p.\n *\n * @param {Vertex} p - The point to find the closest curve point for.\n * @return {number} A value t with 0.0 <= t <= 1.0.\n **/\n getClosestT(p) {\n // Find the spline to extract the value from\n var minIndex = -1;\n var minDist = 0.0;\n var dist = 0.0;\n var curveT = 0.0;\n var uMin = 0.0;\n var u = 0.0;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n curveT = this.bezierCurves[i].getClosestT(p);\n dist = this.bezierCurves[i].getPointAt(curveT).distance(p);\n if (minIndex == -1 || dist < minDist) {\n minIndex = i;\n minDist = dist;\n uMin = u + curveT * this.bezierCurves[i].getLength();\n }\n u += this.bezierCurves[i].getLength();\n }\n return Math.max(0.0, Math.min(1.0, uMin / this.totalArcLength));\n }\n /**\n * Get the point on the bézier path at the given relative path location.\n *\n * @method getPoint\n * @param {number} u - The relative path position: <pre>0 <= u <= this.getLength()</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The point at the relative path position.\n **/\n getPoint(u) {\n if (u < 0 || u > this.totalArcLength) {\n console.warn(\"[BezierPath.getPoint(u)] u is out of bounds: \" + u + \".\");\n u = Math.min(this.totalArcLength, Math.max(u, 0));\n }\n // Find the spline to extract the value from\n var i = 0;\n var uTemp = 0.0;\n while (i < this.bezierCurves.length && uTemp + this.bezierCurves[i].getLength() < u) {\n uTemp += this.bezierCurves[i].getLength();\n i++;\n }\n // if u == arcLength\n // -> i is max\n if (i >= this.bezierCurves.length)\n return this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().clone();\n var bCurve = this.bezierCurves[i];\n var relativeU = u - uTemp;\n return bCurve.getPoint(relativeU);\n }\n /**\n * Get the point on the bézier path at the given path fraction.\n *\n * @method getPointAt\n * @param {number} t - The absolute path position: <pre>0.0 <= t <= 1.0</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The point at the absolute path position.\n **/\n getPointAt(t) {\n return this.getPoint(t * this.totalArcLength);\n }\n /**\n * Get the tangent of the bézier path at the given path fraction.<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getTangentAt\n * @param {number} t - The absolute path position: <pre>0.0 <= t <= 1.0</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The tangent vector at the absolute path position.\n **/\n getTangentAt(t) {\n return this.getTangent(t * this.totalArcLength);\n }\n /**\n * Get the tangent of the bézier path at the given path location.<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getTangent\n * @param {number} u - The relative path position: <pre>0 <= u <= getLength()</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The tangent vector at the relative path position.\n **/\n getTangent(u) {\n if (u < 0 || u > this.totalArcLength) {\n console.warn(\"[BezierPath.getTangent(u)] u is out of bounds: \" + u + \".\");\n // return undefined;\n u = Math.min(this.totalArcLength, Math.max(0, u));\n }\n // Find the spline to extract the value from\n var i = 0;\n var uTemp = 0.0;\n while (i < this.bezierCurves.length && uTemp + this.bezierCurves[i].getLength() < u) {\n uTemp += this.bezierCurves[i].getLength();\n i++;\n }\n var bCurve = this.bezierCurves[i];\n var relativeU = u - uTemp;\n return bCurve.getTangent(relativeU);\n }\n /**\n * Get the perpendicular of the bézier path at the given absolute path location (fraction).<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getPerpendicularAt\n * @param {number} t - The absolute path position: <pre>0.0 <= t <= 1.0</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The perpendicluar vector at the absolute path position.\n **/\n getPerpendicularAt(t) {\n return this.getPerpendicular(t * this.totalArcLength);\n }\n /**\n * Get the perpendicular of the bézier path at the given relative path location.<br>\n * <br>\n * Note that the returned vector is not normalized.\n *\n * @method getPerpendicular\n * @param {number} u - The relative path position: <pre>0 <= u <= getLength()</pre>\n * @instance\n * @memberof BezierPath\n * @return {Vertex} The perpendicluar vector at the relative path position.\n **/\n getPerpendicular(u) {\n if (u < 0 || u > this.totalArcLength) {\n console.log(\"[BezierPath.getPerpendicular(u)] u is out of bounds: \" + u + \".\");\n u = Math.min(this.totalArcLength, Math.max(0, u));\n }\n // Find the spline to extract the value from\n var uResult = BezierPath._locateUIndex(this, u);\n var bCurve = this.bezierCurves[uResult.i];\n var relativeU = u - uResult.uPart;\n return bCurve.getPerpendicular(relativeU);\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get all line intersections with this shape.\n *\n * This method returns all intersections (as vertices) with this shape. The returned array of vertices is in no specific order.\n *\n * @param {VertTuple} line - The line to find intersections with.\n * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are returned (located strictly between start and end vertex).\n * @returns {Array<Vertex>} - An array of all intersections with the shape's outline.\n */\n lineIntersections(line, inVectorBoundsOnly = false) {\n return this.bezierCurves.reduce((accu, curCurve) => {\n return accu.concat(curCurve.lineIntersections(line, inVectorBoundsOnly));\n }, []);\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n return this.bezierCurves.reduce((accu, curCurve) => {\n return accu.concat(curCurve.lineIntersectionTangents(line, inVectorBoundsOnly));\n }, []);\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * This is a helper function to locate the curve index for a given\n * absolute path position u.\n *\n * I decided to put this into privat scope as it is really specific. Maybe\n * put this into a utils wrapper.\n *\n * Returns:\n * - {number} i - the index of the containing curve.\n * - {number} uPart - the absolute curve length sum (length from the beginning to u, should equal u itself).\n * - {number} uBefore - the absolute curve length for all segments _before_ the matched curve (usually uBefore <= uPart).\n **/\n static _locateUIndex(path, u) {\n var i = 0;\n var uTemp = 0.0;\n var uBefore = 0.0;\n while (i < path.bezierCurves.length && uTemp + path.bezierCurves[i].getLength() < u) {\n uTemp += path.bezierCurves[i].getLength();\n if (i + 1 < path.bezierCurves.length)\n uBefore += path.bezierCurves[i].getLength();\n i++;\n }\n return { i: i, uPart: uTemp, uBefore: uBefore };\n }\n /**\n * Get a specific sub path from this path. The start and end position are specified by\n * ratio number in [0..1].\n *\n * 0.0 is at the beginning of the path.\n * 1.0 is at the end of the path.\n *\n * Values below 0 or beyond 1 are cropped down to the [0..1] interval.\n *\n * startT > endT is allowed, the returned sub path will have inverse direction then.\n *\n * @method getSubPathAt\n * @param {number} startT - The start position of the sub path.\n * @param {number} endT - The end position of the sub path.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} The desired sub path in the bounds [startT..endT].\n **/\n getSubPathAt(startT, endT) {\n startT = Math.max(0, startT);\n endT = Math.min(1.0, endT);\n let startU = startT * this.totalArcLength;\n let endU = endT * this.totalArcLength;\n var uStartResult = BezierPath._locateUIndex(this, startU); // { i:int, uPart:float, uBefore:float }\n var uEndResult = BezierPath._locateUIndex(this, endU); // { i:int, uPart:float, uBefore:float }\n var firstT = (startU - uStartResult.uBefore) / this.bezierCurves[uStartResult.i].getLength();\n if (uStartResult.i == uEndResult.i) {\n // Subpath begins and ends in the same path segment (just get a simple sub curve from that path element).\n var lastT = (endU - uEndResult.uBefore) / this.bezierCurves[uEndResult.i].getLength();\n var firstCurve = this.bezierCurves[uStartResult.i].getSubCurveAt(firstT, lastT);\n return BezierPath.fromArray([firstCurve]);\n }\n else {\n var curves = [];\n if (uStartResult.i > uEndResult.i) {\n // Back to front direction\n var firstCurve = this.bezierCurves[uStartResult.i].getSubCurveAt(firstT, 0.0);\n curves.push(firstCurve);\n for (var i = uStartResult.i - 1; i > uEndResult.i; i--) {\n curves.push(this.bezierCurves[i].clone().reverse());\n }\n var lastT = (endU - uEndResult.uBefore) / this.bezierCurves[uEndResult.i].getLength();\n curves.push(this.bezierCurves[uEndResult.i].getSubCurveAt(1.0, lastT));\n }\n else {\n // Front to back direction\n var firstCurve = this.bezierCurves[uStartResult.i].getSubCurveAt(firstT, 1.0);\n curves.push(firstCurve);\n for (var i = uStartResult.i + 1; i < uEndResult.i && i < this.bezierCurves.length; i++) {\n curves.push(this.bezierCurves[i].clone());\n }\n var lastT = (endU - uEndResult.uBefore) / this.bezierCurves[uEndResult.i].getLength();\n curves.push(this.bezierCurves[uEndResult.i].getSubCurveAt(0, lastT));\n }\n return BezierPath.fromArray(curves);\n }\n }\n /**\n * This function moves the addressed curve point (or control point) with\n * keeping up the path's curve integrity.<br>\n * <br>\n * Thus is done by moving neighbour- and control- points as needed.\n *\n * @method moveCurvePoint\n * @param {number} curveIndex - The curve index to move a point from.\n * @param {number} pointID - One of the curve's four point IDs (START_POINT,\n * START_CONTROL_POINT, END_CONTRO_POINT or END_POINT).\n * @param {XYCoords} moveAmount - The amount to move the addressed vertex by.\n * @instance\n * @memberof BezierPath\n * @return {void}\n **/\n moveCurvePoint(curveIndex, pointID, moveAmount) {\n var bCurve = this.getCurveAt(curveIndex);\n bCurve.moveCurvePoint(pointID, moveAmount, true, // move control point, too\n true // updateArcLengths\n );\n // If inner point and NOT control point\n // --> move neightbour\n if (pointID == this.START_POINT && (curveIndex > 0 || this.adjustCircular)) {\n // Set predecessor's control point!\n var predecessor = this.getCurveAt(curveIndex - 1 < 0 ? this.bezierCurves.length + (curveIndex - 1) : curveIndex - 1);\n predecessor.moveCurvePoint(this.END_CONTROL_POINT, moveAmount, true, // move control point, too\n false // updateArcLengths\n );\n }\n else if (pointID == this.END_POINT && (curveIndex + 1 < this.bezierCurves.length || this.adjustCircular)) {\n // Set successcor\n var successor = this.getCurveAt((curveIndex + 1) % this.bezierCurves.length);\n successor.moveCurvePoint(this.START_CONTROL_POINT, moveAmount, true, // move control point, too\n false // updateArcLengths\n );\n }\n else if (pointID == this.START_CONTROL_POINT && curveIndex > 0) {\n this.adjustPredecessorControlPoint(curveIndex, true, // obtain handle length?\n false // update arc lengths\n );\n }\n else if (pointID == this.END_CONTROL_POINT && curveIndex + 1 < this.getCurveCount()) {\n this.adjustSuccessorControlPoint(curveIndex, true, // obtain handle length?\n false // update arc lengths\n );\n }\n // Don't forget to update the arc lengths!\n // Note: this can be optimized as only two curves have changed their lengths!\n this.updateArcLengths();\n }\n /**\n * This helper function adjusts the given point's predecessor's control point.\n *\n * @method adjustPredecessorControlPoint\n * @param {number} curveIndex - The curve index to move a point from.\n * @param {boolean} obtainHandleLength - Moves the point with keeping the original handle length.\n * @param {boolean} updateArcLength - The amount to move the addressed vertex by.\n * @instance\n * @private\n * @memberof BezierPath\n * @return {void}\n **/\n adjustPredecessorControlPoint(curveIndex, obtainHandleLength, updateArcLengths) {\n if (!this.adjustCircular && curveIndex <= 0)\n return; // false;\n var mainCurve = this.getCurveAt(curveIndex);\n var neighbourCurve = this.getCurveAt(curveIndex - 1 < 0 ? this.getCurveCount() + (curveIndex - 1) : curveIndex - 1);\n BezierPath.adjustNeighbourControlPoint(mainCurve, neighbourCurve, mainCurve.getStartPoint(), // the reference point\n mainCurve.getStartControlPoint(), // the dragged control point\n neighbourCurve.getEndPoint(), // the neighbour's point\n neighbourCurve.getEndControlPoint(), // the neighbour's control point to adjust\n obtainHandleLength, updateArcLengths);\n }\n /**\n * This helper function adjusts the given point's successor's control point.\n *\n * @method adjustSuccessorControlPoint\n * @param {number} curveIndex - The curve index to move a point from.\n * @param {boolean} obtainHandleLength - Moves the point with keeping the original handle length.\n * @param {boolean} updateArcLength - The amount to move the addressed vertex by.\n * @instance\n * @private\n * @memberof BezierPath\n * @return {void}\n **/\n adjustSuccessorControlPoint(curveIndex, obtainHandleLength, updateArcLengths) {\n if (!this.adjustCircular && curveIndex + 1 > this.getCurveCount())\n return; // false;\n var mainCurve = this.getCurveAt(curveIndex);\n var neighbourCurve = this.getCurveAt((curveIndex + 1) % this.getCurveCount());\n /* return */ BezierPath.adjustNeighbourControlPoint(mainCurve, neighbourCurve, mainCurve.getEndPoint(), // the reference point\n mainCurve.getEndControlPoint(), // the dragged control point\n neighbourCurve.getStartPoint(), // the neighbour's point\n neighbourCurve.getStartControlPoint(), // the neighbour's control point to adjust\n obtainHandleLength, updateArcLengths);\n }\n /**\n * This helper function adjusts the given point's successor's control point.\n *\n * @method adjustNeighbourControlPoint\n * @param {CubicBezierCurve} mainCurve\n * @param {CubicBezierCurve} neighbourCurve\n * @param {Vertex} mainPoint\n * @param {Vertex} mainControlPoint\n * @param {Vertex} neighbourPoint\n * @param {Vertex} neighbourControlPoint\n * @param {boolean} obtainHandleLengths\n * @param {boolean} updateArcLengths\n * @instance\n * @private\n * @memberof BezierPath\n * @return {void}\n **/\n static adjustNeighbourControlPoint(_mainCurve, // TODO: remove param\n neighbourCurve, mainPoint, mainControlPoint, neighbourPoint, neighbourControlPoint, obtainHandleLengths, _updateArcLengths // TODO: remove param\n ) {\n // Calculate start handle length\n var mainHandleBounds = new Vertex(mainControlPoint.x - mainPoint.x, mainControlPoint.y - mainPoint.y);\n var neighbourHandleBounds = new Vertex(neighbourControlPoint.x - neighbourPoint.x, neighbourControlPoint.y - neighbourPoint.y);\n var mainHandleLength = Math.sqrt(Math.pow(mainHandleBounds.x, 2) + Math.pow(mainHandleBounds.y, 2));\n var neighbourHandleLength = Math.sqrt(Math.pow(neighbourHandleBounds.x, 2) + Math.pow(neighbourHandleBounds.y, 2));\n if (mainHandleLength <= 0.1)\n return; // no secure length available for division? What about zoom? Use EPSILON?\n // Just invert the main handle (keep length or not?\n if (obtainHandleLengths) {\n neighbourControlPoint.set(neighbourPoint.x - mainHandleBounds.x * (neighbourHandleLength / mainHandleLength), neighbourPoint.y - mainHandleBounds.y * (neighbourHandleLength / mainHandleLength));\n }\n else {\n neighbourControlPoint.set(neighbourPoint.x - mainHandleBounds.x, neighbourPoint.y - mainHandleBounds.y);\n }\n neighbourCurve.updateArcLengths();\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this Bézier path.\n *\n * Note the the curves' underlyung segment buffers are used to determine the bounds. The more\n * elements the segment buffers have, the more precise the returned bounds will be.\n *\n * @return {Bounds} The bounds of this Bézier path.\n **/\n getBounds() {\n const min = new Vertex(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);\n const max = new Vertex(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);\n var b;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n b = this.bezierCurves[i].getBounds();\n min.x = Math.min(min.x, b.min.x);\n min.y = Math.min(min.y, b.min.y);\n max.x = Math.max(max.x, b.max.x);\n max.y = Math.max(max.y, b.max.y);\n }\n return new Bounds(min, max);\n }\n //--- END --- Implement interface `IBounded`\n /**\n * Get n 'equally' distributed vertices along this Bézier path.\n *\n * As the changing curvature of the B slines makes prediction of distances difficult, the\n * returned vertices' distances are only relatively equal:\n * - the distance grows where curvature is large.\n * - the distance shrinks where curvature is small.\n *\n * Only the distance mean of all consecutive is 1/n-th of the total arc length.\n *\n * Usually this approximation is good enough for most use cases.\n *\n * @param {number} pointCount - (must be at least 2) The number of desired points (start and end point included).\n * @return {Array<Vertex>}\n */\n getEvenDistributionVertices(pointCount) {\n if (pointCount < 2) {\n throw new Error(\"pointCount must be larger than one; is \" + pointCount + \".\");\n }\n const result = [];\n if (this.bezierCurves.length === 0) {\n return result;\n }\n // Fetch and add the start point from the source polygon\n var polygonPoint = new Vertex(this.bezierCurves[0].startPoint);\n result.push(polygonPoint);\n // if (this.bezierCurves.length === 1) {\n // return result;\n // }\n const perimeter = this.totalArcLength;\n const stepSize = perimeter / (pointCount - 1);\n const n = this.bezierCurves.length;\n let curveIndex = 0;\n let segmentLength = this.bezierCurves[0].arcLength;\n let curSegmentU = stepSize;\n let i = 1;\n while (i < pointCount && curveIndex < n) {\n // Check if next eq point is inside this segment\n if (curSegmentU < segmentLength) {\n var newPoint = this.bezierCurves[curveIndex].getPoint(curSegmentU);\n result.push(newPoint);\n curSegmentU += stepSize;\n i++;\n }\n else {\n curveIndex++;\n curSegmentU = curSegmentU - segmentLength;\n segmentLength = curveIndex < n ? this.bezierCurves[curveIndex].arcLength : 0;\n }\n }\n result.push(new Vertex(this.bezierCurves[n - 1].endPoint));\n return result;\n }\n /**\n * Clone this BezierPath (deep clone).\n *\n * @method clone\n * @instance\n * @memberof BezierPath\n * @return {BezierPath}\n **/\n clone() {\n var path = new BezierPath(); // undefined);\n for (var i = 0; i < this.bezierCurves.length; i++) {\n path.bezierCurves.push(this.bezierCurves[i].clone());\n // Connect splines\n if (i > 0)\n path.bezierCurves[i - 1].endPoint = path.bezierCurves[i].startPoint;\n }\n path.updateArcLengths();\n path.adjustCircular = this.adjustCircular;\n return path;\n }\n /**\n * Compare this and the passed Bézier path.\n *\n * @method equals\n * @param {BezierPath} path - The pass to compare with.\n * @instance\n * @memberof BezierPath\n * @return {boolean}\n **/\n equals(path) {\n if (!path)\n return false;\n // Check if path contains the credentials\n if (!path.bezierCurves)\n return false;\n if (typeof path.bezierCurves.length == \"undefined\")\n return false;\n if (path.bezierCurves.length != this.bezierCurves.length)\n return false;\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (!this.bezierCurves[i].equals(path.bezierCurves[i]))\n return false;\n }\n return true;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n *\n * @method destroy\n * @instance\n * @memberof BezierPath\n */\n destroy() {\n for (var i = 0; i < this.bezierCurves.length; i++) {\n this.bezierCurves[i].destroy();\n }\n this.isDestroyed = true;\n }\n /**\n * Convert this path to an array of path points that can be drawn by the default DrawLib\n * implementations.\n *\n * @method toPathPoints\n * @instance\n * @memberof BezierPath\n * @return {Array<XYCoords>}\n */\n toPathPoints() {\n if (this.bezierCurves.length === 0) {\n return [];\n }\n if (this.bezierCurves.length === 1) {\n return [\n this.bezierCurves[0].startPoint,\n this.bezierCurves[0].startControlPoint,\n this.bezierCurves[0].endControlPoint,\n this.bezierCurves[0].endPoint\n ];\n }\n const arr = [];\n arr.push(this.bezierCurves[0].startPoint);\n arr.push(this.bezierCurves[0].startControlPoint);\n for (var i = 1; i < this.bezierCurves.length; i++) {\n arr.push(this.bezierCurves[i - 1].endControlPoint);\n arr.push(this.bezierCurves[i - 1].endPoint);\n arr.push(this.bezierCurves[i].startPoint);\n arr.push(this.bezierCurves[i].startControlPoint);\n }\n arr.push(this.bezierCurves[0].endControlPoint);\n arr.push(this.bezierCurves[0].endPoint);\n return arr;\n }\n /**\n * Create a JSON string representation of this bézier curve.\n *\n * @method toJSON\n * @param {boolean} prettyFormat - If true then the function will add line breaks.\n * @instance\n * @memberof BezierPath\n * @return {string} The JSON string.\n **/\n toJSON(prettyFormat) {\n var buffer = [];\n buffer.push(\"[\"); // array begin\n for (var i = 0; i < this.bezierCurves.length; i++) {\n if (i > 0)\n buffer.push(\",\");\n if (prettyFormat)\n buffer.push(\"\\n\\t\");\n else\n buffer.push(\" \");\n buffer.push(this.bezierCurves[i].toJSON(prettyFormat));\n }\n if (this.bezierCurves.length != 0)\n buffer.push(\" \");\n buffer.push(\"]\"); // array end\n return buffer.join(\"\"); // Convert to string, with empty separator.\n }\n /**\n * Parse a BezierPath from the given JSON string.\n *\n * @method fromJSON\n * @param {string} jsonString - The string with the JSON data.\n * @throw An error if the string is not JSON or does not contain a bezier path object.\n * @static\n * @memberof BezierPath\n * @return {BezierPath} The parsed bezier path instance.\n **/\n static fromJSON(jsonString) {\n var obj = JSON.parse(jsonString);\n return BezierPath.fromArray(obj);\n }\n /**\n * Construct a new path with a single curve. Adding more curves is always possible.\n *\n * @method fromCurve\n * @param {CubicBezierCurve} curve - The curve to construct a new path from.\n * @static\n * @memberof BezierPath\n * @return {BezierPath} The constructed bezier path instance.\n */\n static fromCurve(curve) {\n const path = new BezierPath(); // []);\n path.addCurve(curve);\n return path;\n }\n /**\n * Create a BezierPath instance from the given array.\n *\n * @method fromArray\n * @param {Vertex[][]} arr - A two-dimensional array containing the bezier path vertices.\n * @throw An error if the array does not contain proper bezier path data.\n * @static\n * @memberof BezierPath\n * @return {BezierPath} The bezier path instance retrieved from the array data.\n **/\n static fromArray(obj) {\n if (!Array.isArray(obj)) {\n throw \"[BezierPath.fromArray] Passed object must be an array.\";\n }\n const arr = obj; // FORCE?\n if (arr.length < 1) {\n throw \"[BezierPath.fromArray] Passed array must contain at least one bezier curve (has \" + arr.length + \").\";\n }\n // Create an empty bezier path\n var bPath = new BezierPath(); // undefined);\n var lastCurve = null;\n for (var i = 0; i < arr.length; i++) {\n // Convert object (or array?) to bezier curve\n var bCurve;\n if (CubicBezierCurve.isInstance(arr[i])) {\n bCurve = arr[i].clone();\n }\n else if (0 in arr[i] && 1 in arr[i] && 2 in arr[i] && 3 in arr[i]) {\n if (!arr[i][0] || !arr[i][1] || !arr[i][2] || !arr[i][3])\n throw \"Cannot convert path data to BezierPath instance. At least one element is undefined (index=\" + i + \"): \" + arr[i];\n bCurve = CubicBezierCurve.fromArray(arr[i]);\n }\n else {\n bCurve = CubicBezierCurve.fromObject(arr[i]);\n }\n // Set curve start point?\n // (avoid duplicate point instances!)\n if (lastCurve)\n bCurve.startPoint = lastCurve.endPoint;\n // Add to path's internal list\n bPath.bezierCurves.push(bCurve);\n // bPath.totalArcLength += bCurve.getLength();\n lastCurve = bCurve;\n }\n bPath.updateArcLengths();\n // Bezier segments added. Done\n return bPath;\n }\n /**\n * This function converts the bezier path into a string containing\n * integer values only.\n * The points' float values are rounded to 1 digit after the comma.\n *\n * The returned string represents a JSON array (with leading '[' and\n * trailing ']', the separator is ',').\n *\n * @method toReducedListRepresentation\n * @param {number} digits - The number of digits to be used after the comma '.'.\n * @instance\n * @memberof BezierPath\n * @return {string} The reduced list representation of this path.\n **/\n toReducedListRepresentation(digits) {\n if (typeof digits == \"undefined\")\n digits = 1;\n var buffer = [];\n buffer.push(\"[\"); // array begin\n for (var i = 0; i < this.bezierCurves.length; i++) {\n var curve = this.bezierCurves[i];\n buffer.push(curve.getStartPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getStartPoint().y.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getStartControlPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getStartControlPoint().y.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getEndControlPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getEndControlPoint().y.toFixed(digits));\n buffer.push(\",\");\n }\n if (this.bezierCurves.length != 0) {\n var curve = this.bezierCurves[this.bezierCurves.length - 1];\n buffer.push(curve.getEndPoint().x.toFixed(digits));\n buffer.push(\",\");\n buffer.push(curve.getEndPoint().y.toFixed(digits));\n }\n buffer.push(\"]\"); // array end\n return buffer.join(\"\"); // Convert to string, with empty separator.\n }\n /**\n * Parse a BezierPath instance from the reduced list representation.<br>\n * <br>\n * The passed string must represent a JSON array containing numbers only.\n *\n * @method fromReducedListRepresentation\n * @param {string} listJSON - The number of digits to be used after the floating point.\n * @throw An error if the string is malformed.\n * @instance\n * @memberof BezierPath\n * @return {BezierPath} The bezier path instance retrieved from the string.\n **/\n static fromReducedListRepresentation(listJSON, adjustCircular) {\n // Parse the array\n var pointArray = JSON.parse(listJSON);\n if (!pointArray.length) {\n console.log(\"Cannot parse bezier path from non-array object nor from empty point list.\");\n throw \"Cannot parse bezier path from non-array object nor from empty point list.\";\n }\n if (pointArray.length < 8) {\n console.log(\"Cannot build bezier path. The passed array must contain at least 8 elements (numbers).\");\n throw \"Cannot build bezier path. The passed array must contain at least 8 elements (numbers).\";\n }\n return BezierPath.fromReducedList(pointArray, adjustCircular);\n }\n /**\n * Convert a reduced list representation (array of numeric coordinates) to a BezierPath instance.\n *\n * The array's length must be 6*n + 2:\n * - [sx, sy, scx, scy, ecx, ecy, ... , ex, ey ]\n * | | | |\n * +--- sequence of curves --------+ +-end-+\n *\n * @param {number[]} pointArray\n * @returns BezierPath\n */\n static fromReducedList(pointArray, adjustCircular) {\n // Convert to object\n var bezierPath = new BezierPath(); // null); // No points yet\n var startPoint = new Vertex();\n var startControlPoint;\n var endControlPoint;\n var endPoint;\n var i = 0;\n do {\n if (i == 0) {\n // firstStartPoint =\n startPoint = new Vertex(pointArray[i], pointArray[i + 1]);\n }\n startControlPoint = new Vertex(pointArray[i + 2], pointArray[i + 3]);\n endControlPoint = new Vertex(pointArray[i + 4], pointArray[i + 5]);\n // if (i + 8 >= pointArray.length) {\n // endPoint = firstStartPoint;\n // } else {\n endPoint = new Vertex(pointArray[i + 6], pointArray[i + 7]);\n // }\n var bCurve = new CubicBezierCurve(startPoint, endPoint, startControlPoint, endControlPoint);\n bezierPath.bezierCurves.push(bCurve);\n startPoint = endPoint;\n i += 6;\n } while (i + 2 < pointArray.length);\n bezierPath.adjustCircular = adjustCircular !== null && adjustCircular !== void 0 ? adjustCircular : false;\n if (adjustCircular) {\n bezierPath.bezierCurves[bezierPath.bezierCurves.length - 1].endPoint = bezierPath.bezierCurves[0].startPoint;\n }\n bezierPath.updateArcLengths();\n return bezierPath;\n }\n}\n// +---------------------------------------------------------------------------------\n// | These constants equal the values from CubicBezierCurve.\n// +-------------------------------\n/** @constant {number} */\nBezierPath.START_POINT = 0;\n/** @constant {number} */\nBezierPath.START_CONTROL_POINT = 1;\n/** @constant {number} */\nBezierPath.END_CONTROL_POINT = 2;\n/** @constant {number} */\nBezierPath.END_POINT = 3;\n//# sourceMappingURL=BezierPath.js.map","/**\n * @author Ikaros Kappler\n * @date 2020-12-17\n * @modified 2021-01-20 Added UID.\n * @modified 2021-02-26 Fixed an error in the svg-arc-calculation (case angle<90deg and anti-clockwise).\n * @modified 2024-01-30 Added a missing type in the `describeSVGArc` function.\n * @modified 2024-03-01 Added the `getStartPoint` and `getEndPoint` methods.\n * @modified 2024-03-08 Added the `containsAngle` method.\n * @modified 2024-03-09 Added the `circleSectorIntersection` method to find coherent sector intersections..\n * @modified 2024-03-09 Added the `angleAt` method to determine any angle at some ratio.\n * @modified 2025-04-02 Adding the `CircleSector.lineIntersections` and `CircleSector.lineIntersectionTangents` and implementing `Intersectable`.\n * @modified 2025-04-09 Adding the `CircleSector.move()` method.\n * @modified 2025-04-19 Tweaking the `CircleSector.containsAngle` method: all values (input angle, start- and end- angle) are wrapped into [0,2*PI) now.\n * @modified 2025-04-19 Class `CircleSector` implements interface `Bounded` now (method `getBounds` added).\n * @version 1.2.0\n **/\nimport { Bounds } from \"./Bounds\";\nimport { Circle } from \"./Circle\";\nimport { Line } from \"./Line\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\nimport { geomutils } from \"./geomutils\";\n/**\n * @classdesc A simple circle sector: circle, start- and end-angle.\n *\n * @requires Line\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n * @requires XYCoords\n **/\nexport class CircleSector {\n /**\n * Create a new circle sector with given circle, start- and end-angle.\n *\n * @constructor\n * @name CircleSector\n * @param {Circle} circle - The circle.\n * @param {number} startAngle - The start angle of the sector.\n * @param {number} endAngle - The end angle of the sector.\n */\n constructor(circle, startAngle, endAngle) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"CircleSector\";\n this.uid = UIDGenerator.next();\n this.circle = circle;\n this.startAngle = startAngle;\n this.endAngle = endAngle;\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this ellipse.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getBounds\n * @instance\n * @memberof VEllipse\n * @return {Bounds} The bounds of this curve.\n **/\n getBounds() {\n const _self = this;\n const circleBounds = this.circle.getBounds();\n // Calculage angles from east, west, north and south box points and check if they are inside\n const candidates = [\n circleBounds.getNorthPoint(),\n circleBounds.getSouthPoint(),\n circleBounds.getWestPoint(),\n circleBounds.getEastPoint()\n ].filter((point) => {\n // Check for each candidate points if they are contained in this sector. Drop if not.\n const angle = new Line(_self.circle.center, point).angle();\n return _self.containsAngle(angle);\n });\n // Compute bounds and inlcude start end end point (they are definitely part of the bounds)\n return Bounds.computeFromVertices(candidates.concat([this.getStartPoint(), this.getEndPoint()]));\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Move the circle sector by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof CircleSector\n * @return {CircleSector} this for chaining\n **/\n move(amount) {\n this.circle.move(amount);\n return this;\n }\n /**\n * Checks wether the given angle (must be inside 0 and PI*2) is contained inside this sector.\n *\n * @param {number} angle - The numeric angle to check.\n * @method containsAngle\n * @instance\n * @memberof CircleSector\n * @return {boolean} True if (and only if) this sector contains the given angle.\n */\n containsAngle(angle) {\n var wrappedAngle = geomutils.mapAngleTo2PI(angle);\n var wrappedStart = geomutils.mapAngleTo2PI(this.startAngle);\n var wrappedEnd = geomutils.mapAngleTo2PI(this.endAngle);\n // TODO: cleanup\n // if (this.startAngle <= this.endAngle) {\n // return angle >= this.startAngle && angle < this.endAngle;\n // } else {\n // // startAngle > endAngle\n // return angle >= this.startAngle || angle < this.endAngle;\n // }\n if (wrappedStart <= wrappedEnd) {\n return wrappedAngle >= wrappedStart && wrappedAngle < wrappedEnd;\n }\n else {\n // startAngle > endAngle\n return wrappedAngle >= wrappedStart || wrappedAngle < wrappedEnd;\n }\n }\n /**\n * Get the angle inside this sector for a given ratio. 0.0 means startAngle, and 1.0 means endAngle.\n *\n * @param {number} t - The ratio inside [0..1].\n * @method angleAt\n * @instance\n * @memberof CircleSector\n * @return {number} The angle inside this sector at a given ratio.\n */\n angleAt(t) {\n if (this.startAngle <= this.endAngle) {\n const angleAtRatio = this.startAngle + (this.endAngle - this.startAngle) * t;\n return angleAtRatio % (Math.PI * 2.0);\n }\n else {\n // startAngle > endAngle\n const angleAtRatio = this.startAngle + (Math.PI * 2 - this.startAngle + this.endAngle) * t;\n return angleAtRatio % (Math.PI * 2.0);\n }\n }\n /**\n * Get the sectors starting point (on the underlying circle, located at the start angle).\n *\n * @method getStartPoint\n * @instance\n * @memberof CircleSector\n * @return {Vertex} The sector's stating point.\n */\n getStartPoint() {\n return this.circle.vertAt(this.startAngle);\n }\n /**\n * Get the sectors ending point (on the underlying circle, located at the end angle).\n *\n * @method getEndPoint\n * @instance\n * @memberof CircleSector\n * @return {Vertex} The sector's ending point.\n */\n getEndPoint() {\n return this.circle.vertAt(this.endAngle);\n }\n /**\n * Calculate the intersection of this circle sector and some other sector.\n *\n * If the two sectors do not corerently intersect (when not both points of the\n * radical line are containted in both source sectors) then null is returned.\n *\n * See demo/53-circle-sector-intersections for a geometric visualisation.\n *\n * @method circleSectorIntersection\n * @instance\n * @memberof CircleSector\n * @return {CircleSector | null} The intersecion of both sectors or null if they don't intersect.\n */\n circleSectorIntersection(sector) {\n const radicalLine = this.circle.circleIntersection(sector.circle);\n if (!radicalLine) {\n // The circles to not intersect at all.\n return null;\n }\n // Circles intersect. Check if this sector interval intersects, too.\n const thisIntersectionAngleA = this.circle.center.angle(radicalLine.a);\n const thisIntersectionAngleB = this.circle.center.angle(radicalLine.b);\n // Is intersection inside this sector?\n if (!this.containsAngle(thisIntersectionAngleA) || !this.containsAngle(thisIntersectionAngleB)) {\n // At least one circle intersection point is not located in this sector.\n // -> no valid intersection at all\n return null;\n }\n // Circles intersect. Check if the passed sector interval intersects, too.\n const thatIntersectionAngleA = sector.circle.center.angle(radicalLine.a);\n const thatIntersectionAngleB = sector.circle.center.angle(radicalLine.b);\n // Is intersection inside this sector?\n if (!sector.containsAngle(thatIntersectionAngleA) || !sector.containsAngle(thatIntersectionAngleB)) {\n // At least one circle intersection point is not located in this sector.\n // -> no valid intersection at all\n return null;\n }\n // The radical line has no direction. Thus the resulting sector _might_ be in reverse order.\n // Make a quick logical check: the center of the gap must still be located inside the result sector.\n // If not: reverse result.\n var gapSector = new CircleSector(this.circle, this.endAngle, this.startAngle);\n var centerOfOriginalGap = gapSector.angleAt(0.5);\n const resultSector = new CircleSector(new Circle(this.circle.center.clone(), this.circle.radius), thisIntersectionAngleA, thisIntersectionAngleB);\n if (resultSector.containsAngle(centerOfOriginalGap)) {\n resultSector.startAngle = thisIntersectionAngleB;\n resultSector.endAngle = thisIntersectionAngleA;\n }\n return resultSector;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the line intersections as vectors with this ellipse.\n *\n * @method lineIntersections\n * @instance\n * @param {VertTuple<Vector> ray - The line/ray to intersect this ellipse with.\n * @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.\n * @returns\n */\n lineIntersections(ray, inVectorBoundsOnly = false) {\n // First get all line intersections from underlying ellipse.\n const ellipseIntersections = this.circle.lineIntersections(ray, inVectorBoundsOnly);\n // Drop all intersection points that are not contained in the circle sectors bounds.\n const tmpLine = new Line(this.circle.center, new Vertex());\n return ellipseIntersections.filter((intersectionPoint) => {\n tmpLine.b.set(intersectionPoint);\n const lineAngle = tmpLine.angle();\n return this.containsAngle(geomutils.wrapMinMax(lineAngle, 0, Math.PI * 2));\n });\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.circle.center, vert);\n const angle = lineFromCenter.angle();\n // console.log(\"angle\", (angle / Math.PI) * 180.0);\n // const angle = Math.random() * Math.PI * 2; // TODO\n // Calculate tangent at angle\n return this.circle.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n describeSVGPath(options) {\n // const buffer: SVGPathParams = [];\n // const start = this.getStartPoint();\n // const end = this.getEndPoint();\n // // describeSVGArc\n // // x: number,\n // // y: number,\n // // radius: number,\n // // startAngle: number,\n // // endAngle: number,\n // // options?: { moveToStart: boolean }\n // // ): SVGPathParams => {\n // var arcRotation = 0.0;\n // var largeArcFlag = 1;\n // var sweepFlag = 0;\n // if (options && options.moveToStart) {\n // buffer.push(\"M\", start.x, start.y);\n // }\n // buffer.push(\"A\", cSector.circle.radius, cSector.circle.radius, arcRotation, largeArcFlag, sweepFlag, end.x, end.y);\n // return buffer;\n const arc = CircleSector.circleSectorUtils.describeSVGArc(this.circle.center.x, // end.x,\n this.circle.center.y, // end.y,\n this.circle.radius, this.startAngle, this.endAngle, options // options?: { moveToStart: boolean }\n );\n return arc;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n *\n * @method destroy\n * @instance\n * @memberof CircleSector\n * @return {void}\n */\n destroy() {\n this.circle.destroy();\n this.isDestroyed = true;\n }\n} // END class\nCircleSector.circleSectorUtils = {\n /**\n * Helper function to convert polar circle coordinates to cartesian coordinates.\n *\n * TODO: generalize for ellipses (two radii).\n *\n * @param {number} angle - The angle in radians.\n */\n polarToCartesian: (centerX, centerY, radius, angle) => {\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n },\n /**\n * Helper function to convert a circle section as SVG arc params (for the `d` attribute).\n * Found at: https://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle\n *\n * TODO: generalize for ellipses (two radii).\n *\n * @param {boolean} options.moveToStart - If false (default=true) the initial 'Move' command will not be used.\n * @return [ 'A', radiusx, radiusy, rotation=0, largeArcFlag=1|0, sweepFlag=0, endx, endy ]\n */\n describeSVGArc: (x, y, radius, startAngle, endAngle, options) => {\n if (typeof options === \"undefined\") {\n options = { moveToStart: true };\n }\n const end = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, endAngle);\n const start = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, startAngle);\n // Split full circles into two halves.\n // Some browsers have problems to render full circles (described by start==end).\n if (Math.PI * 2 - Math.abs(startAngle - endAngle) < 0.001) {\n const firstHalf = CircleSector.circleSectorUtils.describeSVGArc(x, y, radius, startAngle, startAngle + (endAngle - startAngle) / 2, options);\n const secondHalf = CircleSector.circleSectorUtils.describeSVGArc(x, y, radius, startAngle + (endAngle - startAngle) / 2, endAngle, options);\n return firstHalf.concat(secondHalf);\n }\n // Boolean stored as integers (0|1).\n const diff = endAngle - startAngle;\n var largeArcFlag;\n var sweepFlag;\n if (diff < 0) {\n largeArcFlag = Math.abs(diff) < Math.PI ? 1 : 0;\n sweepFlag = 1;\n }\n else {\n largeArcFlag = Math.abs(diff) > Math.PI ? 1 : 0;\n sweepFlag = 1;\n }\n const pathData = [];\n if (options.moveToStart) {\n pathData.push(\"M\", start.x, start.y);\n }\n pathData.push(\"A\", radius, radius, 0, largeArcFlag, sweepFlag, end.x, end.y);\n return pathData;\n }\n};\n//# sourceMappingURL=CircleSector.js.map","/**\n * Draws elements into an SVG node.\n *\n * Note that this library uses buffers and draw cycles. To draw onto an SVG canvas, do this:\n * const drawLib = new drawutilssvg( svgNode, ... );\n * const fillLib = drawLib.copyInstance(true);\n * // Begin draw cycle\n * drawLib.beginDrawCycle(time);\n * // ... draw or fill your stuff ...\n * drawLib.endDrawCycle(time); // Here the elements become visible\n *\n * @author Ikaros Kappler\n * @date 2021-01-03\n * @modified 2021-01-24 Fixed the `fillShapes` attribute in the copyInstance function.\n * @modified 2021-01-26 Changed the `isPrimary` (default true) attribute to `isSecondary` (default false).\n * @modified 2021-02-03 Added the static `createSvg` function.\n * @modified 2021-02-03 Fixed the currentId='background' bug on the clear() function.\n * @modified 2021-02-03 Fixed CSSProperty `stroke-width` (was line-width before, which is wrong).\n * @modified 2021-02-03 Added the static `HEAD_XML` attribute.\n * @modified 2021-02-19 Added the static helper function `transformPathData(...)` for svg path transformations (scale and translate).\n * @modified 2021-02-22 Added the static helper function `copyPathData(...)`.\n * @modified 2021-02-22 Added the `path` drawing function to draw SVG path data.\n * @modified 2021-03-01 Fixed a bug in the `clear` function (curClassName was not cleared).\n * @modified 2021-03-29 Fixed a bug in the `text` function (second y param was wrong, used x here).\n * @modified 2021-03-29 Moved this file from `src/ts/utils/helpers/` to `src/ts/`.\n * @modified 2021-03-31 Added 'ellipseSector' the the class names.\n * @modified 2021-03-31 Implemented buffering using a buffer <g> node and the beginDrawCycle and endDrawCycle methods.\n * @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.\n * @modified 2021-11-15 Adding more parameters tot the `text()` function: fontSize, textAlign, fontFamily, lineHeight.\n * @modified 2021-11-19 Fixing the `label(text,x,y)` position.\n * @modified 2021-11-19 Added the `color` param to the `label(...)` function.\n * @modified 2022-02-03 Added the `lineWidth` param to the `crosshair` function.\n * @modified 2022-02-03 Added the `cross(...)` function.\n * @modified 2022-03-26 Added the private `nodeDefs` and `bufferedNodeDefs` attributes.\n * @modified 2022-03-26 Added the `texturedPoly` function to draw textures polygons.\n * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.\n * @modified 2022-11-10 Tweaking some type issues.\n * @modified 2023-02-04 Fixed a typo in the CSS classname for cubic Bézier paths: cubicBezier (was cubierBezier).\n * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.\n * @modified 2023-09-29 Added initialization checks for null parameters.\n * @modified 2023-09-29 Added a missing implementation to the `drawurilssvg.do(XYCoords,string)` function. Didn't draw anything.\n * @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.\n * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.\n * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-10-04 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.\n * @modified 2024-01-30 Fixing an issue with immutable style sets; changes to the global draw config did not reflect here (do now).\n * @modified 2024-03-10 Fixing some types for Typescript 5 compatibility.\n * @modified 2024-07-24 Caching custom style defs in a private buffer variable.\n * @modified 2025-11-14 Fixing a bug in the CSS `mix-blend-mode` property handling (caused a runtime error).\n * @modified 2026-01-04 Adding `lineJoin` attribute to the methods' `StrokeOptions` param.\n * @modified 2026-01-04 Fixing missing `strokeOptions` param in the `drawutilssvg.polygon` method.\n * @modified 2026-03-18 Adding `isOpen` parameter to `cubicBezierPath` draw method.\n * @version 1.7.0\n **/\nimport { CircleSector } from \"./CircleSector\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { Vertex } from \"./Vertex\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vector } from \"./Vector\";\nconst RAD_TO_DEG = 180 / Math.PI;\n/**\n * @classdesc A helper class for basic SVG drawing operations. This class should\n * be compatible to the default 'draw' class.\n *\n * @requires CubicBzierCurvce\n * @requires Polygon\n * @requires Vertex\n * @requires XYCoords\n */\nexport class drawutilssvg {\n /**\n * Passed from primary to secondary instance.\n */\n //private nodeStyle: SVGStyleElement;\n /**\n * The constructor.\n *\n * @constructor\n * @name drawutilssvg\n * @param {SVGElement} svgNode - The SVG node to use.\n * @param {XYCoords} offset - The draw offset to use.\n * @param {XYCoords} scale - The scale factors to use.\n * @param {XYDimension} canvasSize - The initial canvas size (use setSize to change).\n * @param {boolean} fillShapes - Indicates if the constructed drawutils should fill all drawn shapes (if possible).\n * @param {DrawConfig} drawConfig - The default draw config to use for CSS fallback styles.\n * @param {boolean=} isSecondary - (optional) Indicates if this is the primary or secondary instance. Only primary instances manage child nodes.\n * @param {SVGGElement=} gNode - (optional) Primary and seconday instances share the same &lt;g> node.\n **/\n constructor(svgNode, offset, scale, canvasSize, fillShapes, drawConfig, isSecondary, gNode, bufferGNode, nodeDefs, bufferNodeDefs, nodeStyle) {\n this.svgNode = svgNode;\n this.offset = new Vertex(0, 0).set(offset);\n this.scale = new Vertex(1, 1).set(scale);\n this.fillShapes = fillShapes;\n this.isSecondary = Boolean(isSecondary);\n this.drawConfig = drawConfig;\n this.drawlibConfiguration = {};\n this.cache = new Map();\n this.setSize(canvasSize);\n if (isSecondary) {\n if (!gNode || !bufferGNode || !nodeDefs || !bufferNodeDefs) {\n throw \"Cannot create secondary svg draw lib with undefinde gNode|bufferGNode|nodeDefs|bufferNodeDefs.\";\n }\n this.gNode = gNode;\n this.bufferGNode = bufferGNode;\n this.nodeDefs = nodeDefs;\n this.bufferedNodeDefs = bufferNodeDefs;\n if (nodeStyle) {\n this.nodeStyle = nodeStyle;\n }\n }\n else {\n this.addStyleDefs(drawConfig);\n this.addDefsNode();\n this.gNode = this.createSVGNode(\"g\");\n this.bufferGNode = this.createSVGNode(\"g\");\n this.svgNode.appendChild(this.gNode);\n }\n }\n /**\n * Adds a default style defintion based on the passed DrawConfig.\n * Twaek the draw config to change default colors or line thicknesses.\n *\n * @param {DrawConfig} drawConfig\n */\n addStyleDefs(drawConfig) {\n this.nodeStyle = this.createSVGNode(\"style\");\n this.svgNode.appendChild(this.nodeStyle);\n this.rebuildStyleDefs(drawConfig);\n }\n /**\n * This method is required to re-define the global style defs. It is needed\n * if any value in the DrawConfig changed in the meantime.\n * @param drawConfig\n */\n rebuildStyleDefs(drawConfig) {\n // Which default styles to add? -> All from the DrawConfig.\n // Compare with DrawConfig interface\n const keys = {\n \"bezier\": \"CubicBezierCurve\",\n //\"bezierPath\": \"BezierPath\", // TODO: is this correct?\n \"polygon\": \"Polygon\",\n \"triangle\": \"Triangle\",\n \"ellipse\": \"Ellipse\",\n \"ellipseSector\": \"EllipseSector\",\n \"circle\": \"Circle\",\n \"circleSector\": \"CircleSector\",\n \"vertex\": \"Vertex\",\n \"line\": \"Line\",\n \"vector\": \"Vector\",\n \"image\": \"Image\",\n \"text\": \"Text\"\n };\n // Question: why isn't this working if the svgNode is created dynamically? (nodeStyle.sheet is null)\n const rules = [];\n // console.log(\"drawConfig\", drawConfig);\n for (var k in keys) {\n const className = keys[k];\n const drawSettings = drawConfig[k];\n if (drawSettings) {\n rules.push(`.${className} { fill : none; stroke: ${drawSettings.color}; stroke-width: ${drawSettings.lineWidth}px }`);\n }\n else {\n console.warn(`Warning: your draw config is missing the key '${k}' which is required.`);\n }\n }\n if (this.customStyleDefs) {\n rules.push(\"\\n/* Custom styles */\\n\");\n this.customStyleDefs.forEach((value, key) => {\n rules.push(key + \" { \" + value + \" }\");\n });\n // this.nodeStyle.innerHTML += \"\\n/* Custom styles */\\n\" + rules.join(\"\\n\");\n }\n this.nodeStyle.innerHTML = rules.join(\"\\n\");\n }\n /**\n * Adds the internal <defs> node.\n */\n addDefsNode() {\n this.nodeDefs = this.createSVGNode(\"defs\");\n // this.svgNode.appendChild(this.nodeDefs);\n this.bufferedNodeDefs = this.createSVGNode(\"defs\");\n this.svgNode.appendChild(this.nodeDefs);\n }\n /**\n * This is a simple way to include custom CSS class mappings to the style defs of the generated SVG.\n *\n * The mapping should be of the form\n * [style-class] -> [style-def-string]\n *\n * Example:\n * \"rect.red\" -> \"fill: #ff0000; border: 1px solid red\"\n *\n * @param {Map<string,string>} defs\n */\n addCustomStyleDefs(defs) {\n this.customStyleDefs = defs;\n }\n /**\n * Retieve an old (cached) element.\n * Only if both – key and nodeName – match, the element will be returned (null otherwise).\n *\n * @method findElement\n * @private\n * @memberof drawutilssvg\n * @instance\n * @param {UID} key - The key of the desired element (used when re-drawing).\n * @param {string} nodeName - The expected node name.\n */\n findElement(key, nodeName) {\n if (!key) {\n return null;\n }\n var node = this.cache.get(key);\n if (node && node.nodeName.toUpperCase() === nodeName.toUpperCase()) {\n this.cache.delete(key);\n return node;\n }\n return null;\n }\n /**\n * Create a new DOM node &lt;svg&gt; in the SVG namespace.\n *\n * @method createSVGNode\n * @private\n * @memberof drawutilssvg\n * @instance\n * @param {string} nodeName - The node name (tag-name).\n * @return {SVGElement} A new element in the SVG namespace with the given node name.\n */\n createSVGNode(nodeName) {\n return document.createElementNS(\"http://www.w3.org/2000/svg\", nodeName);\n }\n /**\n * Make a new SVG node (or recycle an old one) with the given node name (circle, path, line, rect, ...).\n *\n * This function is used in draw cycles to re-use old DOM nodes (in hope to boost performance).\n *\n * @method makeNode\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {string} nodeName - The node name.\n * @return {SVGElement} The new node, which is not yet added to any document.\n */\n makeNode(nodeName) {\n // Try to find node in current DOM cache.\n // Unique node keys are strictly necessary.\n // Try to recycle an old element from cache.\n var node = this.findElement(this.curId, nodeName);\n if (!node) {\n // If no such old elements exists (key not found, tag name not matching),\n // then create a new one.\n node = this.createSVGNode(nodeName);\n }\n if (this.drawlibConfiguration.blendMode) {\n const blendMode = node.style[\"mix-blend-mode\"];\n if (typeof blendMode === \"function\") {\n blendMode(this.drawlibConfiguration.blendMode);\n }\n else {\n node.style[\"mix-blend-mode\"] = this.drawlibConfiguration.blendMode;\n }\n }\n // if (this.lineDashEnabled && this.lineDash && this.lineDash.length > 0 && drawutilssvg.nodeSupportsLineDash(nodeName)) {\n // node.setAttribute(\"stroke-dasharray\", this.lineDash.join(\" \"));\n // }\n return node;\n }\n /**\n * This is the final helper function for drawing and filling stuff and binding new\n * nodes to the SVG document.\n * It is not intended to be used from the outside.\n *\n * When in draw mode it draws the current shape.\n * When in fill mode it fills the current shape.\n *\n * This function is usually only called internally.\n *\n * @method _bindFillDraw\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {SVGElement} node - The node to draw/fill and bind.\n * @param {string} className - The class name(s) to use.\n * @param {string} color - A stroke/fill color to use.\n * @param {number=1} lineWidth - (optional) A line width to use for drawing (default is 1).\n * @return {SVGElement} The node itself (for chaining).\n */\n _bindFillDraw(node, className, color, lineWidth, strokeOptions) {\n this._configureNode(node, className, this.fillShapes, color, lineWidth, strokeOptions);\n return this._bindNode(node, undefined);\n }\n /**\n * Bind this given node to a parent. If no parent is passed then the global\n * node buffer will be used.\n *\n * @method _bindNode\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {SVGElement} node - The SVG node to bind.\n * @param {SVGElement=} bindingParent - (optional) You may pass node other than the glober buffer node.\n * @returns {SVGElement} The passed node itself.\n */\n _bindNode(node, bindingParent) {\n if (!node.parentNode) {\n // Attach to DOM only if not already attached\n (bindingParent !== null && bindingParent !== void 0 ? bindingParent : this.bufferGNode).appendChild(node);\n }\n return node;\n }\n /**\n * Add custom CSS class names and the globally defined CSS classname to the\n * given node.\n *\n * @method addCSSClasses\n * @private\n * @instance\n * @memberof drawutilssvg\n * @param {SVGElement} node - The SVG node to bind.\n * @param {string} className - The additional custom classname to add.\n * @returns {void}\n */\n _addCSSClasses(node, className) {\n if (this.curClassName) {\n node.setAttribute(\"class\", `${className} ${this.curClassName}`);\n }\n else {\n node.setAttribute(\"class\", className);\n }\n }\n _configureNode(node, className, fillMode, color, lineWidth, strokeOptions) {\n this._addCSSClasses(node, className);\n node.setAttribute(\"fill\", fillMode && color ? color : \"none\");\n node.setAttribute(\"stroke\", fillMode ? \"none\" : color || \"none\");\n node.setAttribute(\"stroke-width\", `${lineWidth || 1}`);\n if (this.curId) {\n node.setAttribute(\"id\", `${this.curId}`); // Maybe React-style 'key' would be better?\n }\n this.applyStrokeOpts(node, strokeOptions);\n return node;\n }\n /**\n * Sets the size and view box of the document. Call this if canvas size changes.\n *\n * @method setSize\n * @instance\n * @memberof drawutilssvg\n * @param {XYDimension} canvasSize - The new canvas size.\n */\n setSize(canvasSize) {\n this.canvasSize = canvasSize;\n this.svgNode.setAttribute(\"viewBox\", `0 0 ${this.canvasSize.width} ${this.canvasSize.height}`);\n this.svgNode.setAttribute(\"width\", `${this.canvasSize.width}`);\n this.svgNode.setAttribute(\"height\", `${this.canvasSize.height}`);\n }\n /**\n * Creates a 'shallow' (non deep) copy of this instance. This implies\n * that under the hood the same gl context and gl program will be used.\n */\n copyInstance(fillShapes) {\n var copy = new drawutilssvg(this.svgNode, this.offset, this.scale, this.canvasSize, fillShapes, this.drawConfig, // null as any as DrawConfig, // no DrawConfig – this will work as long as `isSecondary===true`\n true, // isSecondary\n this.gNode, this.bufferGNode, this.nodeDefs, this.bufferedNodeDefs, this.nodeStyle);\n return copy;\n }\n /**\n * Set the current drawlib configuration.\n *\n * @name setConfiguration\n * @method\n * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.\n */\n setConfiguration(configuration) {\n this.drawlibConfiguration = configuration;\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * It is used by some libraries for identifying elemente on re-renders.\n *\n * @name setCurrentId\n * @method\n * @param {UID|null} uid - A UID identifying the currently drawn element(s).\n * @instance\n * @memberof drawutilssvg\n **/\n setCurrentId(uid) {\n this.curId = uid;\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * Determine the class name for further usage here.\n *\n * @name setCurrentClassName\n * @method\n * @param {string|null} className - A class name for further custom use cases.\n * @instance\n * @memberof drawutilssvg\n **/\n setCurrentClassName(className) {\n this.curClassName = className;\n }\n /**\n * Called before each draw cycle.\n * This is required for compatibility with other draw classes in the library.\n *\n * @name beginDrawCycle\n * @method\n * @param {UID=} uid - (optional) A UID identifying the currently drawn element(s).\n * @instance\n * @memberof drawutilssvg\n **/\n beginDrawCycle(renderTime) {\n // Clear non-recycable elements from last draw cycle.\n this.cache.clear();\n // Clearing an SVG is equivalent to removing all its child elements.\n for (var i = 0; i < this.bufferGNode.childNodes.length; i++) {\n // Hide all nodes here. Don't throw them away.\n // We can probably re-use them in the next draw cycle.\n var child = this.bufferGNode.childNodes[i];\n this.cache.set(child.getAttribute(\"id\"), child);\n }\n this.removeAllChildNodes();\n }\n /**\n * Called after each draw cycle.\n *\n * This is required for compatibility with other draw classes in the library (like drawgl).\n *\n * @name endDrawCycle\n * @method\n * @param {number} renderTime\n * @instance\n **/\n endDrawCycle(renderTime) {\n this.rebuildStyleDefs(this.drawConfig);\n if (!this.isSecondary) {\n // All elements are drawn into the buffer; they are NOT yet visible, not did the browser perform any\n // layout updates.\n // Replace the old <g>-node with the buffer node.\n // https://stackoverflow.com/questions/27442464/how-to-update-a-svg-image-without-seeing-a-blinking\n this.svgNode.replaceChild(this.bufferedNodeDefs, this.nodeDefs);\n this.svgNode.replaceChild(this.bufferGNode, this.gNode);\n }\n const tmpGNode = this.gNode;\n this.gNode = this.bufferGNode;\n this.bufferGNode = tmpGNode;\n const tmpDefsNode = this.nodeDefs;\n this.nodeDefs = this.bufferedNodeDefs;\n this.bufferedNodeDefs = tmpDefsNode;\n }\n /**\n * A private helper method to apply stroke options to the current\n * context.\n * @param {StrokeOptions=} strokeOptions -\n */\n applyStrokeOpts(node, strokeOptions) {\n // Set line dash options?\n if (strokeOptions &&\n strokeOptions.dashArray &&\n strokeOptions.dashArray.length > 0 &&\n drawutilssvg.nodeSupportsLineDash(node.tagName)) {\n node.setAttribute(\"stroke-dasharray\", strokeOptions.dashArray\n .map((dashArayElem) => {\n return dashArayElem * this.scale.x;\n })\n .join(\" \"));\n if (strokeOptions.dashOffset) {\n node.setAttribute(\"stroke-dashoffset\", `${strokeOptions.dashOffset * this.scale.x}`);\n }\n }\n // Set line join option?\n if (strokeOptions && strokeOptions.lineJoin && drawutilssvg.nodeSupportsLineJoin(node.tagName)) {\n node.setAttribute(\"stroke-linejoin\", strokeOptions.lineJoin);\n }\n }\n _x(x) {\n return this.offset.x + this.scale.x * x;\n }\n _y(y) {\n return this.offset.y + this.scale.y * y;\n }\n /**\n * Draw the line between the given two points with the specified (CSS-) color.\n *\n * @method line\n * @param {XYCoords} zA - The start point of the line.\n * @param {XYCoords} zB - The end point of the line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth? - [optional] The line's width.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n line(zA, zB, color, lineWidth, strokeOptions) {\n // const line: SVGElement = this.makeNode(\"line\");\n // this.applyStrokeOpts(line, strokeOptions);\n // line.setAttribute(\"x1\", `${this._x(zA.x)}`);\n // line.setAttribute(\"y1\", `${this._y(zA.y)}`);\n // line.setAttribute(\"x2\", `${this._x(zB.x)}`);\n // line.setAttribute(\"y2\", `${this._y(zB.y)}`);\n const line = this.makeLineNode(zA, zB, color, lineWidth, strokeOptions);\n return this._bindFillDraw(line, \"line\", color, lineWidth || 1, strokeOptions);\n }\n /**\n * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n arrow(zA, zB, color, lineWidth, headLength = 8, strokeOptions) {\n const group = this.makeNode(\"g\");\n const arrowHeadBasePosition = { x: 0, y: 0 };\n // Just create the child nodes, don't bind them to the root node.\n const arrowHead = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, undefined, arrowHeadBasePosition);\n const line = this.makeLineNode(zA, arrowHeadBasePosition, color, lineWidth, strokeOptions);\n group.appendChild(line);\n group.appendChild(arrowHead);\n this._addCSSClasses(group, \"linear-arrow\");\n this._bindNode(group, undefined);\n return group;\n }\n /**\n * Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.\n *\n * @method cubicBezierArrow\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n */\n cubicBezierArrow(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, headLength = 8, strokeOptions) {\n const group = this.makeNode(\"g\");\n // Just create the child nodes, don't bind them to the root node.\n const arrowHeadBasePosition = new Vertex(0, 0);\n const arrowHead = this.makeArrowHeadNode(endControlPoint, endPoint, color, lineWidth, headLength, undefined, arrowHeadBasePosition);\n const diff = arrowHeadBasePosition.difference(endPoint);\n const bezier = this.makeCubicBezierNode(startPoint, { x: endPoint.x - diff.x, y: endPoint.y - diff.y }, startControlPoint, { x: endControlPoint.x - diff.x, y: endControlPoint.y - diff.y }, color, lineWidth, strokeOptions);\n group.appendChild(bezier);\n group.appendChild(arrowHead);\n this._addCSSClasses(group, \"cubicbezier-arrow\");\n this._bindNode(group, undefined);\n return group;\n }\n /**\n * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n **/\n arrowHead(zA, zB, color, lineWidth, headLength = 8, strokeOptions) {\n const node = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, strokeOptions);\n return this._bindFillDraw(node, \"arrowhead\", color, lineWidth || 1, strokeOptions);\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method image\n * @param {Image} image - The image object to draw.\n * @param {XYCoords} position - The position to draw the the upper left corner at.\n * @param {XYCoords} size - The x/y-size to draw the image with.\n * @param {number=0.0} alpha - (optional, default=0.0) The transparency (1.0=opaque, 0.0=transparent).\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n image(image, position, size, alpha = 1.0) {\n const node = this.makeNode(\"image\");\n // We need to re-adjust the image if it was not yet fully loaded before.\n const setImageSize = (image) => {\n if (image.naturalWidth) {\n const ratioX = size.x / image.naturalWidth;\n const ratioY = size.y / image.naturalHeight;\n node.setAttribute(\"width\", `${image.naturalWidth * this.scale.x}`);\n node.setAttribute(\"height\", `${image.naturalHeight * this.scale.y}`);\n node.setAttribute(\"display\", null); // Dislay when loaded\n // if (alpha) {\n node.setAttribute(\"opacity\", `${alpha}`);\n // }\n node.setAttribute(\"transform\", `translate(${this._x(position.x)} ${this._y(position.y)}) scale(${ratioX} ${ratioY})`);\n }\n };\n image.addEventListener(\"load\", event => {\n setImageSize(image);\n });\n // Safari has a transform-origin bug.\n // Use x=0, y=0 and translate/scale instead (see above)\n node.setAttribute(\"x\", `${0}`);\n node.setAttribute(\"y\", `${0}`);\n node.setAttribute(\"display\", \"none\"); // Hide before loaded\n setImageSize(image);\n node.setAttribute(\"href\", image.src);\n return this._bindFillDraw(node, \"image\", null, null);\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method texturedPoly\n * @param {Image} textureImage - The image object to draw.\n * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.\n * @param {Polygon} polygon - The polygon to use as clip path.\n * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.\n * @param {number} rotation - The rotation to use for the polygon (and for the texture).\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n texturedPoly(textureImage, textureSize, polygon, polygonPosition, rotation) {\n // const basePolygonBounds: Bounds = polygon.getBounds();\n const rotatedScalingOrigin = new Vertex(textureSize.min).clone().rotate(rotation, polygonPosition);\n // const rotationCenter = polygonPosition.clone().add(rotatedScalingOrigin.difference(textureSize.min).inv());\n // Create something like this\n // ...\n // <defs>\n // <clipPath id=\"shape\">\n // <path fill=\"none\" d=\"...\"/>\n // </clipPath>\n // </defs>\n // ...\n // <g clip-path=\"url(#shape)\">\n // <g transform=\"scale(...)\">\n // <image width=\"643\" height=\"643\" transform=\"rotate(...)\" xlink:href=\"https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg\" >\n // </g>\n // </g>\n // </image>\n // ...\n const clipPathNode = this.makeNode(\"clipPath\");\n const clipPathId = `clippath_${UIDGenerator.next()}`; // TODO: use a better UUID generator here?\n clipPathNode.setAttribute(\"id\", clipPathId);\n const gNode = this.makeNode(\"g\");\n const imageNode = this.makeNode(\"image\");\n imageNode.setAttribute(\"x\", `${this._x(rotatedScalingOrigin.x)}`);\n imageNode.setAttribute(\"y\", `${this._y(rotatedScalingOrigin.y)}`);\n imageNode.setAttribute(\"width\", `${textureSize.width}`);\n imageNode.setAttribute(\"height\", `${textureSize.height}`);\n imageNode.setAttribute(\"href\", textureImage.src);\n // imageNode.setAttribute(\"opacity\", \"0.5\");\n // SVG rotations in degrees\n imageNode.setAttribute(\"transform\", `rotate(${rotation * RAD_TO_DEG}, ${this._x(rotatedScalingOrigin.x)}, ${this._y(rotatedScalingOrigin.y)})`);\n const pathNode = this.makeNode(\"path\");\n const pathData = [];\n if (polygon.vertices.length > 0) {\n const self = this;\n pathData.push(\"M\", `${this._x(polygon.vertices[0].x)}`, `${this._y(polygon.vertices[0].y)}`);\n for (var i = 1; i < polygon.vertices.length; i++) {\n pathData.push(\"L\", `${this._x(polygon.vertices[i].x)}`, `${this._y(polygon.vertices[i].y)}`);\n }\n }\n pathNode.setAttribute(\"d\", pathData.join(\" \"));\n clipPathNode.appendChild(pathNode);\n this.bufferedNodeDefs.appendChild(clipPathNode);\n gNode.appendChild(imageNode);\n gNode.setAttribute(\"transform-origin\", `${this._x(rotatedScalingOrigin.x)} ${this._y(rotatedScalingOrigin.y)}`);\n gNode.setAttribute(\"transform\", `scale(${this.scale.x}, ${this.scale.y})`);\n const clipNode = this.makeNode(\"g\");\n clipNode.appendChild(gNode);\n clipNode.setAttribute(\"clip-path\", `url(#${clipPathId})`);\n // TODO: check if the image class is correct here or if we should use a 'clippedImage' class here\n this._bindFillDraw(clipNode, \"image\", null, null); // No color, no lineWidth\n return clipNode;\n }\n /**\n * Draw the given (cubic) bézier curve.\n *\n * @method cubicBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n cubicBezier(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions) {\n const node = this.makeCubicBezierNode(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions);\n return this._bindNode(node, undefined);\n }\n /**\n * Draw the given (cubic) Bézier path.\n *\n * The given path must be an array with n*3+1 vertices, where n is the number of\n * curves in the path:\n * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>\n *\n * @method cubicBezierPath\n * @param {XYCoords[]} path - The cubic bezier path as described above.\n * @param {string} color - The CSS colot to draw the path with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n * @param {boolean} isOpen - (optional) Set to tur if the path should not be closed.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n cubicBezierPath(path, color, lineWidth, strokeOptions, isOpen) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, strokeOptions);\n if (!path || path.length == 0) {\n return node;\n }\n // Draw curve\n const d = [\"M\", this._x(path[0].x), this._y(path[0].y)];\n // Draw curve path\n var endPoint;\n var startControlPoint;\n var endControlPoint;\n for (var i = 1; i < path.length; i += 3) {\n startControlPoint = path[i];\n endControlPoint = path[i + 1];\n endPoint = path[i + 2];\n d.push(\"C\", this._x(startControlPoint.x), this._y(startControlPoint.y), this._x(endControlPoint.x), this._y(endControlPoint.y), this._x(endPoint.x), this._y(endPoint.y));\n }\n if (!isOpen) {\n d.push(\"Z\");\n }\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"cubicBezierPath\", color, lineWidth || 1);\n }\n /**\n * Draw the given handle and handle point (used to draw interactive Bézier curves).\n *\n * The colors for this are fixed and cannot be specified.\n *\n * @method handle\n * @param {Vertex} startPoint - The start of the handle.\n * @param {Vertex} endPoint - The end point of the handle.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n handle(startPoint, endPoint) {\n // TODO: redefine methods like these into an abstract class?\n this.point(startPoint, \"rgb(0,32,192)\");\n this.square(endPoint, 5, \"rgba(0,128,192,0.5)\");\n }\n /**\n * Draw a handle line (with a light grey).\n *\n * @method handleLine\n * @param {XYCoords} startPoint - The start point to draw the handle at.\n * @param {XYCoords} endPoint - The end point to draw the handle at.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n handleLine(startPoint, endPoint) {\n this.line(startPoint, endPoint, \"rgb(128,128,128,0.5)\");\n }\n /**\n * Draw a 1x1 dot with the specified (CSS-) color.\n *\n * @method dot\n * @param {XYCoords} p - The position to draw the dot at.\n * @param {string} color - The CSS color to draw the dot with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n dot(p, color) {\n const node = this.makeNode(\"line\");\n node.setAttribute(\"x1\", `${this._x(p.x)}`);\n node.setAttribute(\"y1\", `${this._y(p.y)}`);\n node.setAttribute(\"x2\", `${this._x(p.x)}`);\n node.setAttribute(\"y2\", `${this._y(p.y)}`);\n return this._bindFillDraw(node, \"dot\", color, 1);\n }\n /**\n * Draw the given point with the specified (CSS-) color and radius 3.\n *\n * @method point\n * @param {XYCoords} p - The position to draw the point at.\n * @param {string} color - The CSS color to draw the point with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n point(p, color) {\n var radius = 3;\n const node = this.makeNode(\"circle\");\n node.setAttribute(\"cx\", `${this._x(p.x)}`);\n node.setAttribute(\"cy\", `${this._y(p.y)}`);\n node.setAttribute(\"r\", `${radius}`);\n return this._bindFillDraw(node, \"point\", color, 1);\n }\n /**\n * Draw a circle with the specified (CSS-) color and radius.<br>\n * <br>\n * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.\n *\n * @method circle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n circle(center, radius, color, lineWidth, strokeOptions) {\n // Todo: draw ellipse when scalex!=scaley\n const node = this.makeNode(\"circle\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"cx\", `${this._x(center.x)}`);\n node.setAttribute(\"cy\", `${this._y(center.y)}`);\n node.setAttribute(\"r\", `${radius * this.scale.x}`); // y?\n return this._bindFillDraw(node, \"circle\", color, lineWidth || 1);\n }\n /**\n * Draw a circular arc (section of a circle) with the given CSS color.\n *\n * @method circleArc\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {number} startAngle - The angle to start at.\n * @param {number} endAngle - The angle to end at.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n circleArc(center, radius, startAngle, endAngle, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, strokeOptions);\n const arcData = CircleSector.circleSectorUtils.describeSVGArc(this._x(center.x), this._y(center.y), radius * this.scale.x, // y?\n startAngle, endAngle);\n node.setAttribute(\"d\", arcData.join(\" \"));\n return this._bindFillDraw(node, \"circleArc\", color, lineWidth || 1);\n }\n /**\n * Draw an ellipse with the specified (CSS-) color and thw two radii.\n *\n * @method ellipse\n * @param {XYCoords} center - The center of the ellipse.\n * @param {number} radiusX - The radius of the ellipse.\n * @param {number} radiusY - The radius of the ellipse.\n * @param {string} color - The CSS color to draw the ellipse with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n ellipse(center, radiusX, radiusY, color, lineWidth, rotation, strokeOptions) {\n if (typeof rotation === \"undefined\") {\n rotation = 0.0;\n }\n const node = this.makeNode(\"ellipse\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"cx\", `${this._x(center.x)}`);\n node.setAttribute(\"cy\", `${this._y(center.y)}`);\n node.setAttribute(\"rx\", `${radiusX * this.scale.x}`);\n node.setAttribute(\"ry\", `${radiusY * this.scale.y}`);\n // node.setAttribute( 'style', `transform: rotate(${rotation} ${center.x} ${center.y})` );\n node.setAttribute(\"transform\", `rotate(${(rotation * 180) / Math.PI} ${this._x(center.x)} ${this._y(center.y)})`);\n return this._bindFillDraw(node, \"ellipse\", color, lineWidth || 1);\n }\n /**\n * Draw square at the given center, size and with the specified (CSS-) color.<br>\n * <br>\n * Note that if the x-scale and the y-scale are different the result will be a rectangle rather than a square.\n *\n * @method square\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {SVGElement}\n * @instance\n * @memberof drawutilssvg\n */\n square(center, size, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"rectangle\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"x\", `${this._x(center.x - size / 2.0)}`);\n node.setAttribute(\"y\", `${this._y(center.y - size / 2.0)}`);\n node.setAttribute(\"width\", `${size * this.scale.x}`);\n node.setAttribute(\"height\", `${size * this.scale.y}`);\n return this._bindFillDraw(node, \"square\", color, lineWidth || 1);\n }\n /**\n * Draw a rectangle.\n *\n * @param {XYCoords} position - The upper left corner of the rectangle.\n * @param {number} width - The width of the rectangle.\n * @param {number} height - The height of the rectangle.\n * @param {string} color - The color to use.\n * @param {number=1} lineWidth - (optional) The line with to use (default is 1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {SVGElement}\n * @instance\n * @memberof drawutilssvg\n **/\n rect(position, width, height, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"rect\");\n this.applyStrokeOpts(node, strokeOptions);\n node.setAttribute(\"x\", `${this._x(position.x)}`);\n node.setAttribute(\"y\", `${this._y(position.y)}`);\n node.setAttribute(\"width\", `${width * this.scale.x}`);\n node.setAttribute(\"height\", `${height * this.scale.y}`);\n return this._bindFillDraw(node, \"rect\", color, lineWidth || 1);\n }\n /**\n * Draw a grid of horizontal and vertical lines with the given (CSS-) color.\n *\n * @method grid\n * @param {XYCoords} center - The center of the grid.\n * @param {number} width - The total width of the grid (width/2 each to the left and to the right).\n * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal grid size.\n * @param {number} sizeY - The vertical grid size.\n * @param {string} color - The CSS color to draw the grid with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n grid(center, width, height, sizeX, sizeY, color) {\n // console.log(\"grid\");\n // const node: SVGElement = this.makeNode(\"pattern\");\n // var patternId = \"pattern_id_\" + Math.floor(Math.random() * 65365);\n // node.setAttribute(\"id\", patternId);\n // node.setAttribute(\"viewBox\", `0,0,${sizeX},${sizeY}`);\n // node.setAttribute(\"width\", `${sizeX}`);\n // node.setAttribute(\"height\", `${sizeX}`);\n // var pattern: SVGElement = this.makeNode(\"path\");\n // const d: SVGPathParams = [];\n // d.push(\"M\", sizeX / 2.0, 0);\n // d.push(\"L\", sizeX / 2.0, sizeY);\n // d.push(\"M\", 0, sizeY / 2.0);\n // d.push(\"L\", sizeX, sizeY / 2.0);\n // node.setAttribute(\"d\", d.join(\" \"));\n // this.bufferedNodeDefs.append(pattern);\n // const fillNode: SVGElement = this.makeNode(\"rect\");\n // // For some strange reason SVG rotation transforms use degrees instead of radians\n // // Note that the background does not scale with the zoom level (always covers full element)\n // fillNode.setAttribute(\"x\", \"0\");\n // fillNode.setAttribute(\"y\", \"0\");\n // fillNode.setAttribute(\"width\", `${this.canvasSize.width}`);\n // fillNode.setAttribute(\"height\", `${this.canvasSize.height}`);\n // fillNode.setAttribute(\"fill\", `url(#${patternId})`);\n // return this._bindFillDraw(fillNode, \"grid\", \"red\", 1);\n const node = this.makeNode(\"path\");\n const d = [];\n var yMin = -Math.ceil((height * 0.5) / sizeY) * sizeY;\n var yMax = height / 2;\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n d.push(\"M\", this._x(center.x + x), this._y(center.y + yMin));\n d.push(\"L\", this._x(center.x + x), this._y(center.y + yMax));\n }\n var xMin = -Math.ceil((width * 0.5) / sizeX) * sizeX;\n var xMax = width / 2;\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n d.push(\"M\", this._x(center.x + xMin), this._y(center.y + y));\n d.push(\"L\", this._x(center.x + xMax), this._y(center.y + y));\n }\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"grid\", color, 1);\n }\n /**\n * Draw a raster of crosshairs in the given grid.<br>\n *\n * This works analogue to the grid() function\n *\n * @method raster\n * @param {XYCoords} center - The center of the raster.\n * @param {number} width - The total width of the raster (width/2 each to the left and to the right).\n * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal raster size.\n * @param {number} sizeY - The vertical raster size.\n * @param {string} color - The CSS color to draw the raster with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n raster(center, width, height, sizeX, sizeY, color) {\n const node = this.makeNode(\"path\");\n const d = [];\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n // Draw a crosshair\n d.push(\"M\", this._x(center.x + x) - 4, this._y(center.y + y));\n d.push(\"L\", this._x(center.x + x) + 4, this._y(center.y + y));\n d.push(\"M\", this._x(center.x + x), this._y(center.y + y) - 4);\n d.push(\"L\", this._x(center.x + x), this._y(center.y + y) + 4);\n }\n }\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"raster\", color, 1);\n }\n /**\n * Draw a diamond handle (square rotated by 45°) with the given CSS color.\n *\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped diamonds.\n *\n * @method diamondHandle\n * @param {XYCoords} center - The center of the diamond.\n * @param {number} size - The x/y-size of the diamond.\n * @param {string} color - The CSS color to draw the diamond with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n diamondHandle(center, size, color) {\n const node = this.makeNode(\"path\");\n const d = [\n \"M\",\n this._x(center.x) - size / 2.0,\n this._y(center.y),\n \"L\",\n this._x(center.x),\n this._y(center.y) - size / 2.0,\n \"L\",\n this._x(center.x) + size / 2.0,\n this._y(center.y),\n \"L\",\n this._x(center.x),\n this._y(center.y) + size / 2.0,\n \"Z\"\n ];\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"diamondHandle\", color, 1);\n }\n /**\n * Draw a square handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped squares.\n *\n * @method squareHandle\n * @param {XYCoords} center - The center of the square.\n * @param {XYCoords} size - The x/y-size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n squareHandle(center, size, color) {\n const node = this.makeNode(\"rect\");\n node.setAttribute(\"x\", `${this._x(center.x) - size / 2.0}`);\n node.setAttribute(\"y\", `${this._y(center.y) - size / 2.0}`);\n node.setAttribute(\"width\", `${size}`);\n node.setAttribute(\"height\", `${size}`);\n return this._bindFillDraw(node, \"squareHandle\", color, 1);\n }\n /**\n * Draw a circle handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped circles.\n *\n * @method circleHandle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n circleHandle(center, radius, color) {\n radius = radius || 3;\n const node = this.makeNode(\"circle\");\n node.setAttribute(\"cx\", `${this._x(center.x)}`);\n node.setAttribute(\"cy\", `${this._y(center.y)}`);\n node.setAttribute(\"r\", `${radius}`);\n return this._bindFillDraw(node, \"circleHandle\", color, 1);\n }\n /**\n * Draw a crosshair with given radius and color at the given position.<br>\n * <br>\n * Note that the crosshair radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=0.5} lineWidth - (optional, default=0.5) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n crosshair(center, radius, color, lineWidth) {\n const node = this.makeNode(\"path\");\n const d = [\n \"M\",\n this._x(center.x) - radius,\n this._y(center.y),\n \"L\",\n this._x(center.x) + radius,\n this._y(center.y),\n \"M\",\n this._x(center.x),\n this._y(center.y) - radius,\n \"L\",\n this._x(center.x),\n this._y(center.y) + radius\n ];\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"crosshair\", color, lineWidth || 0.5);\n }\n /**\n * Draw a cross with diagonal axes with given radius, color and lineWidth at the given position.<br>\n * <br>\n * Note that the x's radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=1} lineWidth - (optional, default=1.0) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cross(center, radius, color, lineWidth) {\n const node = this.makeNode(\"path\");\n const d = [\n \"M\",\n this._x(center.x) - radius,\n this._y(center.y) - radius,\n \"L\",\n this._x(center.x) + radius,\n this._y(center.y) + radius,\n \"M\",\n this._x(center.x) - radius,\n this._y(center.y) + radius,\n \"L\",\n this._x(center.x) + radius,\n this._y(center.y) - radius\n ];\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"cross\", color, lineWidth || 1.0);\n }\n /**\n * Draw a polygon.\n *\n * @method polygon\n * @param {Polygon} polygon - The polygon to draw.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n polygon(polygon, color, lineWidth, strokeOptions) {\n return this.polyline(polygon.vertices, polygon.isOpen, color, lineWidth, strokeOptions);\n }\n /**\n * Draw a polygon line (alternative function to the polygon).\n *\n * @method polyline\n * @param {XYCoords[]} vertices - The polygon vertices to draw.\n * @param {boolan} isOpen - If true the polyline will not be closed at its end.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n polyline(vertices, isOpen, color, lineWidth, strokeOptions) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, strokeOptions);\n if (vertices.length == 0) {\n return node;\n }\n // Draw curve\n const d = [\"M\", this._x(vertices[0].x), this._y(vertices[0].y)];\n var n = vertices.length;\n for (var i = 1; i < n; i++) {\n d.push(\"L\", this._x(vertices[i].x), this._y(vertices[i].y));\n }\n if (!isOpen)\n d.push(\"Z\");\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"polygon\", color, lineWidth || 1);\n }\n /**\n * Draw a text at the given relative position.\n *\n * @method text\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {string=} options.color - The Color to use.\n * @param {string=} options.fontFamily - The font family to use.\n * @param {number=} options.fontSize - The font size (in pixels) to use.\n * @param {FontStyle=} options.fontStyle - The font style to use.\n * @param {FontWeight=} options.fontWeight - The font weight to use.\n * @param {number=} options.lineHeight - The line height (in pixels) to use.\n * @param {number=} options.rotation - The (optional) rotation in radians.\n * @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `\"left\" || \"right\" || \"center\" || \"start\" || \"end\"`.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n text(text, x, y, options) {\n var _a, _b, _c;\n options = options || {};\n const color = options.color || \"black\";\n const lineHeight = ((_b = (_a = options.lineHeight) !== null && _a !== void 0 ? _a : options.fontSize) !== null && _b !== void 0 ? _b : 0) * this.scale.x;\n // https://www.w3.org/TR/SVG/text.html#TextAnchorProperty\n // start | middle | end\n const textAlign = options.textAlign === \"left\" || options.textAlign === \"start\"\n ? \"start\"\n : options.textAlign === \"center\"\n ? \"middle\"\n : options.textAlign === \"right\" || options.textAlign === \"end\"\n ? \"end\"\n : \"start\";\n const transformOrigin = `${this._x(x)}px ${this._y(y)}px`;\n const translate = `translate(${this._x(x)} ${this._y(y) + lineHeight / 2})`;\n // Safari has a transform-origin/rotation bug.\n // It's essential to use rotate(r,x,y) here. \"rotate(r)\"\" with transform-origin(x,y) won't do the job.\n // And rotate and translate cannot be used is combination on a text object.\n // So wrap the text inside a <g>, translate the <g>, and rotate the text inside.\n const rotate = options.rotation ? `rotate(${options.rotation * RAD_TO_DEG} 0 0)` : ``;\n const node = this.makeNode(\"g\");\n const curId = this.curId;\n this.curId = curId + \"_text\";\n const textNode = this.makeNode(\"text\");\n node.appendChild(textNode);\n textNode.setAttribute(\"font-family\", (_c = options.fontFamily) !== null && _c !== void 0 ? _c : \"\"); // May be undefined\n textNode.setAttribute(\"font-size\", options.fontSize ? `${options.fontSize * this.scale.x}` : \"\");\n textNode.setAttribute(\"font-style\", options.fontStyle ? `${options.fontStyle}` : \"\");\n textNode.setAttribute(\"font-weight\", options.fontWeight ? `${options.fontWeight}` : \"\");\n textNode.setAttribute(\"text-anchor\", textAlign);\n textNode.setAttribute(\"transform-origin\", \"0 0\");\n textNode.setAttribute(\"transform\", rotate);\n node.setAttribute(\"transform-origin\", transformOrigin);\n node.setAttribute(\"transform\", translate);\n textNode.innerHTML = text;\n // Restore old ID\n this.curId = curId;\n return this._bindFillDraw(node, \"text\", color, 1);\n }\n /**\n * Draw a non-scaling text label at the given position.\n *\n * @method label\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {number=} rotation - The (optional) rotation in radians.\n * @param {string=\"black\"} color - The color to use (default is black).\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n */\n label(text, x, y, rotation, color) {\n const node = this.makeNode(\"text\");\n // For some strange reason SVG rotation transforms use degrees instead of radians\n node.setAttribute(\"transform\", `translate(${x},${y}), rotate(${((rotation || 0) / Math.PI) * 180})`);\n node.setAttribute(\"font-family\", \"Arial\");\n node.setAttribute(\"font-size\", \"9pt\");\n node.setAttribute(\"font-style\", \"normal\");\n node.setAttribute(\"font-weight\", \"lighter\");\n node.innerHTML = text;\n return this._bindFillDraw(node, \"label\", color || \"black\", null);\n }\n /**\n * Draw an SVG-like path given by the specified path data.\n *\n * @method path\n * @param {SVGPathData} pathData - An array of path commands and params.\n * @param {string=null} color - (optional) The color to draw this path with (default is null).\n * @param {number=1} lineWidth - (optional) the line width to use (default is 1).\n * @param {boolean=false} options.inplace - (optional) If set to true then path transforamtions (scale and translate) will be done in-place in the array. This can boost the performance.\n * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.\n * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.\n *\n * @instance\n * @memberof drawutils\n * @return {R} An instance representing the drawn path.\n */\n path(pathData, color, lineWidth, options) {\n const node = this.makeNode(\"path\");\n this.applyStrokeOpts(node, options);\n // Transform the path: in-place (fast) or copy (slower)\n const d = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);\n drawutilssvg.transformPathData(d, this.offset, this.scale);\n node.setAttribute(\"d\", d.join(\" \"));\n return this._bindFillDraw(node, \"path\", color, lineWidth);\n }\n /**\n * Due to gl compatibility there is a generic 'clear' function required\n * to avoid accessing the context object itself directly.\n *\n * This function just fills the whole canvas with a single color.\n *\n * @param {string} color - The color to clear with.\n * @return {void}\n * @instance\n * @memberof drawutilssvg\n **/\n clear(color) {\n // If this isn't the primary handler then do not remove anything here.\n // The primary handler will do that (no double work).\n if (this.isSecondary) {\n return;\n }\n // Add a covering rect with the given background color\n this.curId = \"background\";\n this.curClassName = null; // undefined;\n const node = this.makeNode(\"rect\");\n // For some strange reason SVG rotation transforms use degrees instead of radians\n // Note that the background does not scale with the zoom level (always covers full element)\n node.setAttribute(\"x\", \"0\");\n node.setAttribute(\"y\", \"0\");\n node.setAttribute(\"width\", `${this.canvasSize.width}`);\n node.setAttribute(\"height\", `${this.canvasSize.height}`);\n // Bind this special element into the document\n this._bindFillDraw(node, this.curId, null, null);\n node.setAttribute(\"fill\", typeof color === \"undefined\" ? \"none\" : color);\n // Clear the current ID again\n this.curId = null; // undefined;\n }\n /**\n * A private helper function to clear all SVG nodes from the &gt;g> node.\n *\n * @private\n */\n removeAllChildNodes() {\n while (this.bufferGNode.lastChild) {\n this.bufferGNode.removeChild(this.bufferGNode.lastChild);\n }\n while (this.bufferedNodeDefs.lastChild) {\n this.bufferedNodeDefs.removeChild(this.bufferedNodeDefs.lastChild);\n }\n }\n /**\n * Create a new and empty `SVGElement` &lt;svg&gt; in the svg-namespace.\n *\n * @name createSvg\n * @static\n * @memberof drawutilssvg\n * @return SVGElement\n */\n static createSvg() {\n return document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n }\n /**\n * Create a copy of the given path data. As path data only consists of strings and numbers,\n * the copy will be shallow by definition.\n *\n * @name copyPathData\n * @static\n * @memberof drawutilssvg\n */\n static copyPathData(data) {\n const copy = new Array(data.length);\n for (var i = 0, n = data.length; i < n; i++) {\n copy[i] = data[i];\n }\n return copy;\n }\n /**\n * Transform the given path data (translate and scale. rotating is not intended here).\n *\n * @name transformPathData\n * @static\n * @memberof drawutilssvg\n * @param {SVGPathParams} data - The data to transform.\n * @param {XYCoords} offset - The translation offset (neutral is x=0, y=0).\n * @param {XYCoords} scale - The scale factors (neutral is x=1, y=1).\n */\n static transformPathData(data, offset, scale) {\n // Scale and translate {x,y}\n const _stx = (index) => {\n data[index] = offset.x + scale.x * Number(data[index]);\n };\n const _sty = (index) => {\n data[index] = offset.y + scale.y * Number(data[index]);\n };\n // scale only {x,y}\n const _sx = (index) => {\n data[index] = scale.x * Number(data[index]);\n };\n const _sy = (index) => {\n data[index] = scale.y * Number(data[index]);\n };\n var i = 0;\n var lastPoint = { x: NaN, y: NaN };\n // \"save last point\"\n var _slp = (index) => {\n lastPoint.x = Number(data[index]);\n lastPoint.y = Number(data[index + 1]);\n };\n while (i < data.length) {\n const cmd = data[i];\n switch (cmd) {\n case \"M\":\n // MoveTo: M|m x y\n case \"L\":\n // LineTo L|l x y\n case \"T\":\n // Shorthand/smooth quadratic Bézier curveto: T|t x y\n _stx(i + 1);\n _sty(i + 2);\n _slp(i + 1);\n i += 3;\n break;\n case \"m\":\n // MoveTo: M|m x y\n case \"l\":\n // LineTo L|l x y\n case \"t\":\n // Shorthand/smooth quadratic Bézier curveto: T|t x y\n _sx(i + 1);\n _sy(i + 2);\n _slp(i + 1);\n i += 3;\n break;\n case \"H\":\n // HorizontalLineTo: H|h x\n _stx(i + 1);\n lastPoint.x = Number(data[i + 1]);\n i += 2;\n break;\n case \"h\":\n // HorizontalLineTo: H|h x\n _sx(i + 1);\n lastPoint.x = Number(data[i + 1]);\n i += 2;\n break;\n case \"V\":\n // VerticalLineTo: V|v y\n _sty(i + 1);\n lastPoint.y = Number(data[i + 1]);\n i += 2;\n break;\n case \"v\":\n // VerticalLineTo: V|v y\n _sy(i + 1);\n lastPoint.y = Number(data[i + 1]);\n i += 2;\n break;\n case \"C\":\n // CurveTo: C|c x1 y1 x2 y2 x y\n _stx(i + 1);\n _sty(i + 2);\n _stx(i + 3);\n _sty(i + 4);\n _stx(i + 5);\n _sty(i + 6);\n _slp(i + 5);\n i += 7;\n break;\n case \"c\":\n // CurveTo: C|c x1 y1 x2 y2 x y\n _sx(i + 1);\n _sy(i + 2);\n _sx(i + 3);\n _sy(i + 4);\n _sx(i + 5);\n _sy(i + 6);\n _slp(i + 5);\n i += 7;\n break;\n case \"S\":\n case \"Q\":\n // Shorthand-/SmoothCurveTo: S|s x2 y2 x y\n // QuadraticCurveTo: Q|q x1 y1 x y\n _stx(i + 1);\n _sty(i + 2);\n _stx(i + 3);\n _sty(i + 4);\n _slp(i + 3);\n i += 5;\n break;\n case \"s\":\n case \"q\":\n // Shorthand-/SmoothCurveTo: S|s x2 y2 x y\n // QuadraticCurveTo: Q|q x1 y1 x y\n _sx(i + 1);\n _sy(i + 2);\n _sx(i + 3);\n _sy(i + 4);\n _slp(i + 3);\n i += 5;\n break;\n case \"A\":\n // EllipticalArcTo: A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y\n // Uniform scale: just scale\n // NOTE: here is something TODO\n // * if scalex!=scaleY this won't work\n // * Arcs have to be converted to Bézier curves here in that case\n _sx(i + 1);\n _sy(i + 2);\n _stx(i + 6);\n _sty(i + 7);\n _slp(i + 6);\n // Update the arc flag when x _or_ y scale is negative\n if ((scale.x < 0 && scale.y >= 0) || (scale.x >= 0 && scale.y < 0)) {\n data[i + 5] = data[i + 5] ? 0 : 1;\n }\n i += 8;\n break;\n case \"a\":\n // EllipticalArcTo: A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y\n _sx(i + 1);\n _sy(i + 2);\n _sx(i + 6);\n _sy(i + 7);\n _slp(i + 6);\n i += 8;\n break;\n case \"z\":\n case \"Z\":\n // ClosePath: Z|z (no arguments)\n // lastPoint.x = firstPoint.x;\n // lastPoint.y = firstPoint.y;\n i++;\n break;\n // Safepoint: continue reading token by token until something is recognized again\n default:\n i++;\n }\n } // END while\n } // END transformPathData\n static nodeSupportsLineDash(nodeName) {\n return [\"line\", \"path\", \"circle\", \"ellipse\", \"rectangle\", \"rect\"].includes(nodeName);\n }\n static nodeSupportsLineJoin(nodeName) {\n return [\"line\", \"path\", \"circle\", \"ellipse\", \"rectangle\", \"rect\"].includes(nodeName);\n }\n /**\n * Creates a basic <line> node with start and end coordinates. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makeLineNode\n * @param {XYCoords} zA - The line's start position.\n * @param {XYCoords} zB - The line's start position.\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.\n * @return {SVGLineElement}\n * @instance\n * @memberof drawutilssvg\n */\n makeLineNode(zA, zB, color, lineWidth, strokeOptions, classNameOverride) {\n const line = this.makeNode(\"line\");\n line.setAttribute(\"x1\", `${this._x(zA.x)}`);\n line.setAttribute(\"y1\", `${this._y(zA.y)}`);\n line.setAttribute(\"x2\", `${this._x(zB.x)}`);\n line.setAttribute(\"y2\", `${this._y(zB.y)}`);\n this._configureNode(line, classNameOverride !== null && classNameOverride !== void 0 ? classNameOverride : \"line\", this.fillShapes, color, lineWidth || 1, strokeOptions);\n return line;\n }\n /**\n * Creates a basic <path> node with given path string data. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makePathNode\n * @param {string} pathString - The path data (must be a valid path data string).\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.\n * @return {SVGPathElement}\n * @instance\n * @memberof drawutilssvg\n */\n makePathNode(pathString, color, lineWidth, strokeOptions, classNameOverride) {\n const path = this.makeNode(\"path\");\n path.setAttribute(\"d\", pathString);\n this._configureNode(path, classNameOverride !== null && classNameOverride !== void 0 ? classNameOverride : \"path\", this.fillShapes, color, lineWidth || 1, strokeOptions);\n return path;\n }\n /**\n * Creates a basic arrow head node (<path> node) at the end of the given line coordinates. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makeArrowHeadNode\n * @param {string} pathString - The path data (must be a valid path data string).\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {number=8} headLength - (optional) The length of the arrow head; if none is specified then the head will be 8 absolute units long.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.\n * @return {SVGPathElement}\n * @instance\n * @memberof drawutilssvg\n */\n makeArrowHeadNode(zA, zB, color, lineWidth, headLength = 8, strokeOptions, arrowHeadBasePositionBuffer) {\n var vertices = Vector.utils.buildArrowHead(zA, zB, headLength, this.scale.x, this.scale.y);\n const d = [\"M\", this.offset.x + vertices[0].x, this.offset.y + vertices[0].y];\n if (arrowHeadBasePositionBuffer) {\n arrowHeadBasePositionBuffer.x = vertices[0].x / this.scale.x;\n arrowHeadBasePositionBuffer.y = vertices[0].y / this.scale.y;\n }\n for (var i = 1; i <= vertices.length; i++) {\n d.push(\"L\");\n // Note: only use offset here (the vertices are already scaled)\n d.push(this.offset.x + vertices[i % vertices.length].x);\n d.push(this.offset.y + vertices[i % vertices.length].y);\n }\n const node = this.makePathNode(d.join(\" \"), color, lineWidth, strokeOptions, \"arrowhead\");\n return node;\n }\n /**\n * Creates a basic cubic Bézier path node (<path> node) with the given cubic Bézier data. The created node will not\n * be bound to any root node.\n *\n * @private\n * @method makeCubicBezierNode\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the point with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.\n * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.\n * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.\n * @return {SVGPathElement}\n * @instance\n * @memberof drawutilssvg\n */\n makeCubicBezierNode(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions) {\n if (startPoint instanceof CubicBezierCurve) {\n return this.cubicBezier(startPoint.startPoint, startPoint.endPoint, startPoint.startControlPoint, startPoint.endControlPoint, color, lineWidth);\n }\n // Draw curve\n const d = [\n \"M\",\n this._x(startPoint.x),\n this._y(startPoint.y),\n \"C\",\n this._x(startControlPoint.x),\n this._y(startControlPoint.y),\n this._x(endControlPoint.x),\n this._y(endControlPoint.y),\n this._x(endPoint.x),\n this._y(endPoint.y)\n ];\n const node = this.makePathNode(d.join(\" \"), color, lineWidth, strokeOptions, \"cubicBezier\");\n return node;\n }\n}\ndrawutilssvg.HEAD_XML = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>',\n '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" ',\n ' \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">',\n \"\"\n].join(\"\\n\");\n//# sourceMappingURL=drawutilssvg.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-04-22\n * @modified 2018-08-16 Added the curve() function to draw cubic bézier curves.\n * @modified 2018-10-23 Recognizing the offset param in the circle() function.\n * @modified 2018-11-27 Added the diamondHandle() function.\n * @modified 2018-11-28 Added the grid() function and the ellipse() function.\n * @modified 2018-11-30 Renamed the text() function to label() as it is not scaling.\n * @modified 2018-12-06 Added a test function for drawing arc in SVG style.\n * @modified 2018-12-09 Added the dot(Vertex,color) function (copied from Feigenbaum-plot-script).\n * @modified 2019-01-30 Added the arrow(Vertex,Vertex,color) function for drawing arrow heads.\n * @modified 2019-01-30 Added the image(Image,Vertex,Vertex) function for drawing images.\n * @modified 2019-04-27 Fixed a severe drawing bug in the arrow(...) function. Scaling arrows did not work properly.\n * @modified 2019-04-28 Added Math.round to the dot() drawing parameters to really draw a singlt dot.\n * @modified 2019-06-07 Fixed an issue in the cubicBezier() function. Paths were always closed.\n * @modified 2019-10-03 Added the beginDrawCycle hook.\n * @modified 2019-10-25 Polygons are no longer drawn with dashed lines (solid lines instead).\n * @modified 2019-11-18 Added the polyline function.\n * @modified 2019-11-22 Added a second workaround for th drawImage bug in Safari.\n * @modified 2019-12-07 Added the 'lineWidth' param to the line(...) function.\n * @modified 2019-12-07 Added the 'lineWidth' param to the cubicBezier(...) function.\n * @modified 2019-12-11 Added the 'color' param to the label(...) function.\n * @modified 2019-12-18 Added the quadraticBezier(...) function (for the sake of approximating Lissajous curves).\n * @modified 2019-12-20 Added the 'lineWidth' param to the polyline(...) function.\n * @modified 2020-01-09 Added the 'lineWidth' param to the ellipse(...) function.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-05-05 Added the 'lineWidth' param to the circle(...) function.\n * @modified 2020-05-12 Drawing any handles (square, circle, diamond) with lineWidth 1 now; this was not reset before.\n * @modified 2020-06-22 Added a context.clearRect() call to the clear() function; clearing with alpha channel did not work as expected.\n * @modified 2020-09-07 Added the circleArc(...) function to draw sections of circles.\n * @modified 2020-10-06 Removed the .closePath() instruction from the circleArc function.\n * @modified 2020-10-15 Re-added the text() function.\n * @modified 2020-10-28 Added the path(Path2D) function.\n * @modified 2020-12-28 Added the `singleSegment` mode (test).\n * @modified 2021-01-05 Added the image-loaded/broken check.\n * @modified 2021-01-24 Added the `setCurrentId` function from the `DrawLib` interface.\n * @modified 2021-02-22 Added the `path` drawing function to draw SVG path data.\n * @modified 2021-03-31 Added the `endDrawCycle` function from `DrawLib`.\n * @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.\n * @modified 2021-11-12 Adding more parameters tot the `text()` function: fontSize, textAlign, fontFamily, lineHeight.\n * @modified 2021-11-19 Added the `color` param to the `label(...)` function.\n * @modified 2022-02-03 Added the `lineWidth` param to the `crosshair` function.\n * @modified 2022-02-03 Added the `cross(...)` function.\n * @modified 2022-03-27 Added the `texturedPoly` function.\n * @modified 2022-06-01 Tweaked the `polyline` function; lineWidth now scales with scale.x.\n * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.\n * @modified 2022-08-23 Fixed a type issue in the `polyline` function.\n * @modified 2022-08-23 Fixed a type issue in the `setConfiguration` function.\n * @modified 2022-08-23 Fixed a type issue in the `path` function.\n * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.\n * @modified 2023-09-29 Removed unused method stub for texturedPoly helper function (cleanup).\n * @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.\n * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.\n * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `lineDashes` attribute.\n * @modified 2023-09-30 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.\n * @modified 2023-10-07 Adding the optional `arrowHeadBasePositionBuffer` param to the arrowHead(...) method.\n * @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.\n * @modified 2026-01-04 Adding `lineJoin` attribute to the `StrokeOptions`.\n * @modified 2026-03-18 Adding `isOpen` parameter to `cubicBezierPath` draw method.\n * @version 1.14.0\n **/\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { Vertex } from \"./Vertex\";\nimport { drawutilssvg } from \"./drawutilssvg\";\nimport { Vector } from \"./Vector\";\n// Todo: rename this class to Drawutils?\n/**\n * @classdesc A wrapper class for basic drawing operations.\n *\n * @requires CubicBzierCurvce\n * @requires Polygon\n * @requires Vertex\n * @requires XYCoords\n */\nexport class drawutils {\n /**\n * The constructor.\n *\n * @constructor\n * @name drawutils\n * @param {anvasRenderingContext2D} context - The drawing context.\n * @param {boolean} fillShaped - Indicates if the constructed drawutils should fill all drawn shapes (if possible).\n **/\n constructor(context, fillShapes) {\n this.ctx = context;\n // this.lineDash = [];\n this.offset = new Vertex(0, 0);\n this.scale = new Vertex(1, 1);\n this.fillShapes = fillShapes;\n }\n /**\n * A private helper method to apply stroke options to the current\n * context.\n * @param {StrokeOptions=} strokeOptions -\n */\n applyStrokeOpts(strokeOptions) {\n var _a, _b, _c;\n this.ctx.setLineDash(((_a = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.dashArray) !== null && _a !== void 0 ? _a : []).map((dashArrayElem) => {\n // Note assume scale.x === scale.y\n // Invariant scale makes funny stuff anyway.\n return dashArrayElem * this.scale.x;\n }));\n this.ctx.lineDashOffset = ((_b = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.dashOffset) !== null && _b !== void 0 ? _b : 0) * this.scale.x;\n this.ctx.lineJoin = (_c = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.lineJoin) !== null && _c !== void 0 ? _c : null;\n }\n // +---------------------------------------------------------------------------------\n // | This is the final helper function for drawing and filling stuff. It is not\n // | intended to be used from the outside.\n // |\n // | When in draw mode it draws the current shape.\n // | When in fill mode it fills the current shape.\n // |\n // | This function is usually only called internally.\n // |\n // | @param color A stroke/fill color to use.\n // +-------------------------------\n // TODO: convert this to a STATIC function.\n _fillOrDraw(color) {\n if (this.fillShapes) {\n this.ctx.fillStyle = color;\n this.ctx.fill();\n }\n else {\n this.ctx.strokeStyle = color;\n this.ctx.stroke();\n }\n }\n /**\n * Called before each draw cycle.\n * @param {UID=} uid - (optional) A UID identifying the currently drawn element(s).\n **/\n beginDrawCycle(renderTime) {\n // NOOP\n }\n /**\n * Called after each draw cycle.\n *\n * This is required for compatibility with other draw classes in the library (like drawgl).\n *\n * @name endDrawCycle\n * @method\n * @param {number} renderTime\n * @instance\n **/\n endDrawCycle(renderTime) {\n // NOOP\n }\n /**\n * Set the current drawlib configuration.\n *\n * @name setConfiguration\n * @method\n * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.\n */\n setConfiguration(configuration) {\n this.ctx.globalCompositeOperation = configuration.blendMode || \"source-over\";\n }\n // /**\n // * Set or clear the line-dash configuration. Pass `null` for un-dashed lines.\n // *\n // * See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray\n // * and https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash\n // * for how line dashes work.\n // *\n // * @method\n // * @param {Array<number> lineDashes - The line-dash array configuration.\n // * @returns {void}\n // */\n // setLineDash(lineDash: Array<number>) {\n // this.lineDash = lineDash;\n // }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * It is used by some libraries for identifying elemente on re-renders.\n *\n * @name setCurrentId\n * @method\n * @param {UID|null} uid - A UID identifying the currently drawn element(s).\n **/\n setCurrentId(uid) {\n // NOOP\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * Determine the class name for further usage here.\n *\n * @name setCurrentClassName\n * @method\n * @param {string|null} className - A class name for further custom use cases.\n **/\n setCurrentClassName(className) {\n // NOOP\n }\n /**\n * Draw the line between the given two points with the specified (CSS-) color.\n *\n * @method line\n * @param {XYCoords} zA - The start point of the line.\n * @param {XYCoords} zB - The end point of the line.\n * @param {string} color - Any valid CSS color string.\n * @param {number} lineWidth? - [optional] The line's width.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n line(zA, zB, color, lineWidth, strokeOptions) {\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + zA.x * this.scale.x, this.offset.y + zA.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + zB.x * this.scale.x, this.offset.y + zB.y * this.scale.y);\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = lineWidth || 1;\n this.ctx.stroke();\n this.ctx.restore();\n }\n /**\n * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n arrow(zA, zB, color, lineWidth, headLength = 8, strokeOptions) {\n const arrowHeadBasePosition = new Vertex(0, 0);\n this.arrowHead(zA, zB, color, lineWidth, headLength, undefined, arrowHeadBasePosition); // Will NOT use dash configuration\n this.line(zA, arrowHeadBasePosition, color, lineWidth, strokeOptions); // Will use dash configuration\n }\n /**\n * Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.\n *\n * @method cubicBezierArrow\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n */\n cubicBezierArrow(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, headLength, strokeOptions) {\n const arrowHeadBasePosition = new Vertex(0, 0);\n // Will NOT use dash configuration\n this.arrowHead(endControlPoint, endPoint, color, lineWidth, headLength, undefined, arrowHeadBasePosition);\n const diff = arrowHeadBasePosition.difference(endPoint);\n // Will use dash configuration\n this.cubicBezier(startPoint, { x: endPoint.x - diff.x, y: endPoint.y - diff.y }, startControlPoint, { x: endControlPoint.x - diff.x, y: endControlPoint.y - diff.y }, color, lineWidth, strokeOptions);\n }\n /**\n * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n * @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n **/\n arrowHead(zA, zB, color, lineWidth, headLength = 8, strokeOptions, arrowHeadBasePositionBuffer) {\n // var headLength: number = 8; // length of head in pixels\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n var vertices = Vector.utils.buildArrowHead(zA, zB, headLength, this.scale.x, this.scale.y);\n if (arrowHeadBasePositionBuffer) {\n arrowHeadBasePositionBuffer.x = vertices[0].x / this.scale.x;\n arrowHeadBasePositionBuffer.y = vertices[0].y / this.scale.y;\n }\n this.ctx.moveTo(this.offset.x + vertices[0].x, this.offset.y + vertices[0].y);\n for (var i = 0; i < vertices.length; i++) {\n this.ctx.lineTo(this.offset.x + vertices[i].x, this.offset.y + vertices[i].y);\n }\n this.ctx.lineTo(this.offset.x + vertices[0].x, this.offset.y + vertices[0].y);\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method image\n * @param {Image} image - The image object to draw.\n * @param {XYCoords} position - The position to draw the the upper left corner at.\n * @param {XYCoords} size - The x/y-size to draw the image with.\n * @param {number=0.0} alpha - (optional, default=0.0) The transparency (1.0=opaque, 0.0=transparent).\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n image(image, position, size, alpha = 1.0) {\n if (!image.complete || !image.naturalWidth) {\n // Avoid drawing un-unloaded or broken images\n return;\n }\n this.ctx.save();\n this.ctx.globalAlpha = alpha;\n // Note that there is a Safari bug with the 3 or 5 params variant.\n // Only the 9-param varaint works.\n this.ctx.drawImage(image, 0, 0, image.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n image.naturalHeight - 1, // To avoid errors substract 1 here.\n this.offset.x + position.x * this.scale.x, this.offset.y + position.y * this.scale.y, size.x * this.scale.x, size.y * this.scale.y);\n this.ctx.restore();\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method texturedPoly\n * @param {Image} textureImage - The image object to draw.\n * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.\n * @param {Polygon} polygon - The polygon to use as clip path.\n * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.\n * @param {number} rotation - The rotation to use for the polygon (and for the texture).\n * @param {XYCoords={x:0,y:0}} rotationCenter - (optional) The rotational center; default is center of bounding box.\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n texturedPoly(textureImage, textureSize, polygon, polygonPosition, rotation) {\n var basePolygonBounds = polygon.getBounds();\n // var targetCenterDifference = polygonPosition.clone().difference(basePolygonBounds.getCenter());\n var targetCenterDifference = new Vertex(polygonPosition.x, polygonPosition.y).difference(basePolygonBounds.getCenter());\n // var tileCenter = basePolygonBounds.getCenter().sub(targetCenterDifference);\n // Get the position offset of the polygon\n var targetTextureSize = new Vertex(textureSize.width, textureSize.height);\n // var targetTextureOffset = new Vertex(-textureSize.width / 2, -textureSize.height / 2).sub(targetCenterDifference);\n var targetTextureOffset = new Vertex(textureSize.min.x, textureSize.min.y).sub(polygonPosition);\n this.ctx.save();\n // this.ctx.translate(this.offset.x + rotationCenter.x * this.scale.x, this.offset.y + rotationCenter.y * this.scale.y);\n this.ctx.translate(this.offset.x + polygonPosition.x * this.scale.x, this.offset.y + polygonPosition.y * this.scale.y);\n drawutils.helpers.clipPoly(this.ctx, {\n x: -polygonPosition.x * this.scale.x,\n y: -polygonPosition.y * this.scale.y\n }, this.scale, polygon.vertices);\n this.ctx.scale(this.scale.x, this.scale.y);\n this.ctx.rotate(rotation);\n this.ctx.drawImage(textureImage, 0, 0, textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n textureImage.naturalHeight - 1, // To avoid errors substract 1 here.\n targetTextureOffset.x, // * this.scale.x,\n targetTextureOffset.y, // * this.scale.y,\n targetTextureSize.x, // * this.scale.x,\n targetTextureSize.y // * this.scale.y\n );\n this.ctx.restore();\n }\n /*\n _texturedPoly(\n textureImage: HTMLImageElement,\n textureSize: Bounds,\n polygon: Polygon,\n polygonPosition: XYCoords,\n rotation: number,\n rotationCenter: XYCoords = { x: 0, y: 0 }\n ): void {\n var basePolygonBounds = polygon.getBounds();\n var targetCenterDifference = polygonPosition.clone().difference(basePolygonBounds.getCenter());\n var rotationalOffset = rotationCenter ? polygonPosition.difference(rotationCenter) : { x: 0, y: 0 };\n // var rotationalOffset = { x: 0, y: 0 };\n var tileCenter = basePolygonBounds.getCenter().sub(targetCenterDifference);\n \n // Get the position offset of the polygon\n var targetTextureSize = new Vertex(textureSize.width, textureSize.height);\n var targetTextureOffset = new Vertex(-textureSize.width / 2, -textureSize.height / 2).sub(targetCenterDifference);\n \n this.ctx.save();\n \n // this.ctx.translate(\n // this.offset.x + (tileCenter.x - rotationalOffset.x * 0 + targetTextureOffset.x * 0.0) * this.scale.x,\n // this.offset.y + (tileCenter.y - rotationalOffset.y * 0 + targetTextureOffset.y * 0.0) * this.scale.y\n // );\n this.ctx.translate(\n this.offset.x + (tileCenter.x - rotationalOffset.x * 0 + targetTextureOffset.x * 0.0) * this.scale.x,\n this.offset.y + (tileCenter.y - rotationalOffset.y * 0 + targetTextureOffset.y * 0.0) * this.scale.y\n );\n this.ctx.rotate(rotation);\n \n drawutils.helpers.clipPoly(\n this.ctx,\n {\n x: (-targetCenterDifference.x * 1 - tileCenter.x - rotationalOffset.x) * this.scale.x,\n y: (-targetCenterDifference.y * 1 - tileCenter.y - rotationalOffset.y) * this.scale.y\n },\n this.scale,\n polygon.vertices\n );\n this.ctx.drawImage(\n textureImage,\n 0,\n 0,\n textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n textureImage.naturalHeight - 1, // To avoid errors substract 1 here.\n (-polygonPosition.x + targetTextureOffset.x * 1 - rotationalOffset.x * 1) * this.scale.x,\n (-polygonPosition.y + targetTextureOffset.y * 1 - rotationalOffset.y * 1) * this.scale.y,\n targetTextureSize.x * this.scale.x,\n targetTextureSize.y * this.scale.y\n );\n \n // const scaledTextureSize = new Bounds(\n // new Vertex(\n // -polygonPosition.x + targetTextureOffset.x - rotationalOffset.x,\n // -polygonPosition.y + targetTextureOffset.y - rotationalOffset.y\n // ).scaleXY(this.scale, rotationCenter),\n // new Vertex(\n // -polygonPosition.x + targetTextureOffset.x - rotationalOffset.x + targetTextureSize.x,\n // -polygonPosition.y + targetTextureOffset.y - rotationalOffset.y + targetTextureSize.y\n // ).scaleXY(this.scale, rotationCenter)\n // );\n // this.ctx.drawImage(\n // textureImage,\n // 0,\n // 0,\n // textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)\n // textureImage.naturalHeight - 1, // To avoid errors substract 1 here.\n // scaledTextureSize.min.x,\n // scaledTextureSize.min.y,\n // scaledTextureSize.width,\n // scaledTextureSize.height\n // );\n \n this.ctx.restore();\n }\n */\n /**\n * Draw a rectangle.\n *\n * @param {XYCoords} position - The upper left corner of the rectangle.\n * @param {number} width - The width of the rectangle.\n * @param {number} height - The height of the rectangle.\n * @param {string} color - The color to use.\n * @param {number=1} lineWidth - (optional) The line with to use (default is 1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n rect(position, width, height, color, lineWidth, strokeOptions) {\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + position.x * this.scale.x, this.offset.y + position.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + (position.x + width) * this.scale.x, this.offset.y + position.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + (position.x + width) * this.scale.x, this.offset.y + (position.y + height) * this.scale.y);\n this.ctx.lineTo(this.offset.x + position.x * this.scale.x, this.offset.y + (position.y + height) * this.scale.y);\n // this.ctx.lineTo( this.offset.x+position.x*this.scale.x, this.offset.y+position.y*this.scale.y );\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given (cubic) bézier curve.\n *\n * @method cubicBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezier(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions) {\n if (startPoint instanceof CubicBezierCurve) {\n this.cubicBezier(startPoint.startPoint, startPoint.endPoint, startPoint.startControlPoint, startPoint.endControlPoint, color, lineWidth);\n return;\n }\n // Draw curve\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + startPoint.x * this.scale.x, this.offset.y + startPoint.y * this.scale.y);\n this.ctx.bezierCurveTo(this.offset.x + startControlPoint.x * this.scale.x, this.offset.y + startControlPoint.y * this.scale.y, this.offset.x + endControlPoint.x * this.scale.x, this.offset.y + endControlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);\n //this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 2;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given (quadratic) bézier curve.\n *\n * @method quadraticBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} controlPoint - The control point the cubic Bézier curve.\n * @param {XYCoords} endPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number|string} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n quadraticBezier(startPoint, controlPoint, endPoint, color, lineWidth, strokeOptions) {\n // Draw curve\n this.ctx.save();\n this.ctx.beginPath();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + startPoint.x * this.scale.x, this.offset.y + startPoint.y * this.scale.y);\n this.ctx.quadraticCurveTo(this.offset.x + controlPoint.x * this.scale.x, this.offset.y + controlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);\n this.ctx.lineWidth = lineWidth || 2;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given (cubic) Bézier path.\n *\n * The given path must be an array with n*3+1 vertices, where n is the number of\n * curves in the path:\n * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>\n *\n * @method cubicBezierPath\n * @param {XYCoords[]} path - The cubic bezier path as described above.\n * @param {string} color - The CSS colot to draw the path with.\n * @param {number=1} lineWidth - (optional) The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezierPath(path, color, lineWidth, strokeOptions, isOpen) {\n if (!path || path.length == 0) {\n return;\n }\n // Draw curve\n this.ctx.save();\n this.ctx.beginPath();\n var endPoint;\n var startControlPoint;\n var endControlPoint;\n this.applyStrokeOpts(strokeOptions);\n this.ctx.moveTo(this.offset.x + path[0].x * this.scale.x, this.offset.y + path[0].y * this.scale.y);\n for (var i = 1; i < path.length; i += 3) {\n startControlPoint = path[i];\n endControlPoint = path[i + 1];\n endPoint = path[i + 2];\n this.ctx.bezierCurveTo(this.offset.x + startControlPoint.x * this.scale.x, this.offset.y + startControlPoint.y * this.scale.y, this.offset.x + endControlPoint.x * this.scale.x, this.offset.y + endControlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);\n }\n if (!isOpen) {\n this.ctx.closePath();\n }\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given handle and handle point (used to draw interactive Bézier curves).\n *\n * The colors for this are fixed and cannot be specified.\n *\n * @method handle\n * @param {XYCoords} startPoint - The start of the handle.\n * @param {XYCoords} endPoint - The end point of the handle.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handle(startPoint, endPoint) {\n // Draw handles\n // (No need to save and restore here)\n this.point(startPoint, \"rgb(0,32,192)\");\n this.square(endPoint, 5, \"rgba(0,128,192,0.5)\");\n }\n /**\n * Draw a handle line (with a light grey).\n *\n * @method handleLine\n * @param {XYCoords} startPoint - The start point to draw the handle at.\n * @param {XYCoords} endPoint - The end point to draw the handle at.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handleLine(startPoint, endPoint) {\n // Draw handle lines\n this.line(startPoint, endPoint, \"rgba(128,128,128, 0.5)\", undefined);\n }\n /**\n * Draw a 1x1 dot with the specified (CSS-) color.\n *\n * @method dot\n * @param {XYCoords} p - The position to draw the dot at.\n * @param {string} color - The CSS color to draw the dot with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n dot(p, color) {\n this.ctx.save();\n this.ctx.beginPath();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.moveTo(Math.round(this.offset.x + this.scale.x * p.x), Math.round(this.offset.y + this.scale.y * p.y));\n this.ctx.lineTo(Math.round(this.offset.x + this.scale.x * p.x + 1), Math.round(this.offset.y + this.scale.y * p.y + 1));\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n this.ctx.restore();\n }\n /**\n * Draw the given point with the specified (CSS-) color and radius 3.\n *\n * @method point\n * @param {XYCoords} p - The position to draw the point at.\n * @param {string} color - The CSS color to draw the point with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n point(p, color) {\n var radius = 3;\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.arc(this.offset.x + p.x * this.scale.x, this.offset.y + p.y * this.scale.y, radius, 0, 2 * Math.PI, false);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a circle with the specified (CSS-) color and radius.<br>\n * <br>\n * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.\n *\n * @method circle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {number} lineWidth - The line width (optional, default=1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circle(center, radius, color, lineWidth, strokeOptions) {\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius * this.scale.x, radius * this.scale.y, 0.0, 0.0, Math.PI * 2);\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a circular arc (section of a circle) with the given CSS color.\n *\n * @method circleArc\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {number} startAngle - The angle to start at.\n * @param {number} endAngle - The angle to end at.\n * @param {string=#000000} color - The CSS color to draw the circle with.\n * @param {number=1} lineWidth - The line width to use\n * @param {boolean=false} options.asSegment - If `true` then no beginPath and no draw will be applied (as part of larger path).\n * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.\n * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleArc(center, radius, startAngle, endAngle, color, lineWidth, options) {\n if (!options || !options.asSegment) {\n this.ctx.beginPath();\n }\n this.applyStrokeOpts(options);\n this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius * this.scale.x, radius * this.scale.y, 0.0, startAngle, endAngle, false);\n if (!options || !options.asSegment) {\n // this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color || \"#000000\");\n }\n }\n /**\n * Draw an ellipse with the specified (CSS-) color and thw two radii.\n *\n * @method ellipse\n * @param {XYCoords} center - The center of the ellipse.\n * @param {number} radiusX - The radius of the ellipse.\n * @param {number} radiusY - The radius of the ellipse.\n * @param {string} color - The CSS color to draw the ellipse with.\n * @param {number} lineWidth=1 - An optional line width param (default is 1).\n * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n ellipse(center, radiusX, radiusY, color, lineWidth, rotation, strokeOptions) {\n if (typeof rotation === \"undefined\") {\n rotation = 0.0;\n }\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radiusX * this.scale.x, radiusY * this.scale.y, rotation, 0.0, Math.PI * 2);\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw square at the given center, size and with the specified (CSS-) color.<br>\n * <br>\n * Note that if the x-scale and the y-scale are different the result will be a rectangle rather than a square.\n *\n * @method square\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @param {number} lineWidth - The line with to use (optional, default is 1).\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n square(center, size, color, lineWidth, strokeOptions) {\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.rect(this.offset.x + (center.x - size / 2.0) * this.scale.x, this.offset.y + (center.y - size / 2.0) * this.scale.y, size * this.scale.x, size * this.scale.y);\n this.ctx.closePath();\n this.ctx.lineWidth = lineWidth || 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a grid of horizontal and vertical lines with the given (CSS-) color.\n *\n * @method grid\n * @param {XYCoords} center - The center of the grid.\n * @param {number} width - The total width of the grid (width/2 each to the left and to the right).\n * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal grid size.\n * @param {number} sizeY - The vertical grid size.\n * @param {string} color - The CSS color to draw the grid with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n grid(center, width, height, sizeX, sizeY, color) {\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n var yMin = -Math.ceil((height * 0.5) / sizeY) * sizeY;\n var yMax = height / 2;\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n this.ctx.moveTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + yMin) * this.scale.y);\n this.ctx.lineTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + yMax) * this.scale.y);\n }\n var xMin = -Math.ceil((width * 0.5) / sizeX) * sizeX; // -Math.ceil((height*0.5)/sizeY)*sizeY;\n var xMax = width / 2; // height/2;\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n this.ctx.moveTo(this.offset.x + (center.x + xMin) * this.scale.x - 4, this.offset.y + (center.y + y) * this.scale.y);\n this.ctx.lineTo(this.offset.x + (center.x + xMax) * this.scale.x + 4, this.offset.y + (center.y + y) * this.scale.y);\n }\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = 1.0;\n this.ctx.stroke();\n this.ctx.closePath();\n }\n /**\n * Draw a raster of crosshairs in the given grid.<br>\n *\n * This works analogue to the grid() function\n *\n * @method raster\n * @param {XYCoords} center - The center of the raster.\n * @param {number} width - The total width of the raster (width/2 each to the left and to the right).\n * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal raster size.\n * @param {number} sizeY - The vertical raster size.\n * @param {string} color - The CSS color to draw the raster with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n raster(center, width, height, sizeX, sizeY, color) {\n this.ctx.save();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {\n for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {\n // Draw a crosshair\n this.ctx.moveTo(this.offset.x + (center.x + x) * this.scale.x - 4, this.offset.y + (center.y + y) * this.scale.y);\n this.ctx.lineTo(this.offset.x + (center.x + x) * this.scale.x + 4, this.offset.y + (center.y + y) * this.scale.y);\n this.ctx.moveTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + y) * this.scale.y - 4);\n this.ctx.lineTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + y) * this.scale.y + 4);\n }\n }\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = 1.0;\n this.ctx.stroke();\n this.ctx.closePath();\n this.ctx.restore();\n }\n /**\n * Draw a diamond handle (square rotated by 45°) with the given CSS color.\n *\n * It is an inherent feature of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped diamonds.\n *\n * @method diamondHandle\n * @param {XYCoords} center - The center of the diamond.\n * @param {number} size - The x/y-size of the diamond.\n * @param {string} color - The CSS color to draw the diamond with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n diamondHandle(center, size, color) {\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - size / 2.0, this.offset.y + center.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y - size / 2.0);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + size / 2.0, this.offset.y + center.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y + size / 2.0);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a square handle with the given CSS color.<br>\n * <br>\n * It is an inherent feature of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped squares.\n *\n * @method squareHandle\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The x/y-size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n squareHandle(center, size, color) {\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.rect(this.offset.x + center.x * this.scale.x - size / 2.0, this.offset.y + center.y * this.scale.y - size / 2.0, size, size);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a circle handle with the given CSS color.<br>\n * <br>\n * It is an inherent feature of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped circles.\n *\n * @method circleHandle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleHandle(center, radius, color) {\n radius = radius || 3;\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.arc(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius, 0, 2 * Math.PI, false);\n this.ctx.closePath();\n this.ctx.lineWidth = 1;\n this._fillOrDraw(color);\n }\n /**\n * Draw a crosshair with given radius and color at the given position.<br>\n * <br>\n * Note that the crosshair radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=0.5} lineWidth - (optional, default=0.5) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n crosshair(center, radius, color, lineWidth) {\n this.ctx.save();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - radius, this.offset.y + center.y * this.scale.y);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + radius, this.offset.y + center.y * this.scale.y);\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y - radius);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y + radius);\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = lineWidth || 0.5;\n this.ctx.stroke();\n this.ctx.closePath();\n this.ctx.restore();\n }\n /**\n * Draw a cross with diagonal axes with given radius, color and lineWidth at the given position.<br>\n * <br>\n * Note that the x's radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=1} lineWidth - (optional, default=1.0) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cross(center, radius, color, lineWidth) {\n this.ctx.save();\n this.ctx.setLineDash([]); // Clear line-dash settings\n this.ctx.beginPath();\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - radius, this.offset.y + center.y * this.scale.y - radius);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + radius, this.offset.y + center.y * this.scale.y + radius);\n this.ctx.moveTo(this.offset.x + center.x * this.scale.x - radius, this.offset.y + center.y * this.scale.y + radius);\n this.ctx.lineTo(this.offset.x + center.x * this.scale.x + radius, this.offset.y + center.y * this.scale.y - radius);\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = lineWidth || 1.0;\n this.ctx.stroke();\n this.ctx.closePath();\n this.ctx.restore();\n }\n /**\n * Draw a polygon.\n *\n * @method polygon\n * @param {Polygon} polygon - The polygon to draw.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {string} lineWidth - The line width to use.\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polygon(polygon, color, lineWidth, strokeOptions) {\n this.polyline(polygon.vertices, polygon.isOpen, color, lineWidth, strokeOptions);\n }\n /**\n * Draw a polygon line (alternative function to the polygon).\n *\n * @method polyline\n * @param {XYCoords[]} vertices - The polygon vertices to draw.\n * @param {boolan} isOpen - If true the polyline will not be closed at its end.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number} lineWidth - The line width (default is 1.0);\n * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.\n *\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polyline(vertices, isOpen, color, lineWidth, strokeOptions) {\n if (vertices.length <= 1) {\n return;\n }\n this.ctx.save();\n this.applyStrokeOpts(strokeOptions);\n this.ctx.beginPath();\n this.ctx.lineWidth = lineWidth || 1.0;\n this.ctx.moveTo(this.offset.x + vertices[0].x * this.scale.x, this.offset.y + vertices[0].y * this.scale.y);\n for (var i = 0; i < vertices.length; i++) {\n this.ctx.lineTo(this.offset.x + vertices[i].x * this.scale.x, this.offset.y + vertices[i].y * this.scale.y);\n }\n if (!isOpen)\n // && vertices.length > 2 )\n this.ctx.closePath();\n this._fillOrDraw(color);\n this.ctx.closePath();\n this.ctx.setLineDash([]);\n this.ctx.restore();\n }\n /**\n * Draw a text at the given relative position.\n *\n * @method text\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {string=} options.color - The Color to use.\n * @param {string=} options.fontFamily - The font family to use.\n * @param {number=} options.fontSize - The font size (in pixels) to use.\n * @param {FontStyle=} options.fontStyle - The font style to use.\n * @param {FontWeight=} options.fontWeight - The font weight to use.\n * @param {number=} options.lineHeight - The line height (in pixels) to use.\n * @param {number=} options.rotation - The (optional) rotation in radians.\n * @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `\"left\" || \"right\" || \"center\" || \"start\" || \"end\"`.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n text(text, x, y, options) {\n // See https://stackoverflow.com/a/23523697\n var _a, _b, _c;\n options = options || {};\n this.ctx.save();\n let relX = this.offset.x + x * this.scale.x;\n let relY = this.offset.y + y * this.scale.y;\n const color = options.color || \"black\";\n if (options.fontSize || options.fontFamily) {\n // Scaling of text only works in uniform mode\n this.ctx.font =\n (options.fontWeight ? options.fontWeight + \" \" : \"\") +\n (options.fontStyle ? options.fontStyle + \" \" : \"\") +\n (options.fontSize ? options.fontSize * this.scale.x + \"px \" : \" \") +\n (options.fontFamily\n ? options.fontFamily.indexOf(\" \") === -1\n ? options.fontFamily\n : `\"${options.fontFamily}\"`\n : \"Arial\");\n }\n if (options.textAlign) {\n this.ctx.textAlign = options.textAlign;\n }\n const rotation = (_a = options.rotation) !== null && _a !== void 0 ? _a : 0.0;\n const lineHeight = ((_c = (_b = options.lineHeight) !== null && _b !== void 0 ? _b : options.fontSize) !== null && _c !== void 0 ? _c : 0) * this.scale.x;\n this.ctx.translate(relX, relY);\n this.ctx.rotate(rotation);\n if (this.fillShapes) {\n this.ctx.fillStyle = color;\n this.ctx.fillText(text, 0, lineHeight / 2);\n }\n else {\n this.ctx.strokeStyle = color;\n this.ctx.strokeText(text, 0, lineHeight / 2);\n }\n // this.ctx.translate(-relX, -relY);\n // this.ctx.rotate(-rotation); // is this necessary before 'restore()'?\n this.ctx.restore();\n }\n /**\n * Draw a non-scaling text label at the given position.\n *\n * Note that these are absolute label positions, they are not affected by offset or scale.\n *\n * @method label\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {number=} rotation - The (optional) rotation in radians (default=0).\n * @param {string=} color - The color to render the text with (default=black).\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n label(text, x, y, rotation, color) {\n this.ctx.save();\n this.ctx.font = \"lighter 9pt Arial\";\n this.ctx.translate(x, y);\n if (typeof rotation !== \"undefined\")\n this.ctx.rotate(rotation);\n this.ctx.fillStyle = color || \"black\";\n if (this.fillShapes) {\n this.ctx.fillText(text, 0, 0);\n }\n else {\n this.ctx.strokeText(text, 0, 0);\n }\n this.ctx.restore();\n }\n /**\n * Draw an SVG-like path given by the specified path data.\n *\n *\n * @method path\n * @param {SVGPathData} pathData - An array of path commands and params.\n * @param {string=null} color - (optional) The color to draw this path with (default is null).\n * @param {number=1} lineWidth - (optional) the line width to use (default is 1).\n * @param {boolean=false} options.inplace - (optional) If set to true then path transforamtions (scale and translate) will be done in-place in the array. This can boost the performance.\n * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.\n * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.\n * @instance\n * @memberof drawutils\n * @return {R} An instance representing the drawn path.\n */\n path(pathData, color, lineWidth, options) {\n const d = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);\n drawutilssvg.transformPathData(d, this.offset, this.scale);\n if (color) {\n this.ctx.strokeStyle = color;\n }\n this.ctx.lineWidth = lineWidth || 1;\n this.applyStrokeOpts(options);\n if (this.fillShapes) {\n if (color) {\n this.ctx.fillStyle = color;\n }\n this.ctx.fill(new Path2D(d.join(\" \")));\n }\n else {\n if (color) {\n this.ctx.strokeStyle = color;\n }\n this.ctx.stroke(new Path2D(d.join(\" \")));\n }\n }\n /**\n * Due to gl compatibility there is a generic 'clear' function required\n * to avoid accessing the context object itself directly.\n *\n * This function just fills the whole canvas with a single color.\n *\n * @param {string} color - The color to clear with.\n **/\n clear(color) {\n this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n this.ctx.fillStyle = color;\n this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n }\n}\ndrawutils.helpers = {\n // A helper function to define the clipping path.\n // This could be a candidate for the draw library.\n clipPoly: (ctx, offset, scale, vertices) => {\n ctx.beginPath();\n // Set clip mask\n ctx.moveTo(offset.x + vertices[0].x * scale.x, offset.y + vertices[0].y * scale.y);\n for (var i = 1; i < vertices.length; i++) {\n const vert = vertices[i];\n ctx.lineTo(offset.x + vert.x * scale.x, offset.y + vert.y * scale.y);\n }\n ctx.closePath();\n ctx.clip();\n }\n};\n//# sourceMappingURL=draw.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-09-18\n * @modified 2019-10-03 Added the beginDrawCycle hook.\n * @modified 2020-03-25 Ported stub to Typescript.\n * @modified 2020-10-15 Re-added the text() function.\n * @modified 2021-01-24 Added the `setCurrentId` function.\n * @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.\n * @modified 2022-02-03 Added the `lineWidth` param to the `crosshair` function.\n * @modified 2022-02-03 Added the `cross(...)` function.\n * @modified 2022-03-27 Added the `texturedPoly` function.\n * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.\n * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.\n * @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.\n * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.\n * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.\n * @modified 2023-09-29 Added the `lineDashes` attribute.\n * @modified 2026-03-18 Adding `isOpen` parameter to `cubicBezierPath` draw method.\n * @version 0.0.10\n **/\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A wrapper class for basic drawing operations. This is the WebGL\n * implementation whih sould work with shaders.\n *\n * @requires CubicBzierCurvce\n * @requires Polygon\n * @requires SVGSerializable\n * @requires Vertex\n * @requires XYCoords\n */\nexport class drawutilsgl {\n /**\n * The constructor.\n *\n * @constructor\n * @name drawutils\n * @param {WebGLRenderingContext|null} context - The drawing context.\n * @param {boolean} fillShaped - Indicates if the constructed drawutils should fill all drawn shapes (if possible).\n **/\n constructor(context, fillShapes) {\n this.gl = context;\n this.offset = new Vertex(0, 0);\n this.scale = new Vertex(1, 1);\n this.fillShapes = fillShapes;\n this._zindex = 0.0;\n if (context == null || typeof context === \"undefined\")\n return;\n this.glutils = new GLU(context);\n // PROBLEM: CANNOT USE MULTIPLE SHADER PROGRAM INSTANCES ON THE SAME CONTEXT!\n // SOLUTION: USE SHARED SHADER PROGRAM!!! ... somehow ...\n // This needs to be considered in the overlying component; both draw-instances need to\n // share their gl context.\n // That's what the copyInstace(boolean) method is good for.\n this._vertShader = this.glutils.compileShader(drawutilsgl.vertCode, this.gl.VERTEX_SHADER);\n this._fragShader = this.glutils.compileShader(drawutilsgl.fragCode, this.gl.FRAGMENT_SHADER);\n this._program = this.glutils.makeProgram(this._vertShader, this._fragShader);\n // Create an empty buffer object\n this.vertex_buffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n // this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertex_buffer);\n console.log(\"gl initialized\");\n }\n _x2rel(x) {\n return ((this.scale.x * x + this.offset.x) / this.gl.canvas.width) * 2.0 - 1.0;\n }\n _y2rel(y) {\n return ((this.offset.y - this.scale.y * y) / this.gl.canvas.height) * 2.0 - 1.0;\n }\n /**\n * Creates a 'shallow' (non deep) copy of this instance. This implies\n * that under the hood the same gl context and gl program will be used.\n */\n copyInstance(fillShapes) {\n var copy = new drawutilsgl(null, fillShapes);\n copy.gl = this.gl;\n copy.glutils = this.glutils;\n copy._vertShader = this._vertShader;\n copy._fragShader = this._fragShader;\n copy._program = this._program;\n return copy;\n }\n /**\n * Called before each draw cycle.\n * @param {number} renderTime\n **/\n beginDrawCycle(renderTime) {\n this._zindex = 0.0;\n this.renderTime = renderTime;\n }\n /**\n * Called after each draw cycle.\n *\n * This is required for compatibility with other draw classes in the library (like drawgl).\n *\n * @name endDrawCycle\n * @method\n * @param {number} renderTime\n * @instance\n **/\n endDrawCycle(renderTime) {\n // NOOP\n }\n /**\n * Set the current drawlib configuration.\n *\n * @name setConfiguration\n * @method\n * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.\n */\n setConfiguration(configuration) {\n // TODO\n }\n // /**\n // * Set or clear the line-dash configuration. Pass `null` for un-dashed lines.\n // *\n // * See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray\n // * and https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash\n // * for how line dashes work.\n // *\n // * @method\n // * @param {Array<number> lineDashes - The line-dash array configuration.\n // * @returns {void}\n // */\n // setLineDash(lineDashes: Array<number>) {\n // // TODO\n // }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * It is used by some libraries for identifying elemente on re-renders.\n *\n * @name setCurrentId\n * @method\n * @param {UID|null} uid - A UID identifying the currently drawn element(s).es.\n **/\n setCurrentId(uid) {\n // NOOP\n this.curId = uid;\n }\n /**\n * This method shouled be called each time the currently drawn `Drawable` changes.\n * Determine the class name for further usage here.\n *\n * @name setCurrentClassName\n * @method\n * @param {string|null} className - A class name for further custom use cases.\n **/\n setCurrentClassName(className) {\n // NOOP\n }\n /**\n * Draw the line between the given two points with the specified (CSS-) color.\n *\n * @method line\n * @param {XYCoords} zA - The start point of the line.\n * @param {XYCoords} zB - The end point of the line.\n * @param {string} color - Any valid CSS color string.\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n line(zA, zB, color) {\n const vertices = new Float32Array(6);\n vertices[0] = this._x2rel(zA.x);\n vertices[1] = this._y2rel(zA.y);\n vertices[2] = this._zindex;\n vertices[3] = this._x2rel(zB.x);\n vertices[4] = this._y2rel(zB.y);\n vertices[5] = this._zindex;\n this._zindex += 0.001;\n // Create an empty buffer object\n // const vertex_buffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertex_buffer);\n // Pass the vertex data to the buffer\n this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);\n // Bind vertex buffer object\n // this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertex_buffer);\n // Get the attribute location\n var coord = this.gl.getAttribLocation(this._program, \"position\");\n // Point an attribute to the currently bound VBO\n this.gl.vertexAttribPointer(coord, 3, this.gl.FLOAT, false, 0, 0);\n // Enable the attribute\n this.gl.enableVertexAttribArray(coord);\n // Unbind the buffer?\n //this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n // Set the view port\n this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);\n let uRotationVector = this.gl.getUniformLocation(this._program, \"uRotationVector\");\n // let radians = currentAngle * Math.PI / 180.0;\n let currentRotation = [0.0, 1.0];\n //currentRotation[0] = Math.sin(radians);\n //currentRotation[1] = Math.cos(radians);\n this.gl.uniform2fv(uRotationVector, currentRotation);\n this.gl.lineWidth(5);\n // Draw the line\n this.gl.drawArrays(this.gl.LINES, 0, vertices.length / 3);\n // POINTS, LINE_STRIP, LINE_LOOP, LINES,\n // TRIANGLE_STRIP,TRIANGLE_FAN, TRIANGLES\n }\n /**\n * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n arrow(zA, zB, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.\n *\n * @method cubicBezierArrow\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number} lineWidth - (optional) The line width to use.\n * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).\n *\n * @return {void}\n * @instance\n * @memberof DrawLib\n */\n cubicBezierArrow(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, headLength) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.\n *\n * @method arrow\n * @param {XYCoords} zA - The start point of the arrow-line.\n * @param {XYCoords} zB - The end point of the arrow-line.\n * @param {string} color - Any valid CSS color string.\n * @param {number=1} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).\n * @return {void}\n * @instance\n * @memberof DrawLib\n **/\n arrowHead(zA, zB, color, lineWidth, headLength) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method image\n * @param {Image} image - The image object to draw.\n * @param {XYCoords} position - The position to draw the the upper left corner at.\n * @param {XYCoords} size - The x/y-size to draw the image with.\n * @param {number=0.0} alpha - (optional, default=0.0) The transparency (0.0=opaque, 1.0=transparent).\n * @return {void}\n * @instance\n * @memberof drawutils\n **/\n image(image, position, size, alpha = 0.0) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an image at the given position with the given size.<br>\n * <br>\n * Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n *\n * @method texturedPoly\n * @param {Image} textureImage - The image object to draw.\n * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.\n * @param {Polygon} polygon - The polygon to use as clip path.\n * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.\n * @param {number} rotation - The rotation to use for the polygon (and for the texture).\n * @return {void}\n * @instance\n * @memberof drawutilsgl\n **/\n texturedPoly(textureImage, textureSize, polygon, polygonPosition, rotation) {\n // NOT YET IMPLEMENTED\n }\n // +---------------------------------------------------------------------------------\n // | This is the final helper function for drawing and filling stuff. It is not\n // | intended to be used from the outside.\n // |\n // | When in draw mode it draws the current shape.\n // | When in fill mode it fills the current shape.\n // |\n // | This function is usually only called internally.\n // |\n // | @param color A stroke/fill color to use.\n // +-------------------------------\n _fillOrDraw(color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given (cubic) bézier curve.\n *\n * @method cubicBezier\n * @param {XYCoords} startPoint - The start point of the cubic Bézier curve\n * @param {XYCoords} endPoint - The end point the cubic Bézier curve.\n * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.\n * @param {VertXYCoordsex} endControlPoint - The end control point the cubic Bézier curve.\n * @param {string} color - The CSS color to draw the curve with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezier(startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given (cubic) Bézier path.\n *\n * The given path must be an array with n*3+1 vertices, where n is the number of\n * curves in the path:\n * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>\n *\n * @method cubicBezierPath\n * @param {XYCoords[]} path - The cubic bezier path as described above.\n * @param {string} color - The CSS colot to draw the path with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cubicBezierPath(path, color, lineWidth, strokeOptions, isOpen) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given handle and handle point (used to draw interactive Bézier curves).\n *\n * The colors for this are fixed and cannot be specified.\n *\n * @method handle\n * @param {XYCoords} startPoint - The start of the handle.\n * @param {XYCoords} endPoint - The end point of the handle.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handle(startPoint, endPoint) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a handle line (with a light grey).\n *\n * @method handleLine\n * @param {XYCoords} startPoint - The start point to draw the handle at.\n * @param {XYCoords} endPoint - The end point to draw the handle at.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n handleLine(startPoint, endPoint) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a 1x1 dot with the specified (CSS-) color.\n *\n * @method dot\n * @param {XYCoords} p - The position to draw the dot at.\n * @param {string} color - The CSS color to draw the dot with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n dot(p, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw the given point with the specified (CSS-) color and radius 3.\n *\n * @method point\n * @param {XYCoords} p - The position to draw the point at.\n * @param {string} color - The CSS color to draw the point with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n point(p, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a circle with the specified (CSS-) color and radius.<br>\n * <br>\n * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.\n *\n * @method circle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circle(center, radius, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a circular arc (section of a circle) with the given CSS color.\n *\n * @method circleArc\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {number} startAngle - The angle to start at.\n * @param {number} endAngle - The angle to end at.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleArc(center, radius, startAngle, endAngle, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an ellipse with the specified (CSS-) color and thw two radii.\n *\n * @method ellipse\n * @param {XYCoords} center - The center of the ellipse.\n * @param {number} radiusX - The radius of the ellipse.\n * @param {number} radiusY - The radius of the ellipse.\n * @param {string} color - The CSS color to draw the ellipse with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n ellipse(center, radiusX, radiusY, color, lineWidth, rotation) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw square at the given center, size and with the specified (CSS-) color.<br>\n * <br>\n * Note that if the x-scale and the y-scale are different the result will be a rectangle rather than a square.\n *\n * @method square\n * @param {XYCords} center - The center of the square.\n * @param {number} size - The size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n square(center, size, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a rectangle.\n *\n * @param {XYCoords} position - The upper left corner of the rectangle.\n * @param {number} width - The width of the rectangle.\n * @param {number} height - The height of the rectangle.\n * @param {string} color - The color to use.\n * @param {number=1} lineWidth - (optional) The line with to use (default is 1).\n **/\n rect(position, width, height, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a grid of horizontal and vertical lines with the given (CSS-) color.\n *\n * @method grid\n * @param {XYCoords} center - The center of the grid.\n * @param {number} width - The total width of the grid (width/2 each to the left and to the right).\n * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal grid size.\n * @param {number} sizeY - The vertical grid size.\n * @param {string} color - The CSS color to draw the grid with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n grid(center, width, height, sizeX, sizeY, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a raster of crosshairs in the given grid.<br>\n *\n * This works analogue to the grid() function\n *\n * @method raster\n * @param {XYCoords} center - The center of the raster.\n * @param {number} width - The total width of the raster (width/2 each to the left and to the right).\n * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).\n * @param {number} sizeX - The horizontal raster size.\n * @param {number} sizeY - The vertical raster size.\n * @param {string} color - The CSS color to draw the raster with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n raster(center, width, height, sizeX, sizeY, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a diamond handle (square rotated by 45°) with the given CSS color.\n *\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped diamonds.\n *\n * @method diamondHandle\n * @param {XYCoords} center - The center of the diamond.\n * @param {number} size - The x/y-size of the diamond.\n * @param {string} color - The CSS color to draw the diamond with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n diamondHandle(center, size, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a square handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped squares.\n *\n * @method squareHandle\n * @param {XYCoords} center - The center of the square.\n * @param {number} size - The x/y-size of the square.\n * @param {string} color - The CSS color to draw the square with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n squareHandle(center, size, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a circle handle with the given CSS color.<br>\n * <br>\n * It is an inherent featur of the handle functions that the drawn elements are not scaled and not\n * distorted. So even if the user zooms in or changes the aspect ratio, the handles will be drawn\n * as even shaped circles.\n *\n * @method circleHandle\n * @param {XYCoords} center - The center of the circle.\n * @param {number} radius - The radius of the circle.\n * @param {string} color - The CSS color to draw the circle with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n circleHandle(center, size, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a crosshair with given radius and color at the given position.<br>\n * <br>\n * Note that the crosshair radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=0.5} lineWidth - (optional, default=0.5) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n crosshair(center, radius, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a cross with diagonal axes with given radius, color and lineWidth at the given position.<br>\n * <br>\n * Note that the x's radius will not be affected by scaling.\n *\n * @method crosshair\n * @param {XYCoords} center - The center of the crosshair.\n * @param {number} radius - The radius of the crosshair.\n * @param {string} color - The CSS color to draw the crosshair with.\n * @param {number=1} lineWidth - (optional, default=1.0) The line width to use.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n cross(center, radius, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a polygon.\n *\n * @method polygon\n * @param {Polygon} polygon - The polygon to draw.\n * @param {string} color - The CSS color to draw the polygon with.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polygon(polygon, color, lineWidth) {\n const vertices = new Float32Array(polygon.vertices.length * 3);\n for (var i = 0; i < polygon.vertices.length; i++) {\n vertices[i * 3 + 0] = this._x2rel(polygon.vertices[i].x);\n vertices[i * 3 + 1] = this._y2rel(polygon.vertices[i].y);\n vertices[i * 3 + 2] = this._zindex;\n }\n this._zindex += 0.001;\n //console.log( vertices );\n // Create an empty buffer object\n // const vertex_buffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertex_buffer);\n // Pass the vertex data to the buffer\n this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);\n // Bind vertex buffer object\n // this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertex_buffer);\n // Get the attribute location\n var coord = this.gl.getAttribLocation(this._program, \"position\");\n // Point an attribute to the currently bound VBO\n this.gl.vertexAttribPointer(coord, 3, this.gl.FLOAT, false, 0, 0);\n // Enable the attribute\n this.gl.enableVertexAttribArray(coord);\n // Unbind the buffer?\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n // Set the view port\n this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);\n let uRotationVector = this.gl.getUniformLocation(this._program, \"uRotationVector\");\n // let radians = currentAngle * Math.PI / 180.0;\n let currentRotation = [0.0, 1.0];\n //currentRotation[0] = Math.sin(radians);\n //currentRotation[1] = Math.cos(radians);\n this.gl.uniform2fv(uRotationVector, currentRotation);\n // Draw the polygon\n this.gl.drawArrays(this.gl.TRIANGLE_FAN, 0, vertices.length / 3);\n // POINTS, LINE_STRIP, LINE_LOOP, LINES,\n // TRIANGLE_STRIP,TRIANGLE_FAN, TRIANGLES\n }\n /**\n * Draw a polygon line (alternative function to the polygon).\n *\n * @method polyline\n * @param {XYCoords[]} vertices - The polygon vertices to draw.\n * @param {boolan} isOpen - If true the polyline will not be closed at its end.\n * @param {string} color - The CSS color to draw the polygon with.\n * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n polyline(vertices, isOpen, color, lineWidth) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a text at the given relative position.\n *\n * @method text\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {string=} options.color - The Color to use.\n * @param {string=} options.fontFamily - The font family to use.\n * @param {number=} options.fontSize - The font size (in pixels) to use.\n * @param {FontStyle=} options.fontStyle - The font style to use.\n * @param {FontWeight=} options.fontWeight - The font weight to use.\n * @param {number=} options.lineHeight - The line height (in pixels) to use.\n * @param {number=} options.rotation - The (optional) rotation in radians.\n * @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `\"left\" || \"right\" || \"center\" || \"start\" || \"end\"`.\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n text(text, x, y, options) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw a non-scaling text label at the given position.\n *\n * @method label\n * @param {string} text - The text to draw.\n * @param {number} x - The x-position to draw the text at.\n * @param {number} y - The y-position to draw the text at.\n * @param {number=} rotation - The (aoptional) rotation in radians.\n * @param {string=\"black\"} color - The color to use (default is black).\n * @return {void}\n * @instance\n * @memberof drawutils\n */\n label(text, x, y, rotation, color) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Draw an SVG-like path given by the specified path data.\n *\n * @method path\n * @param {SVGPathData} pathData - An array of path commands and params.\n * @param {string=null} color - (optional) The color to draw this path with (default is null).\n * @param {number=1} lineWidth - (optional) the line width to use (default is 1).\n * @param {boolean=false} options.inplace - (optional) If set to true then path transforamtions (scale and translate) will be done in-place in the array. This can boost the performance.\n * @instance\n * @memberof drawutils\n * @return {R} An instance representing the drawn path.\n */\n path(pathData, color, lineWidth, options) {\n // NOT YET IMPLEMENTED\n }\n /**\n * Due to gl compatibility there is a generic 'clear' function required\n * to avoid accessing the context object itself directly.\n *\n * This function just fills the whole canvas with a single color.\n *\n * @param {string} color - The color to clear with.\n **/\n clear(color) {\n // NOT YET IMPLEMENTED\n // if( typeof color == 'string' )\n // color = Color.parse(color); // Color class does not yet exist in TS\n // Clear the canvas\n this.gl.clearColor(1.0, 1.0, 1.0, 1.0);\n // Enable the depth test\n this.gl.enable(this.gl.DEPTH_TEST);\n // Clear the color and depth buffer\n this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n }\n}\n// Vertex shader source code\ndrawutilsgl.vertCode = `\n precision mediump float;\n\n attribute vec3 position;\n\n uniform vec2 uRotationVector;\n\n void main(void) {\n\tvec2 rotatedPosition = vec2(\n\t position.x * uRotationVector.y +\n\t\tposition.y * uRotationVector.x,\n\t position.y * uRotationVector.y -\n\t\tposition.x * uRotationVector.x\n\t);\n\n\tgl_Position = vec4(rotatedPosition, position.z, 1.0);\n }`;\n// Fragment shader source code\ndrawutilsgl.fragCode = `\n precision highp float;\n\n void main(void) {\n\tgl_FragColor = vec4(0.0,0.75,1.0,1.0);\n }`;\n/**\n * Some GL helper utils.\n **/\nclass GLU {\n constructor(gl) {\n this.gl = gl;\n }\n bufferData(verts) {\n // Create an empty buffer object\n var vbuffer = this.gl.createBuffer();\n // Bind appropriate array buffer to it\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vbuffer);\n // Pass the vertex data to the buffer\n this.gl.bufferData(this.gl.ARRAY_BUFFER, verts, this.gl.STATIC_DRAW);\n // Unbind the buffer\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n return vbuffer;\n }\n /*=================== Shaders ====================*/\n compileShader(shaderCode, shaderType) {\n // Create a vertex shader object\n var shader = this.gl.createShader(shaderType);\n // Attach vertex shader source code\n this.gl.shaderSource(shader, shaderCode);\n // Compile the vertex shader\n this.gl.compileShader(shader);\n const vertStatus = this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS);\n if (!vertStatus) {\n console.warn(\"Error in shader:\" + this.gl.getShaderInfoLog(shader));\n this.gl.deleteShader(shader);\n return null;\n }\n return shader;\n }\n makeProgram(vertShader, fragShader) {\n // Create a shader program object to store\n // the combined shader program\n var program = this.gl.createProgram();\n // Attach a vertex shader\n this.gl.attachShader(program, vertShader);\n // Attach a fragment shader\n this.gl.attachShader(program, fragShader);\n // Link both the programs\n this.gl.linkProgram(program);\n // Use the combined shader program object\n this.gl.useProgram(program);\n /*======= Do some cleanup ======*/\n this.gl.detachShader(program, vertShader);\n this.gl.detachShader(program, fragShader);\n this.gl.deleteShader(vertShader);\n this.gl.deleteShader(fragShader);\n return program;\n }\n}\n//# sourceMappingURL=drawgl.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-11-28\n * @modified 2018-12-09 Added the utils: baseLog(Number,Number) and mapRasterScale(Number,Number).\n * @version 1.0.1\n *\n * @file Grid\n * @fileoverview Note that the PlotBoilerplate already has a Grid instance member. The Grid is not meant\n * to be added to the canvas as a drawable as it encapsulates more an abstract concept of the canvas\n * rather than a drawable object.\n * @public\n **/\n/**\n * @classdesc A grid class with vertical and horizontal lines (or a raster).\n *\n * Note that the PlotBoilerplate already has a Grid instance member. The Grid is not meant\n * to be added to the canvas as a drawable as it encapsulates more an abstract concept of the canvas\n * rather than a drawable object.\n *\n * @requires Vertex\n */\nexport class Grid {\n /**\n * The constructor.\n *\n * @constructor\n * @name Grid\n * @param {Vertex} center - The offset of the grid (default is [0,0]).\n * @param {Vertex} size - The x- and y-size of the grid.\n **/\n constructor(center, size) {\n this.center = center;\n this.size = size;\n }\n ;\n}\n/**\n * @memberof Grid\n **/\nGrid.utils = {\n /**\n * Calculate the logarithm of the given number (num) to a given base.<br>\n * <br>\n * This function returns the number l with<br>\n * <pre>num == Math.pow(base,l)</pre>\n *\n * @member baseLog\n * @function\n * @memberof Grid\n * @inner\n * @param {number} base - The base to calculate the logarithm to.\n * @param {number} num - The number to calculate the logarithm for.\n * @return {number} <pre>log(base)/log(num)</pre>\n **/\n baseLog: (base, num) => { return Math.log(base) / Math.log(num); },\n /**\n * Calculate the raster scale for a given logarithmic mapping.<br>\n * <br>\n * Example (with adjustFactor=2):<br>\n * <pre>\n * If scale is 4.33, then the mapping is 1/2 (because 2^2 <= 4.33 <= 2^3)<br>\n * If scale is 0.33, then the mapping is 2 because (2^(1/2) >= 0.33 >= 2^(1/4)\n * </pre>\n *\n * @member mapRasterScale\n * @function\n * @memberof Grid\n * @inner\n * @param {number} adjustFactor The base for the logarithmic raster scaling when zoomed.\n * @param {number} scale The currently used scale factor.\n * @return {number}\n **/\n mapRasterScale: (adjustFactor, scale) => {\n var gf = 1.0;\n if (scale >= 1) {\n gf = Math.abs(Math.floor(1 / Grid.utils.baseLog(adjustFactor, scale)));\n gf = 1 / Math.pow(adjustFactor, gf);\n }\n else {\n gf = Math.abs(Math.floor(Grid.utils.baseLog(1 / adjustFactor, 1 / (scale + 1))));\n }\n return gf;\n }\n};\n//# sourceMappingURL=Grid.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-11-11 (Alaaf)\n * @modified 2020-03-28 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-07-28 Changed the `delete` key code from 8 to 46.\n * @modified 2020-10-04 Changed `window` to `globalThis`.\n * @modified 2020-10-04 Added extended JSDoc.\n * @modified 2022-02-02 Added the `destroy` method.\n * @version 1.1.0\n *\n * @file KeyHandler\n * @public\n **/\n/**\n * @classdesc A generic key handler.\n *\n * Example\n * =======\n * @example\n * // Javascript\n *\tnew KeyHandler( { trackAll : true } )\n *\t .down('enter',function() { console.log('ENTER was hit.'); } )\n *\t .press('enter',function() { console.log('ENTER was pressed.'); } )\n *\t .up('enter',function() { console.log('ENTER was released.'); } )\n *\n * .down('e',function() { console.log('e was hit. shift is pressed?',keyHandler.isDown('shift')); } )\n *\n *\t .up('windows',function() { console.log('windows was released.'); } )\n *\t;\n */\nexport class KeyHandler {\n /**\n * The constructor.\n *\n * @constructor\n * @instance\n * @memberof KeyHandler\n * @param {HTMLElement} options.element (optional) The HTML element to listen on; if null then 'window' will be used.\n * @param {boolean} options.trackAll (optional) Set to true if you want to keep track of _all_ keys (keyStatus).\n **/\n constructor(options) {\n this.downListeners = [];\n this.pressListeners = [];\n this.upListeners = [];\n this.keyStates = {};\n options = options || {};\n this.element = options.element ? options.element : globalThis;\n this.downListeners = [];\n this.pressListeners = [];\n this.upListeners = [];\n this.keyStates = [];\n // This could be made configurable in a later version. It allows to\n // keep track of the key status no matter if there are any listeners\n // on the key or not.\n this.trackAllKeys = options.trackAll || false;\n // Install the listeners\n this.installListeners();\n }\n /**\n * A helper function to fire key events from this KeyHandler.\n *\n * @param {KeyboardEvent} event - The key event to fire.\n * @param {Array<XKeyListener>} listener - The listeners to fire to.\n */\n fireEvent(event, listeners) {\n let hasListener = false;\n for (var i in listeners) {\n var lis = listeners[i];\n if (lis.keyCode != event.keyCode)\n continue;\n lis.listener(event);\n hasListener = true;\n }\n return hasListener;\n }\n /**\n * Internal function to fire a new keydown event to all listeners.\n * You should not call this function on your own unless you know what you do.\n *\n * @name fireDownEvent\n * @memberof KeyHandler\n * @instance\n * @private\n * @param {KeyboardEvent} e\n * @param {KeyHandler} handler\n * @return {void}\n */\n fireDownEvent(e, handler) {\n if (handler.fireEvent(e, handler.downListeners) || handler.trackAllKeys) {\n // Down event has listeners. Update key state.\n handler.keyStates[e.keyCode] = \"down\";\n }\n }\n /**\n * Internal function to fire a new keypress event to all listeners.\n * You should not call this function on your own unless you know what you do.\n *\n * @name firePressEvent\n * @memberof KeyHandler\n * @instance\n * @private\n * @param {KeyboardEvent} e\n * @param {KeyHandler} handler\n * @return void\n */\n firePressEvent(e, handler) {\n handler.fireEvent(e, handler.pressListeners);\n }\n /**\n * Internal function to fire a new keyup event to all listeners.\n * You should not call this function on your own unless you know what you do.\n *\n * @name fireUpEvent\n * @memberof KeyHandler\n * @instance\n * @private\n * @param {KeyboardEvent} e\n * @param {KeyHandler} handler\n * @return {void}\n */\n fireUpEvent(e, handler) {\n if (handler.fireEvent(e, handler.upListeners) || handler.trackAllKeys) {\n // Up event has listeners. Clear key state.\n delete handler.keyStates[e.keyCode];\n }\n }\n /**\n * Resolve the key/name code.\n */\n static key2code(key) {\n if (typeof key == \"number\")\n return key;\n if (typeof key != \"string\")\n throw \"Unknown key name or key type (should be a string or integer): \" + key;\n if (KeyHandler.KEY_CODES[key])\n return KeyHandler.KEY_CODES[key];\n throw \"Unknown key (cannot resolve key code): \" + key;\n }\n /**\n * Install the required listeners into the initially passed element.\n *\n * By default the listeners are installed into the root element specified on\n * construction (or 'window').\n */\n installListeners() {\n var _self = this;\n this.element.addEventListener(\"keydown\", (this._keyDownListener = (e) => {\n _self.fireDownEvent(e, _self);\n }));\n this.element.addEventListener(\"keypress\", (this._keyPressListener = (e) => {\n _self.firePressEvent(e, _self);\n }));\n this.element.addEventListener(\"keyup\", (this._keyUpListener = (e) => {\n _self.fireUpEvent(e, _self);\n }));\n }\n /**\n * Remove all installed event listeners from the underlying element.\n */\n releaseListeners() {\n this.element.removeEventListener(\"keydown\", this._keyDownListener);\n this.element.removeEventListener(\"keypress\", this._keyPressListener);\n this.element.removeEventListener(\"keyup\", this._keyUpListener);\n }\n /**\n * Listen for key down. This function allows chaining.\n *\n * Example: new KeyHandler().down('enter',function() {console.log('Enter hit.')});\n *\n * @name down\n * @memberof KeyHandler\n * @instance\n * @param {string|number} key - Any key identifier, key code or one from the KEY_CODES list.\n * @param {(e:KeyboardEvent)=>void} e - The callback to be triggered.\n * @return {KeyHandler} this\n */\n down(key, listener) {\n this.downListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });\n return this;\n }\n /**\n * Listen for key press.\n *\n * Example: new KeyHandler().press('enter',function() {console.log('Enter pressed.')});\n *\n * @name press\n * @memberof KeyHandler\n * @instance\n * @param {string|number} key - Any key identifier, key code or one from the KEY_CODES list.\n * @param {(e:KeyboardEvent)=>void} listener - The callback to be triggered.\n * @return {KeyHandler} this\n */\n press(key, listener) {\n this.pressListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });\n return this;\n }\n /**\n * Listen for key up.\n *\n * Example: new KeyHandler().up('enter',function() {console.log('Enter released.')});\n *\n * @name up\n * @memberof KeyHandler\n * @instance\n * @param {string} key - Any key identifier, key code or one from the KEY_CODES list.\n * @param {(e:KeyboardEvent)=>void)} e - The callback to be triggered.\n * @return {KeyHandler} this\n */\n up(key, listener) {\n this.upListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });\n return this;\n }\n /**\n * Check if a specific key is currently held pressed.\n *\n * @param {string|number} key - Any key identifier, key code or one from the KEY_CODES list.\n */\n isDown(key) {\n if (typeof key == \"number\")\n return this.keyStates[key] ? true : false;\n else\n return this.keyStates[KeyHandler.key2code(key)] ? true : false;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used any more.\n */\n destroy() {\n this.releaseListeners();\n }\n}\n/**\n * Source:\n * https://keycode.info/\n */\n// prettier-ignore\nKeyHandler.KEY_CODES = {\n 'break': 3, // alternate: 19\n 'backspace': 8,\n // 'delete'\t : 8, // alternate: 46\n 'tab': 9,\n 'clear': 12,\n 'enter': 13,\n 'shift': 16,\n 'ctrl': 17,\n 'alt': 18,\n 'pause': 19,\n // 'break'\t : 19,\n 'capslock': 20,\n 'hangul': 21,\n 'hanja': 25,\n 'escape': 27,\n 'conversion': 28,\n 'non-conversion': 29, // alternate: 235?\n 'spacebar': 32,\n 'pageup': 33,\n 'pagedown': 34,\n 'end': 35,\n 'home': 36, // alternate: 172?\n 'leftarrow': 37,\n 'uparrow': 38,\n 'rightarrow': 39,\n 'downarrow': 40,\n 'select': 41,\n 'print': 42,\n 'execute': 43,\n 'printscreen': 44,\n 'insert': 45,\n 'delete': 46, // alternate: 8\n 'help': 47,\n '0': 48,\n '1': 49,\n '2': 50,\n '3': 51,\n '4': 52,\n '5': 53,\n '6': 54,\n '7': 55,\n '8': 56,\n '9': 57,\n ':': 58,\n 'semicolon (firefox)': 59,\n 'equals': 59,\n '<': 60,\n 'equals (firefox)': 61,\n 'ß': 63,\n '@ (firefox)': 64,\n 'a': 65,\n 'b': 66,\n 'c': 67,\n 'd': 68,\n 'e': 69,\n 'f': 70,\n 'g': 71,\n 'h': 72,\n 'i': 73,\n 'j': 74,\n 'k': 75,\n 'l': 76,\n 'm': 77,\n 'n': 78,\n 'o': 79,\n 'p': 80,\n 'q': 81,\n 'r': 82,\n 's': 83,\n 't': 84,\n 'u': 85,\n 'v': 86,\n 'w': 87,\n 'x': 88,\n 'y': 89,\n 'z': 90,\n 'windows': 91,\n 'leftcommand': 91, // left ⌘\n 'chromebooksearch': 91,\n 'rightwindowkey': 92,\n 'windowsmenu': 93,\n 'rightcommant': 93, // right ⌘\n 'sleep': 95,\n 'numpad0': 96,\n 'numpad1': 97,\n 'numpad2': 98,\n 'numpad3': 99,\n 'numpad4': 100,\n 'numpad5': 101,\n 'numpad6': 102,\n 'numpad7': 103,\n 'numpad8': 104,\n 'numpad9': 105,\n 'multiply': 106,\n 'add': 107,\n 'numpadperiod': 108, // firefox, 194 on chrome\n 'subtract': 109,\n 'decimalpoint': 110,\n 'divide': 111,\n 'f1': 112,\n 'f2': 113,\n 'f3': 114,\n 'f4': 115,\n 'f5': 116,\n 'f6': 117,\n 'f7': 118,\n 'f8': 119,\n 'f9': 120,\n 'f10': 121,\n 'f11': 122,\n 'f12': 123,\n 'f13': 124,\n 'f14': 125,\n 'f15': 126,\n 'f16': 127,\n 'f17': 128,\n 'f18': 129,\n 'f19': 130,\n 'f20': 131,\n 'f21': 132,\n 'f22': 133,\n 'f23': 134,\n 'f24': 135,\n 'numlock': 144,\n 'scrolllock': 145,\n '^': 160,\n '!': 161,\n // '؛' \t : 162 // (arabic semicolon)\n '#': 163,\n '$': 164,\n 'ù': 165,\n 'pagebackward': 166,\n 'pageforward': 167,\n 'refresh': 168,\n 'closingparen': 169, // (AZERTY)\n '*': 170,\n '~+*': 171,\n // 'home'\t : 172,\n 'minus': 173, // firefox\n // 'mute' : 173,\n // 'unmute'\t : 173,\n 'decreasevolumelevel': 174,\n 'increasevolumelevel': 175,\n 'next': 176,\n 'previous': 177,\n 'stop': 178,\n 'play/pause': 179,\n 'email': 180,\n 'mute': 181, // firefox, alternate: 173\n 'unmute': 181, // alternate: 173?\n //'decreasevolumelevel'\t182 // firefox\n //'increasevolumelevel'\t183 // firefox\n 'semicolon': 186,\n 'ñ': 186,\n 'equal': 187,\n 'comma': 188,\n 'dash': 189,\n 'period': 190,\n 'forwardslash': 191,\n 'ç': 191, // 231 alternate?\n 'grave accent': 192,\n //'ñ' 192,\n 'æ': 192,\n 'ö': 192,\n '?': 193,\n '/': 193,\n '°': 193,\n // 'numpadperiod'\t : 194, // chrome\n 'openbracket': 219,\n 'backslash': 220,\n 'closebracket': 221,\n 'å': 221,\n 'singlequote': 222,\n 'ø': 222,\n 'ä': 222,\n '`': 223,\n // 'left or right ⌘ key (firefox)'\t224\n 'altgr': 225,\n // '< /git >, left back slash'\t226\n 'GNOME Compose Key': 230,\n 'XF86Forward': 233,\n 'XF86Back': 234,\n 'alphanumeric': 240,\n 'hiragana': 242,\n 'katakana': 242,\n 'half-width': 243,\n 'full-width': 243,\n 'kanji': 244,\n 'unlocktrackpad': 251, // Chrome/Edge\n 'toggletouchpad': 255\n};\n//# sourceMappingURL=KeyHandler.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-03-19\n * @modified 2018-04-28 Added the param 'wasDragged'.\n * @modified 2018-08-16 Added the param 'dragAmount'.\n * @modified 2018-08-27 Added the param 'element'.\n * @modified 2018-11-11 Changed the scope from a simple global var to a member of window/_context.\n * @modified 2018-11-19 Renamed the 'mousedown' function to 'down' and the 'mouseup' function to 'up'.\n * @modified 2018-11-28 Added the 'wheel' listener.\n * @modified 2018-12-09 Cleaned up some code.\n * @modified 2019-02-10 Cleaned up some more code.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-04-08 Fixed the click event (internally fired a 'mouseup' event) (1.0.10)\n * @modified 2020-04-08 Added the optional 'name' property. (1.0.11)\n * @modified 2020-04-08 The new version always installs internal listenrs to track drag events even\n * if there is no external drag listener installed (1.1.0).\n * @modified 2020-10-04 Added extended JSDoc comments.\n * @modified 2020-11-25 Added the `isTouchEvent` param.\n * @modified 2021-01-10 The mouse handler is now also working with SVGElements.\n * @modified 2022-08-16 Fixed a bug in the mouse button detection.\n * @version 1.2.1\n *\n * @file MouseHandler\n * @public\n **/\nexport class XMouseEvent extends MouseEvent {\n}\nexport class XWheelEvent extends WheelEvent {\n}\n/**\n * @classdesc A simple mouse handler for demos.\n * Use to avoid load massive libraries like jQuery.\n *\n * @requires XYCoords\n */\nexport class MouseHandler {\n /**\n * The constructor.\n *\n * Pass the DOM element you want to receive mouse events from.\n *\n * Usage\n * =====\n * @example\n * // Javascript\n * new MouseHandler( document.getElementById('mycanvas') )\n *\t .drag( function(e) {\n *\t\tconsole.log( 'Mouse dragged: ' + JSON.stringify(e) );\n *\t\tif( e.params.leftMouse ) ;\n *\t\telse if( e.params.rightMouse ) ;\n *\t } )\n *\t .move( function(e) {\n *\t\tconsole.log( 'Mouse moved: ' + JSON.stringify(e.params) );\n *\t } )\n * .up( function(e) {\n * console.log( 'Mouse up. Was dragged?', e.params.wasDragged );\n * } )\n * .down( function(e) {\n * console.log( 'Mouse down.' );\n * } )\n * .click( function(e) {\n * console.log( 'Click.' );\n * } )\n * .wheel( function(e) {\n * console.log( 'Wheel. delta='+e.deltaY );\n * } )\n *\n * @example\n * // Typescript\n * new MouseHandler( document.getElementById('mycanvas') )\n *\t .drag( (e:XMouseEvent) => {\n *\t\tconsole.log( 'Mouse dragged: ' + JSON.stringify(e) );\n *\t\tif( e.params.leftMouse ) ;\n *\t\telse if( e.params.rightMouse ) ;\n *\t } )\n *\t .move( (e:XMouseEvent) => {\n *\t\tconsole.log( 'Mouse moved: ' + JSON.stringify(e.params) );\n *\t } )\n * .up( (e:XMouseEvent) => {\n * console.log( 'Mouse up. Was dragged?', e.params.wasDragged );\n * } )\n * .down( (e:XMouseEvent) => {\n * console.log( 'Mouse down.' );\n * } )\n * .click( (e:XMouseEvent) => {\n * console.log( 'Click.' );\n * } )\n * .wheel( (e:XWheelEvent) => {\n * console.log( 'Wheel. delta='+e.deltaY );\n * } )\n *\n * @constructor\n * @instance\n * @memberof MouseHandler\n * @param {HTMLElement} element\n **/\n constructor(element, name) {\n this.mouseDownPos = undefined;\n this.mouseDragPos = undefined;\n // TODO: cc\n // private mousePos : { x:number, y:number }|undefined = undefined;\n this.mouseButton = -1;\n this.listeners = {};\n this.installed = {};\n this.handlers = {};\n // +----------------------------------------------------------------------\n // | Some private vars to store the current mouse/position/button state.\n // +-------------------------------------------------\n this.name = name;\n this.element = element;\n this.mouseDownPos = undefined;\n this.mouseDragPos = undefined;\n // this.mousePos = null;\n this.mouseButton = -1;\n this.listeners = {};\n this.installed = {};\n this.handlers = {};\n // +----------------------------------------------------------------------\n // | Define the internal event handlers.\n // |\n // | They will dispatch the modified event (relative mouse position,\n // | drag offset, ...) to the callbacks.\n // +-------------------------------------------------\n const _self = this;\n this.handlers[\"mousemove\"] = (e) => {\n if (_self.listeners.mousemove)\n _self.listeners.mousemove(_self.mkParams(e, \"mousemove\"));\n if (_self.mouseDragPos && _self.listeners.drag)\n _self.listeners.drag(_self.mkParams(e, \"drag\"));\n if (_self.mouseDownPos)\n _self.mouseDragPos = _self.relPos(e);\n };\n this.handlers[\"mouseup\"] = (e) => {\n if (_self.listeners.mouseup)\n _self.listeners.mouseup(_self.mkParams(e, \"mouseup\"));\n _self.mouseDragPos = undefined;\n _self.mouseDownPos = undefined;\n _self.mouseButton = -1;\n };\n this.handlers[\"mousedown\"] = (e) => {\n _self.mouseDragPos = _self.relPos(e);\n _self.mouseDownPos = _self.relPos(e);\n _self.mouseButton = e.button;\n if (_self.listeners.mousedown)\n _self.listeners.mousedown(_self.mkParams(e, \"mousedown\"));\n };\n this.handlers[\"click\"] = (e) => {\n if (_self.listeners.click)\n _self.listeners.click(_self.mkParams(e, \"click\"));\n };\n this.handlers[\"wheel\"] = (e) => {\n if (_self.listeners.wheel)\n _self.listeners.wheel(_self.mkParams(e, \"wheel\"));\n };\n this.element.addEventListener(\"mousemove\", this.handlers[\"mousemove\"]);\n this.element.addEventListener(\"mouseup\", this.handlers[\"mouseup\"]);\n this.element.addEventListener(\"mousedown\", this.handlers[\"mousedown\"]);\n this.element.addEventListener(\"click\", this.handlers[\"click\"]);\n this.element.addEventListener(\"wheel\", this.handlers[\"wheel\"]);\n }\n /**\n * Get relative position from the given MouseEvent.\n *\n * @name relPos\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {MouseEvent} e - The mouse event to get the relative position for.\n * @return {XYCoords} The relative mouse coordinates.\n */\n relPos(e) {\n return { x: e.offsetX, y: e.offsetY };\n }\n /**\n * Build the extended event params.\n *\n * @name mkParams\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {MouseEvent} event - The mouse event to get the relative position for.\n * @param {string} eventName - The name of the firing event.\n * @return {XMouseEvent}\n */\n mkParams(event, eventName) {\n var _a, _b;\n const rel = this.relPos(event);\n const xEvent = event;\n xEvent.params = {\n element: this.element,\n name: eventName,\n isTouchEvent: false,\n pos: rel,\n button: event.button, // this.mouseButton,\n leftButton: event.button === 0, // this.mouseButton === 0,\n middleButton: event.button === 1, // this.mouseButton === 1,\n rightButton: event.button === 2, // this.mouseButton === 2,\n mouseDownPos: (_a = this.mouseDownPos) !== null && _a !== void 0 ? _a : { x: NaN, y: NaN },\n draggedFrom: (_b = this.mouseDragPos) !== null && _b !== void 0 ? _b : { x: NaN, y: NaN },\n wasDragged: this.mouseDownPos != null && (this.mouseDownPos.x != rel.x || this.mouseDownPos.y != rel.y),\n dragAmount: this.mouseDragPos != null ? { x: rel.x - this.mouseDragPos.x, y: rel.y - this.mouseDragPos.y } : { x: 0, y: 0 }\n };\n return xEvent;\n }\n /**\n * Install a new listener.\n * Please note that this mouse handler can only handle one listener per event type.\n *\n * @name listenFor\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {string} eventName - The name of the firing event to listen for.\n * @return {void}\n */\n listenFor(eventName) {\n if (this.installed[eventName])\n return;\n // In the new version 1.1.0 has all internal listeners installed by default.\n this.installed[eventName] = true;\n }\n /**\n * Un-install a new listener.\n *\n * @name listenFor\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {string} eventName - The name of the firing event to unlisten for.\n * @return {void}\n */\n unlistenFor(eventName) {\n if (!this.installed[eventName])\n return;\n // In the new version 1.1.0 has all internal listeners installed by default.\n delete this.installed[eventName];\n }\n /**\n * Installer function to listen for a specific event: mouse-drag.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name drag\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The drag-callback to listen for.\n * @return {MouseHandler} this\n */\n drag(callback) {\n if (this.listeners.drag)\n this.throwAlreadyInstalled(\"drag\");\n this.listeners.drag = callback;\n this.listenFor(\"mousedown\");\n this.listenFor(\"mousemove\");\n this.listenFor(\"mouseup\");\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-move.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name move\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The move-callback to listen for.\n * @return {MouseHandler} this\n */\n move(callback) {\n if (this.listeners.mousemove)\n this.throwAlreadyInstalled(\"mousemove\");\n this.listenFor(\"mousemove\");\n this.listeners.mousemove = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-up.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name up\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The up-callback to listen for.\n * @return {MouseHandler} this\n */\n up(callback) {\n if (this.listeners.mouseup)\n this.throwAlreadyInstalled(\"mouseup\");\n this.listenFor(\"mouseup\");\n this.listeners.mouseup = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-down.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name down\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The down-callback to listen for.\n * @return {MouseHandler} this\n */\n down(callback) {\n if (this.listeners.mousedown)\n this.throwAlreadyInstalled(\"mousedown\");\n this.listenFor(\"mousedown\");\n this.listeners.mousedown = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-click.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name click\n * @memberof MouseHandler\n * @instance\n * @param {XMouseCallback} callback - The click-callback to listen for.\n * @return {MouseHandler} this\n */\n click(callback) {\n if (this.listeners.click)\n this.throwAlreadyInstalled(\"click\");\n this.listenFor(\"click\");\n this.listeners.click = callback;\n return this;\n }\n /**\n * Installer function to listen for a specific event: mouse-wheel.\n * Pass your callbacks here.\n *\n * Note: this support chaining.\n *\n * @name wheel\n * @memberof MouseHandler\n * @instance\n * @param {XWheelCallback} callback - The wheel-callback to listen for.\n * @return {MouseHandler} this\n */\n wheel(callback) {\n if (this.listeners.wheel)\n this.throwAlreadyInstalled(\"wheel\");\n this.listenFor(\"wheel\");\n this.listeners.wheel = callback;\n return this;\n }\n /**\n * An internal function to throw events.\n *\n * @name throwAlreadyInstalled\n * @memberof MouseHandler\n * @instance\n * @private\n * @param {string} name - The name of the event.\n * @return {void}\n */\n throwAlreadyInstalled(name) {\n throw `This MouseHandler already has a '${name}' callback. To keep the code simple there is only room for one.`;\n }\n /**\n * Call this when your work is done.\n *\n * The function will un-install all event listeners.\n *\n * @name destroy\n * @memberof MouseHandler\n * @instance\n * @private\n * @return {void}\n */\n destroy() {\n this.unlistenFor(\"mousedown\");\n this.unlistenFor(\"mousemove\");\n this.unlistenFor(\"moseup\");\n this.unlistenFor(\"click\");\n this.unlistenFor(\"wheel\");\n this.element.removeEventListener(\"mousemove\", this.handlers[\"mousemove\"]);\n this.element.removeEventListener(\"mouseup\", this.handlers[\"mousedown\"]);\n this.element.removeEventListener(\"mousedown\", this.handlers[\"mousedown\"]);\n this.element.removeEventListener(\"click\", this.handlers[\"click\"]);\n this.element.removeEventListener(\"wheel\", this.handlers[\"wheel\"]);\n }\n}\n//# sourceMappingURL=MouseHandler.js.map","/**\n * @author Ikaros Kappler\n * @date 2019-01-30\n * @modified 2019-03-23 Added JSDoc tags.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2021-01-20 Added UID.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `PBImage.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @version 1.2.0\n *\n * @file PBImage\n * @fileoverview As native Image objects have only a position and with\n * and height thei are not suitable for UI dragging interfaces.\n * @public\n **/\nimport { UIDGenerator } from \"./UIDGenerator\";\n/**\n * @classdesc A wrapper for image objects. Has an upper left and a lower right corner point.\n *\n * @requires Vertex\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n */\nexport class PBImage {\n /**\n * The constructor.\n *\n * @constructor\n * @name PBImage\n * @param {Image} image - The actual image.\n * @param {Vertex} upperLeft - The upper left corner.\n * @param {Vertex} lowerRight - The lower right corner.\n **/\n constructor(image, upperLeft, lowerRight) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"PBImage\";\n this.uid = UIDGenerator.next();\n this.image = image;\n this.upperLeft = upperLeft;\n this.lowerRight = lowerRight;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.upperLeft.destroy();\n this.lowerRight.destroy();\n this.isDestroyed = true;\n }\n}\n//# sourceMappingURL=PBImage.js.map","/**\n * @author Ikaros Kappler\n * @date 2021-11-16\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2023-09-25 Fixed a type error in the constructor. Nothing vital.\n * @version 1.1.1\n **/\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A simple text element: position, fontSize, fontFamily, color, textAlign, lineHeight and rotation.\n *\n * @requires FontOptions\n * @requires FontSize\n * @requires FontStyle\n * @requires FontWeight\n * @requires Vertex\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class PBText {\n /**\n * Create a new circle with given center point and radius.\n *\n * @constructor\n * @name Circle\n * @param {Vertex} center - The center point of the circle.\n * @param {number} radius - The radius of the circle.\n */\n constructor(text, anchor, options) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"PBText\";\n this.uid = UIDGenerator.next();\n this.text = text;\n this.anchor = anchor !== null && anchor !== void 0 ? anchor : new Vertex();\n this.color = options === null || options === void 0 ? void 0 : options.color;\n this.fontFamily = options === null || options === void 0 ? void 0 : options.fontFamily;\n this.fontSize = options === null || options === void 0 ? void 0 : options.fontSize;\n this.fontStyle = options === null || options === void 0 ? void 0 : options.fontStyle;\n this.fontWeight = options === null || options === void 0 ? void 0 : options.fontWeight;\n this.lineHeight = options === null || options === void 0 ? void 0 : options.lineHeight;\n this.textAlign = options === null || options === void 0 ? void 0 : options.textAlign;\n this.rotation = options === null || options === void 0 ? void 0 : options.rotation;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.anchor.destroy();\n this.isDestroyed = true;\n }\n} // END class\n//# sourceMappingURL=PBText.js.map","/* Port from AlloyFinger v0.1.15\n * Original by dntzhang\n * Typescript port by Ikaros Kappler\n * Github: https://github.com/IkarosKappler/AlloyFinger-Typescript\n *\n * @date 2021-02-10 (Typescript port)\n * @version 0.1.18\n */\n;\n/**\n * Tiny math function to calculate the length of a vector in euclidean space.\n *\n * @param {XYCoords} v - The vector in {x,y} notation.\n * @return {number} The length of the vector.\n */\nconst getLen = (v) => {\n return Math.sqrt(v.x * v.x + v.y * v.y);\n};\n/**\n * Tiny math function to calculate the dot product of two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The dot product of both vectors.\n */\nconst dot = (v1, v2) => {\n return v1.x * v2.x + v1.y * v2.y;\n};\n/**\n * Tiny math function to calculate the angle between two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The angle (in radians) between the two vectors.\n */\nconst getAngle = (v1, v2) => {\n const mr = getLen(v1) * getLen(v2);\n if (mr === 0)\n return 0;\n var r = dot(v1, v2) / mr;\n if (r > 1)\n r = 1;\n return Math.acos(r);\n};\n/**\n * Tiny math function to calculate the cross product of two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The cross product of both vectors.\n */\nconst cross = (v1, v2) => {\n return v1.x * v2.y - v2.x * v1.y;\n};\n/**\n * Tiny math function to calculate the rotate-angle (in degrees) for two vectors.\n *\n * @param {XYCoords} v1 - The first vector in {x,y} notation.\n * @param {XYCoords} v2 - The second vector in {x,y} notation.\n * @return {number} The rotate-angle in degrees for the two vectors.\n */\nconst getRotateAngle = (v1, v2) => {\n var angle = getAngle(v1, v2);\n if (cross(v1, v2) > 0) {\n angle *= -1;\n }\n return angle * 180 / Math.PI;\n};\n/**\n * A HandlerAdmin holds all the added event handlers for one kind of event type.\n */\nclass HandlerAdmin {\n constructor(el) {\n this.handlers = [];\n this.el = el;\n }\n ;\n add(handler) {\n this.handlers.push(handler);\n }\n ;\n del(handler) {\n if (!handler)\n this.handlers = [];\n for (var i = this.handlers.length; i >= 0; i--) {\n if (this.handlers[i] === handler) {\n this.handlers.splice(i, 1);\n }\n }\n }\n ;\n dispatch(..._args) {\n for (var i = 0, len = this.handlers.length; i < len; i++) {\n const handler = this.handlers[i];\n if (typeof handler === 'function') {\n handler.apply(this.el, arguments);\n }\n }\n }\n ;\n} // END class HandlerAdmin\n/**\n * A wrapper for handler functions; converts the passed handler function into a HadlerAdmin instance..\n */\nconst wrapFunc = (el, handler) => {\n const handlerAdmin = new HandlerAdmin(el);\n handlerAdmin.add(handler);\n return handlerAdmin;\n};\n/**\n * @classdesc The AlloyFinger main class. Use this to add handler functions for\n * touch events to any HTML- or SVG-Element.\n **/\nexport class AlloyFinger {\n constructor(el, option) {\n this.element = typeof el == 'string' ? document.querySelector(el) : el;\n // Fancy stuff: change `this` from the start-, move-, end- and cancel-function.\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind\n this.start = this.start.bind(this);\n this.move = this.move.bind(this);\n this.end = this.end.bind(this);\n this.cancel = this.cancel.bind(this);\n this.element.addEventListener(\"touchstart\", this.start, false);\n this.element.addEventListener(\"touchmove\", this.move, false);\n this.element.addEventListener(\"touchend\", this.end, false);\n this.element.addEventListener(\"touchcancel\", this.cancel, false);\n this.preV = { x: null, y: null };\n this.pinchStartLen = null;\n this.zoom = 1;\n this.isDoubleTap = false;\n const noop = () => { };\n this.rotate = wrapFunc(this.element, option.rotate || noop);\n this.touchStart = wrapFunc(this.element, option.touchStart || noop);\n this.multipointStart = wrapFunc(this.element, option.multipointStart || noop);\n this.multipointEnd = wrapFunc(this.element, option.multipointEnd || noop);\n this.pinch = wrapFunc(this.element, option.pinch || noop);\n this.swipe = wrapFunc(this.element, option.swipe || noop);\n this.tap = wrapFunc(this.element, option.tap || noop);\n this.doubleTap = wrapFunc(this.element, option.doubleTap || noop);\n this.longTap = wrapFunc(this.element, option.longTap || noop);\n this.singleTap = wrapFunc(this.element, option.singleTap || noop);\n this.pressMove = wrapFunc(this.element, option.pressMove || noop);\n this.twoFingerPressMove = wrapFunc(this.element, option.twoFingerPressMove || noop);\n this.touchMove = wrapFunc(this.element, option.touchMove || noop);\n this.touchEnd = wrapFunc(this.element, option.touchEnd || noop);\n this.touchCancel = wrapFunc(this.element, option.touchCancel || noop);\n this._cancelAllHandler = this.cancelAll.bind(this);\n if (globalThis && typeof globalThis.addEventListener === \"function\") {\n globalThis.addEventListener('scroll', this._cancelAllHandler);\n }\n this.delta = null;\n this.last = null;\n this.now = null;\n this.tapTimeout = null;\n this.singleTapTimeout = null;\n this.longTapTimeout = null;\n this.swipeTimeout = null;\n this.x1 = this.x2 = this.y1 = this.y2 = null;\n this.preTapPosition = { x: null, y: null };\n }\n ;\n start(evt) {\n if (!evt.touches)\n return;\n const _self = this;\n this.now = Date.now();\n this.x1 = evt.touches[0].pageX;\n this.y1 = evt.touches[0].pageY;\n this.delta = this.now - (this.last || this.now);\n this.touchStart.dispatch(evt, this.element);\n if (this.preTapPosition.x !== null) {\n this.isDoubleTap = (this.delta > 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30);\n if (this.isDoubleTap)\n clearTimeout(this.singleTapTimeout);\n }\n this.preTapPosition.x = this.x1;\n this.preTapPosition.y = this.y1;\n this.last = this.now;\n const preV = this.preV;\n const len = evt.touches.length;\n if (len > 1) {\n this._cancelLongTap();\n this._cancelSingleTap();\n const v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 };\n preV.x = v.x;\n preV.y = v.y;\n this.pinchStartLen = getLen(preV);\n this.multipointStart.dispatch(evt, this.element);\n }\n this._preventTap = false;\n this.longTapTimeout = setTimeout((() => {\n _self.longTap.dispatch(evt, _self.element);\n _self._preventTap = true;\n }).bind(_self), 750);\n }\n ;\n move(event) {\n if (!event.touches)\n return;\n const afEvent = event;\n const preV = this.preV;\n const len = event.touches.length;\n const currentX = event.touches[0].pageX;\n const currentY = event.touches[0].pageY;\n this.isDoubleTap = false;\n if (len > 1) {\n const sCurrentX = afEvent.touches[1].pageX;\n const sCurrentY = afEvent.touches[1].pageY;\n const v = { x: afEvent.touches[1].pageX - currentX, y: afEvent.touches[1].pageY - currentY };\n if (preV.x !== null) {\n if (this.pinchStartLen > 0) {\n afEvent.zoom = getLen(v) / this.pinchStartLen;\n this.pinch.dispatch(afEvent, this.element);\n }\n afEvent.angle = getRotateAngle(v, preV);\n this.rotate.dispatch(afEvent, this.element);\n }\n preV.x = v.x;\n preV.y = v.y;\n if (this.x2 !== null && this.sx2 !== null) {\n afEvent.deltaX = (currentX - this.x2 + sCurrentX - this.sx2) / 2;\n afEvent.deltaY = (currentY - this.y2 + sCurrentY - this.sy2) / 2;\n }\n else {\n afEvent.deltaX = 0;\n afEvent.deltaY = 0;\n }\n this.twoFingerPressMove.dispatch(afEvent, this.element);\n this.sx2 = sCurrentX;\n this.sy2 = sCurrentY;\n }\n else {\n if (this.x2 !== null) {\n afEvent.deltaX = currentX - this.x2;\n afEvent.deltaY = currentY - this.y2;\n //move事件中添加对当前触摸点到初始触摸点的判断,\n //如果曾经大于过某个距离(比如10),就认为是移动到某个地方又移回来,应该不再触发tap事件才对。\n //\n // translation:\n // Add the judgment of the current touch point to the initial touch point in the event,\n // If it has been greater than a certain distance (such as 10), it is considered to be\n // moved to a certain place and then moved back, and the tap event should no longer be triggered.\n const movedX = Math.abs(this.x1 - this.x2);\n const movedY = Math.abs(this.y1 - this.y2);\n if (movedX > 10 || movedY > 10) {\n this._preventTap = true;\n }\n }\n else {\n afEvent.deltaX = 0;\n afEvent.deltaY = 0;\n }\n this.pressMove.dispatch(afEvent, this.element);\n }\n this.touchMove.dispatch(afEvent, this.element);\n this._cancelLongTap();\n this.x2 = currentX;\n this.y2 = currentY;\n if (len > 1) {\n event.preventDefault();\n }\n }\n ; // END move\n end(event) {\n if (!event.changedTouches)\n return;\n const afEvent = event;\n this._cancelLongTap();\n const self = this;\n if (afEvent.touches.length < 2) {\n this.multipointEnd.dispatch(afEvent, this.element);\n this.sx2 = this.sy2 = null;\n }\n //swipe\n if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) ||\n (this.y2 && Math.abs(this.y1 - this.y2) > 30)) {\n afEvent.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2);\n this.swipeTimeout = setTimeout(function () {\n self.swipe.dispatch(afEvent, self.element);\n }, 0);\n }\n else {\n this.tapTimeout = setTimeout(function () {\n if (!self._preventTap) {\n self.tap.dispatch(afEvent, self.element);\n }\n // trigger double tap immediately\n if (self.isDoubleTap) {\n self.doubleTap.dispatch(afEvent, self.element);\n self.isDoubleTap = false;\n }\n }, 0);\n if (!self.isDoubleTap) {\n self.singleTapTimeout = setTimeout(function () {\n self.singleTap.dispatch(afEvent, self.element);\n }, 250);\n }\n }\n this.touchEnd.dispatch(afEvent, this.element);\n this.preV.x = 0;\n this.preV.y = 0;\n this.zoom = 1;\n this.pinchStartLen = null;\n this.x1 = this.x2 = this.y1 = this.y2 = null;\n }\n ; // END end\n cancelAll() {\n this._preventTap = true;\n clearTimeout(this.singleTapTimeout);\n clearTimeout(this.tapTimeout);\n clearTimeout(this.longTapTimeout);\n clearTimeout(this.swipeTimeout);\n }\n ;\n cancel(evt) {\n this.cancelAll();\n this.touchCancel.dispatch(evt, this.element);\n }\n ;\n _cancelLongTap() {\n clearTimeout(this.longTapTimeout);\n }\n ;\n _cancelSingleTap() {\n clearTimeout(this.singleTapTimeout);\n }\n ;\n _swipeDirection(x1, x2, y1, y2) {\n return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down');\n }\n ;\n on(evt, handler) {\n if (this[evt]) {\n // Force the generic parameter into it's expected candidate here ;)\n const admin = this[evt];\n admin.add(handler);\n }\n }\n ;\n off(evt, handler) {\n if (this[evt]) {\n // Force the generic parameter into it's expected candidate here ;)\n const admin = this[evt];\n admin.del(handler);\n }\n }\n ;\n destroy() {\n if (this.singleTapTimeout) {\n clearTimeout(this.singleTapTimeout);\n }\n if (this.tapTimeout) {\n clearTimeout(this.tapTimeout);\n }\n if (this.longTapTimeout) {\n clearTimeout(this.longTapTimeout);\n }\n if (this.swipeTimeout) {\n clearTimeout(this.swipeTimeout);\n }\n this.element.removeEventListener(\"touchstart\", this.start);\n this.element.removeEventListener(\"touchmove\", this.move);\n this.element.removeEventListener(\"touchend\", this.end);\n this.element.removeEventListener(\"touchcancel\", this.cancel);\n this.rotate.del();\n this.touchStart.del();\n this.multipointStart.del();\n this.multipointEnd.del();\n this.pinch.del();\n this.swipe.del();\n this.tap.del();\n this.doubleTap.del();\n this.longTap.del();\n this.singleTap.del();\n this.pressMove.del();\n this.twoFingerPressMove.del();\n this.touchMove.del();\n this.touchEnd.del();\n this.touchCancel.del();\n this.preV = this.pinchStartLen = this.zoom = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = this.twoFingerPressMove = null;\n if (globalThis && typeof globalThis.removeEventListener === \"function\") {\n globalThis.removeEventListener('scroll', this._cancelAllHandler);\n }\n }\n ; // END destroy\n}\n;\nexport default AlloyFinger;\n//# sourceMappingURL=alloy_finger.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-11-28\n * @modified 2018-12-04 Added the toSVGString function.\n * @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.\n * @modified 2021-01-20 Added UID.\n * @modified 2021-02-14 Added functions `radiusH` and `radiusV`.\n * @modified 2021-02-26 Added helper function `decribeSVGArc(...)`.\n * @modified 2021-03-01 Added attribute `rotation` to allow rotation of ellipses.\n * @modified 2021-03-03 Added the `vertAt` and `perimeter` methods.\n * @modified 2021-03-05 Added the `getFoci`, `normalAt` and `tangentAt` methods.\n * @modified 2021-03-09 Added the `clone` and `rotate` methods.\n * @modified 2021-03-10 Added the `toCubicBezier` method.\n * @modified 2021-03-15 Added `VEllipse.quarterSegmentCount` and `VEllipse.scale` functions.\n * @modified 2021-03-19 Added the `VEllipse.rotate` function.\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-02-02 Cleared the `VEllipse.toSVGString` function (deprecated). Use `drawutilssvg` instead.\n * @modified 2025-03-31 ATTENTION: modified the winding direction of the `tangentAt` method to match with the Circle method. This is a breaking change!\n * @modified 2025-03-31 Adding the `VEllipse.move(amount: XYCoords)` method.\n * @modified 2025-04-19 Adding the `VEllipse.getBounds()` method.\n * @modified 2025-04-24 Adding the `VEllipse.getExtremePoints()` method for calculating minima and maxima.\n * @version 1.4.0\n *\n * @file VEllipse\n * @fileoverview Ellipses with a center and an x- and a y-axis (stored as a vertex).\n **/\nimport { Line } from \"./Line\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { Circle } from \"./Circle\";\nimport { Bounds } from \"./Bounds\";\n/**\n * @classdesc An ellipse class based on two vertices [centerX,centerY] and [radiusX,radiusY].\n *\n * @requires SVGSerializable\n * @requires UID\n * @requires UIDGenerator\n * @requires Vertex\n */\nexport class VEllipse {\n /**\n * The constructor.\n *\n * @constructor\n * @param {Vertex} center - The ellipses center.\n * @param {Vertex} axis - The x- and y-axis (the two radii encoded in a control point).\n * @param {Vertex} rotation - [optional, default=0] The rotation of this ellipse.\n * @name VEllipse\n **/\n constructor(center, axis, rotation) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"VEllipse\";\n this.uid = UIDGenerator.next();\n this.center = center;\n this.axis = axis;\n this.rotation = rotation || 0.0;\n }\n /**\n * Clone this ellipse (deep clone).\n *\n * @return {VEllipse} A copy of this ellipse.s\n */\n clone() {\n return new VEllipse(this.center.clone(), this.axis.clone(), this.rotation);\n }\n /**\n * Get the non-negative horizonal radius of this ellipse.\n *\n * @method radiusH\n * @instance\n * @memberof VEllipse\n * @return {number} The unsigned horizontal radius of this ellipse.\n */\n radiusH() {\n return Math.abs(this.signedRadiusH());\n }\n /**\n * Get the signed horizonal radius of this ellipse.\n *\n * @method signedRadiusH\n * @instance\n * @memberof VEllipse\n * @return {number} The signed horizontal radius of this ellipse.\n */\n signedRadiusH() {\n // return Math.abs(this.axis.x - this.center.x);\n // Rotate axis back to origin before calculating radius\n // return Math.abs(new Vertex(this.axis).rotate(-this.rotation,this.center).x - this.center.x);\n return new Vertex(this.axis).rotate(-this.rotation, this.center).x - this.center.x;\n }\n /**\n * Get the non-negative vertical radius of this ellipse.\n *\n * @method radiusV\n * @instance\n * @memberof VEllipse\n * @return {number} The unsigned vertical radius of this ellipse.\n */\n radiusV() {\n return Math.abs(this.signedRadiusV());\n }\n /**\n * Get the signed vertical radius of this ellipse.\n *\n * @method radiusV\n * @instance\n * @memberof VEllipse\n * @return {number} The signed vertical radius of this ellipse.\n */\n signedRadiusV() {\n // Rotate axis back to origin before calculating radius\n return new Vertex(this.axis).rotate(-this.rotation, this.center).y - this.center.y;\n }\n /**\n * Get the the minima and maxima (points) of this (rotated) ellipse.\n *\n * @method getExtremePoints\n * @instance\n * @memberof VEllipse\n * @return {[Vertex, Vertex, Vertex, Vertex]} Get the the minima and maxima (points) of this (rotated) ellipse.\n */\n getExtremePoints() {\n const a = this.radiusH();\n const b = this.radiusV();\n // Calculate t_x values\n const t_x1 = Math.atan2(-b * Math.sin(this.rotation), a * Math.cos(this.rotation));\n const t_x2 = t_x1 + Math.PI;\n // Calculate x values at t_x\n const x_x1 = this.center.x + a * Math.cos(t_x1) * Math.cos(this.rotation) - b * Math.sin(t_x1) * Math.sin(this.rotation);\n const y_x1 = this.center.y + a * Math.cos(t_x1) * Math.sin(this.rotation) + b * Math.sin(t_x1) * Math.cos(this.rotation);\n const x_x2 = this.center.x + a * Math.cos(t_x2) * Math.cos(this.rotation) - b * Math.sin(t_x2) * Math.sin(this.rotation);\n const y_x2 = this.center.y + a * Math.cos(t_x2) * Math.sin(this.rotation) + b * Math.sin(t_x2) * Math.cos(this.rotation);\n let x_max, x_min;\n if (x_x1 > x_x2) {\n x_max = new Vertex(x_x1, y_x1);\n x_min = new Vertex(x_x2, y_x2);\n }\n else {\n x_max = new Vertex(x_x2, y_x2);\n x_min = new Vertex(x_x1, y_x1);\n }\n // Calculate t_y values\n const t_y1 = Math.atan2(b * Math.cos(this.rotation), a * Math.sin(this.rotation));\n const t_y2 = t_y1 + Math.PI;\n // Calculate y values at t_y\n const x_y1 = this.center.x + a * Math.cos(t_y1) * Math.cos(this.rotation) - b * Math.sin(t_y1) * Math.sin(this.rotation);\n const y_y1 = this.center.y + a * Math.cos(t_y1) * Math.sin(this.rotation) + b * Math.sin(t_y1) * Math.cos(this.rotation);\n const x_y2 = this.center.x + a * Math.cos(t_y2) * Math.cos(this.rotation) - b * Math.sin(t_y2) * Math.sin(this.rotation);\n const y_y2 = this.center.y + a * Math.cos(t_y2) * Math.sin(this.rotation) + b * Math.sin(t_y2) * Math.cos(this.rotation);\n let y_max, y_min;\n if (y_y1 > y_y2) {\n y_max = new Vertex(x_y1, y_y1);\n y_min = new Vertex(x_y2, y_y2);\n }\n else {\n y_max = new Vertex(x_y2, y_y2);\n y_min = new Vertex(x_y1, y_y1);\n }\n return [x_max, x_min, y_max, y_min];\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this ellipse.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getBounds\n * @instance\n * @memberof VEllipse\n * @return {Bounds} The bounds of this ellipse.\n **/\n getBounds() {\n // Thanks to Cuixiping\n // https://stackoverflow.com/questions/87734/how-do-you-calculate-the-axis-aligned-bounding-box-of-an-ellipse\n const r1 = this.radiusH();\n const r2 = this.radiusV();\n const ux = r1 * Math.cos(this.rotation);\n const uy = r1 * Math.sin(this.rotation);\n const vx = r2 * Math.cos(this.rotation + Math.PI / 2);\n const vy = r2 * Math.sin(this.rotation + Math.PI / 2);\n const bbox_halfwidth = Math.sqrt(ux * ux + vx * vx);\n const bbox_halfheight = Math.sqrt(uy * uy + vy * vy);\n return new 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 });\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Move the ellipse by the given amount. This is equivalent by moving the `center` and `axis` points.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof VEllipse\n * @return {VEllipse} this for chaining\n **/\n move(amount) {\n this.center.add(amount);\n this.axis.add(amount);\n return this;\n }\n /**\n * Scale this ellipse by the given factor from the center point. The factor will be applied to both radii.\n *\n * @method scale\n * @instance\n * @memberof VEllipse\n * @param {number} factor - The factor to scale by.\n * @return {VEllipse} this for chaining.\n */\n scale(factor) {\n this.axis.scale(factor, this.center);\n return this;\n }\n /**\n * Rotate this ellipse around its center.\n *\n * @method rotate\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to rotate by.\n * @returns {VEllipse} this for chaining.\n */\n rotate(angle) {\n this.axis.rotate(angle, this.center);\n this.rotation += angle;\n return this;\n }\n /**\n * Get the vertex on the ellipse's outline at the given angle.\n *\n * @method vertAt\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to determine the vertex at.\n * @return {Vertex} The vertex on the outline at the given angle.\n */\n vertAt(angle) {\n // Tanks to Narasinham for the vertex-on-ellipse equations\n // https://math.stackexchange.com/questions/22064/calculating-a-point-that-lies-on-an-ellipse-given-an-angle\n const a = this.radiusH();\n const b = this.radiusV();\n return new Vertex(VEllipse.utils.polarToCartesian(this.center.x, this.center.y, a, b, angle)).rotate(this.rotation, this.center);\n }\n /**\n * Get the normal vector at the given angle.\n * The normal vector is the vector that intersects the ellipse in a 90 degree angle\n * at the given point (speicified by the given angle).\n *\n * Length of desired normal vector can be specified, default is 1.0.\n *\n * @method normalAt\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to get the normal vector at.\n * @param {number=1.0} length - [optional, default=1] The length of the returned vector.\n */\n normalAt(angle, length) {\n const point = this.vertAt(angle - this.rotation); // HERE IS THE CORRECT BEHAVIOR!\n const foci = this.getFoci();\n // Calculate the angle between [point,focusA] and [point,focusB]\n const angleA = new Line(point, foci[0]).angle();\n const angleB = new Line(point, foci[1]).angle();\n const centerAngle = angleA + (angleB - angleA) / 2.0;\n const endPointA = point.clone().addX(50).clone().rotate(centerAngle, point);\n const endPointB = point\n .clone()\n .addX(50)\n .clone()\n .rotate(Math.PI + centerAngle, point);\n const resultVector = this.center.distance(endPointA) < this.center.distance(endPointB)\n ? new Vector(point, endPointB)\n : new Vector(point, endPointA);\n if (typeof length === \"number\") {\n resultVector.setLength(length);\n }\n return resultVector;\n }\n /**\n * Get the tangent vector at the given angle.\n * The tangent vector is the vector that touches the ellipse exactly at the given given\n * point (speicified by the given angle).\n *\n * Note that the tangent is just 90 degree rotated normal vector.\n *\n * Length of desired tangent vector can be specified, default is 1.0.\n *\n * @method tangentAt\n * @instance\n * @memberof VEllipse\n * @param {number} angle - The angle to get the tangent vector at.\n * @param {number=1.0} length - [optional, default=1] The length of the returned vector.\n */\n tangentAt(angle, length) {\n const normal = this.normalAt(angle, length);\n return normal.inv().perp();\n }\n /**\n * Get the perimeter of this ellipse.\n *\n * @method perimeter\n * @instance\n * @memberof VEllipse\n * @return {number}\n */\n perimeter() {\n // This method does not use an iterative approximation to determine the perimeter, but it uses\n // a wonderful closed approximation found by Srinivasa Ramanujan.\n // Matt Parker made a neat video about it:\n // https://www.youtube.com/watch?v=5nW3nJhBHL0\n const a = this.radiusH();\n const b = this.radiusV();\n return Math.PI * (3 * (a + b) - Math.sqrt((3 * a + b) * (a + 3 * b)));\n }\n /**\n * Get the two foci of this ellipse.\n *\n * @method getFoci\n * @instance\n * @memberof VEllipse\n * @return {Array<Vertex>} An array with two elements, the two focal points of the ellipse (foci).\n */\n getFoci() {\n // https://www.mathopenref.com/ellipsefoci.html\n const rh = this.radiusH();\n const rv = this.radiusV();\n const sdiff = rh * rh - rv * rv;\n // f is the distance of each focs to the center.\n const f = Math.sqrt(Math.abs(sdiff));\n // Foci on x- or y-axis?\n if (sdiff < 0) {\n return [\n this.center.clone().addY(f).rotate(this.rotation, this.center),\n this.center.clone().addY(-f).rotate(this.rotation, this.center)\n ];\n }\n else {\n return [\n this.center.clone().addX(f).rotate(this.rotation, this.center),\n this.center.clone().addX(-f).rotate(this.rotation, this.center)\n ];\n }\n }\n /**\n * Get equally distributed points on the outline of this ellipse.\n *\n * @method getEquidistantVertices\n * @instance\n * @param {number} pointCount - The number of points.\n * @returns {Array<Vertex>}\n */\n getEquidistantVertices(pointCount) {\n const angles = VEllipse.utils.equidistantVertAngles(this.radiusH(), this.radiusV(), pointCount);\n const result = [];\n for (var i = 0; i < angles.length; i++) {\n result.push(this.vertAt(angles[i]));\n }\n return result;\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the line intersections as vectors with this ellipse.\n *\n * @method lineIntersections\n * @instance\n * @param {VertTuple<Vector> ray - The line/ray to intersect this ellipse with.\n * @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.\n * @returns\n */\n lineIntersections(ray, inVectorBoundsOnly = false) {\n // Question: what happens to extreme versions when ellipse is a line (width or height is zero)?\n // This would result in a Division_by_Zero exception!\n // Step A: create clones for operations (keep originals unchanged)\n const ellipseCopy = this.clone(); // VEllipse\n const rayCopy = ray.clone(); // Vector\n // Step B: move both so ellipse's center is located at (0,0)\n const moveAmount = ellipseCopy.center.clone().inv();\n ellipseCopy.move(moveAmount);\n rayCopy.add(moveAmount);\n // Step C: rotate eclipse backwards it's rotation, so that rotation is zero (0.0).\n // Rotate together with ray!\n const rotationAmount = -ellipseCopy.rotation;\n ellipseCopy.rotate(rotationAmount); // Rotation around (0,0) = center of translated ellipse\n rayCopy.a.rotate(rotationAmount, ellipseCopy.center);\n rayCopy.b.rotate(rotationAmount, ellipseCopy.center);\n // Step D: find x/y factors to use for scaling to transform the ellipse to a circle.\n // Scale together with vector ray.\n const radiusH = ellipseCopy.radiusH();\n const radiusV = ellipseCopy.radiusV();\n const scalingFactors = radiusH > radiusV ? { x: radiusV / radiusH, y: 1.0 } : { x: 1.0, y: radiusH / radiusV };\n // Step E: scale ellipse AND ray by calculated factors.\n ellipseCopy.axis.scaleXY(scalingFactors);\n rayCopy.a.scaleXY(scalingFactors);\n rayCopy.b.scaleXY(scalingFactors);\n // Intermediate result: now the ellipse is transformed to a circle and we can calculate intersections :)\n // Step F: calculate circle+line intersecions\n const tmpCircle = new Circle(new Vertex(), ellipseCopy.radiusH()); // radiusH() === radiusV()\n const intersections = tmpCircle.lineIntersections(rayCopy, inVectorBoundsOnly);\n // Step G: transform intersecions back to original configuration\n intersections.forEach(function (intersectionPoint) {\n // Reverse transformation from above.\n intersectionPoint.scaleXY({ x: 1 / scalingFactors.x, y: 1 / scalingFactors.y }, ellipseCopy.center);\n intersectionPoint.rotate(-rotationAmount, ellipseCopy.center);\n intersectionPoint.sub(moveAmount);\n });\n return intersections;\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.center, vert);\n const angle = lineFromCenter.angle();\n // Calculate tangent at angle\n return this.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Convert this ellipse into cubic Bézier curves.\n *\n * @param {number=3} quarterSegmentCount - The number of segments per base elliptic quarter (default is 3, min is 1).\n * @param {number=0.666666} threshold - The Bézier threshold (default value 0.666666 approximates the ellipse with best results\n * but you might wish to use other values)\n * @return {Array<CubicBezierCurve>} An array of cubic Bézier curves representing this ellipse.\n */\n toCubicBezier(quarterSegmentCount, threshold) {\n // Math by Luc Maisonobe\n // http://www.spaceroots.org/documents/ellipse/node22.html\n // Note that ellipses with radiusH=0 or radiusV=0 cannot be represented as Bézier curves.\n // Return a single line here (as a Bézier curve)?\n // if (Math.abs(this.radiusV()) < 0.00001) {\n // const radiusH = this.radiusH();\n // return [\n // new CubicBezierCurve(\n // this.center.clone().addX(radiusH),\n // this.center.clone().addX(-radiusH),\n // this.center.clone(),\n // this.center.clone()\n // )\n // ]; // TODO: test horizontal line ellipse\n // }\n // if (Math.abs(this.radiusH()) < 0.00001) {\n // const radiusV = this.radiusV();\n // return [\n // new CubicBezierCurve(\n // this.center.clone().addY(radiusV),\n // this.center.clone().addY(-radiusV),\n // this.center.clone(),\n // this.center.clone()\n // )\n // ]; // TODO: test vertical line ellipse\n // }\n // At least 4, but 16 seems to be a good value.\n const segmentCount = Math.max(1, quarterSegmentCount || 3) * 4;\n threshold = typeof threshold === \"undefined\" ? 0.666666 : threshold;\n const radiusH = this.radiusH();\n const radiusV = this.radiusV();\n const curves = [];\n const angles = VEllipse.utils.equidistantVertAngles(radiusH, radiusV, segmentCount);\n let curAngle = angles[0] + this.rotation;\n let startPoint = this.vertAt(curAngle);\n for (var i = 0; i < angles.length; i++) {\n let nextAngle = angles[(i + 1) % angles.length] + this.rotation;\n let endPoint = this.vertAt(nextAngle);\n if (Math.abs(radiusV) < 0.0001 || Math.abs(radiusH) < 0.0001) {\n // Distorted ellipses can only be approximated by linear Bézier segments\n let diff = startPoint.difference(endPoint);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().addXY(diff.x * 0.333, diff.y * 0.333), endPoint.clone().addXY(-diff.x * 0.333, -diff.y * 0.333));\n curves.push(curve);\n }\n else {\n let startTangent = this.tangentAt(curAngle + this.rotation);\n let endTangent = this.tangentAt(nextAngle + this.rotation);\n // Find intersection (ignore that the result might be null in some extreme cases)\n let intersection = startTangent.intersection(endTangent);\n // What if intersection is undefined?\n // --> This *can* not happen if segmentCount > 2 and height and width of the ellipse are not zero.\n let startDiff = startPoint.difference(intersection);\n let endDiff = endPoint.difference(intersection);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().add(startDiff.scale(threshold)), endPoint.clone().add(endDiff.scale(threshold)));\n curves.push(curve);\n }\n startPoint = endPoint;\n curAngle = nextAngle;\n }\n return curves;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.center.destroy();\n this.axis.destroy();\n this.isDestroyed = true;\n }\n}\n/**\n * A static collection of ellipse-related helper functions.\n * @static\n */\nVEllipse.utils = {\n /**\n * Calculate a particular point on the outline of the given ellipse (center plus two radii plus angle).\n *\n * @name polarToCartesian\n * @param {number} centerX - The x coordinate of the elliptic center.\n * @param {number} centerY - The y coordinate of the elliptic center.\n * @param {number} radiusH - The horizontal radius of the ellipse.\n * @param {number} radiusV - The vertical radius of the ellipse.\n * @param {number} angle - The angle (in radians) to get the desired outline point for.\n * @reutn {XYCoords} The outlont point in absolute x-y-coordinates.\n */\n polarToCartesian: (centerX, centerY, radiusH, radiusV, angle) => {\n // Tanks to Narasinham for the vertex-on-ellipse equations\n // https://math.stackexchange.com/questions/22064/calculating-a-point-that-lies-on-an-ellipse-given-an-angle\n var s = Math.sin(Math.PI / 2 - angle);\n var c = Math.cos(Math.PI / 2 - angle);\n return {\n x: centerX + (radiusH * radiusV * s) / Math.sqrt(Math.pow(radiusH * c, 2) + Math.pow(radiusV * s, 2)),\n y: centerY + (radiusH * radiusV * c) / Math.sqrt(Math.pow(radiusH * c, 2) + Math.pow(radiusV * s, 2))\n };\n },\n /**\n * Get the `theta` for a given `phi` (used to determine equidistant points on ellipse).\n *\n * @param radiusH\n * @param radiusV\n * @param phi\n * @returns {number} theta\n */\n phiToTheta: (radiusH, radiusV, phi) => {\n // See https://math.stackexchange.com/questions/172766/calculating-equidistant-points-around-an-ellipse-arc\n var tanPhi = Math.tan(phi);\n var tanPhi2 = tanPhi * tanPhi;\n var theta = -Math.PI / 2 + phi + Math.atan(((radiusH - radiusV) * tanPhi) / (radiusV + radiusH * tanPhi2));\n return theta;\n },\n /**\n * Get n equidistant points on the elliptic arc.\n *\n * @param pointCount\n * @returns\n */\n equidistantVertAngles: (radiusH, radiusV, pointCount) => {\n const angles = [];\n for (var i = 0; i < pointCount; i++) {\n var phi = Math.PI / 2.0 + ((Math.PI * 2) / pointCount) * i;\n let theta = VEllipse.utils.phiToTheta(radiusH, radiusV, phi);\n angles[i] = theta;\n }\n return angles;\n }\n}; // END utils\n//# sourceMappingURL=VEllipse.js.map","/**\n * Implementation of elliptic sectors.\n * Note that sectors are constructed in clockwise direction.\n *\n * @author Ikaros Kappler\n * @date 2021-02-26\n * @modified 2022-02-02 Added the `destroy` method.\n * @modified 2022-11-01 Tweaked the `endpointToCenterParameters` function to handle negative values, too, without errors.\n * @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).\n * @modified 2025-04-02 Adding `VEllipseSector.containsAngle` method.\n * @modified 2025-04-02 Adding `VEllipseSector.lineIntersections` and `VEllipseSector.lineIntersectionTangents` and implementing `Intersectable`.\n * @modified 2025-04-07 Adding value wrapping (0 to TWO_PI) to the `VEllipseSector.containsAngle` method.\n * @modified 2025-04-09 Adding the `VEllipseSector.move` method.\n * @modified 2025-04-19 Added the `VEllipseSector.getStartPoint` and `getEndPoint` methods.\n * @modified 2025-04-23 Added the `VEllipseSector.getBounds` method.\n * @version 1.2.0\n */\nimport { Bounds } from \"./Bounds\";\nimport { CubicBezierCurve } from \"./CubicBezierCurve\";\nimport { geomutils } from \"./geomutils\";\nimport { Line } from \"./Line\";\nimport { UIDGenerator } from \"./UIDGenerator\";\nimport { VEllipse } from \"./VEllipse\";\nimport { Vertex } from \"./Vertex\";\n/**\n * @classdesc A class for elliptic sectors.\n *\n * @requires Line\n * @requires Vector\n * @requires VertTuple\n * @requires Vertex\n * @requires SVGSerializale\n * @requires UID\n * @requires UIDGenerator\n **/\nexport class VEllipseSector {\n /**\n * Create a new elliptic sector from the given ellipse and two angles.\n *\n * Note that the direction from start to end goes clockwise, and that start and end angle\n * will be wrapped to [0,PI*2).\n *\n * @constructor\n * @name VEllipseSector\n * @param {VEllipse} - The underlying ellipse to use.\n * @param {number} startAngle - The start angle of the sector.\n * @param {numner} endAngle - The end angle of the sector.\n */\n constructor(ellipse, startAngle, endAngle) {\n /**\n * Required to generate proper CSS classes and other class related IDs.\n **/\n this.className = \"VEllipseSector\";\n this.uid = UIDGenerator.next();\n this.ellipse = ellipse;\n this.startAngle = geomutils.wrapMinMax(startAngle, 0, Math.PI * 2);\n this.endAngle = geomutils.wrapMinMax(endAngle, 0, Math.PI * 2);\n }\n /**\n * Move the ellipse sector by the given amount.\n *\n * @method move\n * @param {XYCoords} amount - The amount to move.\n * @instance\n * @memberof VEllipseSector\n * @return {VEllipseSector} this for chaining\n **/\n move(amount) {\n this.ellipse.move(amount);\n return this;\n }\n /**\n * Checks wether the given angle (must be inside 0 and PI*2) is contained inside this sector.\n *\n * @param {number} angle - The numeric angle to check.\n * @method containsAngle\n * @instance\n * @memberof VEllipseSectpr\n * @return {boolean} True if (and only if) this sector contains the given angle.\n */\n containsAngle(angle) {\n angle = geomutils.mapAngleTo2PI(angle); // wrapMinMax(angle, 0, Math.PI * 2);\n const sAngle = geomutils.mapAngleTo2PI(this.startAngle);\n const eAngle = geomutils.mapAngleTo2PI(this.endAngle);\n // TODO: cleanup\n // if (this.startAngle <= this.endAngle) {\n // return angle >= this.startAngle && angle < this.endAngle;\n // } else {\n // // startAngle > endAngle\n // return angle >= this.startAngle || angle < this.endAngle;\n // }\n if (sAngle <= eAngle) {\n return angle >= sAngle && angle < eAngle;\n }\n else {\n // startAngle > endAngle\n return angle >= sAngle || angle < eAngle;\n }\n }\n /**\n * Get the sectors starting point (on the underlying ellipse, located at the start angle).\n *\n * @method getStartPoint\n * @instance\n * @memberof VEllipseSector\n * @return {Vertex} The sector's stating point.\n */\n getStartPoint() {\n return this.ellipse.vertAt(this.startAngle);\n }\n /**\n * Get the sectors ending point (on the underlying ellipse, located at the end angle).\n *\n * @method getEndPoint\n * @instance\n * @memberof VEllipseSector\n * @return {Vertex} The sector's ending point.\n */\n getEndPoint() {\n return this.ellipse.vertAt(this.endAngle);\n }\n //--- BEGIN --- Implement interface `IBounded`\n /**\n * Get the bounds of this elliptic sector.\n *\n * The bounds are approximated by the underlying segment buffer; the more segment there are,\n * the more accurate will be the returned bounds.\n *\n * @method getBounds\n * @instance\n * @memberof VEllipse\n * @return {Bounds} The bounds of this elliptic sector.\n **/\n getBounds() {\n // Calculage angles from east, west, north and south box points and check if they are inside\n const extremes = this.ellipse.getExtremePoints();\n const candidates = extremes.filter(point => {\n const angle = new Line(this.ellipse.center, point).angle() - this.ellipse.rotation;\n return this.containsAngle(angle);\n });\n return Bounds.computeFromVertices([this.getStartPoint(), this.getEndPoint()].concat(candidates));\n }\n //--- BEGIN --- Implement interface `Intersectable`\n /**\n * Get the line intersections as vectors with this ellipse.\n *\n * @method lineIntersections\n * @instance\n * @memberof VEllipseSectpr\n * @param {VertTuple<Vector>} ray - The line/ray to intersect this ellipse with.\n * @param {boolean} inVectorBoundsOnly - (default=false) Set to true if only intersections within the vector bounds are of interest.\n * @returns\n */\n lineIntersections(ray, inVectorBoundsOnly = false) {\n // First get all line intersections from underlying ellipse.\n const ellipseIntersections = this.ellipse.lineIntersections(ray, inVectorBoundsOnly);\n // Drop all intersection points that are not contained in the circle sectors bounds.\n const tmpLine = new Line(this.ellipse.center, new Vertex());\n return ellipseIntersections.filter((intersectionPoint) => {\n tmpLine.b.set(intersectionPoint);\n const lineAngle = tmpLine.angle();\n return this.containsAngle(lineAngle - this.ellipse.rotation);\n });\n }\n /**\n * Get all line intersections of this polygon and their tangents along the shape.\n *\n * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.\n *\n * @method lineIntersections\n * @memberof VEllipseSectpr\n * @param line\n * @param lineIntersectionTangents\n * @returns\n */\n lineIntersectionTangents(line, inVectorBoundsOnly = false) {\n // Find the intersections of all lines plus their tangents inside the circle bounds\n const interSectionPoints = this.lineIntersections(line, inVectorBoundsOnly);\n return interSectionPoints.map((vert) => {\n // Calculate angle\n const lineFromCenter = new Line(this.ellipse.center, vert);\n const angle = lineFromCenter.angle();\n // console.log(\"angle\", (angle / Math.PI) * 180.0);\n // const angle = Math.random() * Math.PI * 2; // TODO\n // Calculate tangent at angle\n return this.ellipse.tangentAt(angle);\n });\n }\n //--- END --- Implement interface `Intersectable`\n /**\n * Convert this elliptic sector into cubic Bézier curves.\n *\n * @param {number=3} quarterSegmentCount - The number of segments per base elliptic quarter (default is 3, min is 1).\n * @param {number=0.666666} threshold - The Bézier threshold (default value 0.666666 approximates the ellipse with best results\n * but you might wish to use other values)\n * @return {Array<CubicBezierCurve>} An array of cubic Bézier curves representing the elliptic sector.\n */\n toCubicBezier(quarterSegmentCount, threshold) {\n // There are at least 4 segments required (dour quarters) to approximate a whole\n // ellipse with Bézier curves.\n // A visually 'good' approximation should have 12; this seems to be a good value (anything multiple of 4).\n const segmentCount = Math.max(1, quarterSegmentCount || 3) * 4;\n threshold = typeof threshold === \"undefined\" ? 0.666666 : threshold;\n const radiusH = this.ellipse.radiusH();\n const radiusV = this.ellipse.radiusV();\n var startAngle = VEllipseSector.ellipseSectorUtils.normalizeAngle(this.startAngle);\n var endAngle = VEllipseSector.ellipseSectorUtils.normalizeAngle(this.endAngle);\n // Find all angles inside start and end\n var angles = VEllipseSector.ellipseSectorUtils.equidistantVertAngles(radiusH, radiusV, startAngle, endAngle, segmentCount);\n angles = [startAngle].concat(angles).concat([endAngle]);\n const curves = [];\n let curAngle = angles[0];\n let startPoint = this.ellipse.vertAt(curAngle);\n for (var i = 0; i + 1 < angles.length; i++) {\n let nextAngle = angles[(i + 1) % angles.length];\n let endPoint = this.ellipse.vertAt(nextAngle);\n let startTangent = this.ellipse.tangentAt(curAngle + this.ellipse.rotation);\n let endTangent = this.ellipse.tangentAt(nextAngle + this.ellipse.rotation);\n // Distorted ellipses can only be approximated by linear Bézier segments\n if (Math.abs(radiusV) < 0.0001 || Math.abs(radiusH) < 0.0001) {\n let diff = startPoint.difference(endPoint);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().addXY(diff.x * 0.333, diff.y * 0.333), endPoint.clone().addXY(-diff.x * 0.333, -diff.y * 0.333));\n curves.push(curve);\n }\n else {\n // Find intersection\n let intersection = startTangent.intersection(endTangent);\n // What if intersection is undefined?\n // --> This *can* not happen if segmentCount > 2 and height and width of the ellipse are not zero.\n if (intersection) {\n // It's VERY LIKELY hat this ALWAYS happens; it's just a typesave variant.\n // Intersection cannot be null.\n let startDiff = startPoint.difference(intersection);\n let endDiff = endPoint.difference(intersection);\n let curve = new CubicBezierCurve(startPoint.clone(), endPoint.clone(), startPoint.clone().add(startDiff.scale(threshold)), endPoint.clone().add(endDiff.scale(threshold)));\n curves.push(curve);\n }\n }\n startPoint = endPoint;\n curAngle = nextAngle;\n }\n return curves;\n }\n /**\n * This function should invalidate any installed listeners and invalidate this object.\n * After calling this function the object might not hold valid data any more and\n * should not be used.\n */\n destroy() {\n this.ellipse.destroy();\n this.isDestroyed = true;\n }\n}\nVEllipseSector.ellipseSectorUtils = {\n /**\n * Helper function to convert an elliptic section to SVG arc params (for the `d` attribute).\n * Inspiration found at:\n * https://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle\n *\n * @param {boolean} options.moveToStart - If false (default=true) the initial 'Move' command will not be used.\n * @return [ 'A', radiusH, radiusV, rotation, largeArcFlag=1|0, sweepFlag=0, endx, endy ]\n */\n describeSVGArc: (x, y, radiusH, radiusV, startAngle, endAngle, rotation, options) => {\n if (typeof options === \"undefined\")\n options = { moveToStart: true };\n if (typeof rotation === \"undefined\")\n rotation = 0.0;\n // Important note: this function only works if start- and end-angle are within\n // one whole circle [x,x+2*PI].\n // Revelations of more than 2*PI might result in unexpected arcs.\n // -> Use the geomutils.wrapMax( angle, 2*PI )\n startAngle = geomutils.wrapMax(startAngle, Math.PI * 2);\n endAngle = geomutils.wrapMax(endAngle, Math.PI * 2);\n // Find the start- and end-point on the rotated ellipse\n // XYCoords to Vertex (for rotation)\n var end = new Vertex(VEllipse.utils.polarToCartesian(x, y, radiusH, radiusV, endAngle));\n var start = new Vertex(VEllipse.utils.polarToCartesian(x, y, radiusH, radiusV, startAngle));\n end.rotate(rotation, { x: x, y: y });\n start.rotate(rotation, { x: x, y: y });\n // Boolean stored as integers (0|1).\n var diff = endAngle - startAngle;\n var largeArcFlag;\n if (diff < 0) {\n largeArcFlag = Math.abs(diff) < Math.PI ? 1 : 0;\n }\n else {\n largeArcFlag = Math.abs(diff) > Math.PI ? 1 : 0;\n }\n const sweepFlag = 1;\n const pathData = [];\n if (options.moveToStart) {\n pathData.push(\"M\", start.x, start.y);\n }\n // Arc rotation in degrees, not radians.\n const r2d = 180 / Math.PI;\n pathData.push(\"A\", radiusH, radiusV, rotation * r2d, largeArcFlag, sweepFlag, end.x, end.y);\n return pathData;\n }, // END function describeSVGArc\n /**\n * Helper function to find second-kind elliptic angles, so that the euclidean distance along the the\n * elliptic sector is the same for all.\n *\n * Note that this is based on the full ellipse calculuation and start and end will be cropped; so the\n * distance from the start angle to the first angle and/or the distance from the last angle to\n * the end angle may be different to the others.\n *\n * Furthermore the computation is only possible on un-rotated ellipses; if your source ellipse has\n * a rotation on the plane please 'rotate' the result angles afterwards to find matching angles.\n *\n * Returned angles are normalized to the interval `[ 0, PI*2 ]`.\n *\n * @param {number} radiusH - The first (horizonal) radius of the ellipse.\n * @param {number} radiusV - The second (vertical) radius of the ellipse.\n * @param {number} startAngle - The opening angle of your elliptic sector (please use normalized angles).\n * @param {number} endAngle - The closing angle of your elliptic sector (please use normalized angles).\n * @param {number} fullEllipsePointCount - The number of base segments to use from the source ellipse (12 or 16 are good numbers).\n * @return {Array<number>} An array of n angles inside startAngle and endAngle (where n <= fullEllipsePointCount).\n */\n equidistantVertAngles: (radiusH, radiusV, startAngle, endAngle, fullEllipsePointCount) => {\n var ellipseAngles = VEllipse.utils.equidistantVertAngles(radiusH, radiusV, fullEllipsePointCount);\n ellipseAngles = ellipseAngles.map((angle) => VEllipseSector.ellipseSectorUtils.normalizeAngle(angle));\n const angleIsInRange = (angle) => {\n if (startAngle < endAngle)\n return angle >= startAngle && angle <= endAngle;\n else\n return angle >= startAngle || (angle <= endAngle && angle >= 0);\n };\n // Drop all angles outside the sector\n ellipseAngles = ellipseAngles.filter(angleIsInRange);\n // Now we need to sort the angles to the first one in the array is the closest to startAngle.\n // --> find the angle that is closest to the start angle\n const startIndex = VEllipseSector.ellipseSectorUtils.findClosestToStartAngle(startAngle, endAngle, ellipseAngles);\n // Bring all angles into the correct order\n // Idea: use splice or slice here?\n const angles = [];\n for (var i = 0; i < ellipseAngles.length; i++) {\n angles.push(ellipseAngles[(startIndex + i) % ellipseAngles.length]);\n }\n return angles;\n },\n findClosestToStartAngle: (startAngle, endAngle, ellipseAngles) => {\n // Note: endAngle > 0 && startAngle > 0\n if (startAngle > endAngle) {\n const n = ellipseAngles.length;\n for (var i = 0; i < n; i++) {\n const ea = geomutils.wrapMinMax(ellipseAngles[i], 0, Math.PI * 2);\n if (ea >= startAngle && ea >= endAngle) {\n return i;\n }\n }\n }\n return 0;\n },\n normalizeAngle: (angle) => (angle < 0 ? Math.PI * 2 + angle : angle),\n /**\n * Convert the elliptic arc from endpoint parameters to center parameters as described\n * in the w3c svg arc implementation note.\n *\n * https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter\n *\n * @param {number} x1 - The x component of the start point (end of last SVG command).\n * @param {number} y1 - The y component of the start point (end of last SVG command).\n * @param {number} rx - The first (horizontal) radius of the ellipse.\n * @param {number} ry - The second (vertical) radius of the ellipse.\n * @param {number} phi - The ellipse's rotational angle (angle of axis rotation) in radians (not in degrees as the SVG command uses!)\n * @param {boolean} fa - The large-arc-flag (boolean, not 0 or 1).\n * @param {boolean} fs - The sweep-flag (boolean, not 0 or 1).\n * @param {number} x2 - The x component of the end point (end of last SVG command).\n * @param {number} y2 - The y component of the end point (end of last SVG command).\n * @returns\n */\n endpointToCenterParameters(x1, y1, rx, ry, phi, fa, fs, x2, y2) {\n // console.log(\"endpointToCenterParameters\", x1, y1, phi, rx, ry, fa, fs, x2, y2);\n // Thanks to\n // https://observablehq.com/@toja/ellipse-and-elliptical-arc-conversion\n const abs = Math.abs;\n const sin = Math.sin;\n const cos = Math.cos;\n const sqrt = Math.sqrt;\n const pow = (n) => {\n return n * n;\n };\n const sinphi = sin(phi);\n const cosphi = cos(phi);\n // Step 1: simplify through translation/rotation\n const x = (cosphi * (x1 - x2)) / 2 + (sinphi * (y1 - y2)) / 2;\n const y = (-sinphi * (x1 - x2)) / 2 + (cosphi * (y1 - y2)) / 2;\n const px = pow(x), py = pow(y), prx = pow(rx), pry = pow(ry);\n // correct of out-of-range radii\n const L = px / prx + py / pry;\n if (L > 1) {\n rx = sqrt(L) * abs(rx);\n ry = sqrt(L) * abs(ry);\n }\n else {\n rx = abs(rx);\n ry = abs(ry);\n }\n // Step 2 + 3: compute center\n const sign = fa === fs ? -1 : 1;\n // const M: number = sqrt((prx * pry - prx * py - pry * px) / (prx * py + pry * px)) * sign;\n const M = sqrt(Math.abs((prx * pry - prx * py - pry * px) / (prx * py + pry * px))) * sign;\n const _cx = (M * (rx * y)) / ry;\n const _cy = (M * (-ry * x)) / rx;\n const cx = cosphi * _cx - sinphi * _cy + (x1 + x2) / 2;\n const cy = sinphi * _cx + cosphi * _cy + (y1 + y2) / 2;\n // Step 4: Compute start and end angle\n const center = new Vertex(cx, cy);\n const axis = center.clone().addXY(rx, ry);\n const ellipse = new VEllipse(center, axis, 0);\n // console.log(\"VELLIPSE::::::\", ellipse);\n ellipse.rotate(phi);\n const startAngle = new Line(ellipse.center, new Vertex(x1, y1)).angle();\n const endAngle = new Line(ellipse.center, new Vertex(x2, y2)).angle();\n return new VEllipseSector(ellipse, startAngle - phi, endAngle - phi);\n }\n}; // END ellipseSectorUtils\n//# sourceMappingURL=VEllipseSector.js.map","/**\n * @author Ikaros Kappler\n * @date 2018-10-23\n * @modified 2018-11-19 Added multi-select and multi-drag.\n * @modified 2018-12-04 Added basic SVG export.\n * @modified 2018-12-09 Extended the constructor (canvas).\n * @modified 2018-12-18 Added the config.redrawOnResize param.\n * @modified 2018-12-18 Added the config.defaultCanvas{Width,Height} params.\n * @modified 2018-12-19 Added CSS scaling.\n * @modified 2018-12-28 Removed the unused 'drawLabel' param. Added the 'enableMouse' and 'enableKeys' params.\n * @modified 2018-12-29 Added the 'drawOrigin' param.\n * @modified 2018-12-29 Renamed the 'autoCenterOffset' param to 'autoAdjustOffset'. Added the params 'offsetAdjustXPercent' and 'offsetAdjustYPercent'.\n * @modified 2019-01-14 Added params 'drawBezierHandleLines' and 'drawBezierHandlePoints'. Added the 'redraw' praam to the add() function.\n * @modified 2019-01-16 Added params 'drawHandleLines' and 'drawHandlePoints'. Added the new params to the dat.gui interface.\n * @modified 2019-01-30 Added the 'Vector' type (extending the Line class).\n * @modified 2019-01-30 Added the 'PBImage' type (a wrapper for images).\n * @modified 2019-02-02 Added the 'canvasWidthFactor' and 'canvasHeightFactor' params.\n * @modified 2019-02-03 Removed the drawBackgroundImage() function, with had no purpose at all. Just add an image to the drawables-list.\n * @modified 2019-02-06 Vertices (instace of Vertex) can now be added. Added the 'draggable' attribute to the vertex attributes.\n * @modified 2019-02-10 Fixed a draggable-bug in PBImage handling (scaling was not possible).\n * @modified 2019-02-10 Added the 'enableTouch' option (default is true).\n * @modified 2019-02-14 Added the console for debugging (setConsole(object)).\n * @modified 2019-02-19 Added two new constants: DEFAULT_CLICK_TOLERANCE and DEFAULT_TOUCH_TOLERANCE.\n * @modified 2019-02-19 Added the second param to the locatePointNear(Vertex,Number) function.\n * @modified 2019-02-20 Removed the 'loadFile' entry from the GUI as it was experimental and never in use.\n * @modified 2019-02-23 Removed the 'rebuild' function as it had no purpose.\n * @modified 2019-02-23 Added scaling of the click-/touch-tolerance with the CSS scale.\n * @modified 2019-03-23 Added JSDoc tags. Changed the default value of config.drawOrigin to false.\n * @modified 2019-04-03 Fixed the touch-drag position detection for canvas elements that are not located at document position (0,0).\n * @modified 2019-04-03 Tweaked the fit-to-parent function to work with paddings and borders.\n * @modified 2019-04-28 Added the preClear callback param (called before the canvas was cleared on redraw and before any elements are drawn).\n * @modified 2019-09-18 Added basics for WebGL support (strictly experimental).\n * @modified 2019-10-03 Added the .beginDrawCycle call in the redraw function.\n * @modified 2019-11-06 Added fetch.num, fetch.val, fetch.bool, fetch.func functions.\n * @modified 2019-11-13 Fixed an issue with the mouse-sensitive area around vertices (were affected by zoom).\n * @modified 2019-11-13 Added the 'enableMouseWheel' param.\n * @modified 2019-11-18 Added the Triangle class as a regular drawable element.\n * @modified 2019-11-18 The add function now works with arrays, too.\n * @modified 2019-11-18 Added the _handleColor helper function to determine the render color of non-draggable vertices.\n * @modified 2019-11-19 Fixed a bug in the resizeCanvas function; retina resolution was not possible.\n * @modified 2019-12-04 Added relative positioned zooming.\n * @modified 2019-12-04 Added offsetX and offsetY params.\n * @modified 2019-12-04 Added an 'Set to fullsize retina' button to the GUI config.\n * @modified 2019-12-07 Added the drawConfig for lines, polygons, ellipse, triangles, bezier curves and image control lines.\n * @modified 2019-12-08 Fixed a css scale bug in the viewport() function.\n * @modified 2019-12-08 Added the drawconfig UI panel (line colors and line widths).\n * @modified 2020-02-06 Added handling for the end- and end-control-points of non-cirular Bézier paths (was still missing).\n * @modified 2020-02-06 Fixed a drag-amount bug in the move handling of end points of Bezier paths (control points was not properly moved when non circular).\n * @modified 2020-03-28 Ported this class from vanilla-JS to Typescript.\n * @modified 2020-03-29 Fixed the enableSVGExport flag (read enableEport before).\n * @modified 2020-05-09 Included the Cirlcle class.\n * @modified 2020-06-22 Added the rasterScaleX and rasterScaleY config params.\n * @modified 2020-06-03 Fixed the selectedVerticesOnPolyon(Polygon) function: non-selectable vertices were selected too, before.\n * @modified 2020-07-06 Replacing Touchy.js by AlloyFinger.js\n * @modified 2020-07-27 Added the getVertexNear(XYCoords,number) function\n * @modified 2020-07-27 Extended the remove(Drawable) function: vertices are now removed, too.\n * @modified 2020-07-28 Added PlotBoilerplate.revertMousePosition(number,number) – the inverse function of transformMousePosition(...).\n * @modified 2020-07-31 Added PlotBoilerplate.getDraggedElementCount() to check wether any elements are currently being dragged.\n * @modified 2020-08-19 Added the VertexAttributes.visible attribute to make vertices invisible.\n * @modified 2020-11-17 Added pure click handling (no dragEnd and !wasMoved jiggliny any more) to the PlotBoilerplate.\n * @modified 2020-12-11 Added the `removeAll(boolean)` function.\n * @modified 2020-12-17 Added the `CircleSector` drawable.\n * @modified 2021-01-04 Avoiding multiple redraw call on adding multiple Drawables (array).\n * @modified 2021-01-08 Added param `draw:DraLib<void>` to the methods `drawVertices`, `drawGrid` and `drawSelectPolygon`.\n * @modified 2021-01-08 Added the customizable `drawAll(...)` function.\n * @modified 2021-01-09 Added the `drawDrawable(...)` function.\n * @modified 2021-01-10 Added the `eventCatcher` element (used to track mouse events on SVGs).\n * @modified 2021-01-26 Fixed SVG resizing.\n * @modified 2021-01-26 Replaced the old SVGBuilder by the new `drawutilssvg` library.\n * @modified 2021-02-08 Fixed a lot of es2015 compatibility issues.\n * @modified 2021-02-18 Adding `adjustOffset(boolean)` function.\n * @modified 2021-03-01 Updated the `PlotBoilerplate.draw(...)` function: ellipses are now rotate-able.\n * @modified 2021-03-03 Added the `VEllipseSector` drawable.\n * @modified 2021-03-29 Clearing `currentClassName` and `currentId` after drawing each drawable.\n * @modified 2021-04-25 Extending `remove` to accept arrays of drawables.\n * @modified 2021-11-16 Adding the `PBText` drawable.\n * @modified 2022-08-01 Added `title` to the params.\n * @modified 2022-10-25 Added the `origin` to the default draw config.\n * @modified 2022-11-06 Adding an XML declaration to the SVG export routine.\n * @modified 2022-11-23 Added the `drawRaster` (default=true) option to the config/drawconfig.\n * @modified 2023-02-04 Fixed a bug in the `drawDrawable` function; fill's current classname was not set.\n * @modified 2023-02-10 Fixing an issue of the `style.position` setting when `fitToParent=true` from `absolute` to `static` (default).\n * @modified 2023-02-10 Cleaning up most type errors in the main class (mostly null checks).\n * @modified 2023-02-10 Adding `enableZoom` and `enablePan` (both default true) to have the option to disable these functions.\n * @modified 2023-09-29 Adding proper dicionary key and value types to the params of `PlotBoilerplate.utils.safeMergeByKeys` (was `object` before).\n * @modified 2024-07-08 Adding `PlotBoilerplate.getGUI()` to retrieve the GUI instance.\n * @modified 2024-08-25 Extending main class `PlotBoilerplate` optional param `isBackdropFiltersEnabled`.\n * @modified 2024-12-02 Adding the `triggerRedraw` to the `removeAll` method.\n * @modified 2025-05-07 Changing the return type of `removeVertex` from `void` to `boolean`.\n * @modified 2025-05-07 Handling content changes now with `contentChangeListeners`.\n * @modified 2025-05-07 Added `PlogBoilerplate.addContentChangeListener` and `.removeContentChangeListener`.\n * @modified 2025-05-07 Moving full vectors now by default when vector point a is moved.\n * @modified 2025-05-20 Applying `lineWith` parameter in the draw routine for vectors (had been missing).\n * @modified 2026-03-13 Changed visibility of `setZoom` and `setOffset` to public. There was no good reason to have the private.\n *\n * @version 1.21.2\n *\n * @file PlotBoilerplate\n * @fileoverview The main class.\n * @public\n **/\nvar __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\nvar _a;\nimport AlloyFinger from \"alloyfinger-typescript\";\nimport { drawutils } from \"./draw\";\nimport { drawutilsgl } from \"./drawgl\";\nimport { drawutilssvg } from \"./drawutilssvg\";\nimport { BezierPath } from \"./BezierPath\";\nimport { Bounds } from \"./Bounds\";\nimport { Circle } from \"./Circle\";\nimport { CircleSector } from \"./CircleSector\";\nimport { Grid } from \"./Grid\";\nimport { KeyHandler } from \"./KeyHandler\";\nimport { Line } from \"./Line\";\nimport { MouseHandler } from \"./MouseHandler\";\nimport { PBImage } from \"./PBImage\";\nimport { Polygon } from \"./Polygon\";\nimport { Triangle } from \"./Triangle\";\nimport { VEllipse } from \"./VEllipse\";\nimport { VEllipseSector } from \"./VEllipseSector\";\nimport { Vector } from \"./Vector\";\nimport { Vertex } from \"./Vertex\";\nimport { VertexAttr } from \"./VertexAttr\";\nimport { PBText } from \"./PBText\";\n/**\n * @classdesc The main class of the PlotBoilerplate.\n *\n * @requires Vertex\n * @requires Line\n * @requires Vector\n * @requires Polygon\n * @requires PBImage\n * @requires VEllipse\n * @requires Circle\n * @requires MouseHandler\n * @requires KeyHandler\n * @requires VertexAttr\n * @requires CubicBezierCurve\n * @requires BezierPath\n * @requires Drawable\n * @requires DrawConfig\n * @requires IHooks\n * @requires PBParams\n * @requires Triangle\n * @requires drawutils\n * @requires drawutilsgl\n * @requires SVGSerializable\n * @requires XYCoords\n * @requires XYDimension\n */\nexport class PlotBoilerplate {\n /**\n * The constructor.\n *\n * @constructor\n * @name PlotBoilerplate\n * @public\n * @param {object} config={} - The configuration.\n * @param {HTMLCanvasElement} config.canvas - Your canvas element in the DOM (required).\n * @param {boolean=} [config.fullSize=true] - If set to true the canvas will gain full window size.\n * @param {boolean=} [config.fitToParent=true] - If set to true the canvas will gain the size of its parent container (overrides fullSize).\n * @param {number=} [config.scaleX=1.0] - The initial x-zoom. Default is 1.0.\n * @param {number=} [config.scaleY=1.0] - The initial y-zoom. Default is 1.0.\n * @param {number=} [config.offsetX=1.0] - The initial x-offset. Default is 0.0. Note that autoAdjustOffset=true overrides these values.\n * @param {number=} [config.offsetY=1.0] - The initial y-offset. Default is 0.0. Note that autoAdjustOffset=true overrides these values.\n * @param {boolean=} [config.rasterGrid=true] - If set to true the background grid will be drawn rastered.\n * @param {boolean=} [config.rasterScaleX=1.0] - Define the default horizontal raster scale (default=1.0).\n * @param {boolean=} [config.rasterScaleY=1.0] - Define the default vertical raster scale (default=1.0).\n * @param {number=} [config.rasterAdjustFactor=1.0] - The exponential limit for wrapping down the grid. (2.0 means: halve the grid each 2.0*n zoom step).\n * @param {boolean=} [config.drawOrigin=false] - Draw a crosshair at (0,0).\n * @param {boolean=} [config.autoAdjustOffset=true] - When set to true then the origin of the XY plane will\n * be re-adjusted automatically (see the params\n * offsetAdjust{X,Y}Percent for more).\n * @param {number=} [config.offsetAdjustXPercent=50] - The x-fallback position for the origin after\n * resizing the canvas.\n * @param {number=} [config.offsetAdjustYPercent=50] - The y-fallback position for the origin after\n * resizing the canvas.\n * @param {number=} [config.defaultCanvasWidth=1024] - The canvas size fallback (width) if no automatic resizing\n * is switched on.\n * @param {number=} [config.defaultCanvasHeight=768] - The canvas size fallback (height) if no automatic resizing\n * is switched on.\n * @param {number=} [config.canvasWidthFactor=1.0] - Scaling factor (width) upon the canvas size.\n * In combination with cssScale{X,Y} this can be used to obtain\n * sub pixel resolutions for retina displays.\n * @param {number=} [config.canvasHeightFactor=1.0] - Scaling factor (height) upon the canvas size.\n * In combination with cssScale{X,Y} this can be used to obtain\n * sub pixel resolutions for retina displays.\n * @param {number=} [config.cssScaleX=1.0] - Visually resize the canvas (horizontally) using CSS transforms (scale).\n * @param {number=} [config.cssScaleY=1.0] - Visually resize the canvas (vertically) using CSS transforms (scale).\n * @param {boolan=} [config.cssUniformScale=true] - CSS scale x and y obtaining aspect ratio.\n * @param {boolean=} [config.autoDetectRetina=true] - When set to true (default) the canvas will try to use the display's pixel ratio.\n * @param {string=} [config.backgroundColor=#ffffff] - The backround color.\n * @param {boolean=} [config.redrawOnResize=true] - Switch auto-redrawing on resize on/off (some applications\n * might want to prevent automatic redrawing to avoid data loss from the draw buffer).\n * @param {boolean=} [config.drawBezierHandleLines=true] - Indicates if Bézier curve handles should be drawn (used for\n * editors, no required in pure visualizations).\n * @param {boolean=} [config.drawBezierHandlePoints=true] - Indicates if Bézier curve handle points should be drawn.\n * @param {function=} [config.preClear=null] - A callback function that will be triggered just before the\n * draw function clears the canvas (before anything else was drawn).\n * @param {function=} [config.preDraw=null] - A callback function that will be triggered just before the draw\n * function starts.\n * @param {function=} [config.postDraw=null] - A callback function that will be triggered right after the drawing\n * process finished.\n * @param {boolean=} [config.enableMouse=true] - Indicates if the application should handle mouse events for you.\n * @param {boolean=} [config.enableTouch=true] - Indicates if the application should handle touch events for you.\n * @param {boolean=} [config.enableKeys=true] - Indicates if the application should handle key events for you.\n * @param {boolean=} [config.enableMouseWheel=true] - Indicates if the application should handle mouse wheel events for you.\n * @param {boolean=} [config.enablePan=true] - (default true) Set to false if you want to disable panning completely.\n * @param {boolean=} [config.enableZoom=true] - (default true) Set to false if you want to disable zooming completely.\n * @param {boolean=} [config.enableGL=false] - Indicates if the application should use the experimental WebGL features (not recommended).\n * @param {boolean=} [config.enableSVGExport=true] - Indicates if the SVG export should be enabled (default is true).\n * Note that changes from the postDraw hook might not be visible in the export.\n * @param {string=} [config.title=null] - Specify any hover tile here. It will be attached as a `title` attribute to the most elevated element.\n */\n constructor(config, drawConfig) {\n var _b, _c;\n /**\n * A list of content change listeners.\n */\n this.contentChangeListeners = [];\n /**\n * A discrete timestamp to identify single render cycles.\n * Note that using system time milliseconds is not a safe way to identify render frames, as on modern powerful machines\n * multiple frames might be rendered within each millisecond.\n * @member {number}\n * @memberof plotboilerplate\n * @instance\n * @private\n */\n this.renderTime = 0;\n /**\n * A storage variable for retrieving the GUI instance once it was created.\n */\n this._gui = null;\n // This should be in some static block ...\n VertexAttr.model = {\n bezierAutoAdjust: false,\n renderTime: 0,\n selectable: true,\n isSelected: false,\n draggable: true,\n visible: true\n };\n if (typeof config.canvas === \"undefined\") {\n throw \"No canvas specified.\";\n }\n /**\n * A global config that's attached to the dat.gui control interface.\n *\n * @member {Object}\n * @memberof PlotBoilerplate\n * @instance\n */\n const f = PlotBoilerplate.utils.fetch;\n this.config = {\n canvas: config.canvas,\n fullSize: f.val(config, \"fullSize\", true),\n fitToParent: f.bool(config, \"fitToParent\", true),\n scaleX: f.num(config, \"scaleX\", 1.0),\n scaleY: f.num(config, \"scaleY\", 1.0),\n offsetX: f.num(config, \"offsetX\", 0.0),\n offsetY: f.num(config, \"offsetY\", 0.0),\n rasterGrid: f.bool(config, \"rasterGrid\", true),\n drawRaster: f.bool(config, \"drawRaster\", true),\n rasterScaleX: f.num(config, \"rasterScaleX\", 1.0),\n rasterScaleY: f.num(config, \"rasterScaleY\", 1.0),\n rasterAdjustFactor: f.num(config, \"rasterAdjustdFactror\", 2.0),\n drawOrigin: f.bool(config, \"drawOrigin\", false),\n autoAdjustOffset: f.val(config, \"autoAdjustOffset\", true),\n offsetAdjustXPercent: f.num(config, \"offsetAdjustXPercent\", 50),\n offsetAdjustYPercent: f.num(config, \"offsetAdjustYPercent\", 50),\n backgroundColor: config.backgroundColor || \"#ffffff\",\n redrawOnResize: f.bool(config, \"redrawOnResize\", true),\n defaultCanvasWidth: f.num(config, \"defaultCanvasWidth\", PlotBoilerplate.DEFAULT_CANVAS_WIDTH),\n defaultCanvasHeight: f.num(config, \"defaultCanvasHeight\", PlotBoilerplate.DEFAULT_CANVAS_HEIGHT),\n canvasWidthFactor: f.num(config, \"canvasWidthFactor\", 1.0),\n canvasHeightFactor: f.num(config, \"canvasHeightFactor\", 1.0),\n cssScaleX: f.num(config, \"cssScaleX\", 1.0),\n cssScaleY: f.num(config, \"cssScaleY\", 1.0),\n cssUniformScale: f.bool(config, \"cssUniformScale\", true),\n saveFile: () => {\n _self.hooks.saveFile(_self);\n },\n setToRetina: () => {\n _self._setToRetina();\n },\n autoDetectRetina: f.bool(config, \"autoDetectRetina\", true),\n enableSVGExport: f.bool(config, \"enableSVGExport\", true),\n // Listeners/observers\n preClear: f.func(config, \"preClear\", null),\n preDraw: f.func(config, \"preDraw\", null),\n postDraw: f.func(config, \"postDraw\", null),\n // Interaction\n enableMouse: f.bool(config, \"enableMouse\", true),\n enableTouch: f.bool(config, \"enableTouch\", true),\n enableKeys: f.bool(config, \"enableKeys\", true),\n enableMouseWheel: f.bool(config, \"enableMouseWheel\", true),\n enableZoom: f.bool(config, \"enableZoom\", true), // default=true\n enablePan: f.bool(config, \"enablePan\", true), // default=true\n // Experimental (and unfinished)\n enableGL: f.bool(config, \"enableGL\", false),\n isBackdropFiltersEnabled: f.bool(config, \"isBackdropFiltersEnabled\", true)\n }; // END confog\n /**\n * Configuration for drawing things.\n *\n * @member {Object}\n * @memberof PlotBoilerplate\n * @instance\n */\n this.drawConfig = {\n drawVertices: true,\n drawBezierHandleLines: f.bool(config, \"drawBezierHandleLines\", true),\n drawBezierHandlePoints: f.bool(config, \"drawBezierHandlePoints\", true),\n drawHandleLines: f.bool(config, \"drawHandleLines\", true),\n drawHandlePoints: f.bool(config, \"drawHandlePoints\", true),\n drawGrid: f.bool(config, \"drawGrid\", true),\n drawRaster: f.bool(config, \"drawRaster\", true),\n bezier: {\n color: \"#00a822\",\n lineWidth: 2,\n handleLine: {\n color: \"rgba(180,180,180,0.5)\",\n lineWidth: 1\n },\n pathVertex: {\n color: \"#B400FF\",\n lineWidth: 1,\n fill: true\n },\n controlVertex: {\n color: \"#B8D438\",\n lineWidth: 1,\n fill: true\n }\n },\n // bezierPath: {\n // color: \"#0022a8\",\n // lineWidth: 1\n // },\n polygon: {\n color: \"#0022a8\",\n lineWidth: 1\n },\n triangle: {\n color: \"#6600ff\",\n lineWidth: 1\n },\n ellipse: {\n color: \"#2222a8\",\n lineWidth: 1\n },\n ellipseSector: {\n color: \"#a822a8\",\n lineWidth: 2\n },\n circle: {\n color: \"#22a8a8\",\n lineWidth: 2\n },\n circleSector: {\n color: \"#2280a8\",\n lineWidth: 1\n },\n vertex: {\n color: \"#a8a8a8\",\n lineWidth: 1\n },\n selectedVertex: {\n color: \"#c08000\",\n lineWidth: 2\n },\n line: {\n color: \"#a844a8\",\n lineWidth: 1\n },\n vector: {\n color: \"#ff44a8\",\n lineWidth: 1\n },\n image: {\n color: \"#a8a8a8\",\n lineWidth: 1\n },\n text: {\n color: \"rgba(192,0,128,0.5)\",\n lineWidth: 1,\n fill: true,\n anchor: true\n },\n origin: {\n color: \"#000000\"\n }\n }; // END drawConfig\n // +---------------------------------------------------------------------------------\n // | Object members.\n // +-------------------------------\n this.grid = new Grid(new Vertex(0, 0), new Vertex(50, 50));\n this.canvasSize = { width: PlotBoilerplate.DEFAULT_CANVAS_WIDTH, height: PlotBoilerplate.DEFAULT_CANVAS_HEIGHT };\n const canvasElement = typeof config.canvas === \"string\" ? document.querySelector(config.canvas) : config.canvas;\n if (typeof canvasElement === \"undefined\") {\n throw `Cannot initialize PlotBoilerplate with a null canvas (element \"${config.canvas} not found).`;\n }\n // Which renderer to use: Canvas2D, WebGL (experimental) or SVG?\n if (canvasElement.tagName.toLowerCase() === \"canvas\") {\n this.canvas = canvasElement;\n this.eventCatcher = this.canvas;\n if (this.config.enableGL && typeof drawutilsgl === \"undefined\") {\n console.warn(`Cannot use webgl. Package was compiled without experimental gl support. Please use plotboilerplate-glsupport.min.js instead.`);\n console.warn(`Disabling GL and falling back to Canvas2D.`);\n this.config.enableGL = false;\n }\n if (this.config.enableGL) {\n // Override the case 'null' here. If GL is not supported, well then nothing works.\n const ctx = this.canvas.getContext(\"webgl\"); // webgl-experimental?\n this.draw = new drawutilsgl(ctx, false);\n // PROBLEM: same instance of fill and draw when using WebGL.\n // Shader program cannot be duplicated on the same context.\n this.fill = this.draw.copyInstance(true);\n console.warn(\"Initialized with experimental mode enableGL=true. Note that this is not yet fully implemented.\");\n }\n else {\n // Override the case 'null' here. If context creation is not supported, well then nothing works.\n const ctx = this.canvas.getContext(\"2d\");\n this.draw = new drawutils(ctx, false);\n this.fill = new drawutils(ctx, true);\n }\n }\n else if (canvasElement.tagName.toLowerCase() === \"svg\") {\n if (typeof drawutilssvg === \"undefined\")\n throw `The svg draw library is not yet integrated part of PlotBoilerplate. Please include ./src/js/utils/helpers/drawutils.svg into your document.`;\n this.canvas = canvasElement;\n this.draw = new drawutilssvg(this.canvas, new Vertex(), // offset\n new Vertex(), // scale\n this.canvasSize, false, // fillShapes=false\n this.drawConfig, false // isSecondary=false\n );\n this.fill = this.draw.copyInstance(true); // fillShapes=true\n if (this.canvas.parentElement) {\n this.eventCatcher = document.createElement(\"div\");\n this.eventCatcher.style.position = \"absolute\";\n this.eventCatcher.style.left = \"0\";\n this.eventCatcher.style.top = \"0\";\n this.eventCatcher.style.cursor = \"pointer\";\n this.canvas.parentElement.style.position = \"relative\";\n this.canvas.parentElement.appendChild(this.eventCatcher);\n }\n else {\n this.eventCatcher = document.body;\n }\n }\n else {\n throw \"Element is neither a canvas nor an svg element.\";\n }\n // At this point the event cacher element is deinfed and located at highest elevation.\n // Set `title` attribut?\n if (config.title) {\n this.eventCatcher.setAttribute(\"title\", config.title);\n }\n this.draw.scale.set((_b = this.config.scaleX) !== null && _b !== void 0 ? _b : 1.0, this.config.scaleY);\n this.fill.scale.set((_c = this.config.scaleX) !== null && _c !== void 0 ? _c : 1.0, this.config.scaleY);\n this.vertices = [];\n this.selectPolygon = null;\n this.draggedElements = [];\n this.drawables = [];\n this.console = console;\n this.hooks = {\n // This is changable from the outside\n saveFile: PlotBoilerplate._saveFile\n };\n var _self = this;\n globalThis.addEventListener(\"resize\", () => _self.resizeCanvas());\n this.resizeCanvas();\n if (config.autoDetectRetina) {\n this._setToRetina();\n }\n this.installInputListeners();\n // Apply the configured CSS scale.\n this.updateCSSscale();\n // Init\n this.redraw();\n // Gain focus\n this.canvas.focus();\n } // END constructor\n /**\n * This function opens a save-as file dialog and – once an output file is\n * selected – stores the current canvas contents as an SVG image.\n *\n * It is the default hook for saving files and can be overwritten.\n *\n * @method _saveFile\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n * @private\n **/\n static _saveFile(pb) {\n // Create fake SVG node\n const svgNode = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n // Draw everything to fake node.\n var tosvgDraw = new drawutilssvg(svgNode, pb.draw.offset, pb.draw.scale, pb.canvasSize, false, // fillShapes=false\n pb.drawConfig);\n var tosvgFill = tosvgDraw.copyInstance(true); // fillShapes=true\n tosvgDraw.beginDrawCycle(0);\n tosvgFill.beginDrawCycle(0);\n if (pb.config.preClear) {\n pb.config.preClear();\n }\n tosvgDraw.clear(pb.config.backgroundColor || \"white\");\n if (pb.config.preDraw) {\n pb.config.preDraw(tosvgDraw, tosvgFill);\n }\n pb.drawAll(0, tosvgDraw, tosvgFill);\n pb.drawVertices(0, tosvgDraw);\n if (pb.config.postDraw)\n pb.config.postDraw(tosvgDraw, tosvgFill);\n tosvgDraw.endDrawCycle(0);\n tosvgFill.endDrawCycle(0);\n // Full support in all browsers \\o/\n // https://caniuse.com/xml-serializer\n var serializer = new XMLSerializer();\n var svgCode = serializer.serializeToString(svgNode);\n // Add: '<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' ?\n var blob = new Blob(['<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' + svgCode], { type: \"image/svg;charset=utf-8\" });\n // See documentation for FileSaver.js for usage.\n // https://github.com/eligrey/FileSaver.js\n if (typeof globalThis[\"saveAs\"] !== \"function\") {\n throw \"Cannot save file; did you load the ./utils/savefile helper function and the eligrey/SaveFile library?\";\n }\n var _saveAs = globalThis[\"saveAs\"];\n _saveAs(blob, \"plotboilerplate.svg\");\n }\n /**\n * This function sets the canvas resolution to factor 2.0 (or the preferred pixel ratio of your device) for retina displays.\n * Please not that in non-GL mode this might result in very slow rendering as the canvas buffer size may increase.\n *\n * @method _setToRetina\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n * @private\n **/\n _setToRetina() {\n this.config.autoDetectRetina = true;\n const pixelRatio = globalThis.devicePixelRatio || 1;\n this.config.cssScaleX = this.config.cssScaleY = 1.0 / pixelRatio;\n this.config.canvasWidthFactor = this.config.canvasHeightFactor = pixelRatio;\n this.resizeCanvas();\n this.updateCSSscale();\n }\n /**\n * Set the current zoom and draw offset to fit the given bounds.\n *\n * This method currently restores the aspect zoom ratio.\n *\n **/\n fitToView(bounds) {\n const canvasCenter = new Vertex(this.canvasSize.width / 2.0, this.canvasSize.height / 2.0);\n const canvasRatio = this.canvasSize.width / this.canvasSize.height;\n const ratio = bounds.width / bounds.height;\n // Find the new draw offset\n const center = new Vertex(bounds.max.x - bounds.width / 2.0, bounds.max.y - bounds.height / 2.0)\n .inv()\n .addXY(this.canvasSize.width / 2.0, this.canvasSize.height / 2.0);\n this.setOffset(center);\n if (canvasRatio < ratio) {\n const newUniformZoom = this.canvasSize.width / bounds.width;\n this.setZoom(newUniformZoom, newUniformZoom, canvasCenter);\n }\n else {\n const newUniformZoom = this.canvasSize.height / bounds.height;\n this.setZoom(newUniformZoom, newUniformZoom, canvasCenter);\n }\n this.redraw();\n }\n /**\n * Set the console for this instance.\n *\n * @method setConsole\n * @param {Console} con - The new console object (default is globalThis.console).\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n setConsole(con) {\n this.console = con;\n }\n /**\n * Update the CSS scale for the canvas depending onf the cssScale{X,Y} settings.<br>\n * <br>\n * This function is usually only used inernally.\n *\n * @method updateCSSscale\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n * @private\n **/\n updateCSSscale() {\n var _b, _c, _d, _e;\n if (this.config.cssUniformScale) {\n PlotBoilerplate.utils.setCSSscale(this.canvas, (_b = this.config.cssScaleX) !== null && _b !== void 0 ? _b : 1.0, (_c = this.config.cssScaleX) !== null && _c !== void 0 ? _c : 1.0);\n }\n else {\n PlotBoilerplate.utils.setCSSscale(this.canvas, (_d = this.config.cssScaleX) !== null && _d !== void 0 ? _d : 1.0, (_e = this.config.cssScaleY) !== null && _e !== void 0 ? _e : 1.0);\n }\n }\n /**\n * Adds a new content change listener to this instance. Adding duplicates is not possible.\n *\n * @param {PBContentChangeListener} listener - The listenre to add.\n * @method addContentChangeListener\n * @instance\n * @memberof PlotBoilerplate\n * @returns {void}\n */\n addContentChangeListener(listener) {\n for (var i in this.contentChangeListeners) {\n if (this.contentChangeListeners[i] === listener) {\n return;\n }\n }\n this.contentChangeListeners.push(listener);\n }\n /**\n * Removes an existing content change listener from this instance.\n *\n * @param {PBContentChangeListener} listener - The listenre to add.\n * @method removeContentChangeListener\n * @instance\n * @memberof PlotBoilerplate\n * @returns {void}\n */\n removeContentChangeListener(listener) {\n for (var i = 0; i < this.contentChangeListeners.length; i++) {\n if (this.contentChangeListeners[i] === listener) {\n this.contentChangeListeners.splice(i, 1);\n return;\n }\n }\n }\n _fireContentChanged(addedDrawables, removedDrawables) {\n for (var i in this.contentChangeListeners) {\n const listener = this.contentChangeListeners[i];\n if (listener && typeof listener === \"function\") {\n listener({\n type: addedDrawables.length > 0 ? \"DRAWABLES_ADDED\" : \"DRAWABLES_REMOVED\",\n addedDrawables: addedDrawables,\n removedDrawables: removedDrawables\n });\n }\n }\n }\n /**\n * Add a drawable object.<br>\n * <br>\n * This must be either:<br>\n * <pre>\n * * a Vertex\n * * a Line\n * * a Vector\n * * a VEllipse\n * * a VEllipseSector\n * * a Circle\n * * a Polygon\n * * a Triangle\n * * a BezierPath\n * * a BPImage\n * </pre>\n *\n * @param {Drawable|Drawable[]} drawable - The drawable (of one of the allowed class instance) to add.\n * @param {boolean} [redraw=true] - If true the function will trigger redraw after the drawable(s) was/were added.\n * @method add\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n add(drawable, redraw, doNotFireEvent) {\n if (Array.isArray(drawable)) {\n const arr = drawable;\n for (var i = 0; i < arr.length; i++) {\n this.add(arr[i], false, doNotFireEvent);\n }\n // !doNotFireEvent && this._fireContentChanged(arr, []);\n }\n else {\n const addedDrawables = [drawable];\n if (drawable instanceof Vertex) {\n this.drawables.push(drawable);\n this.vertices.push(drawable);\n }\n else if (drawable instanceof Line) {\n // Add some lines\n this.drawables.push(drawable);\n this.vertices.push(drawable.a);\n this.vertices.push(drawable.b);\n addedDrawables.push(drawable.a, drawable.b);\n }\n else if (drawable instanceof Vector) {\n this.drawables.push(drawable);\n this.vertices.push(drawable.a);\n this.vertices.push(drawable.b);\n addedDrawables.push(drawable.a, drawable.b);\n drawable.a.listeners.addDragListener((event) => {\n drawable.b.add(event.params.dragAmount);\n });\n }\n else if (drawable instanceof VEllipse) {\n this.vertices.push(drawable.center);\n this.vertices.push(drawable.axis);\n addedDrawables.push(drawable.center, drawable.axis);\n this.drawables.push(drawable);\n drawable.center.listeners.addDragListener((event) => {\n drawable.axis.add(event.params.dragAmount);\n });\n }\n else if (drawable instanceof VEllipseSector) {\n this.vertices.push(drawable.ellipse.center);\n this.vertices.push(drawable.ellipse.axis);\n addedDrawables.push(drawable.ellipse.center, drawable.ellipse.axis);\n this.drawables.push(drawable);\n drawable.ellipse.center.listeners.addDragListener((event) => {\n drawable.ellipse.axis.add(event.params.dragAmount);\n });\n }\n else if (drawable instanceof Circle) {\n this.vertices.push(drawable.center);\n addedDrawables.push(drawable.center);\n this.drawables.push(drawable);\n }\n else if (drawable instanceof CircleSector) {\n this.vertices.push(drawable.circle.center);\n addedDrawables.push(drawable.circle.center);\n this.drawables.push(drawable);\n }\n else if (drawable instanceof Polygon) {\n this.drawables.push(drawable);\n for (var i = 0; i < drawable.vertices.length; i++) {\n this.vertices.push(drawable.vertices[i]);\n addedDrawables.push(drawable.vertices[i]);\n }\n }\n else if (drawable instanceof Triangle) {\n this.drawables.push(drawable);\n this.vertices.push(drawable.a);\n this.vertices.push(drawable.b);\n this.vertices.push(drawable.c);\n addedDrawables.push(drawable.a, drawable.b, drawable.c);\n }\n else if (drawable instanceof BezierPath) {\n this.drawables.push(drawable);\n const bezierPath = drawable;\n for (var i = 0; i < bezierPath.bezierCurves.length; i++) {\n if (!drawable.adjustCircular && i == 0) {\n this.vertices.push(bezierPath.bezierCurves[i].startPoint);\n addedDrawables.push(bezierPath.bezierCurves[i].startPoint);\n }\n this.vertices.push(bezierPath.bezierCurves[i].endPoint);\n this.vertices.push(bezierPath.bezierCurves[i].startControlPoint);\n this.vertices.push(bezierPath.bezierCurves[i].endControlPoint);\n addedDrawables.push(bezierPath.bezierCurves[i].endPoint, bezierPath.bezierCurves[i].startControlPoint, bezierPath.bezierCurves[i].endControlPoint);\n bezierPath.bezierCurves[i].startControlPoint.attr.selectable = false;\n bezierPath.bezierCurves[i].endControlPoint.attr.selectable = false;\n }\n PlotBoilerplate.utils.enableBezierPathAutoAdjust(drawable);\n }\n else if (drawable instanceof PBImage) {\n this.vertices.push(drawable.upperLeft);\n this.vertices.push(drawable.lowerRight);\n addedDrawables.push(drawable.upperLeft, drawable.lowerRight);\n this.drawables.push(drawable);\n // Todo: think about a IDragEvent interface\n drawable.upperLeft.listeners.addDragListener((e) => {\n drawable.lowerRight.add(e.params.dragAmount);\n });\n drawable.lowerRight.attr.selectable = false;\n }\n else if (drawable instanceof PBText) {\n this.vertices.push(drawable.anchor);\n addedDrawables.push(drawable.anchor);\n this.drawables.push(drawable);\n drawable.anchor.attr.selectable = false;\n }\n else {\n throw \"Cannot add drawable of unrecognized type: \" + typeof drawable + \".\";\n }\n !doNotFireEvent && this._fireContentChanged(addedDrawables, []);\n }\n // This is a workaround for backwards compatibility when the 'redraw' param was not yet present.\n if (redraw || typeof redraw == \"undefined\") {\n this.redraw();\n }\n }\n /**\n * Remove a drawable object.<br>\n * <br>\n * This must be either:<br>\n * <pre>\n * * a Vertex\n * * a Line\n * * a Vector\n * * a VEllipse\n * * a Circle\n * * a Polygon\n * * a BezierPath\n * * a BPImage\n * * a Triangle\n * </pre>\n *\n * @param {Drawable|Array<Drawable>} drawable - The drawable (of one of the allowed class instance) to remove.\n * @param {boolean} [redraw=false]\n * @param {removeWidth}\n * @method remove\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n remove(drawable, redraw, removeWithVertices, doNotFireEvent) {\n if (Array.isArray(drawable)) {\n const removedDrawables = [];\n for (var i = 0; i < drawable.length; i++) {\n if (this.remove(drawable[i], false, removeWithVertices, true)) {\n removedDrawables.push(drawable[i]);\n }\n }\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], removedDrawables);\n return removedDrawables.length > 0;\n }\n if (drawable instanceof Vertex) {\n const wasRemoved = this.removeVertex(drawable, false, false);\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], [drawable]);\n return wasRemoved;\n }\n let wasRemoved = false;\n const removedDrawables = [];\n for (var i = 0; i < this.drawables.length; i++) {\n if (this.drawables[i] === drawable || this.drawables[i].uid === drawable.uid) {\n this.drawables.splice(i, 1);\n removedDrawables.push(drawable);\n if (removeWithVertices) {\n // Check if some listeners need to be removed\n if (drawable instanceof Line) {\n // Add some lines\n this.removeVertex(drawable.a, false, true);\n this.removeVertex(drawable.b, false, true);\n removedDrawables.push(drawable.a, drawable.b);\n }\n else if (drawable instanceof Vector) {\n this.removeVertex(drawable.a, false, true);\n this.removeVertex(drawable.b, false, true);\n removedDrawables.push(drawable.a, drawable.b);\n }\n else if (drawable instanceof VEllipse) {\n this.removeVertex(drawable.center, false, true);\n this.removeVertex(drawable.axis, false, true);\n removedDrawables.push(drawable.center, drawable.axis);\n }\n else if (drawable instanceof VEllipseSector) {\n this.removeVertex(drawable.ellipse.center, false, true);\n this.removeVertex(drawable.ellipse.axis, false, true);\n removedDrawables.push(drawable.ellipse.center, drawable.ellipse.axis);\n }\n else if (drawable instanceof Circle) {\n this.removeVertex(drawable.center, false, true);\n }\n else if (drawable instanceof CircleSector) {\n this.removeVertex(drawable.circle.center, false, true);\n removedDrawables.push(drawable.circle.center);\n }\n else if (drawable instanceof Polygon) {\n // for( var i in drawable.vertices )\n for (var i = 0; i < drawable.vertices.length; i++) {\n this.removeVertex(drawable.vertices[i], false, true);\n removedDrawables.push(drawable.vertices[i]);\n }\n }\n else if (drawable instanceof Triangle) {\n this.removeVertex(drawable.a, false, true);\n this.removeVertex(drawable.b, false, true);\n this.removeVertex(drawable.c, false, true);\n removedDrawables.push(drawable.a, drawable.b, drawable.c);\n }\n else if (drawable instanceof BezierPath) {\n for (var i = 0; i < drawable.bezierCurves.length; i++) {\n this.removeVertex(drawable.bezierCurves[i].startPoint, false, true);\n this.removeVertex(drawable.bezierCurves[i].startControlPoint, false, true);\n this.removeVertex(drawable.bezierCurves[i].endControlPoint, false, true);\n removedDrawables.push(drawable.bezierCurves[i].startPoint, drawable.bezierCurves[i].startControlPoint, drawable.bezierCurves[i].endControlPoint);\n if (i + 1 == drawable.bezierCurves.length) {\n this.removeVertex(drawable.bezierCurves[i].endPoint, false, true);\n removedDrawables.push(drawable.bezierCurves[i].endPoint);\n }\n }\n }\n else if (drawable instanceof PBImage) {\n this.removeVertex(drawable.upperLeft, false, true);\n this.removeVertex(drawable.lowerRight, false, true);\n removedDrawables.push(drawable.upperLeft, drawable.lowerRight);\n }\n else if (drawable instanceof PBText) {\n this.removeVertex(drawable.anchor, false, true);\n removedDrawables.push(drawable.anchor);\n }\n } // END removeWithVertices\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], removedDrawables);\n wasRemoved = true;\n } // END if\n } // END for\n return wasRemoved;\n }\n /**\n * Remove a vertex from the vertex list.<br>\n *\n * @param {Vertex} vert - The vertex to remove.\n * @param {boolean} [redraw=false]\n * @method removeVertex\n * @instance\n * @memberof PlotBoilerplate\n * @return {boolean}\n **/\n removeVertex(vert, redraw, doNotFireEvent) {\n for (var i = 0; i < this.vertices.length; i++) {\n if (this.vertices[i] === vert) {\n this.vertices.splice(i, 1);\n if (redraw) {\n this.redraw();\n }\n !doNotFireEvent && this._fireContentChanged([], [vert]);\n return true;\n }\n }\n return false;\n }\n /**\n * Remove all elements.\n *\n * If you want to keep the vertices, pass `true`.\n *\n * @method removeAll\n * @param {boolean=false} keepVertices\n * @param {boolean=true} triggerRedraw - By default this method triggers the redraw routine; passing `false` will suppress redrawing.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n */\n removeAll(keepVertices, triggerRedraw) {\n let removedDrawables = this.drawables;\n this.drawables = [];\n if (!Boolean(keepVertices)) {\n removedDrawables = removedDrawables.concat(this.vertices);\n this.vertices = [];\n }\n if (triggerRedraw || typeof triggerRedraw === \"undefined\") {\n this.redraw();\n }\n removedDrawables.length > 0 && this._fireContentChanged([], removedDrawables);\n }\n /**\n * Find the vertex near the given position.\n *\n * The position is the absolute vertex position, not the x-y-coordinates on the canvas.\n *\n * @param {XYCoords} position - The position of the vertex to search for.\n * @param {number} pixelTolerance - A radius around the position to include into the search.\n * Note that the tolerance will be scaled up/down when zoomed.\n * @return The vertex near the given position or undefined if none was found there.\n **/\n getVertexNear(pixelPosition, pixelTolerance) {\n var _b, _c;\n const p = this.locatePointNear(this.transformMousePosition(pixelPosition.x, pixelPosition.y), pixelTolerance / Math.min((_b = this.config.cssScaleX) !== null && _b !== void 0 ? _b : 1.0, (_c = this.config.cssScaleY) !== null && _c !== void 0 ? _c : 1.0));\n if (p && p.typeName == \"vertex\") {\n return this.vertices[p.vindex];\n }\n return undefined;\n }\n /**\n * Draw the grid with the current config settings.<br>\n *\n * This function is usually only used internally.\n *\n * @method drawGrid\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawGrid(draw) {\n if (typeof draw === \"undefined\") {\n draw = this.draw;\n }\n const gScale = {\n x: (Grid.utils.mapRasterScale(this.config.rasterAdjustFactor, this.draw.scale.x) * this.config.rasterScaleX) /\n this.config.cssScaleX,\n y: (Grid.utils.mapRasterScale(this.config.rasterAdjustFactor, this.draw.scale.y) * this.config.rasterScaleY) /\n this.config.cssScaleY\n };\n var gSize = { width: this.grid.size.x * gScale.x, height: this.grid.size.y * gScale.y };\n var cs = { width: this.canvasSize.width / 2, height: this.canvasSize.height / 2 };\n var offset = this.draw.offset.clone().inv();\n // console.log( \"drawGrid\", gScale, gSize, cs, offset );\n offset.x =\n ((Math.round(offset.x + cs.width) / Math.round(gSize.width)) * gSize.width) / this.draw.scale.x +\n (((this.draw.offset.x - cs.width) / this.draw.scale.x) % gSize.width);\n offset.y =\n ((Math.round(offset.y + cs.height) / Math.round(gSize.height)) * gSize.height) / this.draw.scale.y +\n (((this.draw.offset.y - cs.height) / this.draw.scale.x) % gSize.height);\n if (this.drawConfig.drawGrid) {\n draw.setCurrentClassName(null);\n if (this.config.rasterGrid) {\n // TODO: move config member to drawConfig\n draw.setCurrentId(\"raster\");\n draw.raster(offset, this.canvasSize.width / this.draw.scale.x, this.canvasSize.height / this.draw.scale.y, gSize.width, gSize.height, \"rgba(0,128,255,0.125)\");\n }\n else {\n draw.setCurrentId(\"grid\");\n draw.grid(offset, this.canvasSize.width / this.draw.scale.x, this.canvasSize.height / this.draw.scale.y, gSize.width, gSize.height, \"rgba(0,128,255,0.095)\");\n }\n }\n }\n /**\n * Draw the origin with the current config settings.<br>\n *\n * This function is usually only used internally.\n *\n * @method drawOrigin\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawOrigin(draw) {\n // Add a crosshair to mark the origin\n draw.setCurrentId(\"origin\");\n draw.crosshair({ x: 0, y: 0 }, 10, this.drawConfig.origin.color);\n }\n /**\n * This is just a tiny helper function to determine the render color of vertices.\n **/\n _handleColor(h, color) {\n return h.attr.isSelected ? this.drawConfig.selectedVertex.color : h.attr.draggable ? color : \"rgba(128,128,128,0.5)\";\n }\n /**\n * Draw all drawables.\n *\n * This function is usually only used internally.\n *\n * @method drawDrawables\n * @param {number} renderTime - The current render time. It will be used to distinct\n * already draw vertices from non-draw-yet vertices.\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @param {DrawLib} fill - The drawing library to use to fill areas.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawDrawables(renderTime, draw, fill) {\n for (var i in this.drawables) {\n var d = this.drawables[i];\n this.draw.setCurrentId(d.uid);\n this.fill.setCurrentId(d.uid);\n this.draw.setCurrentClassName(d.className);\n this.fill.setCurrentClassName(d.className);\n this.drawDrawable(d, renderTime, draw, fill);\n }\n }\n /**\n * Draw the given drawable.\n *\n * This function is usually only used internally.\n *\n * @method drawDrawable\n * @param {Drawable} d - The drawable to draw.\n * @param {number} renderTime - The current render time. It will be used to distinct\n * already draw vertices from non-draw-yet vertices.\n * @param {DrawLib} draw - The drawing library to use to draw lines.\n * @param {DrawLib} fill - The drawing library to use to fill areas.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawDrawable(d, renderTime, draw, fill) {\n if (d instanceof BezierPath) {\n var curveIndex = 0;\n for (var c in d.bezierCurves) {\n // Restore these settings again in each loop (will be overwritten)\n this.draw.setCurrentId(`${d.uid}-${curveIndex}`);\n this.fill.setCurrentId(`${d.uid}-${curveIndex}`);\n this.draw.setCurrentClassName(d.className);\n this.fill.setCurrentClassName(d.className);\n draw.cubicBezier(d.bezierCurves[c].startPoint, d.bezierCurves[c].endPoint, d.bezierCurves[c].startControlPoint, d.bezierCurves[c].endControlPoint, this.drawConfig.bezier.color, this.drawConfig.bezier.lineWidth);\n if (this.drawConfig.drawBezierHandlePoints && this.drawConfig.drawHandlePoints) {\n if (d.bezierCurves[c].startPoint.attr.visible) {\n const df = this.drawConfig.bezier.pathVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h0`);\n df.setCurrentClassName(`${d.className}-start-handle`);\n if (d.bezierCurves[c].startPoint.attr.bezierAutoAdjust) {\n df.squareHandle(d.bezierCurves[c].startPoint, 5, this._handleColor(d.bezierCurves[c].startPoint, this.drawConfig.bezier.pathVertex.color));\n }\n else {\n df.diamondHandle(d.bezierCurves[c].startPoint, 7, this._handleColor(d.bezierCurves[c].startPoint, this.drawConfig.bezier.pathVertex.color));\n }\n }\n d.bezierCurves[c].startPoint.attr.renderTime = renderTime;\n if (d.bezierCurves[c].endPoint.attr.visible) {\n const df = this.drawConfig.bezier.pathVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h0`);\n df.setCurrentClassName(`${d.className}-start-handle`);\n if (d.bezierCurves[c].endPoint.attr.bezierAutoAdjust) {\n df.squareHandle(d.bezierCurves[c].endPoint, 5, this._handleColor(d.bezierCurves[c].endPoint, this.drawConfig.bezier.pathVertex.color));\n }\n else {\n df.diamondHandle(d.bezierCurves[c].endPoint, 7, this._handleColor(d.bezierCurves[c].endPoint, this.drawConfig.bezier.pathVertex.color));\n }\n }\n if (d.bezierCurves[c].startControlPoint.attr.visible) {\n const df = this.drawConfig.bezier.controlVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h2`);\n df.setCurrentClassName(`${d.className}-start-control-handle`);\n df.circleHandle(d.bezierCurves[c].startControlPoint, 3, this._handleColor(d.bezierCurves[c].startControlPoint, this.drawConfig.bezier.controlVertex.color));\n }\n if (d.bezierCurves[c].endControlPoint.attr.visible) {\n const df = this.drawConfig.bezier.controlVertex.fill ? fill : draw;\n df.setCurrentId(`${d.uid}_h3`);\n df.setCurrentClassName(`${d.className}-end-control-handle`);\n df.circleHandle(d.bezierCurves[c].endControlPoint, 3, this._handleColor(d.bezierCurves[c].endControlPoint, this.drawConfig.bezier.controlVertex.color));\n }\n d.bezierCurves[c].startPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].startControlPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endControlPoint.attr.renderTime = renderTime;\n }\n else {\n d.bezierCurves[c].startPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].startControlPoint.attr.renderTime = renderTime;\n d.bezierCurves[c].endControlPoint.attr.renderTime = renderTime;\n }\n if (this.drawConfig.drawBezierHandleLines && this.drawConfig.drawHandleLines) {\n draw.setCurrentId(`${d.uid}_l0`);\n draw.setCurrentClassName(`${d.className}-start-line`);\n draw.handleLine(d.bezierCurves[c].startPoint, d.bezierCurves[c].startControlPoint);\n draw.setCurrentId(`${d.uid}_l1`);\n draw.setCurrentClassName(`${d.className}-end-line`);\n draw.handleLine(d.bezierCurves[c].endPoint, d.bezierCurves[c].endControlPoint);\n }\n curveIndex++;\n } // END for\n }\n else if (d instanceof Polygon) {\n draw.polygon(d, this.drawConfig.polygon.color, this.drawConfig.polygon.lineWidth);\n if (!this.drawConfig.drawHandlePoints) {\n for (var i in d.vertices) {\n d.vertices[i].attr.renderTime = renderTime;\n }\n }\n }\n else if (d instanceof Triangle) {\n draw.polyline([d.a, d.b, d.c], false, this.drawConfig.triangle.color, this.drawConfig.triangle.lineWidth);\n if (!this.drawConfig.drawHandlePoints) {\n d.a.attr.renderTime = d.b.attr.renderTime = d.c.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof VEllipse) {\n if (this.drawConfig.drawHandleLines) {\n draw.setCurrentId(`${d.uid}_e0`);\n draw.setCurrentClassName(`${d.className}-v-line`);\n draw.handleLine(d.center.clone().add(0, d.signedRadiusV()).rotate(d.rotation, d.center), d.axis); // , \"#c8c8c8\");\n draw.setCurrentId(`${d.uid}_e1`);\n draw.setCurrentClassName(`${d.className}-h-line`);\n draw.handleLine(d.center.clone().add(d.signedRadiusH(), 0).rotate(d.rotation, d.center), d.axis); // , \"#c8c8c8\");\n }\n draw.setCurrentId(d.uid);\n draw.setCurrentClassName(`${d.className}`);\n draw.ellipse(d.center, \n // Math.abs(d.axis.x-d.center.x), Math.abs(d.axis.y-d.center.y),\n d.radiusH(), d.radiusV(), this.drawConfig.ellipse.color, this.drawConfig.ellipse.lineWidth, d.rotation);\n if (!this.drawConfig.drawHandlePoints) {\n d.center.attr.renderTime = renderTime;\n d.axis.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof VEllipseSector) {\n draw.setCurrentId(d.uid);\n draw.setCurrentClassName(`${d.className}`);\n const data = 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 });\n draw.path(data, this.drawConfig.ellipseSector.color, this.drawConfig.ellipseSector.lineWidth);\n }\n else if (d instanceof Circle) {\n draw.circle(d.center, d.radius, this.drawConfig.circle.color, this.drawConfig.circle.lineWidth);\n }\n else if (d instanceof CircleSector) {\n draw.circleArc(d.circle.center, d.circle.radius, d.startAngle, d.endAngle, this.drawConfig.circleSector.color, this.drawConfig.circleSector.lineWidth);\n }\n else if (d instanceof Vertex) {\n if (this.drawConfig.drawVertices && (!d.attr.selectable || !d.attr.draggable) && d.attr.visible) {\n // Draw as special point (grey)\n draw.circleHandle(d, 7, this.drawConfig.vertex.color);\n d.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof Line) {\n draw.line(d.a, d.b, this.drawConfig.line.color, this.drawConfig.line.lineWidth);\n if (!this.drawConfig.drawHandlePoints || !d.a.attr.selectable)\n d.a.attr.renderTime = renderTime;\n if (!this.drawConfig.drawHandlePoints || !d.b.attr.selectable)\n d.b.attr.renderTime = renderTime;\n }\n else if (d instanceof Vector) {\n draw.arrow(d.a, d.b, this.drawConfig.vector.color, this.drawConfig.vector.lineWidth);\n if (this.drawConfig.drawHandlePoints && d.b.attr.selectable && d.b.attr.visible) {\n draw.setCurrentId(`${d.uid}_h0`);\n draw.setCurrentClassName(`${d.className}-handle`);\n draw.circleHandle(d.b, 3, \"#a8a8a8\");\n }\n else {\n d.b.attr.renderTime = renderTime;\n }\n if (!this.drawConfig.drawHandlePoints || !d.a.attr.selectable)\n d.a.attr.renderTime = renderTime;\n if (!this.drawConfig.drawHandlePoints || !d.b.attr.selectable)\n d.b.attr.renderTime = renderTime;\n }\n else if (d instanceof PBImage) {\n if (this.drawConfig.drawHandleLines) {\n draw.setCurrentId(`${d.uid}_l0`);\n draw.setCurrentClassName(`${d.className}-line`);\n draw.line(d.upperLeft, d.lowerRight, this.drawConfig.image.color, this.drawConfig.image.lineWidth);\n }\n fill.setCurrentId(d.uid);\n fill.image(d.image, d.upperLeft, d.lowerRight.clone().sub(d.upperLeft));\n if (this.drawConfig.drawHandlePoints) {\n draw.setCurrentId(`${d.uid}_h0`);\n draw.setCurrentClassName(`${d.className}-lower-right`);\n draw.circleHandle(d.lowerRight, 3, this.drawConfig.image.color);\n d.lowerRight.attr.renderTime = renderTime;\n }\n }\n else if (d instanceof PBText) {\n fill.setCurrentId(d.uid);\n fill.text(d.text, d.anchor.x, d.anchor.y, d);\n if (this.drawConfig.text.anchor) {\n draw.setCurrentId(`${d.uid}_a0`);\n draw.setCurrentClassName(`${d.className}-anchor`);\n (this.drawConfig.text.fill ? fill : draw).point(d.anchor, this.drawConfig.text.color);\n }\n d.anchor.attr.renderTime = renderTime;\n }\n else {\n console.error(\"Cannot draw object. Unknown class.\");\n }\n draw.setCurrentClassName(null);\n draw.setCurrentId(null);\n fill.setCurrentClassName(null);\n fill.setCurrentId(null);\n }\n /**\n * Draw the select-polygon (if there is one).\n *\n * This function is usually only used internally.\n *\n * @method drawSelectPolygon\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawSelectPolygon(draw) {\n // Draw select polygon?\n if (this.selectPolygon != null && this.selectPolygon.vertices.length > 0) {\n draw.setCurrentId(this.selectPolygon.uid);\n draw.polygon(this.selectPolygon, \"#888888\");\n draw.crosshair(this.selectPolygon.vertices[0], 3, \"#008888\");\n }\n }\n /**\n * Draw all vertices that were not yet drawn with the given render time.<br>\n * <br>\n * This function is usually only used internally.\n *\n * @method drawVertices\n * @private\n * @param {number} renderTime - The current render time. It is used to distinct\n * already draw vertices from non-draw-yet vertices.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawVertices(renderTime, draw) {\n // Draw all vertices as small squares if they were not already drawn by other objects\n for (var i in this.vertices) {\n if (this.drawConfig.drawVertices && this.vertices[i].attr.renderTime != renderTime && this.vertices[i].attr.visible) {\n draw.setCurrentId(this.vertices[i].uid);\n draw.squareHandle(this.vertices[i], 5, this._handleColor(this.vertices[i], \"rgb(0,128,192)\"));\n this.vertices[i].attr.renderTime = renderTime;\n }\n }\n }\n /**\n * Trigger redrawing of all objects.<br>\n * <br>\n * Usually this function is automatically called when objects change.\n *\n * @method redraw\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n redraw() {\n const renderTime = this.renderTime++;\n // Tell the drawing library that a new drawing cycle begins (required for the GL lib).\n this.draw.beginDrawCycle(renderTime);\n this.fill.beginDrawCycle(renderTime);\n if (this.config.preClear)\n this.config.preClear();\n this.clear();\n if (this.config.preDraw)\n this.config.preDraw(this.draw, this.fill);\n this.drawAll(renderTime, this.draw, this.fill);\n if (this.config.postDraw)\n this.config.postDraw(this.draw, this.fill);\n this.draw.endDrawCycle(renderTime);\n this.fill.endDrawCycle(renderTime);\n }\n /**\n * Draw all: drawables, grid, select-polygon and vertices.\n *\n * @method drawAll\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n drawAll(renderTime, draw, fill) {\n if (this.config.drawRaster) {\n this.drawGrid(draw);\n }\n if (this.config.drawOrigin) {\n this.drawOrigin(draw);\n }\n this.drawDrawables(renderTime, draw, fill);\n this.drawVertices(renderTime, draw);\n this.drawSelectPolygon(draw);\n // Clear IDs and classnames (postDraw hook might draw somthing and the do not want\n // to interfered with that).\n draw.setCurrentId(null);\n draw.setCurrentClassName(null);\n } // END redraw\n /**\n * This function clears the canvas with the configured background color.<br>\n * <br>\n * This function is usually only used internally.\n *\n * @method clear\n * @private\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n clear() {\n // Note that elements might have an alpha channel. Clear the scene first.\n this.draw.clear(this.config.backgroundColor || \"white\");\n }\n /**\n * Clear the selection.<br>\n * <br>\n * This function is usually only used internally.\n *\n * @method clearSelection\n * @private\n * @param {boolean=} [redraw=false] - Indicates if the redraw function should be triggered.\n * @instance\n * @memberof PlotBoilerplate\n * @return {PlotBoilerplate} this\n **/\n clearSelection(redraw) {\n for (var i in this.vertices)\n this.vertices[i].attr.isSelected = false;\n if (redraw)\n this.redraw();\n return this;\n }\n /**\n * Get the current view port.\n *\n * @method viewport\n * @instance\n * @memberof PlotBoilerplate\n * @return {Bounds} The current viewport.\n **/\n viewport() {\n var _b, _c;\n return new Bounds(this.transformMousePosition(0, 0), this.transformMousePosition(this.canvasSize.width * ((_b = this.config.cssScaleX) !== null && _b !== void 0 ? _b : 1.0), this.canvasSize.height * ((_c = this.config.cssScaleY) !== null && _c !== void 0 ? _c : 1.0)));\n }\n /**\n * Trigger the saveFile.hook.\n *\n * @method saveFile\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n saveFile() {\n this.hooks.saveFile(this);\n }\n /**\n * Internal helper function used to get 'float' properties from elements.\n * Used to determine border withs and paddings that were defined using CSS.\n */\n // TODO: this was moved to the DOM utils\n getFProp(elem, propName) {\n return parseFloat(globalThis.getComputedStyle(elem, null).getPropertyValue(propName));\n }\n /**\n * Get the available inner space of the given container.\n *\n * Size minus padding minus border.\n **/\n // TODO: this was moved to the DOM utils\n getAvailableContainerSpace() {\n const _self = this;\n const container = _self.canvas.parentNode; // Element | Document | DocumentFragment;\n _self.canvas.style.display = \"none\";\n var padding = this.getFProp(container, \"padding\") || 0, border = this.getFProp(_self.canvas, \"border-width\") || 0, pl = this.getFProp(container, \"padding-left\") || padding, pr = this.getFProp(container, \"padding-right\") || padding, pt = this.getFProp(container, \"padding-top\") || padding, pb = this.getFProp(container, \"padding-bottom\") || padding, bl = this.getFProp(_self.canvas, \"border-left-width\") || border, br = this.getFProp(_self.canvas, \"border-right-width\") || border, bt = this.getFProp(_self.canvas, \"border-top-width\") || border, bb = this.getFProp(_self.canvas, \"border-bottom-width\") || border;\n var w = container.clientWidth;\n var h = container.clientHeight;\n _self.canvas.style.display = \"block\";\n return { width: w - pl - pr - bl - br, height: h - pt - pb - bt - bb };\n }\n /**\n * This function resizes the canvas to the required settings (toggles fullscreen).<br>\n * <br>\n * This function is usually only used internally but feel free to call it if resizing required.\n *\n * @method resizeCanvas\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n resizeCanvas() {\n var _b, _c, _d, _e, _f, _g;\n const _self = this;\n const _setSize = (w, h) => {\n var _b, _c;\n w *= (_b = _self.config.canvasWidthFactor) !== null && _b !== void 0 ? _b : 1.0;\n h *= (_c = _self.config.canvasHeightFactor) !== null && _c !== void 0 ? _c : 1.0;\n _self.canvasSize.width = w;\n _self.canvasSize.height = h;\n if (_self.canvas instanceof HTMLCanvasElement) {\n _self.canvas.width = w;\n _self.canvas.height = h;\n }\n else if (_self.canvas instanceof SVGElement) {\n this.canvas.setAttribute(\"viewBox\", `0 0 ${w} ${h}`);\n this.canvas.setAttribute(\"width\", `${w}`);\n this.canvas.setAttribute(\"height\", `${h}`);\n this.draw.setSize(_self.canvasSize); // No need to set size to this.fill (instance copy)\n this.eventCatcher.style.width = `${w}px`;\n this.eventCatcher.style.height = `${h}px`;\n }\n else {\n console.error(\"Error: cannot resize canvas element because it seems neither be a HTMLCanvasElement nor an SVGElement.\");\n }\n if (_self.config.autoAdjustOffset) {\n // _self.draw.offset.x = _self.fill.offset.x = _self.config.offsetX = w*(_self.config.offsetAdjustXPercent/100);\n // _self.draw.offset.y = _self.fill.offset.y = _self.config.offsetY = h*(_self.config.offsetAdjustYPercent/100);\n _self.adjustOffset(false);\n }\n };\n if (_self.config.fullSize && !_self.config.fitToParent) {\n // Set editor size\n var width = globalThis.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;\n var height = globalThis.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;\n _self.canvas.style.position = \"absolute\";\n _self.canvas.style.width = ((_b = _self.config.canvasWidthFactor) !== null && _b !== void 0 ? _b : 1.0) * width + \"px\";\n _self.canvas.style.height = ((_c = _self.config.canvasWidthFactor) !== null && _c !== void 0 ? _c : 1.0) * height + \"px\";\n _self.canvas.style.top = \"0px\";\n _self.canvas.style.left = \"0px\";\n _setSize(width, height);\n }\n else if (_self.config.fitToParent) {\n // Set editor size\n _self.canvas.style.position = \"static\";\n const space = this.getAvailableContainerSpace();\n _self.canvas.style.width = ((_d = _self.config.canvasWidthFactor) !== null && _d !== void 0 ? _d : 1.0) * space.width + \"px\";\n _self.canvas.style.height = ((_e = _self.config.canvasHeightFactor) !== null && _e !== void 0 ? _e : 1.0) * space.height + \"px\";\n _self.canvas.style.top = \"\";\n _self.canvas.style.left = \"\";\n _setSize(space.width, space.height);\n }\n else {\n _self.canvas.style.width = \"\";\n _self.canvas.style.height = \"\";\n _setSize((_f = _self.config.defaultCanvasWidth) !== null && _f !== void 0 ? _f : 1024, (_g = _self.config.defaultCanvasHeight) !== null && _g !== void 0 ? _g : 768);\n }\n if (_self.config.redrawOnResize)\n _self.redraw();\n }\n /**\n * Add all vertices inside the polygon to the current selection.<br>\n *\n * @method selectVerticesInPolygon\n * @param {Polygon} polygon - The polygonal selection area.\n * @instance\n * @memberof PlotBoilerplate\n * @return {void}\n **/\n selectVerticesInPolygon(polygon) {\n for (var i in this.vertices) {\n if (this.vertices[i].attr.selectable && polygon.containsVert(this.vertices[i]))\n this.vertices[i].attr.isSelected = true;\n }\n }\n /**\n * (Helper) Locates the point (index) at the passed position. Using an internal tolerance of 7 pixels.\n *\n * The result is an object { type : 'bpath', pindex, cindex, pid }\n *\n * Returns false if no point is near the passed position.\n *\n * @method locatePointNear\n * @param {Vertex} point - The polygonal selection area.\n * @param {number=} [tolerance=7] - The tolerance to use identtifying vertices.\n * @private\n * @return {IDraggable} Or false if none found.\n **/\n locatePointNear(point, tolerance) {\n const _self = this;\n if (typeof tolerance == \"undefined\")\n tolerance = 7;\n // Apply the zoom (the tolerant area should not shrink or grow when zooming)\n tolerance /= _self.draw.scale.x;\n // Search in vertices\n for (var vindex = 0; vindex < _self.vertices.length; vindex++) {\n var vert = _self.vertices[vindex];\n if ((vert.attr.draggable || vert.attr.selectable) && vert.distance(point) < tolerance) {\n // { type : 'vertex', vindex : vindex };\n return new PlotBoilerplate.Draggable(vert, PlotBoilerplate.Draggable.VERTEX).setVIndex(vindex);\n }\n }\n return null;\n }\n /**\n * Handle left-click event.<br>\n *\n * @method handleClick\n * @param {number} x - The click X position on the canvas.\n * @param {number} y - The click Y position on the canvas.\n * @private\n * @return {void}\n **/\n handleClick(e) {\n const _self = this;\n var point = this.locatePointNear(_self.transformMousePosition(e.params.pos.x, e.params.pos.y), PlotBoilerplate.DEFAULT_CLICK_TOLERANCE / Math.min(_self.config.cssScaleX || 1.0, _self.config.cssScaleY || 1.0));\n if (point) {\n _self.vertices[point.vindex].listeners.fireClickEvent(e);\n if (this.keyHandler && this.keyHandler.isDown(\"shift\")) {\n if (point.typeName == \"bpath\") {\n let vert = _self.paths[point.pindex].bezierCurves[point.cindex].getPointByID(point.pid);\n if (vert.attr.selectable)\n vert.attr.isSelected = !vert.attr.isSelected;\n }\n else if (point.typeName == \"vertex\") {\n let vert = _self.vertices[point.vindex];\n if (vert.attr.selectable)\n vert.attr.isSelected = !vert.attr.isSelected;\n }\n _self.redraw();\n }\n else if (this.keyHandler && this.keyHandler.isDown(\"y\")) {\n _self.vertices[point.vindex].attr.bezierAutoAdjust = !_self.vertices[point.vindex].attr.bezierAutoAdjust;\n _self.redraw();\n }\n }\n else if (_self.selectPolygon != null) {\n const vert = _self.transformMousePosition(e.params.pos.x, e.params.pos.y);\n _self.selectPolygon.vertices.push(new Vertex(vert.x, vert.y));\n _self.redraw();\n }\n }\n /**\n * Transforms the given x-y-(mouse-)point to coordinates respecting the view offset\n * and the zoom settings.\n *\n * @method transformMousePosition\n * @param {number} x - The x position relative to the canvas.\n * @param {number} y - The y position relative to the canvas.\n * @instance\n * @memberof PlotBoilerplate\n * @return {XYCoords} A simple object <pre>{ x : Number, y : Number }</pre> with the transformed coordinates.\n **/\n transformMousePosition(x, y) {\n return {\n x: (x / this.config.cssScaleX - this.config.offsetX) / this.config.scaleX,\n y: (y / this.config.cssScaleY - this.config.offsetY) / this.config.scaleY\n };\n }\n /**\n * Revert a transformed mouse position back to canvas coordinates.\n *\n * This is the inverse function of `transformMousePosition`.\n *\n * @method revertMousePosition\n * @param {number} x - The x component of the position to revert.\n * @param {number} y - The y component of the position to revert.\n * @instance\n * @memberof PlotBoilerplate\n * @return {XYCoords} The canvas coordinates for the given position.\n **/\n revertMousePosition(x, y) {\n return { x: x / this.config.cssScaleX + this.config.offsetX, y: y / this.config.cssScaleY + this.config.offsetY };\n }\n /**\n * Determine if any elements are currently being dragged (on mouse move or touch move).\n *\n * @method getDraggedElementCount\n * @instance\n * @memberof PlotBoilerplate\n * @return {number} The number of elements that are currently being dragged.\n **/\n getDraggedElementCount() {\n return this.draggedElements.length;\n }\n /**\n * (Helper) The mouse-down handler.\n *\n * It selects vertices for dragging.\n *\n * @method mouseDownHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseDownHandler(e) {\n const _self = this;\n if (e.button != 0)\n return; // Only react on left mouse or touch events\n var draggablePoint = _self.locatePointNear(_self.transformMousePosition(e.params.pos.x, e.params.pos.y), PlotBoilerplate.DEFAULT_CLICK_TOLERANCE / Math.min(_self.config.cssScaleX, _self.config.cssScaleY));\n if (!draggablePoint)\n return;\n // Drag all selected elements?\n if (draggablePoint.typeName == \"vertex\" && _self.vertices[draggablePoint.vindex].attr.isSelected) {\n // Multi drag\n // for( var i in _self.vertices ) {\n for (var i = 0; i < _self.vertices.length; i++) {\n if (_self.vertices[i].attr.isSelected) {\n _self.draggedElements.push(new PlotBoilerplate.Draggable(_self.vertices[i], PlotBoilerplate.Draggable.VERTEX).setVIndex(i));\n _self.vertices[i].listeners.fireDragStartEvent(e);\n }\n }\n }\n else {\n // Single drag\n if (!_self.vertices[draggablePoint.vindex].attr.draggable)\n return;\n _self.draggedElements.push(draggablePoint);\n if (draggablePoint.typeName == \"bpath\")\n _self.paths[draggablePoint.pindex].bezierCurves[draggablePoint.cindex]\n .getPointByID(draggablePoint.pid)\n .listeners.fireDragStartEvent(e);\n else if (draggablePoint.typeName == \"vertex\")\n _self.vertices[draggablePoint.vindex].listeners.fireDragStartEvent(e);\n }\n _self.redraw();\n }\n /**\n * The mouse-drag handler.\n *\n * It moves selected elements around or performs the panning if the ctrl-key if\n * hold down.\n *\n * @method mouseDragHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseDragHandler(e) {\n const _self = this;\n const oldDragAmount = { x: e.params.dragAmount.x, y: e.params.dragAmount.y };\n e.params.dragAmount.x /= _self.config.cssScaleX;\n e.params.dragAmount.y /= _self.config.cssScaleY;\n // Important note to: this.keyHandler.isDown('ctrl')\n // We should not use this for any input.\n // Reason: most browsers use [Ctrl]+[t] to create new browser tabs.\n // If so, the key-up event for [Ctrl] will be fired in the _new tab_,\n // not this one. So this tab will never receive any [Ctrl-down] events\n // until next keypress; the implication is, that [Ctrl] would still\n // considered to be pressed which is not true.\n if (this.keyHandler && (this.keyHandler.isDown(\"alt\") || this.keyHandler.isDown(\"spacebar\"))) {\n if (!this.config.enablePan) {\n return;\n }\n _self.setOffset(_self.draw.offset.clone().add(e.params.dragAmount));\n _self.redraw();\n }\n else {\n // Convert drag amount by scaling\n // Warning: this possibly invalidates the dragEvent for other listeners!\n // Rethink the solution when other features are added.\n e.params.dragAmount.x /= _self.draw.scale.x;\n e.params.dragAmount.y /= _self.draw.scale.y;\n for (var i in _self.draggedElements) {\n var p = _self.draggedElements[i];\n if (p.typeName == \"bpath\") {\n _self.paths[p.pindex].moveCurvePoint(p.cindex, p.pid, new Vertex(e.params.dragAmount.x, e.params.dragAmount.y));\n _self.paths[p.pindex].bezierCurves[p.cindex].getPointByID(p.pid).listeners.fireDragEvent(e);\n }\n else if (p.typeName == \"vertex\") {\n if (!_self.vertices[p.vindex].attr.draggable)\n continue;\n _self.vertices[p.vindex].add(e.params.dragAmount);\n _self.vertices[p.vindex].listeners.fireDragEvent(e);\n }\n }\n }\n // Restore old event values!\n e.params.dragAmount.x = oldDragAmount.x;\n e.params.dragAmount.y = oldDragAmount.y;\n _self.redraw();\n }\n /**\n * The mouse-up handler.\n *\n * It clears the dragging-selection.\n *\n * @method mouseUpHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseUpHandler(e) {\n const _self = this;\n if (e.button != 0)\n return; // Only react on left mouse;\n if (!e.params.wasDragged) {\n _self.handleClick(e); // e.params.pos.x, e.params.pos.y );\n }\n for (var i in _self.draggedElements) {\n var p = _self.draggedElements[i];\n if (p.typeName == \"bpath\") {\n _self.paths[p.pindex].bezierCurves[p.cindex].getPointByID(p.pid).listeners.fireDragEndEvent(e);\n }\n else if (p.typeName == \"vertex\") {\n _self.vertices[p.vindex].listeners.fireDragEndEvent(e);\n }\n }\n _self.draggedElements = [];\n _self.redraw();\n }\n /**\n * The mouse-wheel handler.\n *\n * It performs the zooming.\n *\n * @method mouseWheelHandler.\n * @param {XMouseEvent} e - The event to handle\n * @private\n * @return {void}\n **/\n mouseWheelHandler(e) {\n if (!this.config.enableZoom) {\n return;\n }\n var zoomStep = 1.25; // Make configurable?\n // CHANGED replaced _self by this\n const _self = this;\n const we = e;\n if (we.deltaY < 0) {\n _self.setZoom(_self.config.scaleX * zoomStep, _self.config.scaleY * zoomStep, new Vertex(e.params.pos.x, e.params.pos.y));\n }\n else if (we.deltaY > 0) {\n _self.setZoom(_self.config.scaleX / zoomStep, _self.config.scaleY / zoomStep, new Vertex(e.params.pos.x, e.params.pos.y));\n }\n e.preventDefault();\n _self.redraw();\n }\n /**\n * Re-adjust the configured offset depending on the current canvas size and zoom (scaleX and scaleY).\n *\n * @method adjustOffset\n * @param {boolean=false} redraw - [optional] If set the canvas will redraw with the new offset (default=false).\n * @return {void}\n **/\n adjustOffset(redraw) {\n this.draw.offset.x =\n this.fill.offset.x =\n this.config.offsetX =\n this.canvasSize.width * (this.config.offsetAdjustXPercent / 100);\n this.draw.offset.y =\n this.fill.offset.y =\n this.config.offsetY =\n this.canvasSize.height * (this.config.offsetAdjustYPercent / 100);\n if (redraw) {\n this.redraw();\n }\n }\n /**\n * Set the new draw offset.\n *\n * Note: the function will not trigger any redraws.\n *\n * @param {Vertex} newOffset - The new draw offset to use.\n **/\n setOffset(newOffset) {\n this.draw.offset.set(newOffset);\n this.fill.offset.set(newOffset);\n this.config.offsetX = newOffset.x;\n this.config.offsetY = newOffset.y;\n }\n /**\n * Set a new zoom value (and re-adjust the draw offset).\n *\n * Note: the function will not trigger any redraws.\n *\n * @param {number} zoomFactorX - The new horizontal zoom value.\n * @param {number} zoomFactorY - The new vertical zoom value.\n * @param {Vertex} interactionPos - The position of mouse/touch interaction.\n **/\n setZoom(zoomFactorX, zoomFactorY, interactionPos) {\n let oldPos = this.transformMousePosition(interactionPos.x, interactionPos.y);\n this.draw.scale.x = this.fill.scale.x = this.config.scaleX = Math.max(zoomFactorX, 0.01);\n this.draw.scale.y = this.fill.scale.y = this.config.scaleY = Math.max(zoomFactorY, 0.01);\n let newPos = this.transformMousePosition(interactionPos.x, interactionPos.y);\n let newOffsetX = this.draw.offset.x + (newPos.x - oldPos.x) * this.draw.scale.x;\n let newOffsetY = this.draw.offset.y + (newPos.y - oldPos.y) * this.draw.scale.y;\n this.setOffset({ x: newOffsetX, y: newOffsetY });\n }\n installInputListeners() {\n var _self = this;\n if (this.config.enableMouse) {\n // Install a mouse handler on the canvas.\n new MouseHandler(this.eventCatcher ? this.eventCatcher : this.canvas)\n .down((e) => {\n _self.mouseDownHandler(e);\n })\n .drag((e) => {\n _self.mouseDragHandler(e);\n })\n .up((e) => {\n _self.mouseUpHandler(e);\n });\n }\n else {\n _self.console.log(\"Mouse interaction disabled.\");\n }\n if (this.config.enableMouseWheel) {\n // Install a mouse handler on the canvas.\n new MouseHandler(this.eventCatcher ? this.eventCatcher : this.canvas).wheel((e) => {\n _self.mouseWheelHandler(e);\n });\n }\n else {\n _self.console.log(\"Mouse wheel interaction disabled.\");\n }\n if (this.config.enableTouch) {\n // Install a touch handler on the canvas.\n const relPos = (pos) => {\n const bounds = _self.canvas.getBoundingClientRect();\n return { x: pos.x - bounds.left, y: pos.y - bounds.top };\n };\n // Make PB work together with both, AlloyFinger as a esm module or a commonjs function.\n if (typeof globalThis[\"AlloyFinger\"] === \"function\" ||\n typeof globalThis[\"createAlloyFinger\"] === \"function\") {\n try {\n var touchMovePos = null;\n var touchDownPos = null;\n var draggedElement = null;\n var multiTouchStartScale = null;\n const clearTouch = () => {\n touchMovePos = null;\n touchDownPos = null;\n draggedElement = null;\n multiTouchStartScale = null;\n _self.draggedElements = [];\n };\n const afProps = {\n // touchStart: (evt: TouchEvent) => {\n touchStart: (evt) => {\n if (evt.touches.length == 1) {\n touchMovePos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));\n touchDownPos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));\n draggedElement = _self.locatePointNear(_self.transformMousePosition(touchMovePos.x, touchMovePos.y), PlotBoilerplate.DEFAULT_TOUCH_TOLERANCE / Math.min(_self.config.cssScaleX, _self.config.cssScaleY));\n if (draggedElement && draggedElement.typeName == \"vertex\") {\n var draggingVertex = _self.vertices[draggedElement.vindex];\n var fakeEvent = {\n params: {\n isTouchEvent: true,\n dragAmount: { x: 0, y: 0 },\n wasDragged: false,\n mouseDownPos: touchDownPos.clone(),\n mouseDragPos: touchDownPos.clone(),\n vertex: draggingVertex\n }\n };\n _self.draggedElements = [draggedElement];\n draggingVertex.listeners.fireDragStartEvent(fakeEvent);\n }\n }\n },\n touchMove: (evt) => {\n if (evt.touches.length == 1 && draggedElement) {\n evt.preventDefault();\n evt.stopPropagation();\n if (!touchDownPos || !touchMovePos) {\n return;\n }\n var rel = relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY });\n var trans = _self.transformMousePosition(rel.x, rel.y);\n var diff = new Vertex(_self.transformMousePosition(touchMovePos.x, touchMovePos.y)).difference(trans);\n if (draggedElement.typeName == \"vertex\") {\n if (!_self.vertices[draggedElement.vindex].attr.draggable)\n return;\n _self.vertices[draggedElement.vindex].add(diff);\n var draggingVertex = _self.vertices[draggedElement.vindex];\n var fakeEvent = {\n isTouchEvent: true,\n params: {\n dragAmount: diff.clone(),\n wasDragged: true,\n mouseDownPos: touchDownPos.clone(),\n mouseDragPos: touchDownPos.clone().add(diff),\n vertex: draggingVertex\n }\n };\n draggingVertex.listeners.fireDragEvent(fakeEvent);\n _self.redraw();\n }\n touchMovePos = new Vertex(rel);\n }\n else if (evt.touches.length == 2) {\n if (!this.config.enablePan) {\n return;\n }\n // If at least two fingers touch and move, then change the draw offset (panning).\n evt.preventDefault();\n evt.stopPropagation();\n _self.setOffset(_self.draw.offset\n .clone()\n .addXY(evt.deltaX, evt.deltaY)); // Apply zoom?\n _self.redraw();\n }\n },\n touchEnd: (evt) => {\n // Note: e.touches.length is 0 here\n if (draggedElement && draggedElement.typeName == \"vertex\") {\n if (!touchDownPos) {\n return;\n }\n var draggingVertex = _self.vertices[draggedElement.vindex];\n var fakeEvent = {\n isTouchEvent: true,\n params: {\n dragAmount: { x: 0, y: 0 },\n wasDragged: false,\n mouseDownPos: touchDownPos.clone(),\n mouseDragPos: touchDownPos.clone(),\n vertex: draggingVertex\n }\n };\n // Check if vertex was moved\n if (touchMovePos && touchDownPos && touchDownPos.distance(touchMovePos) < 0.001) {\n // if( e.touches.length == 1 && diff.x == 0 && diff.y == 0 ) {\n draggingVertex.listeners.fireClickEvent(fakeEvent);\n }\n else {\n draggingVertex.listeners.fireDragEndEvent(fakeEvent);\n }\n }\n clearTouch();\n },\n touchCancel: (evt) => {\n clearTouch();\n },\n multipointStart: (evt) => {\n multiTouchStartScale = _self.draw.scale.clone();\n },\n multipointEnd: (evt) => {\n multiTouchStartScale = null;\n },\n pinch: (evt) => {\n if (!this.config.enableZoom) {\n return;\n }\n const touchItem0 = evt.touches.item(0);\n const touchItem1 = evt.touches.item(1);\n if (!evt.touches || !multiTouchStartScale || !touchItem0 || !touchItem1) {\n return;\n }\n // For pinching there must be at least two touch items\n const fingerA = new Vertex(touchItem0.clientX, touchItem0.clientY);\n const fingerB = new Vertex(touchItem1.clientX, touchItem1.clientY);\n const center = new Line(fingerA, fingerB).vertAt(0.5);\n _self.setZoom(multiTouchStartScale.x * evt.zoom, multiTouchStartScale.y * evt.zoom, center);\n _self.redraw();\n }\n }; // END afProps\n if (window[\"createAlloyFinger\"]) {\n // window[\"createAlloyFinger\"](this.eventCatcher ? this.eventCatcher : this.canvas, afProps);\n const createAlloyFinger = window[\"createAlloyFinger\"];\n createAlloyFinger(this.eventCatcher ? this.eventCatcher : this.canvas, afProps);\n }\n else {\n /* tslint:disable-next-line */\n new AlloyFinger(this.eventCatcher ? this.eventCatcher : this.canvas, afProps);\n }\n }\n catch (e) {\n console.error(\"Failed to initialize AlloyFinger!\");\n console.error(e);\n }\n }\n else if (globalThis[\"Touchy\"] && typeof globalThis[\"Touchy\"] == \"function\") {\n console.error(\"[Deprecation] Found Touchy which is not supported any more. Please use AlloyFinger instead.\");\n // Convert absolute touch positions to relative DOM element position (relative to canvas)\n }\n else {\n console.warn(\"Cannot initialize the touch handler. AlloyFinger is missig. Did you include it?\");\n }\n }\n else {\n _self.console.log(\"Touch interaction disabled.\");\n }\n if (this.config.enableKeys) {\n // Install key handler\n this.keyHandler = new KeyHandler({ trackAll: true })\n .down(\"escape\", function () {\n _self.clearSelection(true);\n })\n .down(\"shift\", function () {\n _self.selectPolygon = new Polygon();\n _self.redraw();\n })\n .up(\"shift\", function () {\n // Find and select vertices in the drawn area\n if (_self.selectPolygon == null)\n return;\n _self.selectVerticesInPolygon(_self.selectPolygon);\n _self.selectPolygon = null;\n _self.redraw();\n });\n } // END IF enableKeys?\n else {\n _self.console.log(\"Keyboard interaction disabled.\");\n }\n }\n /**\n * Creates a control GUI (a dat.gui instance) for this\n * plot boilerplate instance.\n *\n * @method createGUI\n * @instance\n * @memberof PlotBoilerplate\n * @return {dat.gui.GUI}\n **/\n createGUI(props) {\n // This function moved to the helper utils.\n // We do not want to include the whole dat.GUI package.\n const utils = globalThis[\"utils\"];\n // if (globalThis[\"utils\"] && typeof globalThis[\"utils\"].createGUI == \"function\") {\n // return (globalThis[\"utils\" as keyof Object] as any as ({createGUI : (pb:PlotBoilerplate,props:DatGuiProps|undefined)=>GUI })).createGUI(this, props);\n if (utils && typeof utils.createGUI === \"function\") {\n return (this._gui = utils.createGUI(this, props));\n }\n else {\n throw \"Cannot create dat.GUI or lil-gui instance; did you load the ./utils/creategui helper function an the dat.GUI/lil-gui library?\";\n }\n }\n /**\n * Retriebe the GUI once it was created. If the `createGUI` method was not called or failed to create any\n * GUI then null is returned.\n * @returns {GUI | null}\n */\n getGUI() {\n return this._gui;\n }\n} // END class PlotBoilerplate\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_CANVAS_WIDTH = 1024;\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_CANVAS_HEIGHT = 768;\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_CLICK_TOLERANCE = 8;\n/** @constant {number} */\nPlotBoilerplate.DEFAULT_TOUCH_TOLERANCE = 32;\n/**\n * A wrapper class for draggable items (mostly vertices).\n * @private\n **/\nPlotBoilerplate.Draggable = (_a = class {\n constructor(item, typeName) {\n this.item = item;\n this.typeName = typeName;\n }\n isVertex() {\n return this.typeName == PlotBoilerplate.Draggable.VERTEX;\n }\n setVIndex(vindex) {\n this.vindex = vindex;\n return this;\n }\n },\n __setFunctionName(_a, \"Draggable\"),\n _a.VERTEX = \"vertex\",\n _a);\n/**\n * A set of helper functions.\n **/\nPlotBoilerplate.utils = {\n /**\n * Merge the elements in the 'extension' object into the 'base' object based on\n * the keys of 'base'.\n *\n * @param {Object} base\n * @param {Object} extension\n * @return {Object} base extended by the new attributes.\n **/\n safeMergeByKeys: (base, extension) => {\n for (var k in extension) {\n if (!extension.hasOwnProperty(k)) {\n continue;\n }\n if (base.hasOwnProperty(k)) {\n const typ = typeof base[k];\n const extVal = extension[k];\n try {\n if (typ == \"boolean\") {\n if (typeof extVal === \"string\")\n base[k] = Boolean(!!JSON.parse(extVal));\n else\n base[k] = extVal;\n }\n else if (typ == \"number\") {\n if (typeof extVal === \"string\")\n base[k] = Number(JSON.parse(extVal) * 1);\n else\n base[k] = extension[k];\n }\n else if (typ == \"function\" && typeof extVal == \"function\") {\n base[k] = extension[k];\n }\n else {\n // Probably a sting\n base[k] = extension[k];\n }\n }\n catch (e) {\n console.error(\"error in key \", k, extVal, e);\n }\n }\n else {\n base[k] = extension[k];\n }\n }\n return base;\n },\n /*\n __safeMergeByKeys: <KeyType extends string | number | symbol, ValueType extends boolean | number | string | Function>(\n base: Record<KeyType, ValueType>,\n extension: Record<KeyType, string>\n ): Record<KeyType, ValueType> => {\n for (var k in extension) {\n if (!extension.hasOwnProperty(k)) continue;\n if (base.hasOwnProperty(k)) {\n var typ = typeof base[k];\n try {\n if (typ == \"boolean\") base[k] = !!JSON.parse(extension[k]);\n else if (typ == \"number\") base[k] = JSON.parse(extension[k]) * 1;\n else if (typ == \"function\" && typeof extension[k] == \"function\") base[k] = extension[k];\n else base[k] = extension[k];\n } catch (e) {\n console.error(\"error in key \", k, extension[k], e);\n }\n } else {\n base[k] = extension[k];\n }\n }\n return base;\n },\n *()\n\n /**\n * A helper function to scale elements (usually the canvas) using CSS.\n *\n * transform-origin is at (0,0).\n *\n * @param {HTMLElement} element - The DOM element to scale.\n * @param {number} scaleX The - X scale factor.\n * @param {number} scaleY The - Y scale factor.\n * @return {void}\n **/\n setCSSscale: (element, scaleX, scaleY) => {\n // element.style[\"transform-origin\"] = \"0 0\";\n element.style.transformOrigin = \"0 0\";\n if (scaleX == 1.0 && scaleY == 1.0) {\n // element.style.transform = null;\n element.style.removeProperty(\"transform\");\n }\n else\n element.style.transform = \"scale(\" + scaleX + \",\" + scaleY + \")\";\n },\n // A helper for fetching data from objects.\n fetch: {\n /**\n * A helper function to the the object property value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {any} fallback - A default value if the key does not exist.\n **/\n val: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] == \"undefined\")\n return fallback;\n return obj[key];\n },\n /**\n * A helper function to the the object property numeric value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {number} fallback - A default value if the key does not exist.\n * @return {number}\n **/\n num: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] === \"number\")\n return obj[key];\n else {\n try {\n return JSON.parse(obj[key]) * 1;\n }\n catch (e) {\n return fallback;\n }\n }\n },\n /**\n * A helper function to the the object property boolean value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {boolean} fallback - A default value if the key does not exist.\n * @return {boolean}\n **/\n bool: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] == \"boolean\")\n return obj[key];\n else {\n try {\n return !!JSON.parse(obj[key]);\n }\n catch (e) {\n return fallback;\n }\n }\n },\n /**\n * A helper function to the the object property function-value specified by the given key.\n *\n * @param {any} object - The object to get the property's value from. Must not be null.\n * @param {string} key - The key of the object property (the name).\n * @param {function} fallback - A default value if the key does not exist.\n * @return {function}\n **/\n func: (obj, key, fallback) => {\n if (!obj.hasOwnProperty(key))\n return fallback;\n if (typeof obj[key] !== \"function\")\n return fallback;\n return obj[key];\n }\n }, // END fetch\n /**\n * Installs vertex listeners to the path's vertices so that controlpoints\n * move with their path points when dragged.\n *\n * Bézier path points with attr.bezierAutoAdjust==true will have their\n * two control points audo-updated if moved, too (keep path connections smooth).\n *\n * @param {BezierPath} bezierPath - The path to use auto-adjustment for.\n **/\n enableBezierPathAutoAdjust: (bezierPath) => {\n for (var i = 0; i < bezierPath.bezierCurves.length; i++) {\n // This should be wrapped into the BezierPath implementation.\n bezierPath.bezierCurves[i].startPoint.listeners.addDragListener(function (e) {\n var cindex = bezierPath.locateCurveByStartPoint(e.params.vertex);\n bezierPath.bezierCurves[cindex].startPoint.addXY(-e.params.dragAmount.x, -e.params.dragAmount.y);\n bezierPath.moveCurvePoint(cindex * 1, bezierPath.START_POINT, e.params.dragAmount);\n bezierPath.updateArcLengths();\n });\n bezierPath.bezierCurves[i].startControlPoint.listeners.addDragListener(function (e) {\n var cindex = bezierPath.locateCurveByStartControlPoint(e.params.vertex);\n if (!bezierPath.bezierCurves[cindex].startPoint.attr.bezierAutoAdjust)\n return;\n bezierPath.adjustPredecessorControlPoint(cindex * 1, true, // obtain handle length?\n false // update arc lengths\n );\n bezierPath.updateArcLengths();\n });\n bezierPath.bezierCurves[i].endControlPoint.listeners.addDragListener(function (e) {\n var cindex = bezierPath.locateCurveByEndControlPoint(e.params.vertex);\n if (!bezierPath.bezierCurves[cindex % bezierPath.bezierCurves.length].endPoint.attr.bezierAutoAdjust)\n return;\n bezierPath.adjustSuccessorControlPoint(cindex * 1, true, // obtain handle length?\n false // update arc lengths\n );\n bezierPath.updateArcLengths();\n });\n if (i + 1 == bezierPath.bezierCurves.length) {\n // && !bezierPath.adjustCircular ) {\n // Move last control point with the end point (if not circular)\n bezierPath.bezierCurves[bezierPath.bezierCurves.length - 1].endPoint.listeners.addDragListener(function (e) {\n if (!bezierPath.adjustCircular) {\n var cindex = bezierPath.locateCurveByEndPoint(e.params.vertex);\n bezierPath.moveCurvePoint(cindex * 1, bezierPath.END_CONTROL_POINT, new Vertex({ x: e.params.dragAmount.x, y: e.params.dragAmount.y }));\n }\n bezierPath.updateArcLengths();\n });\n }\n } // END for\n }\n}; // END utils\nexport default PlotBoilerplate;\n//# sourceMappingURL=PlotBoilerplate.js.map"],"names":["VertexAttr","constructor","key","this","draggable","selectable","isSelected","visible","model","UIDGenerator","next","current","VertexListeners","vertex","click","drag","dragStart","dragEnd","addClickListener","listener","_addListener","removeClickListener","_removeListener","addDragListener","removeDragListener","addDragStartListener","removeDragStartListener","addDragEndListener","removeDragEndListener","fireClickEvent","e","_fireEvent","fireDragEvent","fireDragStartEvent","fireDragEndEvent","removeAllListeners","_self","listeners","ve","i","params","newListener","push","oldListener","length","splice","Circle","center","radius","className","uid","move","amount","add","containsPoint","point","distance","containsCircle","circle","lineDistance","line","getClosestPoint","vertAt","angle","circleUtils","tangentAt","pointA","Vector","Vertex","perp","getBounds","Bounds","clone","subXY","Math","abs","addXY","circleIntersection","p0","p1","d","a","h","sqrt","p2","scale","x3","x","y","y3","x4","y4","Line","lineIntersection","b","interA","interB","transA","sub","transB","diff","difference","dist","det","distSquared","belowSqrt","sign","lineIntersections","inVectorBoundsOnly","intersectioLine","filter","vert","hasPoint","lineIntersectionTangents","map","closestPoint","destroy","isDestroyed","cos","sin","Triangle","c","calcCircumcircle","fromArray","arr","getArea","utils","signedArea","getCentroid","scaleToCentroid","factor","centroid","bounds","getCircumcircle","isAdjacent","tri","equals","getThirdVertex","vert1","vert2","A","B","C","D","E","F","G","dx","dy","EPSILON","min","max","cx","cy","radius_squared","inCircumcircle","v","min3","max3","Polygon","locateLineIntersecion","intersectionTuple","intersection","polyLine","getEdgeAt","edgeIndex","moveTo","modIndex","toPolygon","determinant","p","pointIsInTriangle","getIncircularTriangle","lineA","lineB","lineC","bisector1","geomutils","nsectAngle","bisector2","circleIntersA","circleIntersB","circleIntersC","getIncircle","getIncenter","toString","p0x","p0y","p1x","p1y","p2x","p2y","px","py","area","s","t","mapAngleTo2PI","new_angle","asin","PI","dist4","x1","y1","x2","y2","pow","dotProduct","vertA","vertB","pA","pB","pC","n","triangle","lineAB","lineAC","insideAngle","clockwise","scaleFactor","result","rotate","wrapMax","wrapMinMax","tuple","NaN","attr","set","setX","setY","invX","invY","amountX","amountY","addX","addY","subX","subY","eqX","eqY","origin","atan2","scaleXY","lerp","target","lerpAbs","u","step","factors","len","ZERO","multiplyScalar","scalar","round","inv","computeFromVertices","precision","toFixed","randomVertex","viewPort","random","buildArrowHead","zA","zB","headlen","scaleX","scaleY","console","warn","vertices","arrayToJSON","JSON","stringify","undefined","Number","VertTuple","factory","setLength","revert","tmp","normalize","newA","v0","v1","denominator","colinear","epsilon","getClosestT","l2","vtutils","dist2","insideBoundsOnly","pointDistance","w","super","inverse","numerator1","numerator2","getOrthogonal","linePoint","startPoint","isNaN","getStartPoint","getEndPoint","getStartTangent","getEndTangent","reverse","intersections","intrsctn","isOpen","addVertex","addVertexAt","index","vertIndex","getVertexAt","getEdges","lines","getInnerAngleAt","p3","isAcute","isAngleAcute","zero","p2mp1","p3mp2","p2mp1_len","p3mp2_len","lengthProduct","acos","containsVert","inside","j","xi","yi","xj","yj","containsVerts","verts","every","containsPolygon","polygon","lineSegment","isClockwise","perimeter","log","getMeanCenter","cur","lineIntersectionTangentsIndices","closestLineIntersection","closestInterSectionIndex","closestLineIntersectionIndex","allIntersections","closestIntersection","MAX_VALUE","curDist","curVert","getInterpolationPolygon","interpolationCount","nextVert","lerpAmount","getEvenDistributionPolygon","pointCount","Error","polygonPoint","stepSize","polygonIndex","nextPolygonPoint","segmentLength","loopMax","curSegmentU","newPoint","elimitateColinearEdges","tolerance","eps","slice","areColinear","vertC","toQuadraticBezierData","qbezier","cc0","cc1","edgeCenter","limit","toQuadraticBezierSVGString","qdata","buffer","join","toCubicBezierData","threshold","cbezier","aCenter","bCenter","a2","b0","toCubicBezierSVGString","toCubicBezierPath","pathdata","BezierPath","total","l","sum","intersectionPoints","width","height","getWidth","getHeight","getScaled","getCenter","newMin","newMax","getMoved","moveAmount","getNorthPoint","getSouthPoint","getWestPoint","getEastPoint","getNorthWestPoint","getNorthEastPoint","getSouthEastPoint","getSouthWestPoint","getMinDimension","getMaxDimension","randomPoint","horizontalSafeArea","verticalSafeArea","absHorizontalSafeArea","absVerticalSafeArea","xMin","xMax","yMin","yMax","computeFromBoundsSet","boundingBoxes","fromDimension","CubicBezierCurve","endPoint","startControlPoint","endControlPoint","START_POINT","START_CONTROL_POINT","END_CONTROL_POINT","END_POINT","curveIntervals","segmentCache","segmentLengths","updateArcLengths","moveCurvePoint","pointID","moveControlPoint","getStartControlPoint","getEndControlPoint","translate","getLength","arcLength","pointB","curveStep","newLength","tmpLength","getPointAt","tPrev","tNext","iteration","locateIntervalByDistance","tStart","tEnd","stepCount","minIndex","minDist","tDiff","xMinMax","cubicPolyMinMax","xl","xh","yMinMax","yl","yh","getPointByID","id","evaluateT","getPoint","getTangentAt","t2","nt2","tX","tY","trimStart","uValue","trimStartAt","convertU2T","subCurbePoints","getSubCurvePointsAt","trimEnd","trimEndAt","getSubCurve","uStart","uEnd","getSubCurveAt","getTangent","getPerpendicular","getPerpendicularAt","tangentVector","lineIntersectionTs","intersectionTangents","vec","bx","bezierCoeffs","by","poly","Array","cubicRoots","root","curve","isInstance","obj","toJSON","prettyFormat","fromJSON","jsonString","parse","fromObject","isArray","polyX","cubicPoly","disc","t1","startVec","endVec","S","T","Q","R","ts","sgn","th","sort","coeffs","totalArcLength","adjustCircular","bezierCurves","addCurve","adjustSuccessorControlPoint","locateCurveByStartPoint","locateCurveByEndPoint","locateCurveByStartControlPoint","locateCurveByEndControlPoint","getCurveCount","getCurveAt","curveIndex","anchor","scaleFactors","curveT","uMin","uTemp","relativeU","uResult","_locateUIndex","bCurve","uPart","reduce","accu","curCurve","concat","path","uBefore","getSubPathAt","startT","endT","startU","endU","uStartResult","uEndResult","firstT","lastT","firstCurve","curves","adjustPredecessorControlPoint","obtainHandleLength","mainCurve","neighbourCurve","adjustNeighbourControlPoint","_mainCurve","mainPoint","mainControlPoint","neighbourPoint","neighbourControlPoint","obtainHandleLengths","_updateArcLengths","mainHandleBounds","neighbourHandleBounds","mainHandleLength","neighbourHandleLength","POSITIVE_INFINITY","NEGATIVE_INFINITY","getEvenDistributionVertices","toPathPoints","fromCurve","bPath","lastCurve","toReducedListRepresentation","digits","fromReducedListRepresentation","listJSON","pointArray","fromReducedList","bezierPath","CircleSector","startAngle","endAngle","circleBounds","candidates","containsAngle","wrappedAngle","wrappedStart","wrappedEnd","angleAt","circleSectorIntersection","sector","radicalLine","thisIntersectionAngleA","thisIntersectionAngleB","thatIntersectionAngleA","thatIntersectionAngleB","centerOfOriginalGap","resultSector","ray","ellipseIntersections","tmpLine","intersectionPoint","lineAngle","describeSVGPath","options","circleSectorUtils","describeSVGArc","polarToCartesian","centerX","centerY","moveToStart","end","start","firstHalf","secondHalf","largeArcFlag","sweepFlag","pathData","RAD_TO_DEG","drawutilssvg","svgNode","offset","canvasSize","fillShapes","drawConfig","isSecondary","gNode","bufferGNode","nodeDefs","bufferNodeDefs","nodeStyle","Boolean","drawlibConfiguration","cache","Map","setSize","bufferedNodeDefs","addStyleDefs","addDefsNode","createSVGNode","appendChild","rebuildStyleDefs","keys","bezier","ellipse","ellipseSector","circleSector","vector","image","text","rules","k","drawSettings","color","lineWidth","customStyleDefs","forEach","value","innerHTML","addCustomStyleDefs","defs","findElement","nodeName","node","get","toUpperCase","delete","document","createElementNS","makeNode","curId","blendMode","style","_bindFillDraw","strokeOptions","_configureNode","_bindNode","bindingParent","parentNode","_addCSSClasses","curClassName","setAttribute","fillMode","applyStrokeOpts","copyInstance","setConfiguration","configuration","setCurrentId","setCurrentClassName","beginDrawCycle","renderTime","clear","childNodes","child","getAttribute","removeAllChildNodes","endDrawCycle","replaceChild","tmpGNode","tmpDefsNode","dashArray","nodeSupportsLineDash","tagName","dashArayElem","dashOffset","lineJoin","nodeSupportsLineJoin","_x","_y","makeLineNode","arrow","headLength","group","arrowHeadBasePosition","arrowHead","makeArrowHeadNode","cubicBezierArrow","makeCubicBezierNode","position","size","alpha","setImageSize","naturalWidth","ratioX","ratioY","naturalHeight","addEventListener","event","src","texturedPoly","textureImage","textureSize","polygonPosition","rotation","rotatedScalingOrigin","clipPathNode","clipPathId","imageNode","pathNode","clipNode","cubicBezier","cubicBezierPath","handle","square","handleLine","dot","circleArc","arcData","radiusX","radiusY","rect","grid","sizeX","sizeY","ceil","raster","diamondHandle","squareHandle","circleHandle","crosshair","cross","polyline","_a","_b","_c","lineHeight","fontSize","textAlign","transformOrigin","textNode","fontFamily","fontStyle","fontWeight","label","inplace","copyPathData","transformPathData","lastChild","removeChild","createSvg","data","copy","_stx","_sty","_sx","_sy","_slp","includes","classNameOverride","makePathNode","pathString","arrowHeadBasePositionBuffer","HEAD_XML","drawutils","context","ctx","setLineDash","dashArrayElem","lineDashOffset","_fillOrDraw","fillStyle","fill","strokeStyle","stroke","globalCompositeOperation","save","beginPath","lineTo","restore","complete","globalAlpha","drawImage","basePolygonBounds","targetTextureSize","targetTextureOffset","helpers","clipPoly","closePath","bezierCurveTo","quadraticBezier","controlPoint","quadraticCurveTo","arc","asSegment","relX","relY","font","indexOf","fillText","strokeText","Path2D","clearRect","canvas","fillRect","clip","drawutilsgl","gl","_zindex","glutils","GLU","_vertShader","compileShader","vertCode","VERTEX_SHADER","_fragShader","fragCode","FRAGMENT_SHADER","_program","makeProgram","vertex_buffer","createBuffer","_x2rel","_y2rel","Float32Array","bindBuffer","ARRAY_BUFFER","bufferData","STATIC_DRAW","coord","getAttribLocation","vertexAttribPointer","FLOAT","enableVertexAttribArray","viewport","uRotationVector","getUniformLocation","uniform2fv","drawArrays","LINES","TRIANGLE_FAN","clearColor","enable","DEPTH_TEST","COLOR_BUFFER_BIT","DEPTH_BUFFER_BIT","vbuffer","shaderCode","shaderType","shader","createShader","shaderSource","getShaderParameter","COMPILE_STATUS","getShaderInfoLog","deleteShader","vertShader","fragShader","program","createProgram","attachShader","linkProgram","useProgram","detachShader","Grid","baseLog","base","num","mapRasterScale","adjustFactor","gf","floor","KeyHandler","downListeners","pressListeners","upListeners","keyStates","element","globalThis","trackAllKeys","trackAll","installListeners","fireEvent","hasListener","lis","keyCode","fireDownEvent","handler","firePressEvent","fireUpEvent","key2code","KEY_CODES","_keyDownListener","_keyPressListener","_keyUpListener","releaseListeners","removeEventListener","down","press","up","isDown","break","backspace","tab","enter","shift","ctrl","alt","pause","capslock","hangul","hanja","escape","conversion","spacebar","pageup","pagedown","home","leftarrow","uparrow","rightarrow","downarrow","select","print","execute","printscreen","insert","help","f","g","m","o","q","r","z","windows","leftcommand","chromebooksearch","rightwindowkey","windowsmenu","rightcommant","sleep","numpad0","numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9","multiply","numpadperiod","subtract","decimalpoint","divide","f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","f12","f13","f14","f15","f16","f17","f18","f19","f20","f21","f22","f23","f24","numlock","scrolllock","$","pagebackward","pageforward","refresh","closingparen","minus","decreasevolumelevel","increasevolumelevel","previous","stop","email","mute","unmute","semicolon","equal","comma","dash","period","forwardslash","openbracket","backslash","closebracket","singlequote","altgr","XF86Forward","XF86Back","alphanumeric","hiragana","katakana","kanji","unlocktrackpad","toggletouchpad","XMouseEvent","MouseEvent","XWheelEvent","WheelEvent","MouseHandler","name","mouseDownPos","mouseDragPos","mouseButton","installed","handlers","mousemove","mkParams","relPos","mouseup","button","mousedown","wheel","offsetX","offsetY","eventName","rel","xEvent","isTouchEvent","pos","leftButton","middleButton","rightButton","draggedFrom","wasDragged","dragAmount","listenFor","unlistenFor","callback","throwAlreadyInstalled","PBImage","upperLeft","lowerRight","PBText","getLen","getRotateAngle","v2","mr","getAngle","HandlerAdmin","el","del","dispatch","_args","apply","arguments","wrapFunc","handlerAdmin","AlloyFinger","option","querySelector","bind","cancel","preV","pinchStartLen","zoom","isDoubleTap","noop","touchStart","multipointStart","multipointEnd","pinch","swipe","tap","doubleTap","longTap","singleTap","pressMove","twoFingerPressMove","touchMove","touchEnd","touchCancel","_cancelAllHandler","cancelAll","delta","last","now","tapTimeout","singleTapTimeout","longTapTimeout","swipeTimeout","preTapPosition","evt","touches","Date","pageX","pageY","clearTimeout","_cancelLongTap","_cancelSingleTap","_preventTap","setTimeout","afEvent","currentX","currentY","sCurrentX","sCurrentY","sx2","deltaX","deltaY","sy2","movedX","movedY","preventDefault","changedTouches","self","direction","_swipeDirection","on","off","VEllipse","axis","radiusH","signedRadiusH","radiusV","signedRadiusV","getExtremePoints","t_x1","t_x2","x_x1","y_x1","x_x2","y_x2","x_max","x_min","t_y1","t_y2","x_y1","y_y1","x_y2","y_y2","y_max","y_min","r1","r2","ux","uy","vx","vy","bbox_halfwidth","bbox_halfheight","normalAt","foci","getFoci","angleA","centerAngle","endPointA","endPointB","resultVector","rh","rv","sdiff","getEquidistantVertices","angles","equidistantVertAngles","ellipseCopy","rayCopy","rotationAmount","scalingFactors","toCubicBezier","quarterSegmentCount","segmentCount","curAngle","nextAngle","startTangent","endTangent","startDiff","endDiff","phiToTheta","phi","tanPhi","tan","tanPhi2","atan","theta","VEllipseSector","sAngle","eAngle","ellipseSectorUtils","normalizeAngle","r2d","fullEllipsePointCount","ellipseAngles","startIndex","findClosestToStartAngle","ea","endpointToCenterParameters","rx","ry","fa","fs","sinphi","cosphi","prx","pry","L","M","_cx","_cy","__setFunctionName","prefix","description","Object","defineProperty","configurable","PlotBoilerplate","config","contentChangeListeners","_gui","bezierAutoAdjust","fetch","fullSize","val","fitToParent","bool","rasterGrid","drawRaster","rasterScaleX","rasterScaleY","rasterAdjustFactor","drawOrigin","autoAdjustOffset","offsetAdjustXPercent","offsetAdjustYPercent","backgroundColor","redrawOnResize","defaultCanvasWidth","DEFAULT_CANVAS_WIDTH","defaultCanvasHeight","DEFAULT_CANVAS_HEIGHT","canvasWidthFactor","canvasHeightFactor","cssScaleX","cssScaleY","cssUniformScale","saveFile","hooks","setToRetina","_setToRetina","autoDetectRetina","enableSVGExport","preClear","func","preDraw","postDraw","enableMouse","enableTouch","enableKeys","enableMouseWheel","enableZoom","enablePan","enableGL","isBackdropFiltersEnabled","drawVertices","drawBezierHandleLines","drawBezierHandlePoints","drawHandleLines","drawHandlePoints","drawGrid","pathVertex","controlVertex","selectedVertex","canvasElement","toLowerCase","eventCatcher","getContext","draw","parentElement","createElement","left","top","cursor","body","title","selectPolygon","draggedElements","drawables","_saveFile","resizeCanvas","installInputListeners","updateCSSscale","redraw","focus","pb","tosvgDraw","tosvgFill","drawAll","svgCode","XMLSerializer","serializeToString","blob","Blob","type","_saveAs","pixelRatio","devicePixelRatio","fitToView","canvasCenter","canvasRatio","ratio","setOffset","newUniformZoom","setZoom","setConsole","con","_d","_e","setCSSscale","addContentChangeListener","removeContentChangeListener","_fireContentChanged","addedDrawables","removedDrawables","drawable","doNotFireEvent","enableBezierPathAutoAdjust","remove","removeWithVertices","wasRemoved","removeVertex","removeAll","keepVertices","triggerRedraw","getVertexNear","pixelPosition","pixelTolerance","locatePointNear","transformMousePosition","typeName","vindex","gScale","gSize","cs","_handleColor","drawDrawables","drawDrawable","df","error","drawSelectPolygon","clearSelection","getFProp","elem","propName","parseFloat","getComputedStyle","getPropertyValue","getAvailableContainerSpace","container","display","padding","border","pl","pr","pt","bl","br","bt","bb","clientWidth","clientHeight","_f","_g","_setSize","HTMLCanvasElement","SVGElement","adjustOffset","innerWidth","documentElement","innerHeight","space","selectVerticesInPolygon","Draggable","VERTEX","setVIndex","handleClick","DEFAULT_CLICK_TOLERANCE","keyHandler","paths","pindex","cindex","pid","revertMousePosition","getDraggedElementCount","mouseDownHandler","draggablePoint","mouseDragHandler","oldDragAmount","mouseUpHandler","mouseWheelHandler","zoomStep","we","newOffset","zoomFactorX","zoomFactorY","interactionPos","oldPos","newPos","newOffsetX","newOffsetY","getBoundingClientRect","touchMovePos","touchDownPos","draggedElement","multiTouchStartScale","clearTouch","afProps","clientX","clientY","DEFAULT_TOUCH_TOLERANCE","draggingVertex","fakeEvent","stopPropagation","trans","touchItem0","item","touchItem1","fingerA","fingerB","window","createAlloyFinger","createGUI","props","getGUI","isVertex","safeMergeByKeys","extension","hasOwnProperty","typ","extVal","removeProperty","transform","fallback"],"mappings":"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"}