plotboilerplate 1.17.1 → 1.19.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 (117) hide show
  1. package/README.md +63 -6
  2. package/dist/index.esm.js +278 -60
  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 +276 -58
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +1 -1
  11. package/src/cjs/Bounds.d.ts +11 -1
  12. package/src/cjs/Bounds.js +13 -1
  13. package/src/cjs/Bounds.js.map +1 -1
  14. package/src/cjs/Circle.d.ts +36 -2
  15. package/src/cjs/Circle.js +81 -1
  16. package/src/cjs/Circle.js.map +1 -1
  17. package/src/cjs/CubicBezierCurve.d.ts +20 -3
  18. package/src/cjs/CubicBezierCurve.js +25 -2
  19. package/src/cjs/CubicBezierCurve.js.map +1 -1
  20. package/src/cjs/Line.d.ts +46 -4
  21. package/src/cjs/Line.js +60 -3
  22. package/src/cjs/Line.js.map +1 -1
  23. package/src/cjs/MouseHandler.d.ts +3 -2
  24. package/src/cjs/MouseHandler.js +16 -14
  25. package/src/cjs/MouseHandler.js.map +1 -1
  26. package/src/cjs/PlotBoilerplate.d.ts +4 -2
  27. package/src/cjs/PlotBoilerplate.js +44 -28
  28. package/src/cjs/PlotBoilerplate.js.map +1 -1
  29. package/src/cjs/Polygon.js +1 -1
  30. package/src/cjs/Polygon.js.map +1 -1
  31. package/src/cjs/Vector.d.ts +14 -3
  32. package/src/cjs/Vector.js +21 -2
  33. package/src/cjs/Vector.js.map +1 -1
  34. package/src/cjs/draw.d.ts +4 -1
  35. package/src/cjs/draw.js +15 -6
  36. package/src/cjs/draw.js.map +1 -1
  37. package/src/cjs/interfaces/additionals.d.ts +95 -0
  38. package/src/cjs/interfaces/additionals.js +3 -0
  39. package/src/cjs/interfaces/additionals.js.map +1 -0
  40. package/src/cjs/interfaces/core.d.ts +4 -0
  41. package/src/cjs/interfaces/core.js +1 -0
  42. package/src/cjs/interfaces/core.js.map +1 -1
  43. package/src/cjs/interfaces/index.d.ts +1 -0
  44. package/src/cjs/interfaces/index.js +1 -0
  45. package/src/cjs/interfaces/index.js.map +1 -1
  46. package/src/cjs/utils/algorithms/arrayShuffle.d.ts +8 -0
  47. package/src/cjs/utils/algorithms/arrayShuffle.js +15 -0
  48. package/src/cjs/utils/algorithms/arrayShuffle.js.map +1 -0
  49. package/src/cjs/utils/algorithms/detectPaths.d.ts +20 -0
  50. package/src/cjs/utils/algorithms/detectPaths.js +169 -0
  51. package/src/cjs/utils/algorithms/detectPaths.js.map +1 -0
  52. package/src/cjs/utils/datastructures/GenericPath.d.ts +75 -0
  53. package/src/cjs/utils/datastructures/GenericPath.js +105 -0
  54. package/src/cjs/utils/datastructures/GenericPath.js.map +1 -0
  55. package/src/cjs/utils/datastructures/GirihTile.d.ts +1 -1
  56. package/src/esm/Bounds.d.ts +11 -1
  57. package/src/esm/Bounds.js +13 -1
  58. package/src/esm/Bounds.js.map +1 -1
  59. package/src/esm/Circle.d.ts +36 -2
  60. package/src/esm/Circle.js +81 -1
  61. package/src/esm/Circle.js.map +1 -1
  62. package/src/esm/CubicBezierCurve.d.ts +20 -3
  63. package/src/esm/CubicBezierCurve.js +25 -2
  64. package/src/esm/CubicBezierCurve.js.map +1 -1
  65. package/src/esm/Line.d.ts +46 -4
  66. package/src/esm/Line.js +60 -3
  67. package/src/esm/Line.js.map +1 -1
  68. package/src/esm/MouseHandler.d.ts +3 -2
  69. package/src/esm/MouseHandler.js +16 -14
  70. package/src/esm/MouseHandler.js.map +1 -1
  71. package/src/esm/PlotBoilerplate.d.ts +4 -2
  72. package/src/esm/PlotBoilerplate.js +44 -28
  73. package/src/esm/PlotBoilerplate.js.map +1 -1
  74. package/src/esm/Polygon.js +1 -1
  75. package/src/esm/Polygon.js.map +1 -1
  76. package/src/esm/Vector.d.ts +13 -2
  77. package/src/esm/Vector.js +23 -4
  78. package/src/esm/Vector.js.map +1 -1
  79. package/src/esm/draw.d.ts +4 -1
  80. package/src/esm/draw.js +15 -6
  81. package/src/esm/draw.js.map +1 -1
  82. package/src/esm/interfaces/additionals.d.ts +95 -0
  83. package/src/esm/interfaces/additionals.js +2 -0
  84. package/src/esm/interfaces/additionals.js.map +1 -0
  85. package/src/esm/interfaces/core.d.ts +4 -0
  86. package/src/esm/interfaces/core.js +1 -0
  87. package/src/esm/interfaces/core.js.map +1 -1
  88. package/src/esm/interfaces/index.d.ts +1 -0
  89. package/src/esm/interfaces/index.js +1 -0
  90. package/src/esm/interfaces/index.js.map +1 -1
  91. package/src/esm/utils/algorithms/arrayShuffle.d.ts +8 -0
  92. package/src/esm/utils/algorithms/arrayShuffle.js +11 -0
  93. package/src/esm/utils/algorithms/arrayShuffle.js.map +1 -0
  94. package/src/esm/utils/algorithms/detectPaths.d.ts +20 -0
  95. package/src/esm/utils/algorithms/detectPaths.js +165 -0
  96. package/src/esm/utils/algorithms/detectPaths.js.map +1 -0
  97. package/src/esm/utils/datastructures/GenericPath.d.ts +75 -0
  98. package/src/esm/utils/datastructures/GenericPath.js +100 -0
  99. package/src/esm/utils/datastructures/GenericPath.js.map +1 -0
  100. package/src/esm/utils/datastructures/GirihTile.d.ts +1 -1
  101. package/src/ts/Bounds.ts +14 -1
  102. package/src/ts/Circle.ts +92 -2
  103. package/src/ts/CubicBezierCurve.ts +29 -4
  104. package/src/ts/Line.ts +70 -6
  105. package/src/ts/MouseHandler.ts +16 -15
  106. package/src/ts/PlotBoilerplate.ts +47 -32
  107. package/src/ts/Polygon.ts +1 -1
  108. package/src/ts/Vector.ts +24 -4
  109. package/src/ts/draw.ts +15 -6
  110. package/src/ts/interfaces/additionals.ts +105 -0
  111. package/src/ts/interfaces/core.ts +2 -0
  112. package/src/ts/interfaces/index.ts +1 -0
  113. package/src/ts/utils/algorithms/arrayShuffle.ts +11 -0
  114. package/src/ts/utils/algorithms/detectPaths.ts +195 -0
  115. package/src/ts/utils/datastructures/GenericPath.ts +113 -0
  116. package/src/ts/utils/datastructures/GirihTile.ts +1 -1
  117. package/changelog.md +0 -722
package/src/ts/Line.ts CHANGED
@@ -13,7 +13,9 @@
13
13
  * @modified 2020-03-23 Ported to Typescript from JS.
14
14
  * @modified 2020-12-04 The `intersection` function returns undefined if both lines are parallel.
15
15
  * @modified 2022-02-02 Added the `destroy` method.
16
- * @version 2.2.0
16
+ * @modified 2022-10-09 Changed the actual return value of the `intersection` function to null (was undefined before).
17
+ * @modified 2022-10-17 Adding these methods from the `PathSegment` interface: getStartPoint, getEndPoint, revert.
18
+ * @version 2.3.0
17
19
  *
18
20
  * @file Line
19
21
  * @public
@@ -21,7 +23,7 @@
21
23
 
22
24
  import { VertTuple } from "./VertTuple";
23
25
  import { Vertex } from "./Vertex";
24
- import { SVGSerializable } from "./interfaces";
26
+ import { PathSegment, SVGSerializable } from "./interfaces";
25
27
 
26
28
  /**
27
29
  * @classdesc A line consists of two vertices a and b.<br>
@@ -31,7 +33,7 @@ import { SVGSerializable } from "./interfaces";
31
33
  *
32
34
  * @requires Vertex
33
35
  */
34
- export class Line extends VertTuple<Line> implements SVGSerializable {
36
+ export class Line extends VertTuple<Line> implements SVGSerializable, PathSegment {
35
37
  /**
36
38
  * Required to generate proper CSS classes and other class related IDs.
37
39
  **/
@@ -59,9 +61,11 @@ export class Line extends VertTuple<Line> implements SVGSerializable {
59
61
  * @memberof Line
60
62
  **/
61
63
  // !!! DO NOT MOVE TO VertTuple
62
- intersection(line: Line): Vertex | undefined {
64
+ intersection(line: Line): Vertex | null {
63
65
  const denominator: number = this.denominator(line);
64
- if (denominator == 0) return null;
66
+ if (denominator == 0) {
67
+ return null;
68
+ }
65
69
 
66
70
  let a: number = this.a.y - line.a.y;
67
71
  let b: number = this.a.x - line.a.x;
@@ -75,10 +79,70 @@ export class Line extends VertTuple<Line> implements SVGSerializable {
75
79
  const y: number = this.a.y + a * (this.b.y - this.a.y);
76
80
 
77
81
  if (isNaN(a) || isNaN(x) || isNaN(y)) {
78
- return undefined;
82
+ return null;
79
83
  }
80
84
 
81
85
  // if we cast these lines infinitely in both directions, they intersect here:
82
86
  return new Vertex(x, y);
83
87
  }
88
+
89
+ //--- Implement PathSegment ---
90
+ /**
91
+ * Get the start point of this path segment.
92
+ *
93
+ * @method getStartPoint
94
+ * @memberof PathSegment
95
+ * @return {Vertex} The start point of this path segment.
96
+ */
97
+ getStartPoint(): Vertex {
98
+ return this.a;
99
+ }
100
+
101
+ /**
102
+ * Get the end point of this path segment.
103
+ *
104
+ * @method getEndPoint
105
+ * @memberof PathSegment
106
+ * @return {Vertex} The end point of this path segment.
107
+ */
108
+ getEndPoint(): Vertex {
109
+ return this.b;
110
+ }
111
+
112
+ /**
113
+ * Get the tangent's end point at the start point of this segment.
114
+ *
115
+ * @method getStartTangent
116
+ * @memberof PathSegment
117
+ * @return {Vertex} The end point of the starting point's tangent.
118
+ */
119
+ getStartTangent(): Vertex {
120
+ return this.b;
121
+ }
122
+
123
+ /**
124
+ * Get the tangent's end point at the end point of this segment.
125
+ *
126
+ * @method getEndTangent
127
+ * @memberof PathSegment
128
+ * @return {Vertex} The end point of the ending point's tangent.
129
+ */
130
+ getEndTangent(): Vertex {
131
+ return this.a;
132
+ }
133
+
134
+ /**
135
+ * Inverse this path segment (in-place) and return this same instance (useful for chaining).
136
+ *
137
+ * @method reverse
138
+ * @memberof PathSegment
139
+ * @return {PathSegment} This path segment instance (for chaining).
140
+ */
141
+ reverse(): Line {
142
+ var tmp = this.a;
143
+ this.a = this.b;
144
+ this.b = tmp;
145
+ return this;
146
+ }
147
+ //--- END Implement PathSegment ---
84
148
  }
@@ -17,7 +17,8 @@
17
17
  * @modified 2020-10-04 Added extended JSDoc comments.
18
18
  * @modified 2020-11-25 Added the `isTouchEvent` param.
19
19
  * @modified 2021-01-10 The mouse handler is now also working with SVGElements.
20
- * @version 1.2.0
20
+ * @modified 2022-08-16 Fixed a bug in the mouse button detection.
21
+ * @version 1.2.1
21
22
  *
22
23
  * @file MouseHandler
23
24
  * @public
@@ -58,7 +59,7 @@ export type XWheelCallback = (e: XWheelEvent) => void;
58
59
  * @requires XYCoords
59
60
  */
60
61
  export class MouseHandler {
61
- private name: string;
62
+ private name: string | undefined;
62
63
  private element: HTMLElement | SVGElement;
63
64
  private mouseDownPos: { x: number; y: number } | undefined = undefined;
64
65
  private mouseDragPos: { x: number; y: number } | undefined = undefined;
@@ -135,8 +136,8 @@ export class MouseHandler {
135
136
  // +-------------------------------------------------
136
137
  this.name = name;
137
138
  this.element = element;
138
- this.mouseDownPos = null;
139
- this.mouseDragPos = null;
139
+ this.mouseDownPos = undefined;
140
+ this.mouseDragPos = undefined;
140
141
  // this.mousePos = null;
141
142
  this.mouseButton = -1;
142
143
  this.listeners = {};
@@ -202,26 +203,26 @@ export class MouseHandler {
202
203
  * @memberof MouseHandler
203
204
  * @instance
204
205
  * @private
205
- * @param {MouseEvent} e - The mouse event to get the relative position for.
206
+ * @param {MouseEvent} event - The mouse event to get the relative position for.
206
207
  * @param {string} eventName - The name of the firing event.
207
208
  * @return {XMouseEvent}
208
209
  */
209
- private mkParams(e: MouseEvent, eventName: string): XMouseEvent {
210
- const rel: { x: number; y: number } = this.relPos(e);
211
- const xEvent: XMouseEvent = e as unknown as XMouseEvent;
210
+ private mkParams(event: MouseEvent, eventName: string): XMouseEvent {
211
+ const rel: { x: number; y: number } = this.relPos(event);
212
+ const xEvent: XMouseEvent = event as unknown as XMouseEvent;
212
213
  xEvent.params = {
213
214
  element: this.element,
214
215
  name: eventName,
215
216
  isTouchEvent: false,
216
217
  pos: rel,
217
- button: this.mouseButton,
218
- leftButton: this.mouseButton == 0,
219
- middleButton: this.mouseButton == 1,
220
- rightButton: this.mouseButton == 2,
221
- mouseDownPos: this.mouseDownPos,
222
- draggedFrom: this.mouseDragPos,
218
+ button: event.button, // this.mouseButton,
219
+ leftButton: event.button === 0, // this.mouseButton === 0,
220
+ middleButton: event.button === 1, // this.mouseButton === 1,
221
+ rightButton: event.button === 2, // this.mouseButton === 2,
222
+ mouseDownPos: this.mouseDownPos ?? { x: NaN, y: NaN },
223
+ draggedFrom: this.mouseDragPos ?? { x: NaN, y: NaN },
223
224
  wasDragged: this.mouseDownPos != null && (this.mouseDownPos.x != rel.x || this.mouseDownPos.y != rel.y),
224
- dragAmount: this.mouseDownPos != null ? { x: rel.x - this.mouseDragPos.x, y: rel.y - this.mouseDragPos.y } : { x: 0, y: 0 }
225
+ dragAmount: this.mouseDragPos != null ? { x: rel.x - this.mouseDragPos.x, y: rel.y - this.mouseDragPos.y } : { x: 0, y: 0 }
225
226
  };
226
227
  return xEvent;
227
228
  }
@@ -75,7 +75,9 @@
75
75
  * @modified 2021-04-25 Extending `remove` to accept arrays of drawables.
76
76
  * @modified 2021-11-16 Adding the `PBText` drawable.
77
77
  * @modified 2022-08-01 Added `title` to the params.
78
- * @version 1.15.1
78
+ * @modified 2022-10-25 Added the `origin` to the default draw config.
79
+ * @modified 2022-11-06 Adding an XML declaration to the SVG export routine.
80
+ * @version 1.16.0
79
81
  *
80
82
  * @file PlotBoilerplate
81
83
  * @fileoverview The main class.
@@ -270,7 +272,7 @@ export class PlotBoilerplate {
270
272
  * @memberof PlotBoilerplate
271
273
  * @instance
272
274
  */
273
- selectPolygon: Polygon;
275
+ selectPolygon: Polygon | null;
274
276
 
275
277
  /**
276
278
  * @member {Array<IDraggable>}
@@ -532,6 +534,9 @@ export class PlotBoilerplate {
532
534
  lineWidth: 1,
533
535
  fill: true,
534
536
  anchor: true
537
+ },
538
+ origin: {
539
+ color: "#000000"
535
540
  }
536
541
  }; // END drawConfig
537
542
 
@@ -554,14 +559,16 @@ export class PlotBoilerplate {
554
559
  this.config.enableGL = false;
555
560
  }
556
561
  if (this.config.enableGL) {
557
- const ctx: WebGLRenderingContext = this.canvas.getContext("webgl"); // webgl-experimental?
562
+ // Override the case 'null' here. If GL is not supported, well then nothing works.
563
+ const ctx: WebGLRenderingContext = this.canvas.getContext("webgl") as WebGLRenderingContext; // webgl-experimental?
558
564
  this.draw = new drawutilsgl(ctx, false);
559
565
  // PROBLEM: same instance of fill and draw when using WebGL.
560
566
  // Shader program cannot be duplicated on the same context.
561
567
  this.fill = (this.draw as drawutilsgl).copyInstance(true);
562
568
  console.warn("Initialized with experimental mode enableGL=true. Note that this is not yet fully implemented.");
563
569
  } else {
564
- const ctx: CanvasRenderingContext2D = this.canvas.getContext("2d");
570
+ // Override the case 'null' here. If context creation is not supported, well then nothing works.
571
+ const ctx: CanvasRenderingContext2D = this.canvas.getContext("2d") as CanvasRenderingContext2D;
565
572
  this.draw = new drawutils(ctx, false);
566
573
  this.fill = new drawutils(ctx, true);
567
574
  }
@@ -599,8 +606,8 @@ export class PlotBoilerplate {
599
606
  if (config.title) {
600
607
  this.eventCatcher.setAttribute("title", config.title);
601
608
  }
602
- this.draw.scale.set(this.config.scaleX, this.config.scaleY);
603
- this.fill.scale.set(this.config.scaleX, this.config.scaleY);
609
+ this.draw.scale.set(this.config.scaleX ?? 1.0, this.config.scaleY);
610
+ this.fill.scale.set(this.config.scaleX ?? 1.0, this.config.scaleY);
604
611
  this.vertices = [];
605
612
  this.selectPolygon = null;
606
613
  this.draggedElements = [];
@@ -655,9 +662,13 @@ export class PlotBoilerplate {
655
662
 
656
663
  tosvgDraw.beginDrawCycle(0);
657
664
  tosvgFill.beginDrawCycle(0);
658
- if (pb.config.preClear) pb.config.preClear();
659
- tosvgDraw.clear(pb.config.backgroundColor);
660
- if (pb.config.preDraw) pb.config.preDraw(tosvgDraw, tosvgFill);
665
+ if (pb.config.preClear) {
666
+ pb.config.preClear();
667
+ }
668
+ tosvgDraw.clear(pb.config.backgroundColor || "white");
669
+ if (pb.config.preDraw) {
670
+ pb.config.preDraw(tosvgDraw, tosvgFill);
671
+ }
661
672
  pb.drawAll(0, tosvgDraw, tosvgFill);
662
673
  pb.drawVertices(0, tosvgDraw);
663
674
  if (pb.config.postDraw) pb.config.postDraw(tosvgDraw, tosvgFill);
@@ -669,7 +680,8 @@ export class PlotBoilerplate {
669
680
  var serializer = new XMLSerializer();
670
681
  var svgCode = serializer.serializeToString(svgNode);
671
682
 
672
- var blob = new Blob([svgCode], { type: "image/svg;charset=utf-8" });
683
+ // Add: '<?xml version="1.0" encoding="utf-8"?>\n' ?
684
+ var blob = new Blob(['<?xml version="1.0" encoding="utf-8"?>\n' + svgCode], { type: "image/svg;charset=utf-8" });
673
685
  // See documentation for FileSaver.js for usage.
674
686
  // https://github.com/eligrey/FileSaver.js
675
687
  if (typeof globalThis["saveAs"] !== "function")
@@ -751,9 +763,9 @@ export class PlotBoilerplate {
751
763
  **/
752
764
  private updateCSSscale() {
753
765
  if (this.config.cssUniformScale) {
754
- PlotBoilerplate.utils.setCSSscale(this.canvas, this.config.cssScaleX, this.config.cssScaleX);
766
+ PlotBoilerplate.utils.setCSSscale(this.canvas, this.config.cssScaleX ?? 1.0, this.config.cssScaleX ?? 1.0);
755
767
  } else {
756
- PlotBoilerplate.utils.setCSSscale(this.canvas, this.config.cssScaleX, this.config.cssScaleY);
768
+ PlotBoilerplate.utils.setCSSscale(this.canvas, this.config.cssScaleX ?? 1.0, this.config.cssScaleY ?? 1.0);
757
769
  }
758
770
  }
759
771
 
@@ -1011,7 +1023,7 @@ export class PlotBoilerplate {
1011
1023
  getVertexNear(pixelPosition: XYCoords, pixelTolerance: number): Vertex | undefined {
1012
1024
  var p: IDraggable | undefined = this.locatePointNear(
1013
1025
  this.transformMousePosition(pixelPosition.x, pixelPosition.y),
1014
- pixelTolerance / Math.min(this.config.cssScaleX, this.config.cssScaleY)
1026
+ pixelTolerance / Math.min(this.config.cssScaleX ?? 1.0, this.config.cssScaleY ?? 1.0)
1015
1027
  );
1016
1028
  if (p && p.typeName == "vertex") {
1017
1029
  return this.vertices[p.vindex];
@@ -1095,7 +1107,7 @@ export class PlotBoilerplate {
1095
1107
  drawOrigin(draw: DrawLib<any>) {
1096
1108
  // Add a crosshair to mark the origin
1097
1109
  draw.setCurrentId("origin");
1098
- draw.crosshair({ x: 0, y: 0 }, 10, "#000000");
1110
+ draw.crosshair({ x: 0, y: 0 }, 10, this.drawConfig.origin.color);
1099
1111
  }
1100
1112
 
1101
1113
  /**
@@ -1360,10 +1372,10 @@ export class PlotBoilerplate {
1360
1372
  } else {
1361
1373
  console.error("Cannot draw object. Unknown class.");
1362
1374
  }
1363
- draw.setCurrentClassName(null);
1364
- draw.setCurrentId(null);
1365
- fill.setCurrentClassName(null);
1366
- fill.setCurrentId(null);
1375
+ draw.setCurrentClassName(undefined);
1376
+ draw.setCurrentId(undefined);
1377
+ fill.setCurrentClassName(undefined);
1378
+ fill.setCurrentId(undefined);
1367
1379
  }
1368
1380
 
1369
1381
  /**
@@ -1473,7 +1485,7 @@ export class PlotBoilerplate {
1473
1485
  **/
1474
1486
  clear() {
1475
1487
  // Note that elements might have an alpha channel. Clear the scene first.
1476
- this.draw.clear(this.config.backgroundColor);
1488
+ this.draw.clear(this.config.backgroundColor || "white");
1477
1489
  }
1478
1490
 
1479
1491
  /**
@@ -1505,7 +1517,10 @@ export class PlotBoilerplate {
1505
1517
  viewport(): Bounds {
1506
1518
  return new Bounds(
1507
1519
  this.transformMousePosition(0, 0),
1508
- this.transformMousePosition(this.canvasSize.width * this.config.cssScaleX, this.canvasSize.height * this.config.cssScaleY)
1520
+ this.transformMousePosition(
1521
+ this.canvasSize.width * (this.config.cssScaleX ?? 1.0),
1522
+ this.canvasSize.height * (this.config.cssScaleY ?? 1.0)
1523
+ )
1509
1524
  );
1510
1525
  }
1511
1526
 
@@ -1569,8 +1584,8 @@ export class PlotBoilerplate {
1569
1584
  resizeCanvas() {
1570
1585
  const _self: PlotBoilerplate = this;
1571
1586
  const _setSize = (w: number, h: number) => {
1572
- w *= _self.config.canvasWidthFactor;
1573
- h *= _self.config.canvasHeightFactor;
1587
+ w *= _self.config.canvasWidthFactor ?? 1.0;
1588
+ h *= _self.config.canvasHeightFactor ?? 1.0;
1574
1589
  _self.canvasSize.width = w;
1575
1590
  _self.canvasSize.height = h;
1576
1591
  if (_self.canvas instanceof HTMLCanvasElement) {
@@ -1597,8 +1612,8 @@ export class PlotBoilerplate {
1597
1612
  var width: number = globalThis.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
1598
1613
  var height: number = globalThis.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
1599
1614
  _self.canvas.style.position = "absolute";
1600
- _self.canvas.style.width = _self.config.canvasWidthFactor * width + "px";
1601
- _self.canvas.style.height = _self.config.canvasWidthFactor * height + "px";
1615
+ _self.canvas.style.width = (_self.config.canvasWidthFactor ?? 1.0) * width + "px";
1616
+ _self.canvas.style.height = (_self.config.canvasWidthFactor ?? 1.0) * height + "px";
1602
1617
  _self.canvas.style.top = "0px";
1603
1618
  _self.canvas.style.left = "0px";
1604
1619
  _setSize(width, height);
@@ -1606,15 +1621,15 @@ export class PlotBoilerplate {
1606
1621
  // Set editor size
1607
1622
  _self.canvas.style.position = "absolute";
1608
1623
  const space: XYDimension = this.getAvailableContainerSpace();
1609
- _self.canvas.style.width = _self.config.canvasWidthFactor * space.width + "px";
1610
- _self.canvas.style.height = _self.config.canvasHeightFactor * space.height + "px";
1611
- _self.canvas.style.top = null;
1612
- _self.canvas.style.left = null;
1624
+ _self.canvas.style.width = (_self.config.canvasWidthFactor ?? 1.0) * space.width + "px";
1625
+ _self.canvas.style.height = (_self.config.canvasHeightFactor ?? 1.0) * space.height + "px";
1626
+ _self.canvas.style.top = "";
1627
+ _self.canvas.style.left = "";
1613
1628
  _setSize(space.width, space.height);
1614
1629
  } else {
1615
- _self.canvas.style.width = null;
1616
- _self.canvas.style.height = null;
1617
- _setSize(_self.config.defaultCanvasWidth, _self.config.defaultCanvasHeight);
1630
+ _self.canvas.style.width = "";
1631
+ _self.canvas.style.height = "";
1632
+ _setSize(_self.config.defaultCanvasWidth ?? 1024, _self.config.defaultCanvasHeight ?? 768);
1618
1633
  }
1619
1634
 
1620
1635
  if (_self.config.redrawOnResize) _self.redraw();
@@ -2269,7 +2284,7 @@ export class PlotBoilerplate {
2269
2284
  * @param {function} fallback - A default value if the key does not exist.
2270
2285
  * @return {function}
2271
2286
  **/
2272
- func: (obj: any, key: string, fallback: (...args: any[]) => any) => {
2287
+ func: (obj: any, key: string, fallback: ((...args: any[]) => any) | null) => {
2273
2288
  if (!obj.hasOwnProperty(key)) return fallback;
2274
2289
  if (typeof obj[key] !== "function") return fallback;
2275
2290
  return obj[key];
package/src/ts/Polygon.ts CHANGED
@@ -99,7 +99,7 @@ export class Polygon implements SVGSerializable {
99
99
  this.uid = UIDGenerator.next();
100
100
  if (typeof vertices == "undefined") vertices = [];
101
101
  this.vertices = vertices;
102
- this.isOpen = isOpen;
102
+ this.isOpen = isOpen || false;
103
103
  }
104
104
 
105
105
  /**
package/src/ts/Vector.ts CHANGED
@@ -11,7 +11,8 @@
11
11
  * @modified 2021-01-20 Added UID.
12
12
  * @modified 2022-02-02 Added the `destroy` method.
13
13
  * @modified 2022-02-02 Cleared the `Vector.toSVGString` function (deprecated). Use `drawutilssvg` instead.
14
- * @version 1.4.0
14
+ * @modified 2022-10-25 Added the `getOrthogonal` method.
15
+ * @version 1.5.0
15
16
  *
16
17
  * @file Vector
17
18
  * @public
@@ -65,7 +66,7 @@ export class Vector extends VertTuple<Vector> implements SVGSerializable {
65
66
  }
66
67
 
67
68
  /**
68
- * The inverse of a vector is a vector witht the same magnitude but oppose direction.
69
+ * The inverse of a vector is a vector with the same magnitude but oppose direction.
69
70
  *
70
71
  * Please not that the origin of this vector changes here: a->b becomes b->a.
71
72
  *
@@ -116,6 +117,25 @@ export class Vector extends VertTuple<Vector> implements SVGSerializable {
116
117
  return new Vertex(this.a.x + a * (this.b.x - this.a.x), this.a.y + a * (this.b.y - this.a.y));
117
118
  }
118
119
 
120
+ /**
121
+ * Get the orthogonal "vector" of this vector (rotated by 90° clockwise).
122
+ *
123
+ * @name getOrthogonal
124
+ * @method getOrthogonal
125
+ * @return {Vector} A new vector with the same length that stands on this vector's point a.
126
+ * @instance
127
+ * @memberof Vector
128
+ **/
129
+ getOrthogonal(): Vector {
130
+ // Orthogonal of vector (0,0)->(x,y) is (0,0)->(-y,x)
131
+ const linePoint = this.a.clone();
132
+ const startPoint = this.b.clone().sub(this.a);
133
+ const tmp = startPoint.x;
134
+ startPoint.x = -startPoint.y;
135
+ startPoint.y = tmp;
136
+ return new Vector(linePoint, startPoint.add(this.a));
137
+ }
138
+
119
139
  static utils = {
120
140
  /**
121
141
  * Generate a four-point arrow head, starting at the vector end minus the
@@ -143,8 +163,8 @@ export class Vector extends VertTuple<Vector> implements SVGSerializable {
143
163
  * @param {number} scaleY - the vertical scaling during draw.
144
164
  **/
145
165
  buildArrowHead: (zA: Vertex, zB: Vertex, headlen: number, scaleX: number, scaleY: number) => {
146
- var angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);
147
- var vertices = [];
166
+ const angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);
167
+ const vertices: Array<Vertex> = [];
148
168
  vertices.push(new Vertex(zB.x * scaleX - headlen * Math.cos(angle), zB.y * scaleY - headlen * Math.sin(angle)));
149
169
  vertices.push(
150
170
  new Vertex(
package/src/ts/draw.ts CHANGED
@@ -44,7 +44,10 @@
44
44
  * @modified 2022-03-27 Added the `texturedPoly` function.
45
45
  * @modified 2022-06-01 Tweaked the `polyline` function; lineWidth now scales with scale.x.
46
46
  * @modified 2022-07-26 Adding `alpha` to the `image(...)` function.
47
- * @version 1.12.2
47
+ * @modified 2022-08-23 Fixed a type issue in the `polyline` function.
48
+ * @modified 2022-08-23 Fixed a type issue in the `setConfiguration` function.
49
+ * @modified 2022-08-23 Fixed a type issue in the `path` function.
50
+ * @version 1.12.3
48
51
  **/
49
52
 
50
53
  import { CubicBezierCurve } from "./CubicBezierCurve";
@@ -141,7 +144,7 @@ export class drawutils implements DrawLib<void> {
141
144
  * @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.
142
145
  */
143
146
  setConfiguration(configuration: DrawLibConfiguration): void {
144
- this.ctx.globalCompositeOperation = configuration.blendMode;
147
+ this.ctx.globalCompositeOperation = configuration.blendMode || "source-over";
145
148
  }
146
149
 
147
150
  /**
@@ -1012,7 +1015,7 @@ export class drawutils implements DrawLib<void> {
1012
1015
  }
1013
1016
  this.ctx.save();
1014
1017
  this.ctx.beginPath();
1015
- this.ctx.lineWidth = lineWidth * this.scale.x || 1.0;
1018
+ this.ctx.lineWidth = (lineWidth || 1.0) * this.scale.x;
1016
1019
  this.ctx.moveTo(this.offset.x + vertices[0].x * this.scale.x, this.offset.y + vertices[0].y * this.scale.y);
1017
1020
  for (var i = 0; i < vertices.length; i++) {
1018
1021
  this.ctx.lineTo(this.offset.x + vertices[i].x * this.scale.x, this.offset.y + vertices[i].y * this.scale.y);
@@ -1147,13 +1150,19 @@ export class drawutils implements DrawLib<void> {
1147
1150
  path(pathData: SVGPathParams, color?: string, lineWidth?: number, options?: { inplace?: boolean }) {
1148
1151
  const d: SVGPathParams = options && options.inplace ? pathData : drawutilssvg.copyPathData(pathData);
1149
1152
  drawutilssvg.transformPathData(d, this.offset, this.scale);
1150
- this.ctx.strokeStyle = color;
1153
+ if (color) {
1154
+ this.ctx.strokeStyle = color;
1155
+ }
1151
1156
  this.ctx.lineWidth = lineWidth || 1;
1152
1157
  if (this.fillShapes) {
1153
- this.ctx.fillStyle = color;
1158
+ if (color) {
1159
+ this.ctx.fillStyle = color;
1160
+ }
1154
1161
  this.ctx.fill(new Path2D(d.join(" ")));
1155
1162
  } else {
1156
- this.ctx.strokeStyle = color;
1163
+ if (color) {
1164
+ this.ctx.strokeStyle = color;
1165
+ }
1157
1166
  this.ctx.stroke(new Path2D(d.join(" ")));
1158
1167
  }
1159
1168
  }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @date 2022-10-17
3
+ */
4
+ import { Vertex } from "../Vertex";
5
+
6
+ /**
7
+ * A common interface for different kinds of path segments.
8
+ */
9
+ export interface PathSegment {
10
+ /**
11
+ * Get the start point of this path segment.
12
+ *
13
+ * @method getStartPoint
14
+ * @memberof PathSegment
15
+ * @return {Vertex} The start point of this path segment.
16
+ */
17
+ getStartPoint(): Vertex;
18
+
19
+ /**
20
+ * Get the end point of this path segment.
21
+ *
22
+ * @method getEndPoint
23
+ * @memberof PathSegment
24
+ * @return {Vertex} The end point of this path segment.
25
+ */
26
+ getEndPoint(): Vertex;
27
+
28
+ /**
29
+ * Get the tangent's end point at the start point of this segment.
30
+ *
31
+ * @method getStartTangent
32
+ * @memberof PathSegment
33
+ * @return {Vertex} The end point of the starting point's tangent.
34
+ */
35
+ getStartTangent(): Vertex;
36
+
37
+ /**
38
+ * Get the tangent's end point at the end point of this segment.
39
+ *
40
+ * @method getEndTangent
41
+ * @memberof PathSegment
42
+ * @return {Vertex} The end point of the ending point's tangent.
43
+ */
44
+ getEndTangent(): Vertex;
45
+
46
+ /**
47
+ * Create a deep clone of this path segment.
48
+ *
49
+ * @method clone
50
+ * @memberof PathSegment
51
+ * @return {PathSegment} A deep clone/copy of this path segment.
52
+ */
53
+ clone: () => PathSegment;
54
+
55
+ /**
56
+ * Revserse this path segment (in-place) and return this same instance (useful for chaining).
57
+ * The new path segment has start and end point swapped.
58
+ *
59
+ * @method reverse
60
+ * @memberof PathSegment
61
+ * @return {PathSegment} This path segment instance (for chaining).
62
+ */
63
+ reverse: () => PathSegment;
64
+ }
65
+
66
+ /**
67
+ * A common interface for general path representations.
68
+ */
69
+ export interface Path extends PathSegment {
70
+ /**
71
+ * Get the number of segments in this path.
72
+ *
73
+ * @method getSegmentCount
74
+ * @memberof Path
75
+ * @return {number} The number (integer) of path segments.
76
+ */
77
+ getSegmentCount: () => number;
78
+
79
+ /**
80
+ * Get the path segment at the given index.
81
+ *
82
+ * @method getSegmentAt
83
+ * @memberof Path
84
+ * @return {PathSegment} The paths segment at the given index.
85
+ */
86
+ getSegmentAt: (index: number) => PathSegment;
87
+
88
+ /**
89
+ * Create a deep clone of this path.
90
+ *
91
+ * @method clone
92
+ * @memberof Path
93
+ * @return {Path} A deep clone/copy of this path.
94
+ */
95
+ clone: () => Path;
96
+
97
+ /**
98
+ * Reverse this path (swap start and end and thus – the direction) in-place.
99
+ *
100
+ * @method revert
101
+ * @memberof Path
102
+ * @return {PathSegment} This path instance.
103
+ */
104
+ reverse: () => Path;
105
+ }
@@ -15,6 +15,7 @@
15
15
  * @modified 2021-06-21 Added `IBounds.getCenter()`.
16
16
  * @modified 2021-11-16 Added `text` options to the `DrawConfig`.
17
17
  * @modified 2022-08-01 Added `title` param to the `PBParams` interface.
18
+ * @modified 2022-10-25 Added `origin` param to the `DrawConfig` interface.
18
19
  **/
19
20
 
20
21
  import { Vertex } from "../Vertex";
@@ -199,6 +200,7 @@ export interface DrawConfig {
199
200
  fill?: boolean;
200
201
  anchor?: boolean;
201
202
  };
203
+ origin: { color: string };
202
204
  }
203
205
 
204
206
  /** This is a fix for the problem, that the constructor's "name" attribute is not
@@ -1,3 +1,4 @@
1
1
  export * from "./core";
2
2
  export * from "./DrawLib";
3
3
  export * from "./externals";
4
+ export * from "./additionals";
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Randomize a given array in-place.
3
+ *
4
+ * @author Ikaros Kappler
5
+ * @date 2022-10-09
6
+ * @version 1.0.0
7
+ **/
8
+
9
+ export const arrayShuffle = (arr: Array<any>): void => {
10
+ arr.sort(() => Math.random() - 0.5);
11
+ };