plotboilerplate 1.24.0 → 1.26.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 (222) hide show
  1. package/README.md +14 -1
  2. package/dist/index.esm.js +433 -162
  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 +12312 -12041
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +9 -5
  11. package/src/cjs/Bounds.d.ts +79 -25
  12. package/src/cjs/Bounds.js +102 -29
  13. package/src/cjs/Bounds.js.map +1 -1
  14. package/src/cjs/CircleSector.d.ts +3 -0
  15. package/src/cjs/CircleSector.js +28 -1
  16. package/src/cjs/CircleSector.js.map +1 -1
  17. package/src/cjs/PlotBoilerplate.d.ts +37 -6
  18. package/src/cjs/PlotBoilerplate.js +222 -116
  19. package/src/cjs/PlotBoilerplate.js.map +1 -1
  20. package/src/cjs/Polygon.d.ts +26 -7
  21. package/src/cjs/Polygon.js +56 -10
  22. package/src/cjs/Polygon.js.map +1 -1
  23. package/src/cjs/Triangle.js +2 -2
  24. package/src/cjs/Triangle.js.map +1 -1
  25. package/src/cjs/Vertex.d.ts +15 -3
  26. package/src/cjs/Vertex.js +18 -1
  27. package/src/cjs/Vertex.js.map +1 -1
  28. package/src/cjs/drawutilssvg.d.ts +2 -1
  29. package/src/cjs/drawutilssvg.js +9 -3
  30. package/src/cjs/drawutilssvg.js.map +1 -1
  31. package/src/cjs/interfaces/core.d.ts +28 -0
  32. package/src/cjs/interfaces/core.js +2 -0
  33. package/src/cjs/interfaces/core.js.map +1 -1
  34. package/src/cjs/utils/LissajousFigure.d.ts +34 -0
  35. package/src/cjs/utils/LissajousFigure.js +100 -0
  36. package/src/cjs/utils/LissajousFigure.js.map +1 -0
  37. package/src/cjs/utils/PerlinNoise.d.ts +19 -0
  38. package/src/cjs/utils/PerlinNoise.js +352 -0
  39. package/src/cjs/utils/PerlinNoise.js.map +1 -0
  40. package/src/cjs/utils/SVGPathUtils.d.ts +22 -0
  41. package/src/cjs/utils/SVGPathUtils.js +45 -0
  42. package/src/cjs/utils/SVGPathUtils.js.map +1 -0
  43. package/src/cjs/utils/algorithms/pixelCornersToRoundPaths.d.ts +23 -0
  44. package/src/cjs/utils/algorithms/pixelCornersToRoundPaths.js +270 -0
  45. package/src/cjs/utils/algorithms/pixelCornersToRoundPaths.js.map +1 -0
  46. package/src/cjs/utils/datastructures/Color.d.ts +147 -1
  47. package/src/cjs/utils/datastructures/Color.js +385 -41
  48. package/src/cjs/utils/datastructures/Color.js.map +1 -1
  49. package/src/cjs/utils/datastructures/ColorGradient.d.ts +79 -0
  50. package/src/cjs/utils/datastructures/ColorGradient.js +171 -0
  51. package/src/cjs/utils/datastructures/ColorGradient.js.map +1 -0
  52. package/src/cjs/utils/datastructures/DataGrid2d.d.ts +6 -0
  53. package/src/cjs/utils/datastructures/DataGrid2dArrayMatrix.d.ts +88 -0
  54. package/src/cjs/utils/datastructures/DataGrid2dArrayMatrix.js +155 -0
  55. package/src/cjs/utils/datastructures/DataGrid2dArrayMatrix.js.map +1 -0
  56. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.d.ts +1 -7
  57. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.js +3 -3
  58. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.js.map +1 -1
  59. package/src/cjs/utils/datastructures/GeometryMesh.d.ts +49 -0
  60. package/src/cjs/utils/datastructures/GeometryMesh.js +58 -0
  61. package/src/cjs/utils/datastructures/GeometryMesh.js.map +1 -0
  62. package/src/cjs/utils/detectDarkMode.js +16 -7
  63. package/src/cjs/utils/detectDarkMode.js.map +1 -1
  64. package/src/cjs/utils/dom/components/ColorGradientPicker.d.ts +246 -0
  65. package/src/cjs/utils/dom/components/ColorGradientPicker.js +667 -0
  66. package/src/cjs/utils/dom/components/ColorGradientPicker.js.map +1 -0
  67. package/src/cjs/utils/dom/components/ColorGradientPickerJSX.d.ts +129 -0
  68. package/src/cjs/utils/dom/components/ColorGradientPickerJSX.js +520 -0
  69. package/src/cjs/utils/dom/components/ColorGradientPickerJSX.js.map +1 -0
  70. package/src/cjs/utils/dom/components/ColorGradientSelector.d.ts +118 -0
  71. package/src/cjs/utils/dom/components/ColorGradientSelector.js +327 -0
  72. package/src/cjs/utils/dom/components/ColorGradientSelector.js.map +1 -0
  73. package/src/cjs/utils/dom/components/Test.d.ts +7 -0
  74. package/src/cjs/utils/dom/components/Test.js +30 -0
  75. package/src/cjs/utils/dom/components/Test.js.map +1 -0
  76. package/src/cjs/utils/dom/guiSizeToggler.js +1 -1
  77. package/src/cjs/utils/dom/guiSizeToggler.js.map +1 -1
  78. package/src/cjs/utils/helpers/BezierPathInteractionHelper.d.ts +9 -3
  79. package/src/cjs/utils/helpers/BezierPathInteractionHelper.js +20 -13
  80. package/src/cjs/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
  81. package/src/cjs/utils/helpers/CircleHelper.d.ts +10 -1
  82. package/src/cjs/utils/helpers/CircleHelper.js +13 -2
  83. package/src/cjs/utils/helpers/CircleHelper.js.map +1 -1
  84. package/src/cjs/utils/helpers/CircleSectorHelper.d.ts +2 -2
  85. package/src/cjs/utils/helpers/CircleSectorHelper.js +1 -0
  86. package/src/cjs/utils/helpers/CircleSectorHelper.js.map +1 -1
  87. package/src/cjs/utils/helpers/TriangleHelper.d.ts +57 -0
  88. package/src/cjs/utils/helpers/TriangleHelper.js +83 -0
  89. package/src/cjs/utils/helpers/TriangleHelper.js.map +1 -0
  90. package/src/cjs/utils/helpers/VEllipseHelper.d.ts +6 -4
  91. package/src/cjs/utils/helpers/VEllipseHelper.js +4 -2
  92. package/src/cjs/utils/helpers/VEllipseHelper.js.map +1 -1
  93. package/src/cjs/utils/helpers/VEllipseSectorHelper.d.ts +3 -2
  94. package/src/cjs/utils/helpers/VEllipseSectorHelper.js +1 -0
  95. package/src/cjs/utils/helpers/VEllipseSectorHelper.js.map +1 -1
  96. package/src/cjs/utils/parsers/LinearColorGradientParser.d.ts +78 -0
  97. package/src/cjs/utils/parsers/LinearColorGradientParser.js +224 -0
  98. package/src/cjs/utils/parsers/LinearColorGradientParser.js.map +1 -0
  99. package/src/cjs/utils/parsers/svg/types.d.ts +8 -8
  100. package/src/createDemoDrawables.js +1 -0
  101. package/src/esm/Bounds.d.ts +79 -25
  102. package/src/esm/Bounds.js +102 -29
  103. package/src/esm/Bounds.js.map +1 -1
  104. package/src/esm/CircleSector.d.ts +3 -0
  105. package/src/esm/CircleSector.js +28 -1
  106. package/src/esm/CircleSector.js.map +1 -1
  107. package/src/esm/PlotBoilerplate.d.ts +37 -6
  108. package/src/esm/PlotBoilerplate.js +222 -116
  109. package/src/esm/PlotBoilerplate.js.map +1 -1
  110. package/src/esm/Polygon.d.ts +26 -7
  111. package/src/esm/Polygon.js +53 -10
  112. package/src/esm/Polygon.js.map +1 -1
  113. package/src/esm/Triangle.js +2 -2
  114. package/src/esm/Triangle.js.map +1 -1
  115. package/src/esm/Vertex.d.ts +15 -3
  116. package/src/esm/Vertex.js +18 -1
  117. package/src/esm/Vertex.js.map +1 -1
  118. package/src/esm/drawutilssvg.d.ts +2 -1
  119. package/src/esm/drawutilssvg.js +9 -3
  120. package/src/esm/drawutilssvg.js.map +1 -1
  121. package/src/esm/interfaces/core.d.ts +28 -0
  122. package/src/esm/interfaces/core.js +2 -0
  123. package/src/esm/interfaces/core.js.map +1 -1
  124. package/src/esm/utils/LissajousFigure.d.ts +34 -0
  125. package/src/esm/utils/LissajousFigure.js +95 -0
  126. package/src/esm/utils/LissajousFigure.js.map +1 -0
  127. package/src/esm/utils/PerlinNoise.d.ts +19 -0
  128. package/src/esm/utils/PerlinNoise.js +346 -0
  129. package/src/esm/utils/PerlinNoise.js.map +1 -0
  130. package/src/esm/utils/SVGPathUtils.d.ts +22 -0
  131. package/src/esm/utils/SVGPathUtils.js +42 -0
  132. package/src/esm/utils/SVGPathUtils.js.map +1 -0
  133. package/src/esm/utils/algorithms/pixelCornersToRoundPaths.d.ts +23 -0
  134. package/src/esm/utils/algorithms/pixelCornersToRoundPaths.js +266 -0
  135. package/src/esm/utils/algorithms/pixelCornersToRoundPaths.js.map +1 -0
  136. package/src/esm/utils/datastructures/Color.d.ts +147 -1
  137. package/src/esm/utils/datastructures/Color.js +386 -42
  138. package/src/esm/utils/datastructures/Color.js.map +1 -1
  139. package/src/esm/utils/datastructures/ColorGradient.d.ts +79 -0
  140. package/src/esm/utils/datastructures/ColorGradient.js +166 -0
  141. package/src/esm/utils/datastructures/ColorGradient.js.map +1 -0
  142. package/src/esm/utils/datastructures/DataGrid2d.d.ts +6 -0
  143. package/src/esm/utils/datastructures/DataGrid2dArrayMatrix.d.ts +88 -0
  144. package/src/esm/utils/datastructures/DataGrid2dArrayMatrix.js +150 -0
  145. package/src/esm/utils/datastructures/DataGrid2dArrayMatrix.js.map +1 -0
  146. package/src/esm/utils/datastructures/DataGrid2dListAdapter.d.ts +1 -7
  147. package/src/esm/utils/datastructures/DataGrid2dListAdapter.js +3 -3
  148. package/src/esm/utils/datastructures/DataGrid2dListAdapter.js.map +1 -1
  149. package/src/esm/utils/datastructures/GeometryMesh.d.ts +49 -0
  150. package/src/esm/utils/datastructures/GeometryMesh.js +53 -0
  151. package/src/esm/utils/datastructures/GeometryMesh.js.map +1 -0
  152. package/src/esm/utils/detectDarkMode.js +16 -7
  153. package/src/esm/utils/detectDarkMode.js.map +1 -1
  154. package/src/esm/utils/dom/components/ColorGradientPicker.d.ts +246 -0
  155. package/src/esm/utils/dom/components/ColorGradientPicker.js +743 -0
  156. package/src/esm/utils/dom/components/ColorGradientPicker.js.map +1 -0
  157. package/src/esm/utils/dom/components/ColorGradientPickerJSX.d.ts +129 -0
  158. package/src/esm/utils/dom/components/ColorGradientPickerJSX.js +582 -0
  159. package/src/esm/utils/dom/components/ColorGradientPickerJSX.js.map +1 -0
  160. package/src/esm/utils/dom/components/ColorGradientSelector.d.ts +118 -0
  161. package/src/esm/utils/dom/components/ColorGradientSelector.js +339 -0
  162. package/src/esm/utils/dom/components/ColorGradientSelector.js.map +1 -0
  163. package/src/esm/utils/dom/components/Test.d.ts +7 -0
  164. package/src/esm/utils/dom/components/Test.js +26 -0
  165. package/src/esm/utils/dom/components/Test.js.map +1 -0
  166. package/src/esm/utils/dom/guiSizeToggler.js +1 -1
  167. package/src/esm/utils/dom/guiSizeToggler.js.map +1 -1
  168. package/src/esm/utils/helpers/BezierPathInteractionHelper.d.ts +9 -3
  169. package/src/esm/utils/helpers/BezierPathInteractionHelper.js +20 -13
  170. package/src/esm/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
  171. package/src/esm/utils/helpers/CircleHelper.d.ts +10 -1
  172. package/src/esm/utils/helpers/CircleHelper.js +13 -2
  173. package/src/esm/utils/helpers/CircleHelper.js.map +1 -1
  174. package/src/esm/utils/helpers/CircleSectorHelper.d.ts +2 -2
  175. package/src/esm/utils/helpers/CircleSectorHelper.js +1 -0
  176. package/src/esm/utils/helpers/CircleSectorHelper.js.map +1 -1
  177. package/src/esm/utils/helpers/TriangleHelper.d.ts +57 -0
  178. package/src/esm/utils/helpers/TriangleHelper.js +78 -0
  179. package/src/esm/utils/helpers/TriangleHelper.js.map +1 -0
  180. package/src/esm/utils/helpers/VEllipseHelper.d.ts +6 -4
  181. package/src/esm/utils/helpers/VEllipseHelper.js +4 -2
  182. package/src/esm/utils/helpers/VEllipseHelper.js.map +1 -1
  183. package/src/esm/utils/helpers/VEllipseSectorHelper.d.ts +3 -2
  184. package/src/esm/utils/helpers/VEllipseSectorHelper.js +1 -0
  185. package/src/esm/utils/helpers/VEllipseSectorHelper.js.map +1 -1
  186. package/src/esm/utils/parsers/LinearColorGradientParser.d.ts +78 -0
  187. package/src/esm/utils/parsers/LinearColorGradientParser.js +217 -0
  188. package/src/esm/utils/parsers/LinearColorGradientParser.js.map +1 -0
  189. package/src/esm/utils/parsers/svg/types.d.ts +8 -8
  190. package/src/external.d.ts +9 -0
  191. package/src/ts/Bounds.ts +107 -22
  192. package/src/ts/CircleSector.ts +39 -6
  193. package/src/ts/PlotBoilerplate.ts +233 -105
  194. package/src/ts/Polygon.ts +68 -14
  195. package/src/ts/Triangle.ts +2 -2
  196. package/src/ts/Vertex.ts +21 -3
  197. package/src/ts/drawutilssvg.ts +8 -3
  198. package/src/ts/interfaces/core.ts +31 -0
  199. package/src/ts/utils/LissajousFigure.ts +110 -0
  200. package/src/ts/utils/PerlinNoise.ts +368 -0
  201. package/src/ts/utils/SVGPathUtils.ts +55 -0
  202. package/src/ts/utils/algorithms/pixelCornersToRoundPaths.ts +379 -0
  203. package/src/ts/utils/datastructures/Color.ts +423 -44
  204. package/src/ts/utils/datastructures/ColorGradient.ts +196 -0
  205. package/src/ts/utils/datastructures/DataGrid2d.ts +7 -0
  206. package/src/ts/utils/datastructures/DataGrid2dArrayMatrix.ts +182 -0
  207. package/src/ts/utils/datastructures/DataGrid2dListAdapter.ts +4 -11
  208. package/src/ts/utils/datastructures/GeometryMesh.ts +79 -0
  209. package/src/ts/utils/detectDarkMode.ts +17 -8
  210. package/src/ts/utils/dom/components/ColorGradientPicker.tsx +889 -0
  211. package/src/ts/utils/dom/components/ColorGradientSelector.tsx +452 -0
  212. package/src/ts/utils/dom/components/Test.tsx +44 -0
  213. package/src/ts/utils/dom/components/_ColorGradientPicker_raw.ts_ +392 -0
  214. package/src/ts/utils/dom/guiSizeToggler.ts +1 -1
  215. package/src/ts/utils/helpers/BezierPathInteractionHelper.ts +25 -15
  216. package/src/ts/utils/helpers/CircleHelper.ts +17 -3
  217. package/src/ts/utils/helpers/CircleSectorHelper.ts +4 -2
  218. package/src/ts/utils/helpers/TriangleHelper.ts +102 -0
  219. package/src/ts/utils/helpers/VEllipseHelper.ts +6 -4
  220. package/src/ts/utils/helpers/VEllipseSectorHelper.ts +3 -2
  221. package/src/ts/utils/parsers/LinearColorGradientParser.ts +297 -0
  222. package/src/ts/utils/parsers/svg/types.ts +8 -8
package/dist/index.esm.js CHANGED
@@ -958,7 +958,7 @@ class Triangle {
958
958
  // Find the intersections of all lines inside the edge bounds
959
959
  return Polygon.utils
960
960
  .locateLineIntersecion(line, [this.a, this.b, this.c], false, inVectorBoundsOnly)
961
- .map(intersectionTuple => intersectionTuple.intersectionPoint);
961
+ .map(intersectionTuple => intersectionTuple.intersection);
962
962
  }
963
963
  /**
964
964
  * Get all line intersections of this polygon and their tangents along the shape.
@@ -976,7 +976,7 @@ class Triangle {
976
976
  .map(intersectionTuple => {
977
977
  // const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
978
978
  const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
979
- return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersectionPoint);
979
+ return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection);
980
980
  });
981
981
  }
982
982
  //--- END --- Implement interface `Intersectable`
@@ -1293,7 +1293,8 @@ const geomutils = {
1293
1293
  * @modified 2024-12-17 Outsourced the euclidean distance calculation of `Vertex.distance` to `geomutils.dist4`.
1294
1294
  * @modified 2025-03-24 Making the second parameter `center` of the `Vertex.rotate` method optional.
1295
1295
  * @modified 2025-04-13 Adding the `Vertex.move(amount: XYCoords)` method (does the same as `add`, added by naming convention).
1296
- * @version 2.10.0
1296
+ * @modified 2025-05-07 Class `Vertex` is now implementing interface `IBounded` (to meet convention).
1297
+ * @version 2.11.0
1297
1298
  *
1298
1299
  * @file Vertex
1299
1300
  * @public
@@ -1838,6 +1839,21 @@ class Vertex {
1838
1839
  this.y = Math.abs(this.y);
1839
1840
  return this;
1840
1841
  }
1842
+ //--- BEGIN --- Implement interface `IBounded`
1843
+ /**
1844
+ * Get the bounding box (bounds) of this Vertex.
1845
+ * This is just by convention – any vertex is just a position without any useful with or height (0).
1846
+ *
1847
+ * @method getBounds
1848
+ * @instance
1849
+ * @memberof Vertex
1850
+ * @return {Bounds} The rectangular bounds of this Vertex (width and height are zero).
1851
+ **/
1852
+ getBounds() {
1853
+ // return Bounds.computeFromVertices([this.a, this.b, this.c]);
1854
+ return Bounds.computeFromVertices([this]);
1855
+ }
1856
+ //--- END --- Implement interface `IBounded`
1841
1857
  /**
1842
1858
  * Get a string representation of this vertex.
1843
1859
  *
@@ -2679,7 +2695,9 @@ class Line extends VertTuple {
2679
2695
  * @modified 2025-03-28 Added the `Polygon.lineIntersectionTangents` method.
2680
2696
  * @modified 2025-04-09 Added the `Polygon.getCentroid` method.
2681
2697
  * @modified 2025-05-16 Class `Polygon` now implements `IBounded`.
2682
- * @version 1.15.0
2698
+ * @modified 2025-05-20 Tweaking `Polygon.getInnerAngleAt` and `Polygo.isAngleAcute` to handle indices out of array bounds as well.
2699
+ * @modified 2025-06-07 Adding `Polygon.closestLineIntersectionIndex` to determine line intersections plus detected edge index.
2700
+ * @version 1.16.0
2683
2701
  *
2684
2702
  * @file Polygon
2685
2703
  * @public
@@ -2786,7 +2804,7 @@ class Polygon {
2786
2804
  * @returns {boolean} `true` is angle is acute, `false` is obtuse.
2787
2805
  */
2788
2806
  getInnerAngleAt(vertIndex) {
2789
- const p2 = this.vertices[vertIndex];
2807
+ const p2 = this.vertices[vertIndex % this.vertices.length];
2790
2808
  const p1 = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();
2791
2809
  const p3 = this.vertices[(vertIndex + 1) % this.vertices.length].clone();
2792
2810
  // See
@@ -2822,7 +2840,7 @@ class Polygon {
2822
2840
  */
2823
2841
  isAngleAcute(vertIndex) {
2824
2842
  const A = this.vertices[(vertIndex + this.vertices.length - 1) % this.vertices.length].clone();
2825
- const B = this.vertices[vertIndex];
2843
+ const B = this.vertices[vertIndex % this.vertices.length];
2826
2844
  const C = this.vertices[(vertIndex + 1) % this.vertices.length].clone();
2827
2845
  // Find local winding number for triangle A B C
2828
2846
  const windingNumber = Triangle.utils.determinant(A, B, C);
@@ -2888,8 +2906,9 @@ class Polygon {
2888
2906
  let xi = this.vertices[i].x, yi = this.vertices[i].y;
2889
2907
  let xj = this.vertices[j].x, yj = this.vertices[j].y;
2890
2908
  var intersect = yi > vert.y != yj > vert.y && vert.x < ((xj - xi) * (vert.y - yi)) / (yj - yi) + xi;
2891
- if (intersect)
2909
+ if (intersect) {
2892
2910
  inside = !inside;
2911
+ }
2893
2912
  }
2894
2913
  return inside;
2895
2914
  }
@@ -3099,7 +3118,7 @@ class Polygon {
3099
3118
  // Find the intersections of all lines inside the edge bounds
3100
3119
  return Polygon.utils
3101
3120
  .locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly)
3102
- .map(intersectionTuple => intersectionTuple.intersectionPoint);
3121
+ .map(intersectionTuple => intersectionTuple.intersection);
3103
3122
  }
3104
3123
  /**
3105
3124
  * Get all line intersections of this polygon and their tangents along the shape.
@@ -3114,10 +3133,29 @@ class Polygon {
3114
3133
  // Find the intersection tangents of all lines inside the edge bounds
3115
3134
  return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {
3116
3135
  const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
3117
- return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersectionPoint);
3136
+ return new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection);
3118
3137
  });
3119
3138
  }
3120
3139
  //--- END --- Implement interface `Intersectable`
3140
+ /**
3141
+ * Get all line intersections of this polygon and their tangents along the shape.
3142
+ *
3143
+ * This method returns all intersection tangents (as vectors) with this shape. The returned array of vectors is in no specific order.
3144
+ *
3145
+ * @param line
3146
+ * @param inVectorBoundsOnly
3147
+ * @returns
3148
+ */
3149
+ lineIntersectionTangentsIndices(line, inVectorBoundsOnly = false) {
3150
+ // Find the intersection tangents of all lines inside the edge bounds
3151
+ return Polygon.utils.locateLineIntersecion(line, this.vertices, this.isOpen, inVectorBoundsOnly).map(intersectionTuple => {
3152
+ const polyLine = this.getEdgeAt(intersectionTuple.edgeIndex);
3153
+ return {
3154
+ intersection: new Vector(polyLine.a.clone(), polyLine.b.clone()).moveTo(intersectionTuple.intersection),
3155
+ edgeIndex: intersectionTuple.edgeIndex
3156
+ };
3157
+ });
3158
+ }
3121
3159
  /**
3122
3160
  * Get the closest line-polygon-intersection point (closest the line point A).
3123
3161
  *
@@ -3125,9 +3163,27 @@ class Polygon {
3125
3163
  *
3126
3164
  * @param {VertTuple} line - The line to find intersections with.
3127
3165
  * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).
3128
- * @returns {Array<Vertex>} - An array of all intersections within the polygon bounds.
3166
+ * @returns {Vertex | null} - The intersection point within the polygon bounds.
3129
3167
  */
3130
3168
  closestLineIntersection(line, inVectorBoundsOnly = false) {
3169
+ var closestInterSectionIndex = this.closestLineIntersectionIndex(line, inVectorBoundsOnly);
3170
+ if (closestInterSectionIndex) {
3171
+ return closestInterSectionIndex.intersection;
3172
+ }
3173
+ else {
3174
+ return null;
3175
+ }
3176
+ }
3177
+ /**
3178
+ * Get the closest line-polygon-intersection point (closest the line point A) plus the edge index..
3179
+ *
3180
+ * See demo `63-measure-angles-on-polygon` for how it works.
3181
+ *
3182
+ * @param {VertTuple} line - The line to find intersections with.
3183
+ * @param {boolean} inVectorBoundsOnly - If set to true only intersecion points on the passed vector are considered (located strictly between start and end vertex).
3184
+ * @returns {PolygonIntersectionTuple| null} - A pair containing the intersection point and the affected polygon edge index.
3185
+ */
3186
+ closestLineIntersectionIndex(line, inVectorBoundsOnly = false) {
3131
3187
  const allIntersections = this.lineIntersections(line, inVectorBoundsOnly);
3132
3188
  if (allIntersections.length <= 0) {
3133
3189
  // Empty polygon -> no intersections
@@ -3135,17 +3191,20 @@ class Polygon {
3135
3191
  }
3136
3192
  // Find the closest intersection
3137
3193
  let closestIntersection = new Vertex(Number.MAX_VALUE, Number.MAX_VALUE);
3194
+ let closestInterSectionIndex = -1;
3138
3195
  let curDist = Number.MAX_VALUE;
3139
- for (var i in allIntersections) {
3196
+ for (var i = 0; i < allIntersections.length; i++) {
3140
3197
  const curVert = allIntersections[i];
3141
3198
  const dist = curVert.distance(line.a);
3142
3199
  if (dist < curDist) {
3143
3200
  // && line.hasPoint(curVert)) {
3144
3201
  curDist = dist;
3145
3202
  closestIntersection = curVert;
3203
+ closestInterSectionIndex = i;
3146
3204
  }
3147
3205
  }
3148
- return closestIntersection;
3206
+ // return [closestIntersection, closestInterSectionIndex];
3207
+ return { edgeIndex: closestInterSectionIndex, intersection: closestIntersection };
3149
3208
  }
3150
3209
  /**
3151
3210
  * Construct a new polygon from this polygon with more vertices on each edge. The
@@ -3503,7 +3562,7 @@ Polygon.utils = {
3503
3562
  if (intersection !== null &&
3504
3563
  polyLine.hasPoint(intersection, true) &&
3505
3564
  (!inVectorBoundsOnly || line.hasPoint(intersection, inVectorBoundsOnly))) {
3506
- intersectionPoints.push({ edgeIndex: i, intersectionPoint: intersection });
3565
+ intersectionPoints.push({ edgeIndex: i, intersection: intersection });
3507
3566
  }
3508
3567
  }
3509
3568
  return intersectionPoints;
@@ -3525,7 +3584,11 @@ Polygon.utils = {
3525
3584
  * @modified 2025-04-18 Change parameter type in `Bounds.computeFromVertices` from `Vertex` to more general `XYCoords`.
3526
3585
  * @modified 2025-04-19 Added methods to `Bounds` class: `getNorthPoint`, `getSouthPoint`, `getEastPoint` and `getWestPoint`.
3527
3586
  * @modified 2025-04-26 Added static method `Bounds.computeFromBoundsSet` to calculate containing bounds for a set of bounding boxes.
3528
- * @version 1.8.0
3587
+ * @modified 2025-10-17 Added the methods `Bounds.getSouthWestPoint`, `getNorthWestPoint`, `getNorthEastPoint` and `getSouthEastPoint`.
3588
+ * @modified 2025-10-18 Added method `Bounds.containsVert(XYCoords)`.
3589
+ * @modified 2025-10-28 Added the `Bounds.getWidth()` and `Bounds.getHeight()`.
3590
+ * @modified 2025-11-12 Added the `Bounds.getMoved()` method.
3591
+ * @version 1.11.0
3529
3592
  **/
3530
3593
  /**
3531
3594
  * @classdesc A bounds class with min and max values. Implementing IBounds.
@@ -3549,6 +3612,35 @@ class Bounds {
3549
3612
  this.width = max.x - min.x;
3550
3613
  this.height = max.y - min.y;
3551
3614
  }
3615
+ /**
3616
+ * Check if the given vertex is inside this bounds.
3617
+ *
3618
+ * @method containsVert
3619
+ * @param {XYCoords} vert - The vertex to check.
3620
+ * @return {boolean} True if the passed vertex is inside this bounds.
3621
+ * @instance
3622
+ * @memberof Bounds
3623
+ **/
3624
+ containsVert(vert) {
3625
+ return this.min.x <= vert.x && vert.x < this.max.x && this.min.y <= vert.y && vert.y < this.max.y;
3626
+ }
3627
+ getWidth() {
3628
+ return this.max.x - this.min.x;
3629
+ }
3630
+ getHeight() {
3631
+ return this.max.y - this.min.y;
3632
+ }
3633
+ getScaled(scaleFactor) {
3634
+ const center = this.getCenter();
3635
+ const newMin = new Vertex(this.min).scale(scaleFactor, center);
3636
+ const newMax = new Vertex(this.max).scale(scaleFactor, center);
3637
+ return new Bounds(newMin, newMax);
3638
+ }
3639
+ getMoved(moveAmount) {
3640
+ const newMin = new Vertex(this.min).move(moveAmount);
3641
+ const newMax = new Vertex(this.max).move(moveAmount);
3642
+ return new Bounds(newMin, newMax);
3643
+ }
3552
3644
  /**
3553
3645
  * Get the center point of the north bound.
3554
3646
  *
@@ -3560,7 +3652,6 @@ class Bounds {
3560
3652
  getNorthPoint() {
3561
3653
  return new Vertex(this.min.x + this.width / 2.0, this.min.y);
3562
3654
  }
3563
- ;
3564
3655
  /**
3565
3656
  * Get the center point of the south bound.
3566
3657
  *
@@ -3572,31 +3663,72 @@ class Bounds {
3572
3663
  getSouthPoint() {
3573
3664
  return new Vertex(this.min.x + this.width / 2.0, this.max.y);
3574
3665
  }
3575
- ;
3576
3666
  /**
3577
- * Get the center point of the west bound.
3578
- *
3579
- * @method getWestPoint
3580
- * @instance
3581
- * @memberof Bounds
3582
- * @return {Vertex} The "westhmost" centered point of this bounding box.
3583
- */
3667
+ * Get the center point of the west bound.
3668
+ *
3669
+ * @method getWestPoint
3670
+ * @instance
3671
+ * @memberof Bounds
3672
+ * @return {Vertex} The "westhmost" centered point of this bounding box.
3673
+ */
3584
3674
  getWestPoint() {
3585
3675
  return new Vertex(this.min.x, this.min.y + this.height / 2.0);
3586
3676
  }
3587
- ;
3588
3677
  /**
3589
- * Get the center point of the east bound.
3590
- *
3591
- * @method getEastPoint
3592
- * @instance
3593
- * @memberof Bounds
3594
- * @return {Vertex} The "easthmost" centered point of this bounding box.
3595
- */
3678
+ * Get the center point of the east bound.
3679
+ *
3680
+ * @method getEastPoint
3681
+ * @instance
3682
+ * @memberof Bounds
3683
+ * @return {Vertex} The "easthmost" centered point of this bounding box.
3684
+ */
3596
3685
  getEastPoint() {
3597
3686
  return new Vertex(this.max.x, this.min.y + this.height / 2.0);
3598
3687
  }
3599
- ;
3688
+ /**
3689
+ * Get the upper left corner point these bounds box.
3690
+ *
3691
+ * @method getNorthWestPoint
3692
+ * @instance
3693
+ * @memberof Bounds
3694
+ * @return {Vertex} The "northwestmost" point of this bounding box.
3695
+ */
3696
+ getNorthWestPoint() {
3697
+ return new Vertex(this.min.x, this.min.y);
3698
+ }
3699
+ /**
3700
+ * Get the upper right corner point these bounds box.
3701
+ *
3702
+ * @method getNorthEastPoint
3703
+ * @instance
3704
+ * @memberof Bounds
3705
+ * @return {Vertex} The "northeastmost" point of this bounding box.
3706
+ */
3707
+ getNorthEastPoint() {
3708
+ return new Vertex(this.max.x, this.min.y);
3709
+ }
3710
+ /**
3711
+ * Get the lower right corner point these bounds box.
3712
+ *
3713
+ * @method getSouthEastPoint
3714
+ * @instance
3715
+ * @memberof Bounds
3716
+ * @return {Vertex} The "southeastmost" point of this bounding box.
3717
+ */
3718
+ getSouthEastPoint() {
3719
+ return new Vertex(this.max.x, this.max.y);
3720
+ }
3721
+ /**
3722
+ * Get the lower left corner point these bounds box.
3723
+ *
3724
+ * @method getSouthWestPoint
3725
+ * @instance
3726
+ * @memberof Bounds
3727
+ * @return {Vertex} The "southwestmost" point of this bounding box.
3728
+ */
3729
+ getSouthWestPoint() {
3730
+ return new Vertex(this.min.x, this.max.y);
3731
+ }
3600
3732
  /**
3601
3733
  * Convert this rectangular bounding box to a polygon with four vertices.
3602
3734
  *
@@ -3707,16 +3839,16 @@ class Bounds {
3707
3839
  return new Bounds(new Vertex(xMin, yMin), new Vertex(xMax, yMax));
3708
3840
  }
3709
3841
  /**
3710
- * Compute the minimal bounding box for a given set of existing bounding boxes.
3711
- *
3712
- * An empty vertex array will return an empty bounding box located at (0,0).
3713
- *
3714
- * @static
3715
- * @method computeFromBoundsSet
3716
- * @memberof Bounds
3717
- * @param {Array<IBounds>} boundingBoxes - The set of existing bounding boxes to get the containing bounding box for.
3718
- * @return The minimal Bounds for the given bounds instances.
3719
- **/
3842
+ * Compute the minimal bounding box for a given set of existing bounding boxes.
3843
+ *
3844
+ * An empty vertex array will return an empty bounding box located at (0,0).
3845
+ *
3846
+ * @static
3847
+ * @method computeFromBoundsSet
3848
+ * @memberof Bounds
3849
+ * @param {Array<IBounds>} boundingBoxes - The set of existing bounding boxes to get the containing bounding box for.
3850
+ * @return The minimal Bounds for the given bounds instances.
3851
+ **/
3720
3852
  static computeFromBoundsSet(boundingBoxes) {
3721
3853
  if (boundingBoxes.length == 0) {
3722
3854
  return new Bounds(new Vertex(0, 0), new Vertex(0, 0));
@@ -6164,6 +6296,32 @@ class CircleSector {
6164
6296
  });
6165
6297
  }
6166
6298
  //--- END --- Implement interface `Intersectable`
6299
+ describeSVGPath(options) {
6300
+ // const buffer: SVGPathParams = [];
6301
+ // const start = this.getStartPoint();
6302
+ // const end = this.getEndPoint();
6303
+ // // describeSVGArc
6304
+ // // x: number,
6305
+ // // y: number,
6306
+ // // radius: number,
6307
+ // // startAngle: number,
6308
+ // // endAngle: number,
6309
+ // // options?: { moveToStart: boolean }
6310
+ // // ): SVGPathParams => {
6311
+ // var arcRotation = 0.0;
6312
+ // var largeArcFlag = 1;
6313
+ // var sweepFlag = 0;
6314
+ // if (options && options.moveToStart) {
6315
+ // buffer.push("M", start.x, start.y);
6316
+ // }
6317
+ // buffer.push("A", cSector.circle.radius, cSector.circle.radius, arcRotation, largeArcFlag, sweepFlag, end.x, end.y);
6318
+ // return buffer;
6319
+ const arc = CircleSector.circleSectorUtils.describeSVGArc(this.circle.center.x, // end.x,
6320
+ this.circle.center.y, // end.y,
6321
+ this.circle.radius, this.startAngle, this.endAngle, options // options?: { moveToStart: boolean }
6322
+ );
6323
+ return arc;
6324
+ }
6167
6325
  /**
6168
6326
  * This function should invalidate any installed listeners and invalidate this object.
6169
6327
  * After calling this function the object might not hold valid data any more and
@@ -6203,8 +6361,9 @@ CircleSector.circleSectorUtils = {
6203
6361
  * @return [ 'A', radiusx, radiusy, rotation=0, largeArcFlag=1|0, sweepFlag=0, endx, endy ]
6204
6362
  */
6205
6363
  describeSVGArc: (x, y, radius, startAngle, endAngle, options) => {
6206
- if (typeof options === "undefined")
6364
+ if (typeof options === "undefined") {
6207
6365
  options = { moveToStart: true };
6366
+ }
6208
6367
  const end = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, endAngle);
6209
6368
  const start = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, startAngle);
6210
6369
  // Split full circles into two halves.
@@ -6284,7 +6443,8 @@ CircleSector.circleSectorUtils = {
6284
6443
  * @modified 2024-01-30 Fixing an issue with immutable style sets; changes to the global draw config did not reflect here (do now).
6285
6444
  * @modified 2024-03-10 Fixing some types for Typescript 5 compatibility.
6286
6445
  * @modified 2024-07-24 Caching custom style defs in a private buffer variable.
6287
- * @version 1.6.10
6446
+ * @modified 2025-11-14 Fixing a bug in the CSS `mix-blend-mode` property handling (caused a runtime error).
6447
+ * @version 1.6.11
6288
6448
  **/
6289
6449
  const RAD_TO_DEG = 180 / Math.PI;
6290
6450
  /**
@@ -6482,8 +6642,13 @@ class drawutilssvg {
6482
6642
  node = this.createSVGNode(nodeName);
6483
6643
  }
6484
6644
  if (this.drawlibConfiguration.blendMode) {
6485
- // node.style["mix-blend-mode"] = this.drawlibConfiguration.blendMode;
6486
- node.style["mix-blend-mode"](this.drawlibConfiguration.blendMode);
6645
+ const blendMode = node.style["mix-blend-mode"];
6646
+ if (typeof blendMode === "function") {
6647
+ blendMode(this.drawlibConfiguration.blendMode);
6648
+ }
6649
+ else {
6650
+ node.style["mix-blend-mode"] = this.drawlibConfiguration.blendMode;
6651
+ }
6487
6652
  }
6488
6653
  // if (this.lineDashEnabled && this.lineDash && this.lineDash.length > 0 && drawutilssvg.nodeSupportsLineDash(nodeName)) {
6489
6654
  // node.setAttribute("stroke-dasharray", this.lineDash.join(" "));
@@ -12325,8 +12490,13 @@ VEllipseSector.ellipseSectorUtils = {
12325
12490
  * @modified 2024-07-08 Adding `PlotBoilerplate.getGUI()` to retrieve the GUI instance.
12326
12491
  * @modified 2024-08-25 Extending main class `PlotBoilerplate` optional param `isBackdropFiltersEnabled`.
12327
12492
  * @modified 2024-12-02 Adding the `triggerRedraw` to the `removeAll` method.
12493
+ * @modified 2025-05-07 Changing the return type of `removeVertex` from `void` to `boolean`.
12494
+ * @modified 2025-05-07 Handling content changes now with `contentChangeListeners`.
12495
+ * @modified 2025-05-07 Added `PlogBoilerplate.addContentChangeListener` and `.removeContentChangeListener`.
12496
+ * @modified 2025-05-07 Moving full vectors now by default when vector point a is moved.
12497
+ * @modified 2025-05-20 Applying `lineWith` parameter in the draw routine for vectors (had been missing).
12328
12498
  *
12329
- * @version 1.20.0
12499
+ * @version 1.21.1
12330
12500
  *
12331
12501
  * @file PlotBoilerplate
12332
12502
  * @fileoverview The main class.
@@ -12429,6 +12599,10 @@ class PlotBoilerplate {
12429
12599
  */
12430
12600
  constructor(config, drawConfig) {
12431
12601
  var _b, _c;
12602
+ /**
12603
+ * A list of content change listeners.
12604
+ */
12605
+ this.contentChangeListeners = [];
12432
12606
  /**
12433
12607
  * A discrete timestamp to identify single render cycles.
12434
12608
  * Note that using system time milliseconds is not a safe way to identify render frames, as on modern powerful machines
@@ -12816,6 +12990,52 @@ class PlotBoilerplate {
12816
12990
  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);
12817
12991
  }
12818
12992
  }
12993
+ /**
12994
+ * Adds a new content change listener to this instance. Adding duplicates is not possible.
12995
+ *
12996
+ * @param {PBContentChangeListener} listener - The listenre to add.
12997
+ * @method addContentChangeListener
12998
+ * @instance
12999
+ * @memberof PlotBoilerplate
13000
+ * @returns {void}
13001
+ */
13002
+ addContentChangeListener(listener) {
13003
+ for (var i in this.contentChangeListeners) {
13004
+ if (this.contentChangeListeners[i] === listener) {
13005
+ return;
13006
+ }
13007
+ }
13008
+ this.contentChangeListeners.push(listener);
13009
+ }
13010
+ /**
13011
+ * Removes an existing content change listener from this instance.
13012
+ *
13013
+ * @param {PBContentChangeListener} listener - The listenre to add.
13014
+ * @method removeContentChangeListener
13015
+ * @instance
13016
+ * @memberof PlotBoilerplate
13017
+ * @returns {void}
13018
+ */
13019
+ removeContentChangeListener(listener) {
13020
+ for (var i = 0; i < this.contentChangeListeners.length; i++) {
13021
+ if (this.contentChangeListeners[i] === listener) {
13022
+ this.contentChangeListeners.splice(i, 1);
13023
+ return;
13024
+ }
13025
+ }
13026
+ }
13027
+ _fireContentChanged(addedDrawables, removedDrawables) {
13028
+ for (var i in this.contentChangeListeners) {
13029
+ const listener = this.contentChangeListeners[i];
13030
+ if (listener && typeof listener === "function") {
13031
+ listener({
13032
+ type: addedDrawables.length > 0 ? "DRAWABLES_ADDED" : "DRAWABLES_REMOVED",
13033
+ addedDrawables: addedDrawables,
13034
+ removedDrawables: removedDrawables
13035
+ });
13036
+ }
13037
+ }
13038
+ }
12819
13039
  /**
12820
13040
  * Add a drawable object.<br>
12821
13041
  * <br>
@@ -12840,100 +13060,121 @@ class PlotBoilerplate {
12840
13060
  * @memberof PlotBoilerplate
12841
13061
  * @return {void}
12842
13062
  **/
12843
- add(drawable, redraw) {
13063
+ add(drawable, redraw, doNotFireEvent) {
12844
13064
  if (Array.isArray(drawable)) {
12845
13065
  const arr = drawable;
12846
13066
  for (var i = 0; i < arr.length; i++) {
12847
- this.add(arr[i], false);
13067
+ this.add(arr[i], false, doNotFireEvent);
12848
13068
  }
13069
+ // !doNotFireEvent && this._fireContentChanged(arr, []);
12849
13070
  }
12850
- else if (drawable instanceof Vertex) {
12851
- this.drawables.push(drawable);
12852
- this.vertices.push(drawable);
12853
- }
12854
- else if (drawable instanceof Line) {
12855
- // Add some lines
12856
- this.drawables.push(drawable);
12857
- this.vertices.push(drawable.a);
12858
- this.vertices.push(drawable.b);
12859
- }
12860
- else if (drawable instanceof Vector) {
12861
- this.drawables.push(drawable);
12862
- this.vertices.push(drawable.a);
12863
- this.vertices.push(drawable.b);
12864
- }
12865
- else if (drawable instanceof VEllipse) {
12866
- this.vertices.push(drawable.center);
12867
- this.vertices.push(drawable.axis);
12868
- this.drawables.push(drawable);
12869
- drawable.center.listeners.addDragListener((event) => {
12870
- drawable.axis.add(event.params.dragAmount);
12871
- });
12872
- }
12873
- else if (drawable instanceof VEllipseSector) {
12874
- this.vertices.push(drawable.ellipse.center);
12875
- this.vertices.push(drawable.ellipse.axis);
12876
- this.drawables.push(drawable);
12877
- drawable.ellipse.center.listeners.addDragListener((event) => {
12878
- drawable.ellipse.axis.add(event.params.dragAmount);
12879
- });
12880
- }
12881
- else if (drawable instanceof Circle) {
12882
- this.vertices.push(drawable.center);
12883
- this.drawables.push(drawable);
12884
- }
12885
- else if (drawable instanceof CircleSector) {
12886
- this.vertices.push(drawable.circle.center);
12887
- this.drawables.push(drawable);
12888
- }
12889
- else if (drawable instanceof Polygon) {
12890
- this.drawables.push(drawable);
12891
- for (var i = 0; i < drawable.vertices.length; i++) {
12892
- this.vertices.push(drawable.vertices[i]);
13071
+ else {
13072
+ const addedDrawables = [drawable];
13073
+ if (drawable instanceof Vertex) {
13074
+ this.drawables.push(drawable);
13075
+ this.vertices.push(drawable);
12893
13076
  }
12894
- }
12895
- else if (drawable instanceof Triangle) {
12896
- this.drawables.push(drawable);
12897
- this.vertices.push(drawable.a);
12898
- this.vertices.push(drawable.b);
12899
- this.vertices.push(drawable.c);
12900
- }
12901
- else if (drawable instanceof BezierPath) {
12902
- this.drawables.push(drawable);
12903
- const bezierPath = drawable;
12904
- for (var i = 0; i < bezierPath.bezierCurves.length; i++) {
12905
- if (!drawable.adjustCircular && i == 0) {
12906
- this.vertices.push(bezierPath.bezierCurves[i].startPoint);
13077
+ else if (drawable instanceof Line) {
13078
+ // Add some lines
13079
+ this.drawables.push(drawable);
13080
+ this.vertices.push(drawable.a);
13081
+ this.vertices.push(drawable.b);
13082
+ addedDrawables.push(drawable.a, drawable.b);
13083
+ }
13084
+ else if (drawable instanceof Vector) {
13085
+ this.drawables.push(drawable);
13086
+ this.vertices.push(drawable.a);
13087
+ this.vertices.push(drawable.b);
13088
+ addedDrawables.push(drawable.a, drawable.b);
13089
+ drawable.a.listeners.addDragListener((event) => {
13090
+ drawable.b.add(event.params.dragAmount);
13091
+ });
13092
+ }
13093
+ else if (drawable instanceof VEllipse) {
13094
+ this.vertices.push(drawable.center);
13095
+ this.vertices.push(drawable.axis);
13096
+ addedDrawables.push(drawable.center, drawable.axis);
13097
+ this.drawables.push(drawable);
13098
+ drawable.center.listeners.addDragListener((event) => {
13099
+ drawable.axis.add(event.params.dragAmount);
13100
+ });
13101
+ }
13102
+ else if (drawable instanceof VEllipseSector) {
13103
+ this.vertices.push(drawable.ellipse.center);
13104
+ this.vertices.push(drawable.ellipse.axis);
13105
+ addedDrawables.push(drawable.ellipse.center, drawable.ellipse.axis);
13106
+ this.drawables.push(drawable);
13107
+ drawable.ellipse.center.listeners.addDragListener((event) => {
13108
+ drawable.ellipse.axis.add(event.params.dragAmount);
13109
+ });
13110
+ }
13111
+ else if (drawable instanceof Circle) {
13112
+ this.vertices.push(drawable.center);
13113
+ addedDrawables.push(drawable.center);
13114
+ this.drawables.push(drawable);
13115
+ }
13116
+ else if (drawable instanceof CircleSector) {
13117
+ this.vertices.push(drawable.circle.center);
13118
+ addedDrawables.push(drawable.circle.center);
13119
+ this.drawables.push(drawable);
13120
+ }
13121
+ else if (drawable instanceof Polygon) {
13122
+ this.drawables.push(drawable);
13123
+ for (var i = 0; i < drawable.vertices.length; i++) {
13124
+ this.vertices.push(drawable.vertices[i]);
13125
+ addedDrawables.push(drawable.vertices[i]);
12907
13126
  }
12908
- this.vertices.push(bezierPath.bezierCurves[i].endPoint);
12909
- this.vertices.push(bezierPath.bezierCurves[i].startControlPoint);
12910
- this.vertices.push(bezierPath.bezierCurves[i].endControlPoint);
12911
- bezierPath.bezierCurves[i].startControlPoint.attr.selectable = false;
12912
- bezierPath.bezierCurves[i].endControlPoint.attr.selectable = false;
12913
13127
  }
12914
- PlotBoilerplate.utils.enableBezierPathAutoAdjust(drawable);
12915
- }
12916
- else if (drawable instanceof PBImage) {
12917
- this.vertices.push(drawable.upperLeft);
12918
- this.vertices.push(drawable.lowerRight);
12919
- this.drawables.push(drawable);
12920
- // Todo: think about a IDragEvent interface
12921
- drawable.upperLeft.listeners.addDragListener((e) => {
12922
- drawable.lowerRight.add(e.params.dragAmount);
12923
- });
12924
- drawable.lowerRight.attr.selectable = false;
12925
- }
12926
- else if (drawable instanceof PBText) {
12927
- this.vertices.push(drawable.anchor);
12928
- this.drawables.push(drawable);
12929
- drawable.anchor.attr.selectable = false;
12930
- }
12931
- else {
12932
- throw "Cannot add drawable of unrecognized type: " + typeof drawable + ".";
13128
+ else if (drawable instanceof Triangle) {
13129
+ this.drawables.push(drawable);
13130
+ this.vertices.push(drawable.a);
13131
+ this.vertices.push(drawable.b);
13132
+ this.vertices.push(drawable.c);
13133
+ addedDrawables.push(drawable.a, drawable.b, drawable.c);
13134
+ }
13135
+ else if (drawable instanceof BezierPath) {
13136
+ this.drawables.push(drawable);
13137
+ const bezierPath = drawable;
13138
+ for (var i = 0; i < bezierPath.bezierCurves.length; i++) {
13139
+ if (!drawable.adjustCircular && i == 0) {
13140
+ this.vertices.push(bezierPath.bezierCurves[i].startPoint);
13141
+ addedDrawables.push(bezierPath.bezierCurves[i].startPoint);
13142
+ }
13143
+ this.vertices.push(bezierPath.bezierCurves[i].endPoint);
13144
+ this.vertices.push(bezierPath.bezierCurves[i].startControlPoint);
13145
+ this.vertices.push(bezierPath.bezierCurves[i].endControlPoint);
13146
+ addedDrawables.push(bezierPath.bezierCurves[i].endPoint, bezierPath.bezierCurves[i].startControlPoint, bezierPath.bezierCurves[i].endControlPoint);
13147
+ bezierPath.bezierCurves[i].startControlPoint.attr.selectable = false;
13148
+ bezierPath.bezierCurves[i].endControlPoint.attr.selectable = false;
13149
+ }
13150
+ PlotBoilerplate.utils.enableBezierPathAutoAdjust(drawable);
13151
+ }
13152
+ else if (drawable instanceof PBImage) {
13153
+ this.vertices.push(drawable.upperLeft);
13154
+ this.vertices.push(drawable.lowerRight);
13155
+ addedDrawables.push(drawable.upperLeft, drawable.lowerRight);
13156
+ this.drawables.push(drawable);
13157
+ // Todo: think about a IDragEvent interface
13158
+ drawable.upperLeft.listeners.addDragListener((e) => {
13159
+ drawable.lowerRight.add(e.params.dragAmount);
13160
+ });
13161
+ drawable.lowerRight.attr.selectable = false;
13162
+ }
13163
+ else if (drawable instanceof PBText) {
13164
+ this.vertices.push(drawable.anchor);
13165
+ addedDrawables.push(drawable.anchor);
13166
+ this.drawables.push(drawable);
13167
+ drawable.anchor.attr.selectable = false;
13168
+ }
13169
+ else {
13170
+ throw "Cannot add drawable of unrecognized type: " + typeof drawable + ".";
13171
+ }
13172
+ !doNotFireEvent && this._fireContentChanged(addedDrawables, []);
12933
13173
  }
12934
13174
  // This is a workaround for backwards compatibility when the 'redraw' param was not yet present.
12935
- if (redraw || typeof redraw == "undefined")
13175
+ if (redraw || typeof redraw == "undefined") {
12936
13176
  this.redraw();
13177
+ }
12937
13178
  }
12938
13179
  /**
12939
13180
  * Remove a drawable object.<br>
@@ -12953,88 +13194,113 @@ class PlotBoilerplate {
12953
13194
  *
12954
13195
  * @param {Drawable|Array<Drawable>} drawable - The drawable (of one of the allowed class instance) to remove.
12955
13196
  * @param {boolean} [redraw=false]
13197
+ * @param {removeWidth}
12956
13198
  * @method remove
12957
13199
  * @instance
12958
13200
  * @memberof PlotBoilerplate
12959
13201
  * @return {void}
12960
13202
  **/
12961
- remove(drawable, redraw, removeWithVertices) {
13203
+ remove(drawable, redraw, removeWithVertices, doNotFireEvent) {
12962
13204
  if (Array.isArray(drawable)) {
13205
+ const removedDrawables = [];
12963
13206
  for (var i = 0; i < drawable.length; i++) {
12964
- this.remove(drawable[i], false, removeWithVertices);
13207
+ if (this.remove(drawable[i], false, removeWithVertices, true)) {
13208
+ removedDrawables.push(drawable[i]);
13209
+ }
12965
13210
  }
12966
13211
  if (redraw) {
12967
13212
  this.redraw();
12968
13213
  }
12969
- return;
13214
+ !doNotFireEvent && this._fireContentChanged([], removedDrawables);
13215
+ return removedDrawables.length > 0;
12970
13216
  }
12971
13217
  if (drawable instanceof Vertex) {
12972
- this.removeVertex(drawable, false);
13218
+ const wasRemoved = this.removeVertex(drawable, false, false);
12973
13219
  if (redraw) {
12974
13220
  this.redraw();
12975
13221
  }
13222
+ !doNotFireEvent && this._fireContentChanged([], [drawable]);
13223
+ return wasRemoved;
12976
13224
  }
13225
+ let wasRemoved = false;
13226
+ const removedDrawables = [];
12977
13227
  for (var i = 0; i < this.drawables.length; i++) {
12978
13228
  if (this.drawables[i] === drawable || this.drawables[i].uid === drawable.uid) {
12979
13229
  this.drawables.splice(i, 1);
13230
+ removedDrawables.push(drawable);
12980
13231
  if (removeWithVertices) {
12981
13232
  // Check if some listeners need to be removed
12982
13233
  if (drawable instanceof Line) {
12983
13234
  // Add some lines
12984
- this.removeVertex(drawable.a, false);
12985
- this.removeVertex(drawable.b, false);
13235
+ this.removeVertex(drawable.a, false, true);
13236
+ this.removeVertex(drawable.b, false, true);
13237
+ removedDrawables.push(drawable.a, drawable.b);
12986
13238
  }
12987
13239
  else if (drawable instanceof Vector) {
12988
- this.removeVertex(drawable.a, false);
12989
- this.removeVertex(drawable.b, false);
13240
+ this.removeVertex(drawable.a, false, true);
13241
+ this.removeVertex(drawable.b, false, true);
13242
+ removedDrawables.push(drawable.a, drawable.b);
12990
13243
  }
12991
13244
  else if (drawable instanceof VEllipse) {
12992
- this.removeVertex(drawable.center, false);
12993
- this.removeVertex(drawable.axis, false);
13245
+ this.removeVertex(drawable.center, false, true);
13246
+ this.removeVertex(drawable.axis, false, true);
13247
+ removedDrawables.push(drawable.center, drawable.axis);
12994
13248
  }
12995
13249
  else if (drawable instanceof VEllipseSector) {
12996
- this.removeVertex(drawable.ellipse.center);
12997
- this.removeVertex(drawable.ellipse.axis);
13250
+ this.removeVertex(drawable.ellipse.center, false, true);
13251
+ this.removeVertex(drawable.ellipse.axis, false, true);
13252
+ removedDrawables.push(drawable.ellipse.center, drawable.ellipse.axis);
12998
13253
  }
12999
13254
  else if (drawable instanceof Circle) {
13000
- this.removeVertex(drawable.center, false);
13255
+ this.removeVertex(drawable.center, false, true);
13001
13256
  }
13002
13257
  else if (drawable instanceof CircleSector) {
13003
- this.removeVertex(drawable.circle.center, false);
13258
+ this.removeVertex(drawable.circle.center, false, true);
13259
+ removedDrawables.push(drawable.circle.center);
13004
13260
  }
13005
13261
  else if (drawable instanceof Polygon) {
13006
13262
  // for( var i in drawable.vertices )
13007
- for (var i = 0; i < drawable.vertices.length; i++)
13008
- this.removeVertex(drawable.vertices[i], false);
13263
+ for (var i = 0; i < drawable.vertices.length; i++) {
13264
+ this.removeVertex(drawable.vertices[i], false, true);
13265
+ removedDrawables.push(drawable.vertices[i]);
13266
+ }
13009
13267
  }
13010
13268
  else if (drawable instanceof Triangle) {
13011
- this.removeVertex(drawable.a, false);
13012
- this.removeVertex(drawable.b, false);
13013
- this.removeVertex(drawable.c, false);
13269
+ this.removeVertex(drawable.a, false, true);
13270
+ this.removeVertex(drawable.b, false, true);
13271
+ this.removeVertex(drawable.c, false, true);
13272
+ removedDrawables.push(drawable.a, drawable.b, drawable.c);
13014
13273
  }
13015
13274
  else if (drawable instanceof BezierPath) {
13016
13275
  for (var i = 0; i < drawable.bezierCurves.length; i++) {
13017
- this.removeVertex(drawable.bezierCurves[i].startPoint, false);
13018
- this.removeVertex(drawable.bezierCurves[i].startControlPoint, false);
13019
- this.removeVertex(drawable.bezierCurves[i].endControlPoint, false);
13276
+ this.removeVertex(drawable.bezierCurves[i].startPoint, false, true);
13277
+ this.removeVertex(drawable.bezierCurves[i].startControlPoint, false, true);
13278
+ this.removeVertex(drawable.bezierCurves[i].endControlPoint, false, true);
13279
+ removedDrawables.push(drawable.bezierCurves[i].startPoint, drawable.bezierCurves[i].startControlPoint, drawable.bezierCurves[i].endControlPoint);
13020
13280
  if (i + 1 == drawable.bezierCurves.length) {
13021
- this.removeVertex(drawable.bezierCurves[i].endPoint, false);
13281
+ this.removeVertex(drawable.bezierCurves[i].endPoint, false, true);
13282
+ removedDrawables.push(drawable.bezierCurves[i].endPoint);
13022
13283
  }
13023
13284
  }
13024
13285
  }
13025
13286
  else if (drawable instanceof PBImage) {
13026
- this.removeVertex(drawable.upperLeft, false);
13027
- this.removeVertex(drawable.lowerRight, false);
13287
+ this.removeVertex(drawable.upperLeft, false, true);
13288
+ this.removeVertex(drawable.lowerRight, false, true);
13289
+ removedDrawables.push(drawable.upperLeft, drawable.lowerRight);
13028
13290
  }
13029
13291
  else if (drawable instanceof PBText) {
13030
- this.removeVertex(drawable.anchor, false);
13292
+ this.removeVertex(drawable.anchor, false, true);
13293
+ removedDrawables.push(drawable.anchor);
13031
13294
  }
13032
13295
  } // END removeWithVertices
13033
13296
  if (redraw) {
13034
13297
  this.redraw();
13035
13298
  }
13036
- }
13037
- }
13299
+ !doNotFireEvent && this._fireContentChanged([], removedDrawables);
13300
+ wasRemoved = true;
13301
+ } // END if
13302
+ } // END for
13303
+ return wasRemoved;
13038
13304
  }
13039
13305
  /**
13040
13306
  * Remove a vertex from the vertex list.<br>
@@ -13044,18 +13310,20 @@ class PlotBoilerplate {
13044
13310
  * @method removeVertex
13045
13311
  * @instance
13046
13312
  * @memberof PlotBoilerplate
13047
- * @return {void}
13313
+ * @return {boolean}
13048
13314
  **/
13049
- removeVertex(vert, redraw) {
13315
+ removeVertex(vert, redraw, doNotFireEvent) {
13050
13316
  for (var i = 0; i < this.vertices.length; i++) {
13051
13317
  if (this.vertices[i] === vert) {
13052
13318
  this.vertices.splice(i, 1);
13053
13319
  if (redraw) {
13054
13320
  this.redraw();
13055
13321
  }
13056
- return;
13322
+ !doNotFireEvent && this._fireContentChanged([], [vert]);
13323
+ return true;
13057
13324
  }
13058
13325
  }
13326
+ return false;
13059
13327
  }
13060
13328
  /**
13061
13329
  * Remove all elements.
@@ -13070,13 +13338,16 @@ class PlotBoilerplate {
13070
13338
  * @return {void}
13071
13339
  */
13072
13340
  removeAll(keepVertices, triggerRedraw) {
13341
+ let removedDrawables = this.drawables;
13073
13342
  this.drawables = [];
13074
13343
  if (!Boolean(keepVertices)) {
13344
+ removedDrawables = removedDrawables.concat(this.vertices);
13075
13345
  this.vertices = [];
13076
13346
  }
13077
13347
  if (triggerRedraw || typeof triggerRedraw === "undefined") {
13078
13348
  this.redraw();
13079
13349
  }
13350
+ removedDrawables.length > 0 && this._fireContentChanged([], removedDrawables);
13080
13351
  }
13081
13352
  /**
13082
13353
  * Find the vertex near the given position.
@@ -13331,7 +13602,7 @@ class PlotBoilerplate {
13331
13602
  d.b.attr.renderTime = renderTime;
13332
13603
  }
13333
13604
  else if (d instanceof Vector) {
13334
- draw.arrow(d.a, d.b, this.drawConfig.vector.color);
13605
+ draw.arrow(d.a, d.b, this.drawConfig.vector.color, this.drawConfig.vector.lineWidth);
13335
13606
  if (this.drawConfig.drawHandlePoints && d.b.attr.selectable && d.b.attr.visible) {
13336
13607
  draw.setCurrentId(`${d.uid}_h0`);
13337
13608
  draw.setCurrentClassName(`${d.className}-handle`);