plotboilerplate 1.20.2 → 1.22.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 (169) hide show
  1. package/dist/index.esm.js +2012 -1366
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/index.esm.min.js +1 -1
  4. package/dist/index.esm.min.js.map +1 -1
  5. package/dist/plotboilerplate.browser.min.js +1 -1
  6. package/dist/plotboilerplate.browser.min.js.map +1 -1
  7. package/dist/plotboilerplate.js +1199 -541
  8. package/dist/plotboilerplate.min.js +1 -1
  9. package/package.json +3 -2
  10. package/src/cjs/BezierPath.d.ts +27 -49
  11. package/src/cjs/BezierPath.js +67 -234
  12. package/src/cjs/BezierPath.js.map +1 -1
  13. package/src/cjs/Bounds.d.ts +14 -1
  14. package/src/cjs/Bounds.js +21 -1
  15. package/src/cjs/Bounds.js.map +1 -1
  16. package/src/cjs/CubicBezierCurve.d.ts +70 -1
  17. package/src/cjs/CubicBezierCurve.js +130 -12
  18. package/src/cjs/CubicBezierCurve.js.map +1 -1
  19. package/src/cjs/Line.d.ts +2 -1
  20. package/src/cjs/Line.js +1 -0
  21. package/src/cjs/Line.js.map +1 -1
  22. package/src/cjs/PBText.d.ts +2 -1
  23. package/src/cjs/PBText.js +10 -9
  24. package/src/cjs/PBText.js.map +1 -1
  25. package/src/cjs/PlotBoilerplate.d.ts +4 -13
  26. package/src/cjs/PlotBoilerplate.js +61 -15
  27. package/src/cjs/PlotBoilerplate.js.map +1 -1
  28. package/src/cjs/Polygon.d.ts +47 -1
  29. package/src/cjs/Polygon.js +116 -1
  30. package/src/cjs/Polygon.js.map +1 -1
  31. package/src/cjs/VEllipse.js +1 -1
  32. package/src/cjs/VEllipse.js.map +1 -1
  33. package/src/cjs/Vector.d.ts +4 -4
  34. package/src/cjs/Vector.js +2 -2
  35. package/src/cjs/Vector.js.map +1 -1
  36. package/src/cjs/VertTuple.d.ts +2 -1
  37. package/src/cjs/VertTuple.js +4 -3
  38. package/src/cjs/VertTuple.js.map +1 -1
  39. package/src/cjs/Vertex.d.ts +14 -3
  40. package/src/cjs/Vertex.js +18 -3
  41. package/src/cjs/Vertex.js.map +1 -1
  42. package/src/cjs/draw.d.ts +154 -75
  43. package/src/cjs/draw.js +308 -137
  44. package/src/cjs/draw.js.map +1 -1
  45. package/src/cjs/drawgl.d.ts +87 -50
  46. package/src/cjs/drawgl.js +86 -31
  47. package/src/cjs/drawgl.js.map +1 -1
  48. package/src/cjs/drawutilssvg.d.ts +226 -53
  49. package/src/cjs/drawutilssvg.js +374 -92
  50. package/src/cjs/drawutilssvg.js.map +1 -1
  51. package/src/cjs/interfaces/DrawLib.d.ts +157 -79
  52. package/src/cjs/interfaces/DrawLib.js +6 -0
  53. package/src/cjs/interfaces/DrawLib.js.map +1 -1
  54. package/src/cjs/interfaces/core.d.ts +13 -2
  55. package/src/cjs/interfaces/core.js +1 -0
  56. package/src/cjs/interfaces/core.js.map +1 -1
  57. package/src/cjs/utils/Params.d.ts +15 -0
  58. package/src/cjs/utils/Params.js +49 -0
  59. package/src/cjs/utils/Params.js.map +1 -0
  60. package/src/cjs/utils/algorithms/ContourLineDetection.d.ts +150 -0
  61. package/src/cjs/utils/algorithms/ContourLineDetection.js +367 -0
  62. package/src/cjs/utils/algorithms/ContourLineDetection.js.map +1 -0
  63. package/src/cjs/utils/algorithms/clearDuplicateVertices.d.ts +21 -0
  64. package/src/cjs/utils/algorithms/clearDuplicateVertices.js +48 -0
  65. package/src/cjs/utils/algorithms/clearDuplicateVertices.js.map +1 -0
  66. package/src/cjs/utils/creategui.js +16 -10
  67. package/src/cjs/utils/datastructures/DataGrid2d.d.ts +47 -0
  68. package/src/cjs/utils/datastructures/DataGrid2d.js +20 -0
  69. package/src/cjs/utils/datastructures/DataGrid2d.js.map +1 -0
  70. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.d.ts +65 -0
  71. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.js +84 -0
  72. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.js.map +1 -0
  73. package/src/cjs/utils/datastructures/GenericPath.d.ts +14 -3
  74. package/src/cjs/utils/datastructures/GenericPath.js +20 -3
  75. package/src/cjs/utils/datastructures/GenericPath.js.map +1 -1
  76. package/src/cjs/utils/detectDarkMode.d.ts +10 -0
  77. package/src/cjs/utils/detectDarkMode.js +32 -0
  78. package/src/cjs/utils/detectDarkMode.js.map +1 -0
  79. package/src/esm/BezierPath.d.ts +27 -49
  80. package/src/esm/BezierPath.js +67 -234
  81. package/src/esm/BezierPath.js.map +1 -1
  82. package/src/esm/Bounds.d.ts +14 -1
  83. package/src/esm/Bounds.js +19 -1
  84. package/src/esm/Bounds.js.map +1 -1
  85. package/src/esm/CubicBezierCurve.d.ts +70 -1
  86. package/src/esm/CubicBezierCurve.js +130 -12
  87. package/src/esm/CubicBezierCurve.js.map +1 -1
  88. package/src/esm/Line.d.ts +2 -1
  89. package/src/esm/Line.js +1 -0
  90. package/src/esm/Line.js.map +1 -1
  91. package/src/esm/PBText.d.ts +2 -1
  92. package/src/esm/PBText.js +10 -9
  93. package/src/esm/PBText.js.map +1 -1
  94. package/src/esm/PlotBoilerplate.d.ts +4 -13
  95. package/src/esm/PlotBoilerplate.js +62 -16
  96. package/src/esm/PlotBoilerplate.js.map +1 -1
  97. package/src/esm/Polygon.d.ts +47 -1
  98. package/src/esm/Polygon.js +114 -1
  99. package/src/esm/Polygon.js.map +1 -1
  100. package/src/esm/VEllipse.js +1 -1
  101. package/src/esm/VEllipse.js.map +1 -1
  102. package/src/esm/Vector.d.ts +4 -4
  103. package/src/esm/Vector.js +2 -2
  104. package/src/esm/Vector.js.map +1 -1
  105. package/src/esm/VertTuple.d.ts +2 -1
  106. package/src/esm/VertTuple.js +4 -3
  107. package/src/esm/VertTuple.js.map +1 -1
  108. package/src/esm/Vertex.d.ts +14 -3
  109. package/src/esm/Vertex.js +18 -3
  110. package/src/esm/Vertex.js.map +1 -1
  111. package/src/esm/draw.d.ts +154 -75
  112. package/src/esm/draw.js +304 -135
  113. package/src/esm/draw.js.map +1 -1
  114. package/src/esm/drawgl.d.ts +87 -50
  115. package/src/esm/drawgl.js +86 -31
  116. package/src/esm/drawgl.js.map +1 -1
  117. package/src/esm/drawutilssvg.d.ts +226 -53
  118. package/src/esm/drawutilssvg.js +369 -92
  119. package/src/esm/drawutilssvg.js.map +1 -1
  120. package/src/esm/interfaces/DrawLib.d.ts +157 -79
  121. package/src/esm/interfaces/DrawLib.js +6 -0
  122. package/src/esm/interfaces/DrawLib.js.map +1 -1
  123. package/src/esm/interfaces/core.d.ts +13 -2
  124. package/src/esm/interfaces/core.js +1 -0
  125. package/src/esm/interfaces/core.js.map +1 -1
  126. package/src/esm/utils/Params.d.ts +15 -0
  127. package/src/esm/utils/Params.js +44 -0
  128. package/src/esm/utils/Params.js.map +1 -0
  129. package/src/esm/utils/algorithms/ContourLineDetection.d.ts +150 -0
  130. package/src/esm/utils/algorithms/ContourLineDetection.js +362 -0
  131. package/src/esm/utils/algorithms/ContourLineDetection.js.map +1 -0
  132. package/src/esm/utils/algorithms/clearDuplicateVertices.d.ts +21 -0
  133. package/src/esm/utils/algorithms/clearDuplicateVertices.js +44 -0
  134. package/src/esm/utils/algorithms/clearDuplicateVertices.js.map +1 -0
  135. package/src/esm/utils/datastructures/DataGrid2d.d.ts +47 -0
  136. package/src/esm/utils/datastructures/DataGrid2d.js +19 -0
  137. package/src/esm/utils/datastructures/DataGrid2d.js.map +1 -0
  138. package/src/esm/utils/datastructures/DataGrid2dListAdapter.d.ts +65 -0
  139. package/src/esm/utils/datastructures/DataGrid2dListAdapter.js +79 -0
  140. package/src/esm/utils/datastructures/DataGrid2dListAdapter.js.map +1 -0
  141. package/src/esm/utils/datastructures/GenericPath.d.ts +14 -3
  142. package/src/esm/utils/datastructures/GenericPath.js +20 -3
  143. package/src/esm/utils/datastructures/GenericPath.js.map +1 -1
  144. package/src/esm/utils/detectDarkMode.d.ts +10 -0
  145. package/src/esm/utils/detectDarkMode.js +28 -0
  146. package/src/esm/utils/detectDarkMode.js.map +1 -0
  147. package/src/ts/BezierPath.ts +72 -241
  148. package/src/ts/Bounds.ts +25 -1
  149. package/src/ts/CubicBezierCurve.ts +139 -12
  150. package/src/ts/Line.ts +2 -1
  151. package/src/ts/PBText.ts +10 -9
  152. package/src/ts/PlotBoilerplate.ts +56 -19
  153. package/src/ts/Polygon.ts +121 -1
  154. package/src/ts/VEllipse.ts +2 -2
  155. package/src/ts/Vector.ts +4 -4
  156. package/src/ts/VertTuple.ts +4 -3
  157. package/src/ts/Vertex.ts +20 -4
  158. package/src/ts/draw.ts +311 -115
  159. package/src/ts/drawgl.ts +133 -71
  160. package/src/ts/drawutilssvg.ts +543 -121
  161. package/src/ts/interfaces/DrawLib.ts +219 -83
  162. package/src/ts/interfaces/core.ts +14 -2
  163. package/src/ts/utils/Params.ts +47 -0
  164. package/src/ts/utils/algorithms/ContourLineDetection.ts +485 -0
  165. package/src/ts/utils/algorithms/clearDuplicateVertices.ts +49 -0
  166. package/src/ts/utils/datastructures/DataGrid2d.ts +54 -0
  167. package/src/ts/utils/datastructures/DataGrid2dListAdapter.ts +121 -0
  168. package/src/ts/utils/datastructures/GenericPath.ts +21 -3
  169. package/src/ts/utils/detectDarkMode.ts +30 -0
@@ -37,7 +37,15 @@
37
37
  * @modified 2022-11-10 Tweaking some type issues.
38
38
  * @modified 2023-02-04 Fixed a typo in the CSS classname for cubic Bézier paths: cubicBezier (was cubierBezier).
39
39
  * @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.
40
- * @version 1.6.4
40
+ * @modified 2023-09-29 Added initialization checks for null parameters.
41
+ * @modified 2023-09-29 Added a missing implementation to the `drawurilssvg.do(XYCoords,string)` function. Didn't draw anything.
42
+ * @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.
43
+ * @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.
44
+ * @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.
45
+ * @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.
46
+ * @modified 2023-10-04 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.
47
+ *
48
+ * @version 1.6.7
41
49
  **/
42
50
 
43
51
  import { CircleSector } from "./CircleSector";
@@ -54,10 +62,12 @@ import {
54
62
  UID,
55
63
  DrawLibConfiguration,
56
64
  FontStyle,
57
- FontWeight
65
+ FontWeight,
66
+ StrokeOptions
58
67
  } from "./interfaces";
59
68
  import { Bounds } from "./Bounds";
60
69
  import { UIDGenerator } from "./UIDGenerator";
70
+ import { Vector } from "./Vector";
61
71
 
62
72
  const RAD_TO_DEG = 180 / Math.PI;
63
73
 
@@ -223,6 +233,9 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
223
233
  this.cache = new Map<UID, SVGElement>();
224
234
  this.setSize(canvasSize);
225
235
  if (isSecondary) {
236
+ if (!gNode || !bufferGNode || !nodeDefs || !bufferNodeDefs) {
237
+ throw "Cannot create secondary svg draw lib with undefinde gNode|bufferGNode|nodeDefs|bufferNodeDefs.";
238
+ }
226
239
  this.gNode = gNode;
227
240
  this.bufferGNode = bufferGNode;
228
241
  this.nodeDefs = nodeDefs;
@@ -369,6 +382,9 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
369
382
  if (this.drawlibConfiguration.blendMode) {
370
383
  node.style["mix-blend-mode"] = this.drawlibConfiguration.blendMode;
371
384
  }
385
+ // if (this.lineDashEnabled && this.lineDash && this.lineDash.length > 0 && drawutilssvg.nodeSupportsLineDash(nodeName)) {
386
+ // node.setAttribute("stroke-dasharray", this.lineDash.join(" "));
387
+ // }
372
388
  return node;
373
389
  }
374
390
 
@@ -392,22 +408,73 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
392
408
  * @param {number=1} lineWidth - (optional) A line width to use for drawing (default is 1).
393
409
  * @return {SVGElement} The node itself (for chaining).
394
410
  */
395
- private _bindFillDraw(node: SVGElement, className: string, color?: string | null, lineWidth?: number | null): SVGElement {
411
+ private _bindFillDraw(
412
+ node: SVGElement,
413
+ className: string,
414
+ color?: string | null,
415
+ lineWidth?: number | null,
416
+ strokeOptions?: StrokeOptions
417
+ ): SVGElement {
418
+ this._configureNode(node, className, this.fillShapes, color, lineWidth, strokeOptions);
419
+ return this._bindNode(node, undefined);
420
+ }
421
+
422
+ /**
423
+ * Bind this given node to a parent. If no parent is passed then the global
424
+ * node buffer will be used.
425
+ *
426
+ * @method _bindNode
427
+ * @private
428
+ * @instance
429
+ * @memberof drawutilssvg
430
+ * @param {SVGElement} node - The SVG node to bind.
431
+ * @param {SVGElement=} bindingParent - (optional) You may pass node other than the glober buffer node.
432
+ * @returns {SVGElement} The passed node itself.
433
+ */
434
+ private _bindNode(node: SVGElement, bindingParent?: SVGElement): SVGElement {
435
+ if (!node.parentNode) {
436
+ // Attach to DOM only if not already attached
437
+ (bindingParent ?? this.bufferGNode).appendChild(node);
438
+ }
439
+ return node;
440
+ }
441
+
442
+ /**
443
+ * Add custom CSS class names and the globally defined CSS classname to the
444
+ * given node.
445
+ *
446
+ * @method addCSSClasses
447
+ * @private
448
+ * @instance
449
+ * @memberof drawutilssvg
450
+ * @param {SVGElement} node - The SVG node to bind.
451
+ * @param {string} className - The additional custom classname to add.
452
+ * @returns {void}
453
+ */
454
+ private _addCSSClasses(node: SVGElement, className: string) {
396
455
  if (this.curClassName) {
397
456
  node.setAttribute("class", `${className} ${this.curClassName}`);
398
457
  } else {
399
458
  node.setAttribute("class", className);
400
459
  }
401
- node.setAttribute("fill", this.fillShapes && color ? color : "none");
402
- node.setAttribute("stroke", this.fillShapes ? "none" : color || "none");
460
+ }
461
+
462
+ private _configureNode(
463
+ node: SVGElement,
464
+ className: string,
465
+ fillMode: boolean,
466
+ color?: string | null,
467
+ lineWidth?: number | null,
468
+ strokeOptions?: StrokeOptions
469
+ ): SVGElement {
470
+ this._addCSSClasses(node, className);
471
+ node.setAttribute("fill", fillMode && color ? color : "none");
472
+ node.setAttribute("stroke", fillMode ? "none" : color || "none");
403
473
  node.setAttribute("stroke-width", `${lineWidth || 1}`);
404
474
  if (this.curId) {
405
475
  node.setAttribute("id", `${this.curId}`); // Maybe React-style 'key' would be better?
406
476
  }
407
- if (!node.parentNode) {
408
- // Attach to DOM only if not already attached
409
- this.bufferGNode.appendChild(node);
410
- }
477
+ this.applyStrokeOpts(node, strokeOptions);
411
478
  return node;
412
479
  }
413
480
 
@@ -437,7 +504,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
437
504
  this.scale,
438
505
  this.canvasSize,
439
506
  fillShapes,
440
- null, // no DrawConfig
507
+ null as any as DrawConfig, // no DrawConfig – this will work as long as `isSecondary===true`
441
508
  true, // isSecondary
442
509
  this.gNode,
443
510
  this.bufferGNode,
@@ -458,6 +525,21 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
458
525
  this.drawlibConfiguration = configuration;
459
526
  }
460
527
 
528
+ // /**
529
+ // * Set or clear the line-dash configuration. Pass `null` for un-dashed lines.
530
+ // *
531
+ // * See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
532
+ // * and https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
533
+ // * for how line dashes work.
534
+ // *
535
+ // * @method
536
+ // * @param {Array<number> lineDashes - The line-dash array configuration.
537
+ // * @returns {void}
538
+ // */
539
+ // setLineDash(lineDashes: Array<number>) {
540
+ // this.lineDash = lineDashes;
541
+ // }
542
+
461
543
  /**
462
544
  * This method shouled be called each time the currently drawn `Drawable` changes.
463
545
  * It is used by some libraries for identifying elemente on re-renders.
@@ -538,6 +620,32 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
538
620
  this.bufferedNodeDefs = tmpDefsNode;
539
621
  }
540
622
 
623
+ /**
624
+ * A private helper method to apply stroke options to the current
625
+ * context.
626
+ * @param {StrokeOptions=} strokeOptions -
627
+ */
628
+ private applyStrokeOpts(node: SVGElement, strokeOptions?: StrokeOptions) {
629
+ if (
630
+ strokeOptions &&
631
+ strokeOptions.dashArray &&
632
+ strokeOptions.dashArray.length > 0 &&
633
+ drawutilssvg.nodeSupportsLineDash(node.tagName)
634
+ ) {
635
+ node.setAttribute(
636
+ "stroke-dasharray",
637
+ strokeOptions.dashArray
638
+ .map((dashArayElem: number) => {
639
+ return dashArayElem * this.scale.x;
640
+ })
641
+ .join(" ")
642
+ );
643
+ if (strokeOptions.dashOffset) {
644
+ node.setAttribute("stroke-dashoffset", `${strokeOptions.dashOffset * this.scale.x}`);
645
+ }
646
+ }
647
+ }
648
+
541
649
  private _x(x: number): number {
542
650
  return this.offset.x + this.scale.x * x;
543
651
  }
@@ -549,49 +657,143 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
549
657
  * Draw the line between the given two points with the specified (CSS-) color.
550
658
  *
551
659
  * @method line
552
- * @param {Vertex} zA - The start point of the line.
553
- * @param {Vertex} zB - The end point of the line.
660
+ * @param {XYCoords} zA - The start point of the line.
661
+ * @param {XYCoords} zB - The end point of the line.
554
662
  * @param {string} color - Any valid CSS color string.
555
663
  * @param {number=1} lineWidth? - [optional] The line's width.
664
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
665
+ *
556
666
  * @return {void}
557
667
  * @instance
558
668
  * @memberof drawutilssvg
559
669
  **/
560
- line(zA: Vertex, zB: Vertex, color: string, lineWidth?: number): SVGElement {
561
- const line: SVGElement = this.makeNode("line");
562
- line.setAttribute("x1", `${this._x(zA.x)}`);
563
- line.setAttribute("y1", `${this._y(zA.y)}`);
564
- line.setAttribute("x2", `${this._x(zB.x)}`);
565
- line.setAttribute("y2", `${this._y(zB.y)}`);
566
-
567
- return this._bindFillDraw(line, "line", color, lineWidth || 1);
670
+ line(zA: XYCoords, zB: XYCoords, color: string, lineWidth?: number, strokeOptions?: StrokeOptions): SVGElement {
671
+ // const line: SVGElement = this.makeNode("line");
672
+ // this.applyStrokeOpts(line, strokeOptions);
673
+ // line.setAttribute("x1", `${this._x(zA.x)}`);
674
+ // line.setAttribute("y1", `${this._y(zA.y)}`);
675
+ // line.setAttribute("x2", `${this._x(zB.x)}`);
676
+ // line.setAttribute("y2", `${this._y(zB.y)}`);
677
+ const line = this.makeLineNode(zA, zB, color, lineWidth, strokeOptions);
678
+ return this._bindFillDraw(line, "line", color, lineWidth || 1, strokeOptions);
568
679
  }
569
680
 
570
681
  /**
571
682
  * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.
572
683
  *
573
684
  * @method arrow
574
- * @param {Vertex} zA - The start point of the arrow-line.
575
- * @param {Vertex} zB - The end point of the arrow-line.
685
+ * @param {XYCoords} zA - The start point of the arrow-line.
686
+ * @param {XYCoords} zB - The end point of the arrow-line.
576
687
  * @param {string} color - Any valid CSS color string.
577
688
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
689
+ * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).
690
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
691
+ *
578
692
  * @return {void}
579
693
  * @instance
580
694
  * @memberof drawutilssvg
581
695
  **/
582
- arrow(zA: Vertex, zB: Vertex, color: string, lineWidth?: number): SVGElement {
583
- const node: SVGElement = this.makeNode("path");
584
- var headlen: number = 8; // length of head in pixels
585
- var vertices: Array<Vertex> = Vertex.utils.buildArrowHead(zA, zB, headlen, this.scale.x, this.scale.y);
586
- const d: Array<string | number> = ["M", this._x(zA.x), this._y(zA.y)];
587
- for (var i = 0; i <= vertices.length; i++) {
588
- d.push("L");
589
- // Note: only use offset here (the vertices are already scaled)
590
- d.push(this.offset.x + vertices[i % vertices.length].x);
591
- d.push(this.offset.y + vertices[i % vertices.length].y);
592
- }
593
- node.setAttribute("d", d.join(" "));
594
- return this._bindFillDraw(node, "arrow", color, lineWidth || 1);
696
+ arrow(
697
+ zA: XYCoords,
698
+ zB: XYCoords,
699
+ color: string,
700
+ lineWidth?: number,
701
+ headLength: number = 8,
702
+ strokeOptions?: StrokeOptions
703
+ ): SVGElement {
704
+ const group: SVGElement = this.makeNode("g");
705
+ const arrowHeadBasePosition: XYCoords = { x: 0, y: 0 };
706
+ // Just create the child nodes, don't bind them to the root node.
707
+ const arrowHead: SVGElement = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, undefined, arrowHeadBasePosition);
708
+ const line: SVGElement = this.makeLineNode(zA, arrowHeadBasePosition, color, lineWidth, strokeOptions);
709
+ group.appendChild(line);
710
+ group.appendChild(arrowHead);
711
+ this._addCSSClasses(group, "linear-arrow");
712
+ this._bindNode(group, undefined);
713
+ return group;
714
+ }
715
+
716
+ /**
717
+ * 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.
718
+ *
719
+ * @method cubicBezierArrow
720
+ * @param {XYCoords} startPoint - The start point of the cubic Bézier curve
721
+ * @param {XYCoords} endPoint - The end point the cubic Bézier curve.
722
+ * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
723
+ * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
724
+ * @param {string} color - The CSS color to draw the curve with.
725
+ * @param {number} lineWidth - (optional) The line width to use.
726
+ * @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).
727
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
728
+ *
729
+ * @return {void}
730
+ * @instance
731
+ * @memberof DrawLib
732
+ */
733
+ cubicBezierArrow(
734
+ startPoint: XYCoords,
735
+ endPoint: XYCoords,
736
+ startControlPoint: XYCoords,
737
+ endControlPoint: XYCoords,
738
+ color: string,
739
+ lineWidth?: number,
740
+ headLength: number = 8,
741
+ strokeOptions?: StrokeOptions
742
+ ): SVGElement {
743
+ const group: SVGElement = this.makeNode("g");
744
+ // Just create the child nodes, don't bind them to the root node.
745
+ const arrowHeadBasePosition = new Vertex(0, 0);
746
+ const arrowHead: SVGElement = this.makeArrowHeadNode(
747
+ endControlPoint,
748
+ endPoint,
749
+ color,
750
+ lineWidth,
751
+ headLength,
752
+ undefined,
753
+ arrowHeadBasePosition
754
+ );
755
+ const diff = arrowHeadBasePosition.difference(endPoint);
756
+ const bezier: SVGElement = this.makeCubicBezierNode(
757
+ startPoint,
758
+ { x: endPoint.x - diff.x, y: endPoint.y - diff.y },
759
+ startControlPoint,
760
+ { x: endControlPoint.x - diff.x, y: endControlPoint.y - diff.y },
761
+ color,
762
+ lineWidth,
763
+ strokeOptions
764
+ );
765
+ group.appendChild(bezier);
766
+ group.appendChild(arrowHead);
767
+ this._addCSSClasses(group, "cubicbezier-arrow");
768
+ this._bindNode(group, undefined);
769
+ return group;
770
+ }
771
+
772
+ /**
773
+ * Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.
774
+ *
775
+ * @method arrow
776
+ * @param {XYCoords} zA - The start point of the arrow-line.
777
+ * @param {XYCoords} zB - The end point of the arrow-line.
778
+ * @param {string} color - Any valid CSS color string.
779
+ * @param {number=1} lineWidth - (optional) The line width to use; default is 1.
780
+ * @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).
781
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
782
+ *
783
+ * @return {void}
784
+ * @instance
785
+ * @memberof DrawLib
786
+ **/
787
+ arrowHead(
788
+ zA: XYCoords,
789
+ zB: XYCoords,
790
+ color: string,
791
+ lineWidth?: number,
792
+ headLength: number = 8,
793
+ strokeOptions?: StrokeOptions
794
+ ): SVGElement {
795
+ const node: SVGElement = this.makeArrowHeadNode(zA, zB, color, lineWidth, headLength, strokeOptions);
796
+ return this._bindFillDraw(node, "arrowhead", color, lineWidth || 1, strokeOptions);
595
797
  }
596
798
 
597
799
  /**
@@ -601,14 +803,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
601
803
  *
602
804
  * @method image
603
805
  * @param {Image} image - The image object to draw.
604
- * @param {Vertex} position - The position to draw the the upper left corner at.
605
- * @param {Vertex} size - The x/y-size to draw the image with.
806
+ * @param {XYCoords} position - The position to draw the the upper left corner at.
807
+ * @param {XYCoords} size - The x/y-size to draw the image with.
606
808
  * @param {number=0.0} alpha - (optional, default=0.0) The transparency (1.0=opaque, 0.0=transparent).
607
809
  * @return {void}
608
810
  * @instance
609
811
  * @memberof drawutilssvg
610
812
  **/
611
- image(image: HTMLImageElement, position: Vertex, size: Vertex, alpha: number = 1.0) {
813
+ image(image: HTMLImageElement, position: XYCoords, size: XYCoords, alpha: number = 1.0) {
612
814
  const node: SVGElement = this.makeNode("image");
613
815
 
614
816
  // We need to re-adjust the image if it was not yet fully loaded before.
@@ -618,7 +820,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
618
820
  const ratioY = size.y / image.naturalHeight;
619
821
  node.setAttribute("width", `${image.naturalWidth * this.scale.x}`);
620
822
  node.setAttribute("height", `${image.naturalHeight * this.scale.y}`);
621
- node.setAttribute("display", null); // Dislay when loaded
823
+ node.setAttribute("display", null as any as string); // Dislay when loaded
622
824
  // if (alpha) {
623
825
  node.setAttribute("opacity", `${alpha}`);
624
826
  // }
@@ -648,7 +850,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
648
850
  * @param {Image} textureImage - The image object to draw.
649
851
  * @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.
650
852
  * @param {Polygon} polygon - The polygon to use as clip path.
651
- * @param {Vertex} polygonPosition - The polygon's position (relative), measured at the bounding box's center.
853
+ * @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.
652
854
  * @param {number} rotation - The rotation to use for the polygon (and for the texture).
653
855
  * @return {void}
654
856
  * @instance
@@ -658,12 +860,12 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
658
860
  textureImage: HTMLImageElement,
659
861
  textureSize: Bounds,
660
862
  polygon: Polygon,
661
- polygonPosition: Vertex,
863
+ polygonPosition: XYCoords,
662
864
  rotation: number
663
865
  ): SVGElement {
664
- const basePolygonBounds: Bounds = polygon.getBounds();
866
+ // const basePolygonBounds: Bounds = polygon.getBounds();
665
867
  const rotatedScalingOrigin = new Vertex(textureSize.min).clone().rotate(rotation, polygonPosition);
666
- const rotationCenter = polygonPosition.clone().add(rotatedScalingOrigin.difference(textureSize.min).inv());
868
+ // const rotationCenter = polygonPosition.clone().add(rotatedScalingOrigin.difference(textureSize.min).inv());
667
869
  // Create something like this
668
870
  // ...
669
871
  // <defs>
@@ -727,50 +929,37 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
727
929
  * Draw the given (cubic) bézier curve.
728
930
  *
729
931
  * @method cubicBezier
730
- * @param {Vertex} startPoint - The start point of the cubic Bézier curve
731
- * @param {Vertex} endPoint - The end point the cubic Bézier curve.
732
- * @param {Vertex} startControlPoint - The start control point the cubic Bézier curve.
733
- * @param {Vertex} endControlPoint - The end control point the cubic Bézier curve.
932
+ * @param {XYCoords} startPoint - The start point of the cubic Bézier curve
933
+ * @param {XYCoords} endPoint - The end point the cubic Bézier curve.
934
+ * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
935
+ * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
734
936
  * @param {string} color - The CSS color to draw the curve with.
735
937
  * @param {number} lineWidth - (optional) The line width to use.
938
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
939
+ *
736
940
  * @return {void}
737
941
  * @instance
738
942
  * @memberof drawutilssvg
739
943
  */
740
944
  cubicBezier(
741
- startPoint: Vertex,
742
- endPoint: Vertex,
743
- startControlPoint: Vertex,
744
- endControlPoint: Vertex,
945
+ startPoint: XYCoords,
946
+ endPoint: XYCoords,
947
+ startControlPoint: XYCoords,
948
+ endControlPoint: XYCoords,
745
949
  color: string,
746
- lineWidth?: number
950
+ lineWidth?: number,
951
+ strokeOptions?: StrokeOptions
747
952
  ): SVGElement {
748
- if (startPoint instanceof CubicBezierCurve) {
749
- return this.cubicBezier(
750
- startPoint.startPoint,
751
- startPoint.endPoint,
752
- startPoint.startControlPoint,
753
- startPoint.endControlPoint,
754
- color,
755
- lineWidth
756
- );
757
- }
758
- const node: SVGElement = this.makeNode("path");
759
- // Draw curve
760
- const d: Array<string | number> = [
761
- "M",
762
- this._x(startPoint.x),
763
- this._y(startPoint.y),
764
- "C",
765
- this._x(startControlPoint.x),
766
- this._y(startControlPoint.y),
767
- this._x(endControlPoint.x),
768
- this._y(endControlPoint.y),
769
- this._x(endPoint.x),
770
- this._y(endPoint.y)
771
- ];
772
- node.setAttribute("d", d.join(" "));
773
- return this._bindFillDraw(node, "cubicBezier", color, lineWidth);
953
+ const node: SVGElement = this.makeCubicBezierNode(
954
+ startPoint,
955
+ endPoint,
956
+ startControlPoint,
957
+ endControlPoint,
958
+ color,
959
+ lineWidth,
960
+ strokeOptions
961
+ );
962
+ return this._bindNode(node, undefined);
774
963
  }
775
964
 
776
965
  /**
@@ -781,24 +970,29 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
781
970
  * <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>
782
971
  *
783
972
  * @method cubicBezierPath
784
- * @param {Vertex[]} path - The cubic bezier path as described above.
973
+ * @param {XYCoords[]} path - The cubic bezier path as described above.
785
974
  * @param {string} color - The CSS colot to draw the path with.
786
975
  * @param {number=1} lineWidth - (optional) The line width to use.
976
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
977
+ *
787
978
  * @return {void}
788
979
  * @instance
789
980
  * @memberof drawutilssvg
790
981
  */
791
- cubicBezierPath(path: Array<Vertex>, color: string, lineWidth?: number): SVGElement {
982
+ cubicBezierPath(path: Array<XYCoords>, color: string, lineWidth?: number, strokeOptions?: StrokeOptions): SVGElement {
792
983
  const node: SVGElement = this.makeNode("path");
793
- if (!path || path.length == 0) return node;
984
+ this.applyStrokeOpts(node, strokeOptions);
985
+ if (!path || path.length == 0) {
986
+ return node;
987
+ }
794
988
 
795
989
  // Draw curve
796
990
  const d: Array<string | number> = ["M", this._x(path[0].x), this._y(path[0].y)];
797
991
 
798
992
  // Draw curve path
799
- var endPoint: Vertex;
800
- var startControlPoint: Vertex;
801
- var endControlPoint: Vertex;
993
+ var endPoint: XYCoords;
994
+ var startControlPoint: XYCoords;
995
+ var endControlPoint: XYCoords;
802
996
  for (var i = 1; i < path.length; i += 3) {
803
997
  startControlPoint = path[i];
804
998
  endControlPoint = path[i + 1];
@@ -829,7 +1023,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
829
1023
  * @instance
830
1024
  * @memberof drawutilssvg
831
1025
  */
832
- handle(startPoint: Vertex, endPoint: Vertex): void {
1026
+ handle(startPoint: XYCoords, endPoint: XYCoords): void {
833
1027
  // TODO: redefine methods like these into an abstract class?
834
1028
  this.point(startPoint, "rgb(0,32,192)");
835
1029
  this.square(endPoint, 5, "rgba(0,128,192,0.5)");
@@ -839,28 +1033,32 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
839
1033
  * Draw a handle line (with a light grey).
840
1034
  *
841
1035
  * @method handleLine
842
- * @param {Vertex} startPoint - The start point to draw the handle at.
843
- * @param {Vertex} endPoint - The end point to draw the handle at.
1036
+ * @param {XYCoords} startPoint - The start point to draw the handle at.
1037
+ * @param {XYCoords} endPoint - The end point to draw the handle at.
844
1038
  * @return {void}
845
1039
  * @instance
846
1040
  * @memberof drawutilssvg
847
1041
  */
848
- handleLine(startPoint: Vertex, endPoint: Vertex): void {
849
- this.line(startPoint, endPoint, "rgb(192,192,192)");
1042
+ handleLine(startPoint: XYCoords, endPoint: XYCoords): void {
1043
+ this.line(startPoint, endPoint, "rgb(128,128,128,0.5)");
850
1044
  }
851
1045
 
852
1046
  /**
853
1047
  * Draw a 1x1 dot with the specified (CSS-) color.
854
1048
  *
855
1049
  * @method dot
856
- * @param {Vertex} p - The position to draw the dot at.
1050
+ * @param {XYCoords} p - The position to draw the dot at.
857
1051
  * @param {string} color - The CSS color to draw the dot with.
858
1052
  * @return {void}
859
1053
  * @instance
860
1054
  * @memberof drawutilssvg
861
1055
  */
862
- dot(p: Vertex, color: string) {
1056
+ dot(p: XYCoords, color: string) {
863
1057
  const node: SVGElement = this.makeNode("line");
1058
+ node.setAttribute("x1", `${this._x(p.x)}`);
1059
+ node.setAttribute("y1", `${this._y(p.y)}`);
1060
+ node.setAttribute("x2", `${this._x(p.x)}`);
1061
+ node.setAttribute("y2", `${this._y(p.y)}`);
864
1062
  return this._bindFillDraw(node, "dot", color, 1);
865
1063
  }
866
1064
 
@@ -868,13 +1066,13 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
868
1066
  * Draw the given point with the specified (CSS-) color and radius 3.
869
1067
  *
870
1068
  * @method point
871
- * @param {Vertex} p - The position to draw the point at.
1069
+ * @param {XYCoords} p - The position to draw the point at.
872
1070
  * @param {string} color - The CSS color to draw the point with.
873
1071
  * @return {void}
874
1072
  * @instance
875
1073
  * @memberof drawutilssvg
876
1074
  */
877
- point(p: Vertex, color: string) {
1075
+ point(p: XYCoords, color: string) {
878
1076
  var radius: number = 3;
879
1077
  const node: SVGElement = this.makeNode("circle");
880
1078
  node.setAttribute("cx", `${this._x(p.x)}`);
@@ -889,17 +1087,21 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
889
1087
  * Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.
890
1088
  *
891
1089
  * @method circle
892
- * @param {Vertex} center - The center of the circle.
1090
+ * @param {XYCoords} center - The center of the circle.
893
1091
  * @param {number} radius - The radius of the circle.
894
1092
  * @param {string} color - The CSS color to draw the circle with.
895
1093
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
1094
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1095
+ *
896
1096
  * @return {void}
897
1097
  * @instance
898
1098
  * @memberof drawutilssvg
899
1099
  */
900
- circle(center: Vertex, radius: number, color: string, lineWidth?: number) {
1100
+ circle(center: XYCoords, radius: number, color: string, lineWidth?: number, strokeOptions?: StrokeOptions) {
901
1101
  // Todo: draw ellipse when scalex!=scaley
902
1102
  const node: SVGElement = this.makeNode("circle");
1103
+ this.applyStrokeOpts(node, strokeOptions);
1104
+
903
1105
  node.setAttribute("cx", `${this._x(center.x)}`);
904
1106
  node.setAttribute("cy", `${this._y(center.y)}`);
905
1107
  node.setAttribute("r", `${radius * this.scale.x}`); // y?
@@ -911,17 +1113,29 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
911
1113
  * Draw a circular arc (section of a circle) with the given CSS color.
912
1114
  *
913
1115
  * @method circleArc
914
- * @param {Vertex} center - The center of the circle.
1116
+ * @param {XYCoords} center - The center of the circle.
915
1117
  * @param {number} radius - The radius of the circle.
916
1118
  * @param {number} startAngle - The angle to start at.
917
1119
  * @param {number} endAngle - The angle to end at.
918
1120
  * @param {string} color - The CSS color to draw the circle with.
1121
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1122
+ *
919
1123
  * @return {void}
920
1124
  * @instance
921
1125
  * @memberof drawutilssvg
922
1126
  */
923
- circleArc(center: Vertex, radius: number, startAngle: number, endAngle: number, color: string, lineWidth?: number) {
1127
+ circleArc(
1128
+ center: XYCoords,
1129
+ radius: number,
1130
+ startAngle: number,
1131
+ endAngle: number,
1132
+ color: string,
1133
+ lineWidth?: number,
1134
+ strokeOptions?: StrokeOptions
1135
+ ) {
924
1136
  const node: SVGElement = this.makeNode("path");
1137
+ this.applyStrokeOpts(node, strokeOptions);
1138
+
925
1139
  const arcData: SVGPathParams = CircleSector.circleSectorUtils.describeSVGArc(
926
1140
  this._x(center.x),
927
1141
  this._y(center.y),
@@ -937,21 +1151,33 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
937
1151
  * Draw an ellipse with the specified (CSS-) color and thw two radii.
938
1152
  *
939
1153
  * @method ellipse
940
- * @param {Vertex} center - The center of the ellipse.
1154
+ * @param {XYCoords} center - The center of the ellipse.
941
1155
  * @param {number} radiusX - The radius of the ellipse.
942
1156
  * @param {number} radiusY - The radius of the ellipse.
943
1157
  * @param {string} color - The CSS color to draw the ellipse with.
944
1158
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
945
1159
  * @param {number=} rotation - (optional, default=0) The rotation of the ellipse.
1160
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1161
+ *
946
1162
  * @return {void}
947
1163
  * @instance
948
1164
  * @memberof drawutilssvg
949
1165
  */
950
- ellipse(center: Vertex, radiusX: number, radiusY: number, color: string, lineWidth?: number, rotation?: number) {
1166
+ ellipse(
1167
+ center: XYCoords,
1168
+ radiusX: number,
1169
+ radiusY: number,
1170
+ color: string,
1171
+ lineWidth?: number,
1172
+ rotation?: number,
1173
+ strokeOptions?: StrokeOptions
1174
+ ) {
951
1175
  if (typeof rotation === "undefined") {
952
1176
  rotation = 0.0;
953
1177
  }
954
1178
  const node: SVGElement = this.makeNode("ellipse");
1179
+ this.applyStrokeOpts(node, strokeOptions);
1180
+
955
1181
  node.setAttribute("cx", `${this._x(center.x)}`);
956
1182
  node.setAttribute("cy", `${this._y(center.y)}`);
957
1183
  node.setAttribute("rx", `${radiusX * this.scale.x}`);
@@ -969,15 +1195,19 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
969
1195
  *
970
1196
  * @method square
971
1197
  * @param {XYCoords} center - The center of the square.
972
- * @param {Vertex} size - The size of the square.
1198
+ * @param {number} size - The size of the square.
973
1199
  * @param {string} color - The CSS color to draw the square with.
974
1200
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
975
- * @return {void}
1201
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1202
+ *
1203
+ * @return {SVGElement}
976
1204
  * @instance
977
1205
  * @memberof drawutilssvg
978
1206
  */
979
- square(center: XYCoords, size: number, color: string, lineWidth?: number) {
1207
+ square(center: XYCoords, size: number, color: string, lineWidth?: number, strokeOptions?: StrokeOptions): SVGElement {
980
1208
  const node: SVGElement = this.makeNode("rectangle");
1209
+ this.applyStrokeOpts(node, strokeOptions);
1210
+
981
1211
  node.setAttribute("x", `${this._x(center.x - size / 2.0)}`);
982
1212
  node.setAttribute("y", `${this._y(center.y - size / 2.0)}`);
983
1213
  node.setAttribute("width", `${size * this.scale.x}`);
@@ -994,9 +1224,23 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
994
1224
  * @param {number} height - The height of the rectangle.
995
1225
  * @param {string} color - The color to use.
996
1226
  * @param {number=1} lineWidth - (optional) The line with to use (default is 1).
1227
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1228
+ *
1229
+ * @return {SVGElement}
1230
+ * @instance
1231
+ * @memberof drawutilssvg
997
1232
  **/
998
- rect(position: XYCoords, width: number, height: number, color: string, lineWidth?: number) {
1233
+ rect(
1234
+ position: XYCoords,
1235
+ width: number,
1236
+ height: number,
1237
+ color: string,
1238
+ lineWidth?: number,
1239
+ strokeOptions?: StrokeOptions
1240
+ ): SVGElement {
999
1241
  const node: SVGElement = this.makeNode("rect");
1242
+ this.applyStrokeOpts(node, strokeOptions);
1243
+
1000
1244
  node.setAttribute("x", `${this._x(position.x)}`);
1001
1245
  node.setAttribute("y", `${this._y(position.y)}`);
1002
1246
  node.setAttribute("width", `${width * this.scale.x}`);
@@ -1009,7 +1253,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1009
1253
  * Draw a grid of horizontal and vertical lines with the given (CSS-) color.
1010
1254
  *
1011
1255
  * @method grid
1012
- * @param {Vertex} center - The center of the grid.
1256
+ * @param {XYCoords} center - The center of the grid.
1013
1257
  * @param {number} width - The total width of the grid (width/2 each to the left and to the right).
1014
1258
  * @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).
1015
1259
  * @param {number} sizeX - The horizontal grid size.
@@ -1019,7 +1263,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1019
1263
  * @instance
1020
1264
  * @memberof drawutilssvg
1021
1265
  */
1022
- grid(center: Vertex, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1266
+ grid(center: XYCoords, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1023
1267
  const node: SVGElement = this.makeNode("path");
1024
1268
  const d: SVGPathParams = [];
1025
1269
 
@@ -1046,7 +1290,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1046
1290
  * This works analogue to the grid() function
1047
1291
  *
1048
1292
  * @method raster
1049
- * @param {Vertex} center - The center of the raster.
1293
+ * @param {XYCoords} center - The center of the raster.
1050
1294
  * @param {number} width - The total width of the raster (width/2 each to the left and to the right).
1051
1295
  * @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).
1052
1296
  * @param {number} sizeX - The horizontal raster size.
@@ -1056,7 +1300,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1056
1300
  * @instance
1057
1301
  * @memberof drawutilssvg
1058
1302
  */
1059
- raster(center: Vertex, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1303
+ raster(center: XYCoords, width: number, height: number, sizeX: number, sizeY: number, color: string) {
1060
1304
  const node: SVGElement = this.makeNode("path");
1061
1305
  const d: SVGPathParams = [];
1062
1306
 
@@ -1083,14 +1327,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1083
1327
  * as even shaped diamonds.
1084
1328
  *
1085
1329
  * @method diamondHandle
1086
- * @param {Vertex} center - The center of the diamond.
1087
- * @param {Vertex} size - The x/y-size of the diamond.
1330
+ * @param {XYCoords} center - The center of the diamond.
1331
+ * @param {number} size - The x/y-size of the diamond.
1088
1332
  * @param {string} color - The CSS color to draw the diamond with.
1089
1333
  * @return {void}
1090
1334
  * @instance
1091
1335
  * @memberof drawutilssvg
1092
1336
  */
1093
- diamondHandle(center: Vertex, size: number, color: string) {
1337
+ diamondHandle(center: XYCoords, size: number, color: string) {
1094
1338
  const node: SVGElement = this.makeNode("path");
1095
1339
  const d: SVGPathParams = [
1096
1340
  "M",
@@ -1119,14 +1363,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1119
1363
  * as even shaped squares.
1120
1364
  *
1121
1365
  * @method squareHandle
1122
- * @param {Vertex} center - The center of the square.
1123
- * @param {Vertex} size - The x/y-size of the square.
1366
+ * @param {XYCoords} center - The center of the square.
1367
+ * @param {XYCoords} size - The x/y-size of the square.
1124
1368
  * @param {string} color - The CSS color to draw the square with.
1125
1369
  * @return {void}
1126
1370
  * @instance
1127
1371
  * @memberof drawutilssvg
1128
1372
  */
1129
- squareHandle(center: Vertex, size: number, color: string) {
1373
+ squareHandle(center: XYCoords, size: number, color: string) {
1130
1374
  const node: SVGElement = this.makeNode("rect");
1131
1375
  node.setAttribute("x", `${this._x(center.x) - size / 2.0}`);
1132
1376
  node.setAttribute("y", `${this._y(center.y) - size / 2.0}`);
@@ -1143,14 +1387,14 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1143
1387
  * as even shaped circles.
1144
1388
  *
1145
1389
  * @method circleHandle
1146
- * @param {Vertex} center - The center of the circle.
1390
+ * @param {XYCoords} center - The center of the circle.
1147
1391
  * @param {number} radius - The radius of the circle.
1148
1392
  * @param {string} color - The CSS color to draw the circle with.
1149
1393
  * @return {void}
1150
1394
  * @instance
1151
1395
  * @memberof drawutilssvg
1152
1396
  */
1153
- circleHandle(center: Vertex, radius: number, color: string) {
1397
+ circleHandle(center: XYCoords, radius: number, color: string) {
1154
1398
  radius = radius || 3;
1155
1399
 
1156
1400
  const node: SVGElement = this.makeNode("circle");
@@ -1247,17 +1491,29 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1247
1491
  * Draw a polygon line (alternative function to the polygon).
1248
1492
  *
1249
1493
  * @method polyline
1250
- * @param {Vertex[]} vertices - The polygon vertices to draw.
1494
+ * @param {XYCoords[]} vertices - The polygon vertices to draw.
1251
1495
  * @param {boolan} isOpen - If true the polyline will not be closed at its end.
1252
1496
  * @param {string} color - The CSS color to draw the polygon with.
1253
1497
  * @param {number=} lineWidth - (optional) The line width to use; default is 1.
1498
+ * @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
1499
+ *
1254
1500
  * @return {void}
1255
1501
  * @instance
1256
1502
  * @memberof drawutilssvg
1257
1503
  */
1258
- polyline(vertices: Array<Vertex>, isOpen: boolean, color: string, lineWidth?: number): SVGElement {
1504
+ polyline(
1505
+ vertices: Array<XYCoords>,
1506
+ isOpen: boolean,
1507
+ color: string,
1508
+ lineWidth?: number,
1509
+ strokeOptions?: StrokeOptions
1510
+ ): SVGElement {
1259
1511
  const node: SVGElement = this.makeNode("path");
1260
- if (vertices.length == 0) return node;
1512
+ this.applyStrokeOpts(node, strokeOptions);
1513
+
1514
+ if (vertices.length == 0) {
1515
+ return node;
1516
+ }
1261
1517
  // Draw curve
1262
1518
  const d: Array<string | number> = ["M", this._x(vertices[0].x), this._y(vertices[0].y)];
1263
1519
  var n = vertices.length;
@@ -1380,12 +1636,17 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1380
1636
  * @param {string=null} color - (optional) The color to draw this path with (default is null).
1381
1637
  * @param {number=1} lineWidth - (optional) the line width to use (default is 1).
1382
1638
  * @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.
1639
+ * @param {number=} options.dashOffset - (optional) `See StrokeOptions`.
1640
+ * @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.
1641
+ *
1383
1642
  * @instance
1384
1643
  * @memberof drawutils
1385
1644
  * @return {R} An instance representing the drawn path.
1386
1645
  */
1387
- path(pathData: SVGPathParams, color?: string, lineWidth?: number, options?: { inplace?: boolean }): SVGElement {
1646
+ path(pathData: SVGPathParams, color?: string, lineWidth?: number, options?: { inplace?: boolean } & StrokeOptions): SVGElement {
1388
1647
  const node: SVGElement = this.makeNode("path");
1648
+ this.applyStrokeOpts(node, options);
1649
+
1389
1650
  // Transform the path: in-place (fast) or copy (slower)
1390
1651
  const d: SVGPathParams = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);
1391
1652
  drawutilssvg.transformPathData(d, this.offset, this.scale);
@@ -1413,7 +1674,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1413
1674
 
1414
1675
  // Add a covering rect with the given background color
1415
1676
  this.curId = "background";
1416
- this.curClassName = undefined;
1677
+ this.curClassName = null; // undefined;
1417
1678
  const node: SVGElement = this.makeNode("rect");
1418
1679
  // For some strange reason SVG rotation transforms use degrees instead of radians
1419
1680
  // Note that the background does not scale with the zoom level (always covers full element)
@@ -1426,7 +1687,7 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1426
1687
  this._bindFillDraw(node, this.curId, null, null);
1427
1688
  node.setAttribute("fill", typeof color === "undefined" ? "none" : color);
1428
1689
  // Clear the current ID again
1429
- this.curId = undefined;
1690
+ this.curId = null; // undefined;
1430
1691
  }
1431
1692
 
1432
1693
  /**
@@ -1637,4 +1898,165 @@ export class drawutilssvg implements DrawLib<void | SVGElement> {
1637
1898
  }
1638
1899
  } // END while
1639
1900
  } // END transformPathData
1901
+
1902
+ private static nodeSupportsLineDash(nodeName: string) {
1903
+ return ["line", "path", "circle", "ellipse", "rectangle", "rect"].includes(nodeName);
1904
+ }
1905
+
1906
+ /**
1907
+ * Creates a basic <line> node with start and end coordinates. The created node will not
1908
+ * be bound to any root node.
1909
+ *
1910
+ * @private
1911
+ * @method makeLineNode
1912
+ * @param {XYCoords} zA - The line's start position.
1913
+ * @param {XYCoords} zB - The line's start position.
1914
+ * @param {string} color - The CSS color to draw the point with.
1915
+ * @param {number=1} lineWidth - (optional) The line width to use.
1916
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
1917
+ * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.
1918
+ * @return {SVGLineElement}
1919
+ * @instance
1920
+ * @memberof drawutilssvg
1921
+ */
1922
+ private makeLineNode(
1923
+ zA: XYCoords,
1924
+ zB: XYCoords,
1925
+ color: string,
1926
+ lineWidth?: number,
1927
+ strokeOptions?: StrokeOptions,
1928
+ classNameOverride?: string
1929
+ ): SVGLineElement {
1930
+ const line: SVGLineElement = this.makeNode("line") as SVGLineElement;
1931
+ line.setAttribute("x1", `${this._x(zA.x)}`);
1932
+ line.setAttribute("y1", `${this._y(zA.y)}`);
1933
+ line.setAttribute("x2", `${this._x(zB.x)}`);
1934
+ line.setAttribute("y2", `${this._y(zB.y)}`);
1935
+ this._configureNode(line, classNameOverride ?? "line", this.fillShapes, color, lineWidth || 1, strokeOptions);
1936
+ return line;
1937
+ }
1938
+
1939
+ /**
1940
+ * Creates a basic <path> node with given path string data. The created node will not
1941
+ * be bound to any root node.
1942
+ *
1943
+ * @private
1944
+ * @method makePathNode
1945
+ * @param {string} pathString - The path data (must be a valid path data string).
1946
+ * @param {string} color - The CSS color to draw the point with.
1947
+ * @param {number=1} lineWidth - (optional) The line width to use.
1948
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
1949
+ * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.
1950
+ * @return {SVGPathElement}
1951
+ * @instance
1952
+ * @memberof drawutilssvg
1953
+ */
1954
+ private makePathNode(
1955
+ pathString: string,
1956
+ color: string,
1957
+ lineWidth?: number,
1958
+ strokeOptions?: StrokeOptions,
1959
+ classNameOverride?: string
1960
+ ): SVGPathElement {
1961
+ const path: SVGPathElement = this.makeNode("path") as SVGPathElement;
1962
+ path.setAttribute("d", pathString);
1963
+ this._configureNode(path, classNameOverride ?? "path", this.fillShapes, color, lineWidth || 1, strokeOptions);
1964
+ return path;
1965
+ }
1966
+
1967
+ /**
1968
+ * Creates a basic arrow head node (<path> node) at the end of the given line coordinates. The created node will not
1969
+ * be bound to any root node.
1970
+ *
1971
+ * @private
1972
+ * @method makeArrowHeadNode
1973
+ * @param {string} pathString - The path data (must be a valid path data string).
1974
+ * @param {string} color - The CSS color to draw the point with.
1975
+ * @param {number=1} lineWidth - (optional) The line width to use.
1976
+ * @param {number=8} headLength - (optional) The length of the arrow head; if none is specified then the head will be 8 absolute units long.
1977
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
1978
+ * @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.
1979
+ * @return {SVGPathElement}
1980
+ * @instance
1981
+ * @memberof drawutilssvg
1982
+ */
1983
+ private makeArrowHeadNode(
1984
+ zA: XYCoords,
1985
+ zB: XYCoords,
1986
+ color: string,
1987
+ lineWidth?: number,
1988
+ headLength: number = 8,
1989
+ strokeOptions?: StrokeOptions,
1990
+ arrowHeadBasePositionBuffer?: XYCoords
1991
+ ): SVGPathElement {
1992
+ var vertices: Array<Vertex> = Vector.utils.buildArrowHead(zA, zB, headLength, this.scale.x, this.scale.y);
1993
+ const d: Array<string | number> = ["M", this.offset.x + vertices[0].x, this.offset.y + vertices[0].y];
1994
+ if (arrowHeadBasePositionBuffer) {
1995
+ arrowHeadBasePositionBuffer.x = vertices[0].x / this.scale.x;
1996
+ arrowHeadBasePositionBuffer.y = vertices[0].y / this.scale.y;
1997
+ }
1998
+ for (var i = 1; i <= vertices.length; i++) {
1999
+ d.push("L");
2000
+ // Note: only use offset here (the vertices are already scaled)
2001
+ d.push(this.offset.x + vertices[i % vertices.length].x);
2002
+ d.push(this.offset.y + vertices[i % vertices.length].y);
2003
+ }
2004
+ const node: SVGPathElement = this.makePathNode(d.join(" "), color, lineWidth, strokeOptions, "arrowhead");
2005
+ return node;
2006
+ }
2007
+
2008
+ /**
2009
+ * Creates a basic cubic Bézier path node (<path> node) with the given cubic Bézier data. The created node will not
2010
+ * be bound to any root node.
2011
+ *
2012
+ * @private
2013
+ * @method makeCubicBezierNode
2014
+ * @param {XYCoords} startPoint - The start point of the cubic Bézier curve
2015
+ * @param {XYCoords} endPoint - The end point the cubic Bézier curve.
2016
+ * @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
2017
+ * @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
2018
+ * @param {string} color - The CSS color to draw the point with.
2019
+ * @param {number=1} lineWidth - (optional) The line width to use.
2020
+ * @param {StrokeOptions=} strokeOptions - (optional) Additional stroke options to use.
2021
+ * @param {string=} classNameOverride - (optional) If nothing is passed the default classname 'path' will be used.
2022
+ * @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.
2023
+ * @return {SVGPathElement}
2024
+ * @instance
2025
+ * @memberof drawutilssvg
2026
+ */
2027
+ private makeCubicBezierNode(
2028
+ startPoint: XYCoords,
2029
+ endPoint: XYCoords,
2030
+ startControlPoint: XYCoords,
2031
+ endControlPoint: XYCoords,
2032
+ color: string,
2033
+ lineWidth?: number,
2034
+ strokeOptions?: StrokeOptions
2035
+ ): SVGElement {
2036
+ if (startPoint instanceof CubicBezierCurve) {
2037
+ return this.cubicBezier(
2038
+ startPoint.startPoint,
2039
+ startPoint.endPoint,
2040
+ startPoint.startControlPoint,
2041
+ startPoint.endControlPoint,
2042
+ color,
2043
+ lineWidth
2044
+ );
2045
+ }
2046
+ // Draw curve
2047
+ const d: Array<string | number> = [
2048
+ "M",
2049
+ this._x(startPoint.x),
2050
+ this._y(startPoint.y),
2051
+ "C",
2052
+ this._x(startControlPoint.x),
2053
+ this._y(startControlPoint.y),
2054
+ this._x(endControlPoint.x),
2055
+ this._y(endControlPoint.y),
2056
+ this._x(endPoint.x),
2057
+ this._y(endPoint.y)
2058
+ ];
2059
+ const node: SVGElement = this.makePathNode(d.join(" "), color, lineWidth, strokeOptions, "cubicBezier");
2060
+ return node;
2061
+ }
1640
2062
  }