plotboilerplate 1.12.10 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/changelog.md +50 -0
- package/dist/index.esm.js +999 -510
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/plotboilerplate.browser.min.js +1 -1
- package/dist/plotboilerplate.browser.min.js.map +1 -1
- package/dist/plotboilerplate.js +1013 -509
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +1 -1
- package/src/cjs/BezierPath.d.ts +45 -2
- package/src/cjs/BezierPath.js +114 -18
- package/src/cjs/BezierPath.js.map +1 -1
- package/src/cjs/Circle.d.ts +25 -10
- package/src/cjs/Circle.js +38 -33
- package/src/cjs/Circle.js.map +1 -1
- package/src/cjs/CircleSector.d.ts +27 -13
- package/src/cjs/CircleSector.js +38 -23
- package/src/cjs/CircleSector.js.map +1 -1
- package/src/cjs/CubicBezierCurve.d.ts +17 -1
- package/src/cjs/CubicBezierCurve.js +78 -79
- package/src/cjs/CubicBezierCurve.js.map +1 -1
- package/src/cjs/KeyHandler.d.ts +10 -3
- package/src/cjs/KeyHandler.js +28 -23
- package/src/cjs/KeyHandler.js.map +1 -1
- package/src/cjs/Line.d.ts +2 -1
- package/src/cjs/Line.js +19 -18
- package/src/cjs/Line.js.map +1 -1
- package/src/cjs/MouseHandler.js +43 -53
- package/src/cjs/MouseHandler.js.map +1 -1
- package/src/cjs/PBImage.d.ts +16 -1
- package/src/cjs/PBImage.js +13 -3
- package/src/cjs/PBImage.js.map +1 -1
- package/src/cjs/PBText.d.ts +130 -0
- package/src/cjs/PBText.js +76 -0
- package/src/cjs/PBText.js.map +1 -0
- package/src/cjs/PlotBoilerplate.d.ts +2 -1
- package/src/cjs/PlotBoilerplate.js +44 -16
- package/src/cjs/PlotBoilerplate.js.map +1 -1
- package/src/cjs/Polygon.d.ts +37 -1
- package/src/cjs/Polygon.js +131 -54
- package/src/cjs/Polygon.js.map +1 -1
- package/src/cjs/Triangle.d.ts +16 -1
- package/src/cjs/Triangle.js +50 -54
- package/src/cjs/Triangle.js.map +1 -1
- package/src/cjs/VEllipse.d.ts +16 -1
- package/src/cjs/VEllipse.js +25 -12
- package/src/cjs/VEllipse.js.map +1 -1
- package/src/cjs/VEllipseSector.d.ts +15 -1
- package/src/cjs/VEllipseSector.js +11 -1
- package/src/cjs/VEllipseSector.js.map +1 -1
- package/src/cjs/Vector.d.ts +3 -1
- package/src/cjs/Vector.js +32 -36
- package/src/cjs/Vector.js.map +1 -1
- package/src/cjs/VertTuple.d.ts +15 -1
- package/src/cjs/VertTuple.js +14 -19
- package/src/cjs/VertTuple.js.map +1 -1
- package/src/cjs/Vertex.d.ts +66 -4
- package/src/cjs/Vertex.js +99 -17
- package/src/cjs/Vertex.js.map +1 -1
- package/src/cjs/VertexListeners.d.ts +12 -8
- package/src/cjs/VertexListeners.js +18 -25
- package/src/cjs/VertexListeners.js.map +1 -1
- package/src/cjs/draw.d.ts +30 -2
- package/src/cjs/draw.js +51 -6
- package/src/cjs/draw.js.map +1 -1
- package/src/cjs/drawgl.d.ts +29 -2
- package/src/cjs/drawgl.js +21 -4
- package/src/cjs/drawgl.js.map +1 -1
- package/src/cjs/drawutilssvg.d.ts +25 -7
- package/src/cjs/drawutilssvg.js +62 -14
- package/src/cjs/drawutilssvg.js.map +1 -1
- package/src/cjs/entry.js +1 -0
- package/src/cjs/index.d.ts +1 -0
- package/src/cjs/index.js +1 -0
- package/src/cjs/index.js.map +1 -1
- package/src/cjs/interfaces/DrawLib.d.ts +27 -6
- package/src/cjs/interfaces/DrawLib.js +3 -0
- package/src/cjs/interfaces/DrawLib.js.map +1 -1
- package/src/cjs/interfaces/core.d.ts +9 -1
- package/src/cjs/interfaces/core.js +1 -0
- package/src/cjs/interfaces/core.js.map +1 -1
- package/src/cjs/utils/creategui.js +1 -1
- package/src/cjs/utils/findInVertexArray.d.ts +19 -0
- package/src/cjs/utils/findInVertexArray.js +29 -0
- package/src/cjs/utils/findInVertexArray.js.map +1 -0
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.d.ts +15 -0
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js +55 -28
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/cjs/utils/io/DndFileHandler.d.ts +63 -0
- package/src/cjs/utils/io/DndFileHandler.js +112 -0
- package/src/cjs/utils/io/DndFileHandler.js.map +1 -0
- package/src/cjs/utils/io/FileDrop.d.ts +98 -0
- package/src/cjs/utils/io/FileDrop.js +142 -0
- package/src/cjs/utils/io/FileDrop.js.map +1 -0
- package/src/esm/BezierPath.d.ts +45 -2
- package/src/esm/BezierPath.js +114 -18
- package/src/esm/BezierPath.js.map +1 -1
- package/src/esm/Circle.d.ts +25 -10
- package/src/esm/Circle.js +38 -33
- package/src/esm/Circle.js.map +1 -1
- package/src/esm/CircleSector.d.ts +27 -13
- package/src/esm/CircleSector.js +38 -23
- package/src/esm/CircleSector.js.map +1 -1
- package/src/esm/CubicBezierCurve.d.ts +17 -1
- package/src/esm/CubicBezierCurve.js +78 -79
- package/src/esm/CubicBezierCurve.js.map +1 -1
- package/src/esm/KeyHandler.d.ts +10 -3
- package/src/esm/KeyHandler.js +28 -23
- package/src/esm/KeyHandler.js.map +1 -1
- package/src/esm/Line.d.ts +2 -1
- package/src/esm/Line.js +19 -18
- package/src/esm/Line.js.map +1 -1
- package/src/esm/MouseHandler.js +43 -53
- package/src/esm/MouseHandler.js.map +1 -1
- package/src/esm/PBImage.d.ts +16 -1
- package/src/esm/PBImage.js +13 -3
- package/src/esm/PBImage.js.map +1 -1
- package/src/esm/PBText.d.ts +130 -0
- package/src/esm/PBText.js +71 -0
- package/src/esm/PBText.js.map +1 -0
- package/src/esm/PlotBoilerplate.d.ts +2 -1
- package/src/esm/PlotBoilerplate.js +44 -16
- package/src/esm/PlotBoilerplate.js.map +1 -1
- package/src/esm/Polygon.d.ts +37 -1
- package/src/esm/Polygon.js +131 -54
- package/src/esm/Polygon.js.map +1 -1
- package/src/esm/Triangle.d.ts +16 -1
- package/src/esm/Triangle.js +50 -54
- package/src/esm/Triangle.js.map +1 -1
- package/src/esm/VEllipse.d.ts +16 -1
- package/src/esm/VEllipse.js +25 -12
- package/src/esm/VEllipse.js.map +1 -1
- package/src/esm/VEllipseSector.d.ts +15 -1
- package/src/esm/VEllipseSector.js +11 -1
- package/src/esm/VEllipseSector.js.map +1 -1
- package/src/esm/Vector.d.ts +3 -1
- package/src/esm/Vector.js +32 -36
- package/src/esm/Vector.js.map +1 -1
- package/src/esm/VertTuple.d.ts +15 -1
- package/src/esm/VertTuple.js +14 -19
- package/src/esm/VertTuple.js.map +1 -1
- package/src/esm/Vertex.d.ts +66 -4
- package/src/esm/Vertex.js +99 -17
- package/src/esm/Vertex.js.map +1 -1
- package/src/esm/VertexListeners.d.ts +12 -8
- package/src/esm/VertexListeners.js +18 -25
- package/src/esm/VertexListeners.js.map +1 -1
- package/src/esm/draw.d.ts +30 -2
- package/src/esm/draw.js +51 -6
- package/src/esm/draw.js.map +1 -1
- package/src/esm/drawgl.d.ts +29 -2
- package/src/esm/drawgl.js +21 -4
- package/src/esm/drawgl.js.map +1 -1
- package/src/esm/drawutilssvg.d.ts +25 -7
- package/src/esm/drawutilssvg.js +62 -14
- package/src/esm/drawutilssvg.js.map +1 -1
- package/src/esm/entry.js +1 -0
- package/src/esm/index.d.ts +1 -0
- package/src/esm/index.js +1 -0
- package/src/esm/index.js.map +1 -1
- package/src/esm/interfaces/DrawLib.d.ts +27 -6
- package/src/esm/interfaces/DrawLib.js +3 -0
- package/src/esm/interfaces/DrawLib.js.map +1 -1
- package/src/esm/interfaces/core.d.ts +9 -1
- package/src/esm/interfaces/core.js +1 -0
- package/src/esm/interfaces/core.js.map +1 -1
- package/src/esm/utils/findInVertexArray.d.ts +19 -0
- package/src/esm/utils/findInVertexArray.js +25 -0
- package/src/esm/utils/findInVertexArray.js.map +1 -0
- package/src/esm/utils/helpers/BezierPathInteractionHelper.d.ts +15 -0
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js +54 -28
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/esm/utils/io/DndFileHandler.d.ts +63 -0
- package/src/esm/utils/io/DndFileHandler.js +106 -0
- package/src/esm/utils/io/DndFileHandler.js.map +1 -0
- package/src/esm/utils/io/FileDrop.d.ts +98 -0
- package/src/esm/utils/io/FileDrop.js +136 -0
- package/src/esm/utils/io/FileDrop.js.map +1 -0
- package/src/ts/BezierPath.ts +133 -16
- package/src/ts/Circle.ts +213 -200
- package/src/ts/CircleSector.ts +171 -141
- package/src/ts/CubicBezierCurve.ts +777 -810
- package/src/ts/KeyHandler.ts +221 -212
- package/src/ts/Line.ts +77 -80
- package/src/ts/MouseHandler.ts +356 -368
- package/src/ts/PBImage.ts +81 -68
- package/src/ts/PBText.ts +166 -0
- package/src/ts/PlotBoilerplate.ts +48 -20
- package/src/ts/Polygon.ts +519 -451
- package/src/ts/Triangle.ts +484 -489
- package/src/ts/VEllipse.ts +36 -11
- package/src/ts/VEllipseSector.ts +20 -1
- package/src/ts/Vector.ts +164 -160
- package/src/ts/VertTuple.ts +333 -338
- package/src/ts/Vertex.ts +117 -16
- package/src/ts/VertexListeners.ts +248 -266
- package/src/ts/draw.ts +71 -8
- package/src/ts/drawgl.ts +48 -8
- package/src/ts/drawutilssvg.ts +94 -17
- package/src/ts/index.ts +1 -0
- package/src/ts/interfaces/DrawLib.ts +30 -4
- package/src/ts/interfaces/core.ts +9 -0
- package/src/ts/utils/findInVertexArray.ts +28 -0
- package/src/ts/utils/helpers/BezierPathInteractionHelper.ts +61 -30
- package/src/ts/utils/io/FileDrop.ts +178 -0
- package/dist/plotboilerplate.browser.min.js.LICENSE.txt +0 -8
- package/src/ts/utils/algorithms/clearPolygonDuplicateVertices.ts~ +0 -5
- package/src/ts/utils/algorithms/findPolygonSelfIntersections.ts~ +0 -45
- package/src/ts/utils/algorithms/sh-tmp.ts~ +0 -59
- package/src/ts/utils/algorithms/splitPolygonToNonIntersecting.ts~ +0 -113
- package/src/ts/utils/algorithms/sutherlandHodgman.ts~ +0 -88
package/dist/index.esm.js
CHANGED
|
@@ -99,7 +99,6 @@ class VertexListeners {
|
|
|
99
99
|
this.dragEnd = [];
|
|
100
100
|
this.vertex = vertex;
|
|
101
101
|
}
|
|
102
|
-
;
|
|
103
102
|
/**
|
|
104
103
|
* Add a click listener.
|
|
105
104
|
*
|
|
@@ -113,7 +112,6 @@ class VertexListeners {
|
|
|
113
112
|
VertexListeners._addListener(this.click, listener);
|
|
114
113
|
return this;
|
|
115
114
|
}
|
|
116
|
-
;
|
|
117
115
|
/**
|
|
118
116
|
* The click listener is a function with a single drag event param.
|
|
119
117
|
* @callback VertexListeners~clickListener
|
|
@@ -132,7 +130,6 @@ class VertexListeners {
|
|
|
132
130
|
this.click = VertexListeners._removeListener(this.click, listener);
|
|
133
131
|
return this;
|
|
134
132
|
}
|
|
135
|
-
;
|
|
136
133
|
/**
|
|
137
134
|
* The click listener is a function with a single drag event param.
|
|
138
135
|
* @callback VertexListeners~clickListener
|
|
@@ -151,7 +148,6 @@ class VertexListeners {
|
|
|
151
148
|
VertexListeners._addListener(this.drag, listener);
|
|
152
149
|
return this;
|
|
153
150
|
}
|
|
154
|
-
;
|
|
155
151
|
/**
|
|
156
152
|
* The drag listener is a function with a single drag event param.
|
|
157
153
|
* @callback VertexListeners~dragListener
|
|
@@ -170,7 +166,6 @@ class VertexListeners {
|
|
|
170
166
|
this.drag = VertexListeners._removeListener(this.drag, listener);
|
|
171
167
|
return this;
|
|
172
168
|
}
|
|
173
|
-
;
|
|
174
169
|
/**
|
|
175
170
|
* Add a dragStart listener.
|
|
176
171
|
*
|
|
@@ -184,7 +179,6 @@ class VertexListeners {
|
|
|
184
179
|
VertexListeners._addListener(this.dragStart, listener);
|
|
185
180
|
return this;
|
|
186
181
|
}
|
|
187
|
-
;
|
|
188
182
|
/**
|
|
189
183
|
* The drag-start listener is a function with a single drag event param.
|
|
190
184
|
* @callback VertexListeners~dragStartListener
|
|
@@ -203,7 +197,6 @@ class VertexListeners {
|
|
|
203
197
|
this.dragStart = VertexListeners._removeListener(this.dragStart, listener);
|
|
204
198
|
return this;
|
|
205
199
|
}
|
|
206
|
-
;
|
|
207
200
|
/**
|
|
208
201
|
* Add a dragEnd listener.
|
|
209
202
|
*
|
|
@@ -218,27 +211,25 @@ class VertexListeners {
|
|
|
218
211
|
VertexListeners._addListener(this.dragEnd, listener);
|
|
219
212
|
return this;
|
|
220
213
|
}
|
|
221
|
-
;
|
|
222
214
|
/**
|
|
223
215
|
* The drag-end listener is a function with a single drag event param.
|
|
224
216
|
* @callback VertexListeners~dragEndListener
|
|
225
217
|
* @param {Event} e - The (extended) drag event.
|
|
226
218
|
*/
|
|
227
219
|
/**
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
220
|
+
* Remove a drag listener.
|
|
221
|
+
*
|
|
222
|
+
* @method removeDragEndListener
|
|
223
|
+
* @param {VertexListeners~clickListener} listener - The drag listener to remove (a callback).
|
|
224
|
+
* @return {VertexListeners} this (for chaining)
|
|
225
|
+
* @instance
|
|
226
|
+
* @memberof VertexListeners
|
|
227
|
+
**/
|
|
236
228
|
removeDragEndListener(listener) {
|
|
237
229
|
// this.drag.push( listener );
|
|
238
230
|
this.dragEnd = VertexListeners._removeListener(this.dragEnd, listener);
|
|
239
231
|
return this;
|
|
240
232
|
}
|
|
241
|
-
;
|
|
242
233
|
/**
|
|
243
234
|
* Fire a click event with the given event instance to all
|
|
244
235
|
* installed click listeners.
|
|
@@ -252,7 +243,6 @@ class VertexListeners {
|
|
|
252
243
|
fireClickEvent(e) {
|
|
253
244
|
VertexListeners._fireEvent(this, this.click, e);
|
|
254
245
|
}
|
|
255
|
-
;
|
|
256
246
|
/**
|
|
257
247
|
* Fire a drag event with the given event instance to all
|
|
258
248
|
* installed drag listeners.
|
|
@@ -266,7 +256,6 @@ class VertexListeners {
|
|
|
266
256
|
fireDragEvent(e) {
|
|
267
257
|
VertexListeners._fireEvent(this, this.drag, e);
|
|
268
258
|
}
|
|
269
|
-
;
|
|
270
259
|
/**
|
|
271
260
|
* Fire a dragStart event with the given event instance to all
|
|
272
261
|
* installed drag-start listeners.
|
|
@@ -280,7 +269,6 @@ class VertexListeners {
|
|
|
280
269
|
fireDragStartEvent(e) {
|
|
281
270
|
VertexListeners._fireEvent(this, this.dragStart, e);
|
|
282
271
|
}
|
|
283
|
-
;
|
|
284
272
|
/**
|
|
285
273
|
* Fire a dragEnd event with the given event instance to all
|
|
286
274
|
* installed drag-end listeners.
|
|
@@ -294,13 +282,21 @@ class VertexListeners {
|
|
|
294
282
|
fireDragEndEvent(e) {
|
|
295
283
|
VertexListeners._fireEvent(this, this.dragEnd, e);
|
|
296
284
|
}
|
|
297
|
-
|
|
285
|
+
/**
|
|
286
|
+
* Removes all listeners from this listeners object.
|
|
287
|
+
*/
|
|
288
|
+
removeAllListeners() {
|
|
289
|
+
this.click = [];
|
|
290
|
+
this.drag = [];
|
|
291
|
+
this.dragStart = [];
|
|
292
|
+
this.dragEnd = [];
|
|
293
|
+
}
|
|
298
294
|
/**
|
|
299
295
|
* @private
|
|
300
296
|
**/
|
|
301
297
|
static _fireEvent(_self, listeners, e) {
|
|
302
298
|
const ve = e;
|
|
303
|
-
if (typeof ve.params ==
|
|
299
|
+
if (typeof ve.params == "undefined")
|
|
304
300
|
ve.params = { vertex: _self.vertex };
|
|
305
301
|
else
|
|
306
302
|
ve.params.vertex = _self.vertex;
|
|
@@ -308,7 +304,6 @@ class VertexListeners {
|
|
|
308
304
|
listeners[i](ve);
|
|
309
305
|
}
|
|
310
306
|
}
|
|
311
|
-
;
|
|
312
307
|
/**
|
|
313
308
|
* @private
|
|
314
309
|
*/
|
|
@@ -320,7 +315,6 @@ class VertexListeners {
|
|
|
320
315
|
listeners.push(newListener);
|
|
321
316
|
return true;
|
|
322
317
|
}
|
|
323
|
-
;
|
|
324
318
|
/**
|
|
325
319
|
* @private
|
|
326
320
|
*/
|
|
@@ -331,7 +325,6 @@ class VertexListeners {
|
|
|
331
325
|
}
|
|
332
326
|
return listeners;
|
|
333
327
|
}
|
|
334
|
-
;
|
|
335
328
|
}
|
|
336
329
|
|
|
337
330
|
/**
|
|
@@ -358,7 +351,13 @@ class VertexListeners {
|
|
|
358
351
|
* @modified 2020-05-26 Added functions addX(number) and addY(number).
|
|
359
352
|
* @modified 2020-10-30 Changed the warnings in `sub(...)` and `add(...)` into real errors.
|
|
360
353
|
* @modified 2021-03-01 Changed the second param `center` in the `rotate` function from Vertex to XYCoords.
|
|
361
|
-
* @
|
|
354
|
+
* @modified 2021-12-01 Changed the type of param of `scale` to XYCoords.
|
|
355
|
+
* @modified 2021-12-01 Added function `scaleXY` for non uniform scaling.
|
|
356
|
+
* @modified 2021-12-17 Added the functions `lerp` and `lerpAbs` for linear interpolations.
|
|
357
|
+
* @modified 2022-01-31 Added `Vertex.utils.arrayToJSON`.
|
|
358
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
359
|
+
* @modified 2022-02-02 Cleared the `Vertex.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
360
|
+
* @version 2.7.0
|
|
362
361
|
*
|
|
363
362
|
* @file Vertex
|
|
364
363
|
* @public
|
|
@@ -699,20 +698,72 @@ class Vertex {
|
|
|
699
698
|
}
|
|
700
699
|
/**
|
|
701
700
|
* This is a vector-like behavior and 'scales' this vertex
|
|
702
|
-
* towards/from a given center.
|
|
701
|
+
* towards/from a given center by one uniform scale factor.
|
|
703
702
|
*
|
|
704
703
|
* @method scale
|
|
705
704
|
* @param {number} factor - The factor to 'scale' this vertex; 1.0 means no change.
|
|
706
|
-
* @param {
|
|
705
|
+
* @param {XYCoords=} center - The origin of scaling; default is (0,0).
|
|
707
706
|
* @return {Vertex} this
|
|
708
707
|
* @instance
|
|
709
708
|
* @memberof Vertex
|
|
710
709
|
**/
|
|
711
710
|
scale(factor, center) {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
711
|
+
return this.scaleXY({ x: factor, y: factor }, center);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Perform a linear interpolation towards the given target vertex.
|
|
715
|
+
* The amount value `t` is relative, `t=0.0` means no change, `t=1.0`
|
|
716
|
+
* means this point will be moved to the exact target position.
|
|
717
|
+
*
|
|
718
|
+
* `t=0.5` will move this point to the middle of the connecting
|
|
719
|
+
* linear segment.
|
|
720
|
+
*
|
|
721
|
+
* @param {XYCoords} target - The target position to lerp this vertex to.
|
|
722
|
+
* @param {number} t - The relative amount, usually in [0..1], but other values will work, too.
|
|
723
|
+
* @returns
|
|
724
|
+
*/
|
|
725
|
+
lerp(target, t) {
|
|
726
|
+
var diff = this.difference(target);
|
|
727
|
+
// return new Vertex(this.x + diff.x * t, this.y + diff.y * t);
|
|
728
|
+
this.x += diff.x * t;
|
|
729
|
+
this.y += diff.y * t;
|
|
730
|
+
return this;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Perform a linear interpolation towards the given target vertex (absolute variant).
|
|
734
|
+
* The amount value `t` is absolute, which means the lerp amount is a direct distance
|
|
735
|
+
* value. This point will have move the amount of the passed distance `u`.
|
|
736
|
+
*
|
|
737
|
+
* @param {XYCoords} target - The target position to lerp this vertex to.
|
|
738
|
+
* @param {number} t - The absolute move amount to use to lerping.
|
|
739
|
+
* @returns
|
|
740
|
+
*/
|
|
741
|
+
lerpAbs(target, u) {
|
|
742
|
+
var dist = this.distance(target);
|
|
743
|
+
var diff = this.difference(target);
|
|
744
|
+
var step = { x: diff.x / dist, y: diff.y / dist };
|
|
745
|
+
// return new Vertex(this.x + step.x * u, this.y + step.y * u);
|
|
746
|
+
this.x += step.x * u;
|
|
747
|
+
this.y += step.y * u;
|
|
748
|
+
return this;
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* This is a vector-like behavior and 'scales' this vertex
|
|
752
|
+
* towards/from a given center by two independent x- and y- scale factors.
|
|
753
|
+
*
|
|
754
|
+
* @method scale
|
|
755
|
+
* @param {number} factor - The factor to 'scale' this vertex; 1.0 means no change.
|
|
756
|
+
* @param {XYCoords=} center - The origin of scaling; default is (0,0).
|
|
757
|
+
* @return {Vertex} this
|
|
758
|
+
* @instance
|
|
759
|
+
* @memberof Vertex
|
|
760
|
+
**/
|
|
761
|
+
scaleXY(factors, center) {
|
|
762
|
+
if (!center || typeof center === "undefined") {
|
|
763
|
+
center = { x: 0, y: 0 };
|
|
764
|
+
}
|
|
765
|
+
this.x = center.x + (this.x - center.x) * factors.x;
|
|
766
|
+
this.y = center.y + (this.y - center.y) * factors.y;
|
|
716
767
|
return this;
|
|
717
768
|
}
|
|
718
769
|
/**
|
|
@@ -801,20 +852,31 @@ class Vertex {
|
|
|
801
852
|
* @return {string} A string representing the SVG code for this vertex.
|
|
802
853
|
* @instance
|
|
803
854
|
* @memberof Vertex
|
|
855
|
+
* @deprecated
|
|
804
856
|
**/
|
|
805
857
|
toSVGString(options) {
|
|
806
|
-
options = options || {};
|
|
807
|
-
var buffer = [];
|
|
808
|
-
buffer.push("<circle");
|
|
809
|
-
if (options.className)
|
|
810
|
-
|
|
811
|
-
buffer.push('
|
|
812
|
-
buffer.push('
|
|
813
|
-
buffer.push(
|
|
814
|
-
buffer.
|
|
815
|
-
return
|
|
858
|
+
// options = options || {};
|
|
859
|
+
// var buffer = [];
|
|
860
|
+
// buffer.push("<circle");
|
|
861
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
862
|
+
// buffer.push(' cx="' + this.x + '"');
|
|
863
|
+
// buffer.push(' cy="' + this.y + '"');
|
|
864
|
+
// buffer.push(' r="2"');
|
|
865
|
+
// buffer.push(" />");
|
|
866
|
+
// return buffer.join("");
|
|
867
|
+
console.warn("[Deprecation] Warning: the Vertex.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
868
|
+
return "";
|
|
816
869
|
}
|
|
817
870
|
// END Vertex
|
|
871
|
+
/**
|
|
872
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
873
|
+
* After calling this function the object might not hold valid data any more and
|
|
874
|
+
* should not be used.
|
|
875
|
+
*/
|
|
876
|
+
destroy() {
|
|
877
|
+
this.listeners.removeAllListeners();
|
|
878
|
+
this.isDestroyed = true;
|
|
879
|
+
}
|
|
818
880
|
/**
|
|
819
881
|
* Create a new random vertex inside the given viewport.
|
|
820
882
|
*
|
|
@@ -869,6 +931,19 @@ Vertex.utils = {
|
|
|
869
931
|
vertices.push(new Vertex(zB.x * scaleX, zB.y * scaleY));
|
|
870
932
|
vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle + Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle + Math.PI / 8)));
|
|
871
933
|
return vertices;
|
|
934
|
+
},
|
|
935
|
+
/**
|
|
936
|
+
* Convert the given vertices (array) to a JSON string.
|
|
937
|
+
*
|
|
938
|
+
* @param {number?} precision - (optional) The numeric precision to be used (number of precision digits).
|
|
939
|
+
* @returns {string}
|
|
940
|
+
*/
|
|
941
|
+
arrayToJSON(vertices, precision) {
|
|
942
|
+
return JSON.stringify(vertices.map(function (vert) {
|
|
943
|
+
return typeof precision === undefined
|
|
944
|
+
? { x: vert.x, y: vert.y }
|
|
945
|
+
: { x: Number(vert.x.toFixed(precision)), y: Number(vert.y.toFixed(precision)) };
|
|
946
|
+
}));
|
|
872
947
|
}
|
|
873
948
|
};
|
|
874
949
|
|
|
@@ -893,7 +968,11 @@ Vertex.utils = {
|
|
|
893
968
|
* @modified 2021-01-29 Added the `isClockwise` function.
|
|
894
969
|
* @modified 2021-01-29 Added the `area` function.
|
|
895
970
|
* @modified 2021-01-29 Changed the param type for `containsVert` from Vertex to XYCoords.
|
|
896
|
-
* @
|
|
971
|
+
* @modified 2021-12-14 Added the `perimeter()` function.
|
|
972
|
+
* @modified 2021-12-16 Added the `getEvenDistributionPolygon()` function.
|
|
973
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
974
|
+
* @modified 2022-02-02 Cleared the `Polygon.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
975
|
+
* @version 1.9.0
|
|
897
976
|
*
|
|
898
977
|
* @file Polygon
|
|
899
978
|
* @public
|
|
@@ -924,12 +1003,11 @@ class Polygon {
|
|
|
924
1003
|
**/
|
|
925
1004
|
this.className = "Polygon";
|
|
926
1005
|
this.uid = UIDGenerator.next();
|
|
927
|
-
if (typeof vertices ==
|
|
1006
|
+
if (typeof vertices == "undefined")
|
|
928
1007
|
vertices = [];
|
|
929
1008
|
this.vertices = vertices;
|
|
930
1009
|
this.isOpen = isOpen;
|
|
931
1010
|
}
|
|
932
|
-
;
|
|
933
1011
|
/**
|
|
934
1012
|
* Add a vertex to the end of the `vertices` array.
|
|
935
1013
|
*
|
|
@@ -941,7 +1019,6 @@ class Polygon {
|
|
|
941
1019
|
addVertex(vert) {
|
|
942
1020
|
this.vertices.push(vert);
|
|
943
1021
|
}
|
|
944
|
-
;
|
|
945
1022
|
/**
|
|
946
1023
|
* Get the polygon vertex at the given position (index).
|
|
947
1024
|
*
|
|
@@ -964,7 +1041,6 @@ class Polygon {
|
|
|
964
1041
|
else
|
|
965
1042
|
return this.vertices[index % this.vertices.length];
|
|
966
1043
|
}
|
|
967
|
-
;
|
|
968
1044
|
/**
|
|
969
1045
|
* Move the polygon's vertices by the given amount.
|
|
970
1046
|
*
|
|
@@ -980,7 +1056,6 @@ class Polygon {
|
|
|
980
1056
|
}
|
|
981
1057
|
return this;
|
|
982
1058
|
}
|
|
983
|
-
;
|
|
984
1059
|
/**
|
|
985
1060
|
* Check if the given vertex is inside this polygon.<br>
|
|
986
1061
|
* <br>
|
|
@@ -1000,14 +1075,12 @@ class Polygon {
|
|
|
1000
1075
|
for (var i = 0, j = this.vertices.length - 1; i < this.vertices.length; j = i++) {
|
|
1001
1076
|
let xi = this.vertices[i].x, yi = this.vertices[i].y;
|
|
1002
1077
|
let xj = this.vertices[j].x, yj = this.vertices[j].y;
|
|
1003
|
-
var intersect =
|
|
1004
|
-
&& (vert.x < (xj - xi) * (vert.y - yi) / (yj - yi) + xi);
|
|
1078
|
+
var intersect = yi > vert.y != yj > vert.y && vert.x < ((xj - xi) * (vert.y - yi)) / (yj - yi) + xi;
|
|
1005
1079
|
if (intersect)
|
|
1006
1080
|
inside = !inside;
|
|
1007
1081
|
}
|
|
1008
1082
|
return inside;
|
|
1009
1083
|
}
|
|
1010
|
-
;
|
|
1011
1084
|
/**
|
|
1012
1085
|
* Calculate the area of the given polygon (unsigned).
|
|
1013
1086
|
*
|
|
@@ -1021,7 +1094,6 @@ class Polygon {
|
|
|
1021
1094
|
area() {
|
|
1022
1095
|
return Polygon.utils.area(this.vertices);
|
|
1023
1096
|
}
|
|
1024
|
-
;
|
|
1025
1097
|
/**
|
|
1026
1098
|
* Calulate the signed polyon area by interpreting the polygon as a matrix
|
|
1027
1099
|
* and calculating its determinant.
|
|
@@ -1034,7 +1106,6 @@ class Polygon {
|
|
|
1034
1106
|
signedArea() {
|
|
1035
1107
|
return Polygon.utils.signedArea(this.vertices);
|
|
1036
1108
|
}
|
|
1037
|
-
;
|
|
1038
1109
|
/**
|
|
1039
1110
|
* Get the winding order of this polgon: clockwise or counterclockwise.
|
|
1040
1111
|
*
|
|
@@ -1046,7 +1117,28 @@ class Polygon {
|
|
|
1046
1117
|
isClockwise() {
|
|
1047
1118
|
return Polygon.utils.signedArea(this.vertices) < 0;
|
|
1048
1119
|
}
|
|
1049
|
-
|
|
1120
|
+
/**
|
|
1121
|
+
* Get the perimeter of this polygon.
|
|
1122
|
+
* The perimeter is the absolute length of the outline.
|
|
1123
|
+
*
|
|
1124
|
+
* If this polygon is open then the last segment (connecting the first and the
|
|
1125
|
+
* last vertex) will be skipped.
|
|
1126
|
+
*
|
|
1127
|
+
* @method perimeter
|
|
1128
|
+
* @instance
|
|
1129
|
+
* @memberof Polygon
|
|
1130
|
+
* @return {number}
|
|
1131
|
+
*/
|
|
1132
|
+
perimeter() {
|
|
1133
|
+
let length = 0;
|
|
1134
|
+
for (var i = 1; i < this.vertices.length; i++) {
|
|
1135
|
+
length += this.vertices[i - 1].distance(this.vertices[i]);
|
|
1136
|
+
}
|
|
1137
|
+
if (!this.isOpen && this.vertices.length > 1) {
|
|
1138
|
+
length += this.vertices[0].distance(this.vertices[this.vertices.length - 1]);
|
|
1139
|
+
}
|
|
1140
|
+
return length;
|
|
1141
|
+
}
|
|
1050
1142
|
/**
|
|
1051
1143
|
* Scale the polygon relative to the given center.
|
|
1052
1144
|
*
|
|
@@ -1059,14 +1151,13 @@ class Polygon {
|
|
|
1059
1151
|
**/
|
|
1060
1152
|
scale(factor, center) {
|
|
1061
1153
|
for (var i in this.vertices) {
|
|
1062
|
-
if (typeof this.vertices[i].scale ==
|
|
1154
|
+
if (typeof this.vertices[i].scale == "function")
|
|
1063
1155
|
this.vertices[i].scale(factor, center);
|
|
1064
1156
|
else
|
|
1065
|
-
console.log(
|
|
1157
|
+
console.log("There seems to be a null vertex!", this.vertices[i]);
|
|
1066
1158
|
}
|
|
1067
1159
|
return this;
|
|
1068
1160
|
}
|
|
1069
|
-
;
|
|
1070
1161
|
/**
|
|
1071
1162
|
* Rotate the polygon around the given center.
|
|
1072
1163
|
*
|
|
@@ -1083,7 +1174,52 @@ class Polygon {
|
|
|
1083
1174
|
}
|
|
1084
1175
|
return this;
|
|
1085
1176
|
}
|
|
1086
|
-
|
|
1177
|
+
/**
|
|
1178
|
+
* Convert this polygon into a new polygon with n evenly distributed vertices.
|
|
1179
|
+
*
|
|
1180
|
+
* @param {number} pointCount - Must not be negative.
|
|
1181
|
+
*/
|
|
1182
|
+
getEvenDistributionPolygon(pointCount) {
|
|
1183
|
+
if (pointCount <= 0) {
|
|
1184
|
+
throw new Error("pointCount must be larger than zero; is " + pointCount + ".");
|
|
1185
|
+
}
|
|
1186
|
+
const result = new Polygon([], this.isOpen);
|
|
1187
|
+
if (this.vertices.length === 0) {
|
|
1188
|
+
return result;
|
|
1189
|
+
}
|
|
1190
|
+
// Fetch and add the start point from the source polygon
|
|
1191
|
+
let polygonPoint = new Vertex(this.vertices[0]);
|
|
1192
|
+
result.vertices.push(polygonPoint);
|
|
1193
|
+
if (this.vertices.length === 1) {
|
|
1194
|
+
return result;
|
|
1195
|
+
}
|
|
1196
|
+
const perimeter = this.perimeter();
|
|
1197
|
+
const stepSize = perimeter / pointCount;
|
|
1198
|
+
const n = this.vertices.length;
|
|
1199
|
+
let polygonIndex = 1;
|
|
1200
|
+
let nextPolygonPoint = new Vertex(this.vertices[1]);
|
|
1201
|
+
let segmentLength = polygonPoint.distance(nextPolygonPoint);
|
|
1202
|
+
let loopMax = this.isOpen ? n : n + 1;
|
|
1203
|
+
let curSegmentU = stepSize;
|
|
1204
|
+
var i = 1;
|
|
1205
|
+
while (i < pointCount && polygonIndex < loopMax) {
|
|
1206
|
+
// Check if next eq point is inside this segment
|
|
1207
|
+
if (curSegmentU < segmentLength) {
|
|
1208
|
+
let newPoint = polygonPoint.clone().lerpAbs(nextPolygonPoint, curSegmentU);
|
|
1209
|
+
result.vertices.push(newPoint);
|
|
1210
|
+
curSegmentU += stepSize;
|
|
1211
|
+
i++;
|
|
1212
|
+
}
|
|
1213
|
+
else {
|
|
1214
|
+
polygonIndex++;
|
|
1215
|
+
polygonPoint = nextPolygonPoint;
|
|
1216
|
+
nextPolygonPoint = new Vertex(this.vertices[polygonIndex % n]);
|
|
1217
|
+
curSegmentU = curSegmentU - segmentLength;
|
|
1218
|
+
segmentLength = polygonPoint.distance(nextPolygonPoint);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1087
1223
|
/**
|
|
1088
1224
|
* Get the bounding box (bounds) of this polygon.
|
|
1089
1225
|
*
|
|
@@ -1095,7 +1231,6 @@ class Polygon {
|
|
|
1095
1231
|
getBounds() {
|
|
1096
1232
|
return Bounds.computeFromVertices(this.vertices);
|
|
1097
1233
|
}
|
|
1098
|
-
;
|
|
1099
1234
|
/**
|
|
1100
1235
|
* Convert this polygon to a sequence of quadratic Bézier curves.<br>
|
|
1101
1236
|
* <br>
|
|
@@ -1127,7 +1262,6 @@ class Polygon {
|
|
|
1127
1262
|
}
|
|
1128
1263
|
return qbezier;
|
|
1129
1264
|
}
|
|
1130
|
-
;
|
|
1131
1265
|
/**
|
|
1132
1266
|
* Convert this polygon to a quadratic bezier curve, represented as an SVG data string.
|
|
1133
1267
|
*
|
|
@@ -1140,13 +1274,12 @@ class Polygon {
|
|
|
1140
1274
|
var qdata = this.toQuadraticBezierData();
|
|
1141
1275
|
if (qdata.length == 0)
|
|
1142
1276
|
return "";
|
|
1143
|
-
var buffer = [
|
|
1277
|
+
var buffer = ["M " + qdata[0].x + " " + qdata[0].y];
|
|
1144
1278
|
for (var i = 1; i < qdata.length; i += 2) {
|
|
1145
|
-
buffer.push(
|
|
1279
|
+
buffer.push("Q " + qdata[i].x + " " + qdata[i].y + ", " + qdata[i + 1].x + " " + qdata[i + 1].y);
|
|
1146
1280
|
}
|
|
1147
|
-
return buffer.join(
|
|
1281
|
+
return buffer.join(" ");
|
|
1148
1282
|
}
|
|
1149
|
-
;
|
|
1150
1283
|
/**
|
|
1151
1284
|
* Convert this polygon to a sequence of cubic Bézier curves.<br>
|
|
1152
1285
|
* <br>
|
|
@@ -1163,7 +1296,7 @@ class Polygon {
|
|
|
1163
1296
|
* @memberof Polygon
|
|
1164
1297
|
**/
|
|
1165
1298
|
toCubicBezierData(threshold) {
|
|
1166
|
-
if (typeof threshold ==
|
|
1299
|
+
if (typeof threshold == "undefined")
|
|
1167
1300
|
threshold = 1.0;
|
|
1168
1301
|
if (this.vertices.length < 3)
|
|
1169
1302
|
return [];
|
|
@@ -1187,7 +1320,6 @@ class Polygon {
|
|
|
1187
1320
|
}
|
|
1188
1321
|
return cbezier;
|
|
1189
1322
|
}
|
|
1190
|
-
;
|
|
1191
1323
|
/**
|
|
1192
1324
|
* Convert this polygon to a cubic bezier curve, represented as an SVG data string.
|
|
1193
1325
|
*
|
|
@@ -1200,13 +1332,23 @@ class Polygon {
|
|
|
1200
1332
|
var qdata = this.toCubicBezierData(threshold);
|
|
1201
1333
|
if (qdata.length == 0)
|
|
1202
1334
|
return "";
|
|
1203
|
-
var buffer = [
|
|
1335
|
+
var buffer = ["M " + qdata[0].x + " " + qdata[0].y];
|
|
1204
1336
|
for (var i = 1; i < qdata.length; i += 3) {
|
|
1205
|
-
buffer.push(
|
|
1206
|
-
|
|
1207
|
-
|
|
1337
|
+
buffer.push("C " +
|
|
1338
|
+
qdata[i].x +
|
|
1339
|
+
" " +
|
|
1340
|
+
qdata[i].y +
|
|
1341
|
+
", " +
|
|
1342
|
+
qdata[i + 1].x +
|
|
1343
|
+
" " +
|
|
1344
|
+
qdata[i + 1].y +
|
|
1345
|
+
", " +
|
|
1346
|
+
qdata[i + 2].x +
|
|
1347
|
+
" " +
|
|
1348
|
+
qdata[i + 2].y);
|
|
1349
|
+
}
|
|
1350
|
+
return buffer.join(" ");
|
|
1208
1351
|
}
|
|
1209
|
-
;
|
|
1210
1352
|
/**
|
|
1211
1353
|
* Convert this polygon to a cubic bezier path instance.
|
|
1212
1354
|
*
|
|
@@ -1225,7 +1367,6 @@ class Polygon {
|
|
|
1225
1367
|
}
|
|
1226
1368
|
return BezierPath.fromArray(pathdata);
|
|
1227
1369
|
}
|
|
1228
|
-
;
|
|
1229
1370
|
/**
|
|
1230
1371
|
* Create an SVG representation of this polygon.
|
|
1231
1372
|
*
|
|
@@ -1237,31 +1378,42 @@ class Polygon {
|
|
|
1237
1378
|
* @memberof Polygon
|
|
1238
1379
|
**/
|
|
1239
1380
|
toSVGString(options) {
|
|
1240
|
-
options = options || {};
|
|
1241
|
-
var buffer = [];
|
|
1242
|
-
buffer.push(
|
|
1243
|
-
if (options.className)
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1381
|
+
// options = options || {};
|
|
1382
|
+
// var buffer: Array<string> = [];
|
|
1383
|
+
// buffer.push("<path");
|
|
1384
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
1385
|
+
// buffer.push(' d="');
|
|
1386
|
+
// if (this.vertices.length > 0) {
|
|
1387
|
+
// buffer.push("M ");
|
|
1388
|
+
// buffer.push(this.vertices[0].x.toString());
|
|
1389
|
+
// buffer.push(" ");
|
|
1390
|
+
// buffer.push(this.vertices[0].y.toString());
|
|
1391
|
+
// for (var i = 1; i < this.vertices.length; i++) {
|
|
1392
|
+
// buffer.push(" L ");
|
|
1393
|
+
// buffer.push(this.vertices[i].x.toString());
|
|
1394
|
+
// buffer.push(" ");
|
|
1395
|
+
// buffer.push(this.vertices[i].y.toString());
|
|
1396
|
+
// }
|
|
1397
|
+
// if (!this.isOpen) {
|
|
1398
|
+
// buffer.push(" Z");
|
|
1399
|
+
// }
|
|
1400
|
+
// }
|
|
1401
|
+
// buffer.push('" />');
|
|
1402
|
+
// return buffer.join("");
|
|
1403
|
+
console.warn("[Deprecation] Warning: the Polygon.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
1404
|
+
return "";
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
1408
|
+
* After calling this function the object might not hold valid data any more and
|
|
1409
|
+
* should not be used.
|
|
1410
|
+
*/
|
|
1411
|
+
destroy() {
|
|
1412
|
+
for (var i = 0; i < this.vertices.length; i++) {
|
|
1413
|
+
this.vertices[i].destroy();
|
|
1260
1414
|
}
|
|
1261
|
-
|
|
1262
|
-
return buffer.join('');
|
|
1415
|
+
this.isDestroyed = true;
|
|
1263
1416
|
}
|
|
1264
|
-
;
|
|
1265
1417
|
}
|
|
1266
1418
|
Polygon.utils = {
|
|
1267
1419
|
/**
|
|
@@ -1281,8 +1433,8 @@ Polygon.utils = {
|
|
|
1281
1433
|
const addY = vertices[(i + 1) % l].y;
|
|
1282
1434
|
const subX = vertices[(i + 1) % l].x;
|
|
1283
1435
|
const subY = vertices[i].y;
|
|
1284
|
-
total +=
|
|
1285
|
-
total -=
|
|
1436
|
+
total += addX * addY * 0.5;
|
|
1437
|
+
total -= subX * subY * 0.5;
|
|
1286
1438
|
}
|
|
1287
1439
|
return Math.abs(total);
|
|
1288
1440
|
},
|
|
@@ -1389,7 +1541,8 @@ class Bounds {
|
|
|
1389
1541
|
* @modified 2020-12-04 Changed `getClosestT` param from `Vertex` to `XYCoords` (generalized).
|
|
1390
1542
|
* @modified 2020-12-04 Added the `hasPoint(XYCoords)` function.
|
|
1391
1543
|
* @modified 2021-01-20 Added UID.
|
|
1392
|
-
* @
|
|
1544
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
1545
|
+
* @version 1.2.0
|
|
1393
1546
|
*/
|
|
1394
1547
|
/**
|
|
1395
1548
|
* @classdesc An abstract base classes for vertex tuple constructs, like Lines or Vectors.
|
|
@@ -1423,7 +1576,6 @@ class VertTuple {
|
|
|
1423
1576
|
length() {
|
|
1424
1577
|
return Math.sqrt(Math.pow(this.b.x - this.a.x, 2) + Math.pow(this.b.y - this.a.y, 2));
|
|
1425
1578
|
}
|
|
1426
|
-
;
|
|
1427
1579
|
/**
|
|
1428
1580
|
* Set the length of this vector to the given amount. This only works if this
|
|
1429
1581
|
* vector is not a null vector.
|
|
@@ -1436,7 +1588,6 @@ class VertTuple {
|
|
|
1436
1588
|
setLength(length) {
|
|
1437
1589
|
return this.scale(length / this.length());
|
|
1438
1590
|
}
|
|
1439
|
-
;
|
|
1440
1591
|
/**
|
|
1441
1592
|
* Substract the given vertex from this line's end points.
|
|
1442
1593
|
*
|
|
@@ -1451,7 +1602,6 @@ class VertTuple {
|
|
|
1451
1602
|
this.b.sub(amount);
|
|
1452
1603
|
return this;
|
|
1453
1604
|
}
|
|
1454
|
-
;
|
|
1455
1605
|
/**
|
|
1456
1606
|
* Add the given vertex to this line's end points.
|
|
1457
1607
|
*
|
|
@@ -1466,7 +1616,6 @@ class VertTuple {
|
|
|
1466
1616
|
this.b.add(amount);
|
|
1467
1617
|
return this;
|
|
1468
1618
|
}
|
|
1469
|
-
;
|
|
1470
1619
|
/**
|
|
1471
1620
|
* Normalize this line (set to length 1).
|
|
1472
1621
|
*
|
|
@@ -1479,7 +1628,6 @@ class VertTuple {
|
|
|
1479
1628
|
this.b.set(this.a.x + (this.b.x - this.a.x) / this.length(), this.a.y + (this.b.y - this.a.y) / this.length());
|
|
1480
1629
|
return this;
|
|
1481
1630
|
}
|
|
1482
|
-
;
|
|
1483
1631
|
/**
|
|
1484
1632
|
* Scale this line by the given factor.
|
|
1485
1633
|
*
|
|
@@ -1493,7 +1641,6 @@ class VertTuple {
|
|
|
1493
1641
|
this.b.set(this.a.x + (this.b.x - this.a.x) * factor, this.a.y + (this.b.y - this.a.y) * factor);
|
|
1494
1642
|
return this;
|
|
1495
1643
|
}
|
|
1496
|
-
;
|
|
1497
1644
|
/**
|
|
1498
1645
|
* Move this line to a new location.
|
|
1499
1646
|
*
|
|
@@ -1509,7 +1656,6 @@ class VertTuple {
|
|
|
1509
1656
|
this.b.add(diff);
|
|
1510
1657
|
return this;
|
|
1511
1658
|
}
|
|
1512
|
-
;
|
|
1513
1659
|
/**
|
|
1514
1660
|
* Get the angle between this and the passed line (in radians).
|
|
1515
1661
|
*
|
|
@@ -1520,7 +1666,7 @@ class VertTuple {
|
|
|
1520
1666
|
* @memberof VertTuple
|
|
1521
1667
|
**/
|
|
1522
1668
|
angle(line) {
|
|
1523
|
-
if (line == null || typeof line ==
|
|
1669
|
+
if (line == null || typeof line == "undefined") {
|
|
1524
1670
|
line = this.factory(new Vertex(0, 0), new Vertex(100, 0));
|
|
1525
1671
|
}
|
|
1526
1672
|
// Compute the angle from x axis and the return the difference :)
|
|
@@ -1530,7 +1676,6 @@ class VertTuple {
|
|
|
1530
1676
|
// The result might be negative, but isn't it usually nicer to determine angles in positive values only?
|
|
1531
1677
|
return Math.atan2(v1.x, v1.y) - Math.atan2(v0.x, v0.y);
|
|
1532
1678
|
}
|
|
1533
|
-
;
|
|
1534
1679
|
/**
|
|
1535
1680
|
* Get line point at position t in [0 ... 1]:<br>
|
|
1536
1681
|
* <pre>[P(0)]=[A]--------------------[P(t)]------[B]=[P(1)]</pre><br>
|
|
@@ -1546,7 +1691,6 @@ class VertTuple {
|
|
|
1546
1691
|
vertAt(t) {
|
|
1547
1692
|
return new Vertex(this.a.x + (this.b.x - this.a.x) * t, this.a.y + (this.b.y - this.a.y) * t);
|
|
1548
1693
|
}
|
|
1549
|
-
;
|
|
1550
1694
|
/**
|
|
1551
1695
|
* Get the denominator of this and the given line.
|
|
1552
1696
|
*
|
|
@@ -1560,9 +1704,8 @@ class VertTuple {
|
|
|
1560
1704
|
**/
|
|
1561
1705
|
denominator(line) {
|
|
1562
1706
|
// http://jsfiddle.net/justin_c_rounds/Gd2S2/
|
|
1563
|
-
return (
|
|
1707
|
+
return (line.b.y - line.a.y) * (this.b.x - this.a.x) - (line.b.x - line.a.x) * (this.b.y - this.a.y);
|
|
1564
1708
|
}
|
|
1565
|
-
;
|
|
1566
1709
|
/**
|
|
1567
1710
|
* Checks if this and the given line are co-linear.
|
|
1568
1711
|
*
|
|
@@ -1577,7 +1720,6 @@ class VertTuple {
|
|
|
1577
1720
|
colinear(line) {
|
|
1578
1721
|
return Math.abs(this.denominator(line)) < Vertex.EPSILON;
|
|
1579
1722
|
}
|
|
1580
|
-
;
|
|
1581
1723
|
/**
|
|
1582
1724
|
* Get the closest position T from this line to the specified point.
|
|
1583
1725
|
*
|
|
@@ -1600,7 +1742,6 @@ class VertTuple {
|
|
|
1600
1742
|
// t = Math.max(0, Math.min(1, t));
|
|
1601
1743
|
return t;
|
|
1602
1744
|
}
|
|
1603
|
-
;
|
|
1604
1745
|
/**
|
|
1605
1746
|
* Check if the given point is located on this line. Optionally also check if
|
|
1606
1747
|
* that point is located between point `a` and `b`.
|
|
@@ -1636,7 +1777,6 @@ class VertTuple {
|
|
|
1636
1777
|
var t = this.getClosestT(p);
|
|
1637
1778
|
return this.vertAt(t);
|
|
1638
1779
|
}
|
|
1639
|
-
;
|
|
1640
1780
|
/**
|
|
1641
1781
|
* The the minimal distance between this line and the specified point.
|
|
1642
1782
|
*
|
|
@@ -1651,7 +1791,6 @@ class VertTuple {
|
|
|
1651
1791
|
// https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
|
|
1652
1792
|
return Math.sqrt(VertTuple.vtutils.dist2(p, this.vertAt(this.getClosestT(p))));
|
|
1653
1793
|
}
|
|
1654
|
-
;
|
|
1655
1794
|
/**
|
|
1656
1795
|
* Create a deep clone of this instance.
|
|
1657
1796
|
*
|
|
@@ -1663,7 +1802,6 @@ class VertTuple {
|
|
|
1663
1802
|
clone() {
|
|
1664
1803
|
return this.factory(this.a.clone(), this.b.clone());
|
|
1665
1804
|
}
|
|
1666
|
-
;
|
|
1667
1805
|
/**
|
|
1668
1806
|
* Create a string representation of this line.
|
|
1669
1807
|
*
|
|
@@ -1675,7 +1813,16 @@ class VertTuple {
|
|
|
1675
1813
|
toString() {
|
|
1676
1814
|
return "{ a : " + this.a.toString() + ", b : " + this.b.toString() + " }";
|
|
1677
1815
|
}
|
|
1678
|
-
|
|
1816
|
+
/**
|
|
1817
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
1818
|
+
* After calling this function the object might not hold valid data any more and
|
|
1819
|
+
* should not be used.
|
|
1820
|
+
*/
|
|
1821
|
+
destroy() {
|
|
1822
|
+
this.a.destroy();
|
|
1823
|
+
this.b.destroy();
|
|
1824
|
+
this.isDestroyed = true;
|
|
1825
|
+
}
|
|
1679
1826
|
}
|
|
1680
1827
|
/**
|
|
1681
1828
|
* @private
|
|
@@ -1697,7 +1844,9 @@ VertTuple.vtutils = {
|
|
|
1697
1844
|
* @modified 2019-12-04 Added the Vector.inv() function.
|
|
1698
1845
|
* @modified 2020-03-23 Ported to Typescript from JS.
|
|
1699
1846
|
* @modified 2021-01-20 Added UID.
|
|
1700
|
-
* @
|
|
1847
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
1848
|
+
* @modified 2022-02-02 Cleared the `Vector.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
1849
|
+
* @version 1.4.0
|
|
1701
1850
|
*
|
|
1702
1851
|
* @file Vector
|
|
1703
1852
|
* @public
|
|
@@ -1728,7 +1877,6 @@ class Vector extends VertTuple {
|
|
|
1728
1877
|
**/
|
|
1729
1878
|
this.className = "Vector";
|
|
1730
1879
|
}
|
|
1731
|
-
;
|
|
1732
1880
|
/**
|
|
1733
1881
|
* Get the perpendicular of this vector which is located at a.
|
|
1734
1882
|
*
|
|
@@ -1743,7 +1891,6 @@ class Vector extends VertTuple {
|
|
|
1743
1891
|
v.b.add(this.a);
|
|
1744
1892
|
return v;
|
|
1745
1893
|
}
|
|
1746
|
-
;
|
|
1747
1894
|
/**
|
|
1748
1895
|
* The inverse of a vector is a vector witht the same magnitude but oppose direction.
|
|
1749
1896
|
*
|
|
@@ -1757,7 +1904,6 @@ class Vector extends VertTuple {
|
|
|
1757
1904
|
this.b = tmp;
|
|
1758
1905
|
return this;
|
|
1759
1906
|
}
|
|
1760
|
-
;
|
|
1761
1907
|
/**
|
|
1762
1908
|
* This function computes the inverse of the vector, which means 'a' stays untouched.
|
|
1763
1909
|
*
|
|
@@ -1768,7 +1914,6 @@ class Vector extends VertTuple {
|
|
|
1768
1914
|
this.b.y = this.a.y - (this.b.y - this.a.y);
|
|
1769
1915
|
return this;
|
|
1770
1916
|
}
|
|
1771
|
-
;
|
|
1772
1917
|
/**
|
|
1773
1918
|
* Get the intersection if this vector and the specified vector.
|
|
1774
1919
|
*
|
|
@@ -1784,16 +1929,15 @@ class Vector extends VertTuple {
|
|
|
1784
1929
|
return null;
|
|
1785
1930
|
var a = this.a.y - line.a.y;
|
|
1786
1931
|
var b = this.a.x - line.a.x;
|
|
1787
|
-
var numerator1 = (
|
|
1788
|
-
var numerator2 = (
|
|
1932
|
+
var numerator1 = (line.b.x - line.a.x) * a - (line.b.y - line.a.y) * b;
|
|
1933
|
+
var numerator2 = (this.b.x - this.a.x) * a - (this.b.y - this.a.y) * b;
|
|
1789
1934
|
a = numerator1 / denominator; // NaN if parallel lines
|
|
1790
1935
|
b = numerator2 / denominator;
|
|
1791
1936
|
// TODO:
|
|
1792
1937
|
// FOR A VECTOR THE LINE-INTERSECTION MUST BE ON BOTH VECTORS
|
|
1793
1938
|
// if we cast these lines infinitely in both directions, they intersect here:
|
|
1794
|
-
return new Vertex(this.a.x +
|
|
1939
|
+
return new Vertex(this.a.x + a * (this.b.x - this.a.x), this.a.y + a * (this.b.y - this.a.y));
|
|
1795
1940
|
}
|
|
1796
|
-
;
|
|
1797
1941
|
/**
|
|
1798
1942
|
* Create an SVG representation of this line.
|
|
1799
1943
|
*
|
|
@@ -1806,31 +1950,30 @@ class Vector extends VertTuple {
|
|
|
1806
1950
|
* @memberof Vector
|
|
1807
1951
|
**/
|
|
1808
1952
|
toSVGString(options) {
|
|
1809
|
-
options = options || {};
|
|
1810
|
-
var buffer = [];
|
|
1811
|
-
var vertices = Vector.utils.buildArrowHead(this.a, this.b, 8, 1.0, 1.0);
|
|
1812
|
-
buffer.push(
|
|
1813
|
-
if (options.className)
|
|
1814
|
-
|
|
1815
|
-
buffer.push(
|
|
1816
|
-
buffer.push('
|
|
1817
|
-
buffer.push('
|
|
1818
|
-
buffer.push('
|
|
1819
|
-
buffer.push('
|
|
1820
|
-
buffer.push(
|
|
1821
|
-
|
|
1822
|
-
//
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
buffer.
|
|
1830
|
-
|
|
1831
|
-
return
|
|
1953
|
+
// options = options || {};
|
|
1954
|
+
// var buffer = [];
|
|
1955
|
+
// var vertices = Vector.utils.buildArrowHead(this.a, this.b, 8, 1.0, 1.0);
|
|
1956
|
+
// buffer.push("<g");
|
|
1957
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
1958
|
+
// buffer.push(">");
|
|
1959
|
+
// buffer.push(" <line");
|
|
1960
|
+
// buffer.push(' x1="' + this.a.x + '"');
|
|
1961
|
+
// buffer.push(' y1="' + this.a.y + '"');
|
|
1962
|
+
// buffer.push(' x2="' + vertices[0].x + '"');
|
|
1963
|
+
// buffer.push(' y2="' + vertices[0].y + '"');
|
|
1964
|
+
// buffer.push(" />");
|
|
1965
|
+
// // Add arrow head
|
|
1966
|
+
// buffer.push(' <polygon points="');
|
|
1967
|
+
// for (var i = 0; i < vertices.length; i++) {
|
|
1968
|
+
// if (i > 0) buffer.push(" ");
|
|
1969
|
+
// buffer.push("" + vertices[i].x + "," + vertices[i].y);
|
|
1970
|
+
// }
|
|
1971
|
+
// buffer.push('"/>');
|
|
1972
|
+
// buffer.push("</g>");
|
|
1973
|
+
// return buffer.join("");
|
|
1974
|
+
console.warn("[Deprecation] Warning: the Vector.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
1975
|
+
return "";
|
|
1832
1976
|
}
|
|
1833
|
-
;
|
|
1834
1977
|
}
|
|
1835
1978
|
Vector.utils = {
|
|
1836
1979
|
/**
|
|
@@ -1861,10 +2004,10 @@ Vector.utils = {
|
|
|
1861
2004
|
buildArrowHead: (zA, zB, headlen, scaleX, scaleY) => {
|
|
1862
2005
|
var angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);
|
|
1863
2006
|
var vertices = [];
|
|
1864
|
-
vertices.push(new Vertex(zB.x * scaleX -
|
|
1865
|
-
vertices.push(new Vertex(zB.x * scaleX -
|
|
2007
|
+
vertices.push(new Vertex(zB.x * scaleX - headlen * Math.cos(angle), zB.y * scaleY - headlen * Math.sin(angle)));
|
|
2008
|
+
vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle - Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle - Math.PI / 8)));
|
|
1866
2009
|
vertices.push(new Vertex(zB.x * scaleX, zB.y * scaleY));
|
|
1867
|
-
vertices.push(new Vertex(zB.x * scaleX -
|
|
2010
|
+
vertices.push(new Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle + Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle + Math.PI / 8)));
|
|
1868
2011
|
return vertices;
|
|
1869
2012
|
}
|
|
1870
2013
|
};
|
|
@@ -1889,7 +2032,9 @@ Vector.utils = {
|
|
|
1889
2032
|
* @modified 2020-07-14 Changed the moveCurvePoint(...,Vertex) to moveCurvePoint(...,XYCoords), which is more generic.
|
|
1890
2033
|
* @modified 2020-07-24 Added the getClosestT function and the helper function locateIntervalByDistance(...).
|
|
1891
2034
|
* @modified 2021-01-20 Added UID.
|
|
1892
|
-
* @
|
|
2035
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
2036
|
+
* @modified 2022-02-02 Cleared the `toSVGPathData` function (deprecated). Use `drawutilssvg` instead.
|
|
2037
|
+
* @version 2.6.0
|
|
1893
2038
|
*
|
|
1894
2039
|
* @file CubicBezierCurve
|
|
1895
2040
|
* @public
|
|
@@ -1938,7 +2083,6 @@ class CubicBezierCurve {
|
|
|
1938
2083
|
this.arcLength = null;
|
|
1939
2084
|
this.updateArcLengths();
|
|
1940
2085
|
}
|
|
1941
|
-
;
|
|
1942
2086
|
/**
|
|
1943
2087
|
* Move the given curve point (the start point, end point or one of the two
|
|
1944
2088
|
* control points).
|
|
@@ -1975,7 +2119,6 @@ class CubicBezierCurve {
|
|
|
1975
2119
|
if (updateArcLengths)
|
|
1976
2120
|
this.updateArcLengths();
|
|
1977
2121
|
}
|
|
1978
|
-
;
|
|
1979
2122
|
/**
|
|
1980
2123
|
* Translate the whole curve by the given {x,y} amount: moves all four points.
|
|
1981
2124
|
*
|
|
@@ -1992,7 +2135,6 @@ class CubicBezierCurve {
|
|
|
1992
2135
|
this.endPoint.add(amount);
|
|
1993
2136
|
return this;
|
|
1994
2137
|
}
|
|
1995
|
-
;
|
|
1996
2138
|
/**
|
|
1997
2139
|
* Reverse this curve, means swapping start- and end-point and swapping
|
|
1998
2140
|
* start-control- and end-control-point.
|
|
@@ -2011,7 +2153,6 @@ class CubicBezierCurve {
|
|
|
2011
2153
|
this.endControlPoint = tmp;
|
|
2012
2154
|
return this;
|
|
2013
2155
|
}
|
|
2014
|
-
;
|
|
2015
2156
|
/**
|
|
2016
2157
|
* Get the total curve length.<br>
|
|
2017
2158
|
* <br>
|
|
@@ -2030,7 +2171,6 @@ class CubicBezierCurve {
|
|
|
2030
2171
|
getLength() {
|
|
2031
2172
|
return this.arcLength;
|
|
2032
2173
|
}
|
|
2033
|
-
;
|
|
2034
2174
|
/**
|
|
2035
2175
|
* Uptate the internal arc segment buffer and their lengths.<br>
|
|
2036
2176
|
* <br>
|
|
@@ -2068,7 +2208,6 @@ class CubicBezierCurve {
|
|
|
2068
2208
|
}
|
|
2069
2209
|
this.arcLength = newLength;
|
|
2070
2210
|
}
|
|
2071
|
-
;
|
|
2072
2211
|
/**
|
|
2073
2212
|
* Get a 't' (relative position on curve) with the closest distance to point 'p'.
|
|
2074
2213
|
*
|
|
@@ -2091,7 +2230,6 @@ class CubicBezierCurve {
|
|
|
2091
2230
|
} while (iteration < 4 && this.getPointAt(result.tPrev).distance(this.getPointAt(result.tNext)) > desiredEpsilon);
|
|
2092
2231
|
return result.t;
|
|
2093
2232
|
}
|
|
2094
|
-
;
|
|
2095
2233
|
/**
|
|
2096
2234
|
* This helper function locates the 't' on a fixed step interval with the minimal distance
|
|
2097
2235
|
* between the curve (at 't') and the given point.
|
|
@@ -2120,12 +2258,12 @@ class CubicBezierCurve {
|
|
|
2120
2258
|
minDist = dist;
|
|
2121
2259
|
}
|
|
2122
2260
|
}
|
|
2123
|
-
return {
|
|
2261
|
+
return {
|
|
2262
|
+
t: tStart + tDiff * (minIndex / stepCount),
|
|
2124
2263
|
tPrev: tStart + tDiff * (Math.max(0, minIndex - 1) / stepCount),
|
|
2125
2264
|
tNext: tStart + tDiff * (Math.min(stepCount, minIndex + 1) / stepCount)
|
|
2126
2265
|
};
|
|
2127
2266
|
}
|
|
2128
|
-
;
|
|
2129
2267
|
/**
|
|
2130
2268
|
* Get the bounds of this bezier curve.
|
|
2131
2269
|
*
|
|
@@ -2147,7 +2285,6 @@ class CubicBezierCurve {
|
|
|
2147
2285
|
}
|
|
2148
2286
|
return new Bounds(min, max);
|
|
2149
2287
|
}
|
|
2150
|
-
;
|
|
2151
2288
|
/**
|
|
2152
2289
|
* Get the start point of the curve.<br>
|
|
2153
2290
|
* <br>
|
|
@@ -2161,7 +2298,6 @@ class CubicBezierCurve {
|
|
|
2161
2298
|
getStartPoint() {
|
|
2162
2299
|
return this.startPoint;
|
|
2163
2300
|
}
|
|
2164
|
-
;
|
|
2165
2301
|
/**
|
|
2166
2302
|
* Get the end point of the curve.<br>
|
|
2167
2303
|
* <br>
|
|
@@ -2175,7 +2311,6 @@ class CubicBezierCurve {
|
|
|
2175
2311
|
getEndPoint() {
|
|
2176
2312
|
return this.endPoint;
|
|
2177
2313
|
}
|
|
2178
|
-
;
|
|
2179
2314
|
/**
|
|
2180
2315
|
* Get the start control point of the curve.<br>
|
|
2181
2316
|
* <br>
|
|
@@ -2189,7 +2324,6 @@ class CubicBezierCurve {
|
|
|
2189
2324
|
getStartControlPoint() {
|
|
2190
2325
|
return this.startControlPoint;
|
|
2191
2326
|
}
|
|
2192
|
-
;
|
|
2193
2327
|
/**
|
|
2194
2328
|
* Get the end control point of the curve.<br>
|
|
2195
2329
|
* <br>
|
|
@@ -2203,7 +2337,6 @@ class CubicBezierCurve {
|
|
|
2203
2337
|
getEndControlPoint() {
|
|
2204
2338
|
return this.endControlPoint;
|
|
2205
2339
|
}
|
|
2206
|
-
;
|
|
2207
2340
|
/**
|
|
2208
2341
|
* Get one of the four curve points specified by the passt point ID.
|
|
2209
2342
|
*
|
|
@@ -2224,7 +2357,6 @@ class CubicBezierCurve {
|
|
|
2224
2357
|
return this.endControlPoint;
|
|
2225
2358
|
throw new Error(`Invalid point ID '${id}'.`);
|
|
2226
2359
|
}
|
|
2227
|
-
;
|
|
2228
2360
|
/**
|
|
2229
2361
|
* Get the curve point at a given position t, where t is in [0,1].<br>
|
|
2230
2362
|
* <br>
|
|
@@ -2239,13 +2371,16 @@ class CubicBezierCurve {
|
|
|
2239
2371
|
**/
|
|
2240
2372
|
getPointAt(t) {
|
|
2241
2373
|
// Perform some powerful math magic
|
|
2242
|
-
const x = this.startPoint.x * Math.pow(1.0 - t, 3) +
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2374
|
+
const x = this.startPoint.x * Math.pow(1.0 - t, 3) +
|
|
2375
|
+
this.startControlPoint.x * 3 * t * Math.pow(1.0 - t, 2) +
|
|
2376
|
+
this.endControlPoint.x * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
2377
|
+
this.endPoint.x * Math.pow(t, 3);
|
|
2378
|
+
const y = this.startPoint.y * Math.pow(1.0 - t, 3) +
|
|
2379
|
+
this.startControlPoint.y * 3 * t * Math.pow(1.0 - t, 2) +
|
|
2380
|
+
this.endControlPoint.y * 3 * Math.pow(t, 2) * (1.0 - t) +
|
|
2381
|
+
this.endPoint.y * Math.pow(t, 3);
|
|
2246
2382
|
return new Vertex(x, y);
|
|
2247
2383
|
}
|
|
2248
|
-
;
|
|
2249
2384
|
/**
|
|
2250
2385
|
* Get the curve point at a given position u, where u is in [0,arcLength].<br>
|
|
2251
2386
|
* <br>
|
|
@@ -2261,7 +2396,6 @@ class CubicBezierCurve {
|
|
|
2261
2396
|
getPoint(u) {
|
|
2262
2397
|
return this.getPointAt(u / this.arcLength);
|
|
2263
2398
|
}
|
|
2264
|
-
;
|
|
2265
2399
|
/**
|
|
2266
2400
|
* Get the curve tangent vector at a given absolute curve position t in [0,1].<br>
|
|
2267
2401
|
* <br>
|
|
@@ -2282,18 +2416,11 @@ class CubicBezierCurve {
|
|
|
2282
2416
|
const t2 = t * t;
|
|
2283
2417
|
// (1 - t)^2 = (1-t)*(1-t) = 1 - t - t + t^2 = 1 - 2*t + t^2
|
|
2284
2418
|
const nt2 = 1 - 2 * t + t2;
|
|
2285
|
-
const tX = -3 * a.x * nt2 +
|
|
2286
|
-
|
|
2287
|
-
c.x * (6 * (t - t2) - 3 * t2) +
|
|
2288
|
-
3 * d.x * t2;
|
|
2289
|
-
const tY = -3 * a.y * nt2 +
|
|
2290
|
-
b.y * (3 * nt2 - 6 * (t - t2)) +
|
|
2291
|
-
c.y * (6 * (t - t2) - 3 * t2) +
|
|
2292
|
-
3 * d.y * t2;
|
|
2419
|
+
const tX = -3 * a.x * nt2 + b.x * (3 * nt2 - 6 * (t - t2)) + c.x * (6 * (t - t2) - 3 * t2) + 3 * d.x * t2;
|
|
2420
|
+
const tY = -3 * a.y * nt2 + b.y * (3 * nt2 - 6 * (t - t2)) + c.y * (6 * (t - t2) - 3 * t2) + 3 * d.y * t2;
|
|
2293
2421
|
// Note: my implementation does NOT normalize tangent vectors!
|
|
2294
2422
|
return new Vertex(tX, tY);
|
|
2295
2423
|
}
|
|
2296
|
-
;
|
|
2297
2424
|
/**
|
|
2298
2425
|
* Get a sub curve at the given start end end offsets (values between 0.0 and 1.0).
|
|
2299
2426
|
*
|
|
@@ -2319,7 +2446,6 @@ class CubicBezierCurve {
|
|
|
2319
2446
|
// pb.draw.cubicBezier( startVec.a, endVec.a, startVec.b, endVec.b, '#8800ff', 2 );
|
|
2320
2447
|
return new CubicBezierCurve(startVec.a, endVec.a, startVec.b, endVec.b);
|
|
2321
2448
|
}
|
|
2322
|
-
;
|
|
2323
2449
|
/**
|
|
2324
2450
|
* Convert a relative curve position u to the absolute curve position t.
|
|
2325
2451
|
*
|
|
@@ -2330,9 +2456,8 @@ class CubicBezierCurve {
|
|
|
2330
2456
|
* @return {number}
|
|
2331
2457
|
**/
|
|
2332
2458
|
convertU2T(u) {
|
|
2333
|
-
return Math.max(0.0, Math.min(1.0,
|
|
2459
|
+
return Math.max(0.0, Math.min(1.0, u / this.arcLength));
|
|
2334
2460
|
}
|
|
2335
|
-
;
|
|
2336
2461
|
/**
|
|
2337
2462
|
* Get the curve tangent vector at a given relative position u in [0,arcLength].<br>
|
|
2338
2463
|
* <br>
|
|
@@ -2347,7 +2472,6 @@ class CubicBezierCurve {
|
|
|
2347
2472
|
getTangent(u) {
|
|
2348
2473
|
return this.getTangentAt(this.convertU2T(u));
|
|
2349
2474
|
}
|
|
2350
|
-
;
|
|
2351
2475
|
/**
|
|
2352
2476
|
* Get the curve perpendicular at a given relative position u in [0,arcLength] as a vector.<br>
|
|
2353
2477
|
* <br>
|
|
@@ -2362,7 +2486,6 @@ class CubicBezierCurve {
|
|
|
2362
2486
|
getPerpendicular(u) {
|
|
2363
2487
|
return this.getPerpendicularAt(this.convertU2T(u));
|
|
2364
2488
|
}
|
|
2365
|
-
;
|
|
2366
2489
|
/**
|
|
2367
2490
|
* Get the curve perpendicular at a given absolute position t in [0,1] as a vector.<br>
|
|
2368
2491
|
* <br>
|
|
@@ -2378,7 +2501,6 @@ class CubicBezierCurve {
|
|
|
2378
2501
|
const tangentVector = this.getTangentAt(t);
|
|
2379
2502
|
return new Vertex(tangentVector.y, -tangentVector.x);
|
|
2380
2503
|
}
|
|
2381
|
-
;
|
|
2382
2504
|
/**
|
|
2383
2505
|
* Clone this Bézier curve (deep clone).
|
|
2384
2506
|
*
|
|
@@ -2390,7 +2512,6 @@ class CubicBezierCurve {
|
|
|
2390
2512
|
clone() {
|
|
2391
2513
|
return new CubicBezierCurve(this.getStartPoint().clone(), this.getEndPoint().clone(), this.getStartControlPoint().clone(), this.getEndControlPoint().clone());
|
|
2392
2514
|
}
|
|
2393
|
-
;
|
|
2394
2515
|
/**
|
|
2395
2516
|
* Check if this and the specified curve are equal.<br>
|
|
2396
2517
|
* <br>
|
|
@@ -2409,17 +2530,25 @@ class CubicBezierCurve {
|
|
|
2409
2530
|
// Let's see if this restricted version works out.
|
|
2410
2531
|
if (!curve)
|
|
2411
2532
|
return false;
|
|
2412
|
-
if (!curve.startPoint ||
|
|
2413
|
-
!curve.endPoint ||
|
|
2414
|
-
!curve.startControlPoint ||
|
|
2415
|
-
!curve.endControlPoint)
|
|
2533
|
+
if (!curve.startPoint || !curve.endPoint || !curve.startControlPoint || !curve.endControlPoint)
|
|
2416
2534
|
return false;
|
|
2417
|
-
return this.startPoint.equals(curve.startPoint)
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2535
|
+
return (this.startPoint.equals(curve.startPoint) &&
|
|
2536
|
+
this.endPoint.equals(curve.endPoint) &&
|
|
2537
|
+
this.startControlPoint.equals(curve.startControlPoint) &&
|
|
2538
|
+
this.endControlPoint.equals(curve.endControlPoint));
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
2542
|
+
* After calling this function the object might not hold valid data any more and
|
|
2543
|
+
* should not be used.
|
|
2544
|
+
*/
|
|
2545
|
+
destroy() {
|
|
2546
|
+
this.startPoint.destroy();
|
|
2547
|
+
this.endPoint.destroy();
|
|
2548
|
+
this.startControlPoint.destroy();
|
|
2549
|
+
this.endControlPoint.destroy();
|
|
2550
|
+
this.isDestroyed = true;
|
|
2421
2551
|
}
|
|
2422
|
-
;
|
|
2423
2552
|
/**
|
|
2424
2553
|
* Quick check for class instance.
|
|
2425
2554
|
* Is there a better way?
|
|
@@ -2445,7 +2574,6 @@ class CubicBezierCurve {
|
|
|
2445
2574
|
*/
|
|
2446
2575
|
return obj instanceof CubicBezierCurve;
|
|
2447
2576
|
}
|
|
2448
|
-
;
|
|
2449
2577
|
/**
|
|
2450
2578
|
* Create an SVG path data representation of this bézier curve.
|
|
2451
2579
|
*
|
|
@@ -2454,32 +2582,34 @@ class CubicBezierCurve {
|
|
|
2454
2582
|
* or in other words<br>
|
|
2455
2583
|
* <pre>'M startoint.x startPoint.y C startControlPoint.x startControlPoint.y endControlPoint.x endControlPoint.y endPoint.x endPoint.y'</pre>
|
|
2456
2584
|
*
|
|
2585
|
+
* @deprecated DEPRECATION Please use the drawutilssvg library and an XMLSerializer instead.
|
|
2457
2586
|
* @method toSVGPathData
|
|
2458
2587
|
* @instance
|
|
2459
2588
|
* @memberof CubicBezierCurve
|
|
2460
2589
|
* @return {string} The SVG path data string.
|
|
2461
2590
|
**/
|
|
2462
2591
|
toSVGPathData() {
|
|
2463
|
-
var buffer = [];
|
|
2464
|
-
buffer.push(
|
|
2465
|
-
buffer.push(this.startPoint.x.toString());
|
|
2466
|
-
buffer.push(
|
|
2467
|
-
buffer.push(this.startPoint.y.toString());
|
|
2468
|
-
buffer.push(
|
|
2469
|
-
buffer.push(this.startControlPoint.x.toString());
|
|
2470
|
-
buffer.push(
|
|
2471
|
-
buffer.push(this.startControlPoint.y.toString());
|
|
2472
|
-
buffer.push(
|
|
2473
|
-
buffer.push(this.endControlPoint.x.toString());
|
|
2474
|
-
buffer.push(
|
|
2475
|
-
buffer.push(this.endControlPoint.y.toString());
|
|
2476
|
-
buffer.push(
|
|
2477
|
-
buffer.push(this.endPoint.x.toString());
|
|
2478
|
-
buffer.push(
|
|
2479
|
-
buffer.push(this.endPoint.y.toString());
|
|
2480
|
-
return buffer.join(
|
|
2592
|
+
// var buffer: Array<string> = [];
|
|
2593
|
+
// buffer.push("M ");
|
|
2594
|
+
// buffer.push(this.startPoint.x.toString());
|
|
2595
|
+
// buffer.push(" ");
|
|
2596
|
+
// buffer.push(this.startPoint.y.toString());
|
|
2597
|
+
// buffer.push(" C ");
|
|
2598
|
+
// buffer.push(this.startControlPoint.x.toString());
|
|
2599
|
+
// buffer.push(" ");
|
|
2600
|
+
// buffer.push(this.startControlPoint.y.toString());
|
|
2601
|
+
// buffer.push(" ");
|
|
2602
|
+
// buffer.push(this.endControlPoint.x.toString());
|
|
2603
|
+
// buffer.push(" ");
|
|
2604
|
+
// buffer.push(this.endControlPoint.y.toString());
|
|
2605
|
+
// buffer.push(" ");
|
|
2606
|
+
// buffer.push(this.endPoint.x.toString());
|
|
2607
|
+
// buffer.push(" ");
|
|
2608
|
+
// buffer.push(this.endPoint.y.toString());
|
|
2609
|
+
// return buffer.join("");
|
|
2610
|
+
console.warn("[Deprecation] Warning: the CubicBezierCurve.toSVGPathData method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
2611
|
+
return "";
|
|
2481
2612
|
}
|
|
2482
|
-
;
|
|
2483
2613
|
/**
|
|
2484
2614
|
* Convert this curve to a JSON string.
|
|
2485
2615
|
*
|
|
@@ -2492,18 +2622,33 @@ class CubicBezierCurve {
|
|
|
2492
2622
|
toJSON(prettyFormat) {
|
|
2493
2623
|
var jsonString = "{ " + // begin object
|
|
2494
2624
|
(prettyFormat ? "\n\t" : "") +
|
|
2495
|
-
"
|
|
2625
|
+
'"startPoint" : [' +
|
|
2626
|
+
this.getStartPoint().x +
|
|
2627
|
+
"," +
|
|
2628
|
+
this.getStartPoint().y +
|
|
2629
|
+
"], " +
|
|
2496
2630
|
(prettyFormat ? "\n\t" : "") +
|
|
2497
|
-
"
|
|
2631
|
+
'"endPoint" : [' +
|
|
2632
|
+
this.getEndPoint().x +
|
|
2633
|
+
"," +
|
|
2634
|
+
this.getEndPoint().y +
|
|
2635
|
+
"], " +
|
|
2498
2636
|
(prettyFormat ? "\n\t" : "") +
|
|
2499
|
-
"
|
|
2637
|
+
'"startControlPoint": [' +
|
|
2638
|
+
this.getStartControlPoint().x +
|
|
2639
|
+
"," +
|
|
2640
|
+
this.getStartControlPoint().y +
|
|
2641
|
+
"], " +
|
|
2500
2642
|
(prettyFormat ? "\n\t" : "") +
|
|
2501
|
-
"
|
|
2643
|
+
'"endControlPoint" : [' +
|
|
2644
|
+
this.getEndControlPoint().x +
|
|
2645
|
+
"," +
|
|
2646
|
+
this.getEndControlPoint().y +
|
|
2647
|
+
"]" +
|
|
2502
2648
|
(prettyFormat ? "\n\t" : "") +
|
|
2503
2649
|
" }"; // end object
|
|
2504
2650
|
return jsonString;
|
|
2505
2651
|
}
|
|
2506
|
-
;
|
|
2507
2652
|
/**
|
|
2508
2653
|
* Parse a Bézier curve from the given JSON string.
|
|
2509
2654
|
*
|
|
@@ -2518,7 +2663,6 @@ class CubicBezierCurve {
|
|
|
2518
2663
|
var obj = JSON.parse(jsonString);
|
|
2519
2664
|
return CubicBezierCurve.fromObject(obj);
|
|
2520
2665
|
}
|
|
2521
|
-
;
|
|
2522
2666
|
/**
|
|
2523
2667
|
* Try to convert the passed object to a CubicBezierCurve.
|
|
2524
2668
|
*
|
|
@@ -2533,16 +2677,15 @@ class CubicBezierCurve {
|
|
|
2533
2677
|
if (typeof obj !== "object")
|
|
2534
2678
|
throw "Can only build from object.";
|
|
2535
2679
|
if (!obj.startPoint)
|
|
2536
|
-
throw
|
|
2680
|
+
throw 'Object member "startPoint" missing.';
|
|
2537
2681
|
if (!obj.endPoint)
|
|
2538
|
-
throw
|
|
2682
|
+
throw 'Object member "endPoint" missing.';
|
|
2539
2683
|
if (!obj.startControlPoint)
|
|
2540
|
-
throw
|
|
2684
|
+
throw 'Object member "startControlPoint" missing.';
|
|
2541
2685
|
if (!obj.endControlPoint)
|
|
2542
|
-
throw
|
|
2686
|
+
throw 'Object member "endControlPoint" missing.';
|
|
2543
2687
|
return new CubicBezierCurve(new Vertex(obj.startPoint[0], obj.startPoint[1]), new Vertex(obj.endPoint[0], obj.endPoint[1]), new Vertex(obj.startControlPoint[0], obj.startControlPoint[1]), new Vertex(obj.endControlPoint[0], obj.endControlPoint[1]));
|
|
2544
2688
|
}
|
|
2545
|
-
;
|
|
2546
2689
|
/**
|
|
2547
2690
|
* Convert a 4-element array of vertices to a cubic bézier curve.
|
|
2548
2691
|
*
|
|
@@ -2559,7 +2702,6 @@ class CubicBezierCurve {
|
|
|
2559
2702
|
throw "Can only build from array with four elements.";
|
|
2560
2703
|
return new CubicBezierCurve(arr[0], arr[1], arr[2], arr[3]);
|
|
2561
2704
|
}
|
|
2562
|
-
;
|
|
2563
2705
|
}
|
|
2564
2706
|
/** @constant {number} */
|
|
2565
2707
|
CubicBezierCurve.START_POINT = 0;
|
|
@@ -2592,7 +2734,10 @@ CubicBezierCurve.END_POINT = 3;
|
|
|
2592
2734
|
* @modified 2020-07-24 Added the getClosestT(Vertex) function.
|
|
2593
2735
|
* @modified 2020-12-29 Constructor is now private (no explicit use intended).
|
|
2594
2736
|
* @modified 2021-05-25 Added BezierPath.fromReducedList( Array<number> ).
|
|
2595
|
-
* @
|
|
2737
|
+
* @modified 2022-01-31 Added `BezierPath.getEvenDistributionVertices(number)`.
|
|
2738
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
2739
|
+
* @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
2740
|
+
* @version 2.5.0
|
|
2596
2741
|
*
|
|
2597
2742
|
* @file BezierPath
|
|
2598
2743
|
* @public
|
|
@@ -3021,6 +3166,35 @@ class BezierPath {
|
|
|
3021
3166
|
this.updateArcLengths();
|
|
3022
3167
|
return this;
|
|
3023
3168
|
}
|
|
3169
|
+
/**
|
|
3170
|
+
* Scale the whole bezier path by the given uniform factor.
|
|
3171
|
+
*
|
|
3172
|
+
* @method scale
|
|
3173
|
+
* @param {Vertex} anchor - The scale origin to scale from.
|
|
3174
|
+
* @param {number} scaleFactor - The scalar to be multiplied with.
|
|
3175
|
+
* @instance
|
|
3176
|
+
* @memberof BezierPath
|
|
3177
|
+
* @return {BezierPath} this for chaining.
|
|
3178
|
+
**/
|
|
3179
|
+
scale(anchor, scaleFactor) {
|
|
3180
|
+
// var scaleFactors : XYCoords = { x : scaleFactor, y : scaleFactor };
|
|
3181
|
+
// for (var i = 0; i < this.bezierCurves.length; i++) {
|
|
3182
|
+
// var curve = this.bezierCurves[i];
|
|
3183
|
+
// curve.getStartPoint().scale(scaleFactor, anchor);
|
|
3184
|
+
// curve.getStartControlPoint().scale(scaleFactor, anchor);
|
|
3185
|
+
// curve.getEndControlPoint().scale(scaleFactor, anchor);
|
|
3186
|
+
// // Do NOT scale the end point here!
|
|
3187
|
+
// // Don't forget that the curves are connected and on curve's end point
|
|
3188
|
+
// // the the successor's start point (same instance)!
|
|
3189
|
+
// }
|
|
3190
|
+
// // Finally move the last end point (was not scaled yet)
|
|
3191
|
+
// if (this.bezierCurves.length > 0 && !this.adjustCircular) {
|
|
3192
|
+
// this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().scale(scaleFactor, anchor);
|
|
3193
|
+
// }
|
|
3194
|
+
// this.updateArcLengths();
|
|
3195
|
+
// return this;
|
|
3196
|
+
return this.scaleXY({ x: scaleFactor, y: scaleFactor }, anchor);
|
|
3197
|
+
}
|
|
3024
3198
|
/**
|
|
3025
3199
|
* Scale the whole bezier path by the given (x,y)-factors.
|
|
3026
3200
|
*
|
|
@@ -3031,19 +3205,19 @@ class BezierPath {
|
|
|
3031
3205
|
* @memberof BezierPath
|
|
3032
3206
|
* @return {BezierPath} this for chaining.
|
|
3033
3207
|
**/
|
|
3034
|
-
|
|
3208
|
+
scaleXY(scaleFactors, anchor) {
|
|
3035
3209
|
for (var i = 0; i < this.bezierCurves.length; i++) {
|
|
3036
3210
|
var curve = this.bezierCurves[i];
|
|
3037
|
-
curve.getStartPoint().
|
|
3038
|
-
curve.getStartControlPoint().
|
|
3039
|
-
curve.getEndControlPoint().
|
|
3211
|
+
curve.getStartPoint().scaleXY(scaleFactors, anchor);
|
|
3212
|
+
curve.getStartControlPoint().scaleXY(scaleFactors, anchor);
|
|
3213
|
+
curve.getEndControlPoint().scaleXY(scaleFactors, anchor);
|
|
3040
3214
|
// Do NOT scale the end point here!
|
|
3041
3215
|
// Don't forget that the curves are connected and on curve's end point
|
|
3042
3216
|
// the the successor's start point (same instance)!
|
|
3043
3217
|
}
|
|
3044
3218
|
// Finally move the last end point (was not scaled yet)
|
|
3045
3219
|
if (this.bezierCurves.length > 0 && !this.adjustCircular) {
|
|
3046
|
-
this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().
|
|
3220
|
+
this.bezierCurves[this.bezierCurves.length - 1].getEndPoint().scaleXY(scaleFactors, anchor);
|
|
3047
3221
|
}
|
|
3048
3222
|
this.updateArcLengths();
|
|
3049
3223
|
return this;
|
|
@@ -3452,6 +3626,59 @@ class BezierPath {
|
|
|
3452
3626
|
}
|
|
3453
3627
|
return new Bounds(min, max);
|
|
3454
3628
|
}
|
|
3629
|
+
/**
|
|
3630
|
+
* Get n 'equally' distributed vertices along this Bézier path.
|
|
3631
|
+
*
|
|
3632
|
+
* As the changing curvature of the B slines makes prediction of distances difficult, the
|
|
3633
|
+
* returned vertices' distances are only relatively equal:
|
|
3634
|
+
* - the distance grows where curvature is large.
|
|
3635
|
+
* - the distance shrinks where curvature is small.
|
|
3636
|
+
*
|
|
3637
|
+
* Only the distance mean of all consecutive is 1/n-th of the total arc length.
|
|
3638
|
+
*
|
|
3639
|
+
* Usually this approximation is good enough for most use cases.
|
|
3640
|
+
*
|
|
3641
|
+
* @param {number} pointCount - (must be at least 2) The number of desired points (start and end point included).
|
|
3642
|
+
* @return {Array<Vertex>}
|
|
3643
|
+
*/
|
|
3644
|
+
getEvenDistributionVertices(pointCount) {
|
|
3645
|
+
if (pointCount < 2) {
|
|
3646
|
+
throw new Error("pointCount must be larger than one; is " + pointCount + ".");
|
|
3647
|
+
}
|
|
3648
|
+
const result = [];
|
|
3649
|
+
if (this.bezierCurves.length === 0) {
|
|
3650
|
+
return result;
|
|
3651
|
+
}
|
|
3652
|
+
// Fetch and add the start point from the source polygon
|
|
3653
|
+
var polygonPoint = new Vertex(this.bezierCurves[0].startPoint);
|
|
3654
|
+
result.push(polygonPoint);
|
|
3655
|
+
// if (this.bezierCurves.length === 1) {
|
|
3656
|
+
// return result;
|
|
3657
|
+
// }
|
|
3658
|
+
const perimeter = this.totalArcLength;
|
|
3659
|
+
const stepSize = perimeter / (pointCount - 1);
|
|
3660
|
+
const n = this.bezierCurves.length;
|
|
3661
|
+
let curveIndex = 0;
|
|
3662
|
+
let segmentLength = this.bezierCurves[0].arcLength;
|
|
3663
|
+
let curSegmentU = stepSize;
|
|
3664
|
+
let i = 1;
|
|
3665
|
+
while (i < pointCount && curveIndex < n) {
|
|
3666
|
+
// Check if next eq point is inside this segment
|
|
3667
|
+
if (curSegmentU < segmentLength) {
|
|
3668
|
+
var newPoint = this.bezierCurves[curveIndex].getPoint(curSegmentU);
|
|
3669
|
+
result.push(newPoint);
|
|
3670
|
+
curSegmentU += stepSize;
|
|
3671
|
+
i++;
|
|
3672
|
+
}
|
|
3673
|
+
else {
|
|
3674
|
+
curveIndex++;
|
|
3675
|
+
curSegmentU = curSegmentU - segmentLength;
|
|
3676
|
+
segmentLength = curveIndex < n ? this.bezierCurves[curveIndex].arcLength : 0;
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
result.push(new Vertex(this.bezierCurves[n - 1].endPoint));
|
|
3680
|
+
return result;
|
|
3681
|
+
}
|
|
3455
3682
|
/**
|
|
3456
3683
|
* Clone this BezierPath (deep clone).
|
|
3457
3684
|
*
|
|
@@ -3509,19 +3736,30 @@ class BezierPath {
|
|
|
3509
3736
|
* @return {string} The SVG string.
|
|
3510
3737
|
**/
|
|
3511
3738
|
toSVGString(options) {
|
|
3512
|
-
options = options || {};
|
|
3513
|
-
var buffer = [];
|
|
3514
|
-
buffer.push("<path");
|
|
3515
|
-
if (options.className)
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3739
|
+
// options = options || {};
|
|
3740
|
+
// var buffer: Array<string> = [];
|
|
3741
|
+
// buffer.push("<path");
|
|
3742
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
3743
|
+
// buffer.push(' d="');
|
|
3744
|
+
// for (var c = 0; c < this.bezierCurves.length; c++) {
|
|
3745
|
+
// if (c > 0) buffer.push(" ");
|
|
3746
|
+
// buffer.push(this.bezierCurves[c].toSVGPathData());
|
|
3747
|
+
// }
|
|
3748
|
+
// buffer.push('" />');
|
|
3749
|
+
// return buffer.join("");
|
|
3750
|
+
console.warn("[Deprecation] Warning: the BezierPath.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
3751
|
+
return "";
|
|
3752
|
+
}
|
|
3753
|
+
/**
|
|
3754
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
3755
|
+
* After calling this function the object might not hold valid data any more and
|
|
3756
|
+
* should not be used.
|
|
3757
|
+
*/
|
|
3758
|
+
destroy() {
|
|
3759
|
+
for (var i = 0; i < this.bezierCurves.length; i++) {
|
|
3760
|
+
this.bezierCurves[i].destroy();
|
|
3522
3761
|
}
|
|
3523
|
-
|
|
3524
|
-
return buffer.join("");
|
|
3762
|
+
this.isDestroyed = true;
|
|
3525
3763
|
}
|
|
3526
3764
|
/**
|
|
3527
3765
|
* Create a JSON string representation of this bézier curve.
|
|
@@ -3748,7 +3986,8 @@ BezierPath.END_POINT = 3;
|
|
|
3748
3986
|
* @modified 2020-03-16 The Line.angle(Line) parameter is now optional. The baseline (x-axis) will be used if not defined.
|
|
3749
3987
|
* @modified 2020-03-23 Ported to Typescript from JS.
|
|
3750
3988
|
* @modified 2020-12-04 The `intersection` function returns undefined if both lines are parallel.
|
|
3751
|
-
* @
|
|
3989
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
3990
|
+
* @version 2.2.0
|
|
3752
3991
|
*
|
|
3753
3992
|
* @file Line
|
|
3754
3993
|
* @public
|
|
@@ -3793,20 +4032,19 @@ class Line extends VertTuple {
|
|
|
3793
4032
|
return null;
|
|
3794
4033
|
let a = this.a.y - line.a.y;
|
|
3795
4034
|
let b = this.a.x - line.a.x;
|
|
3796
|
-
const numerator1 = (
|
|
3797
|
-
const numerator2 = (
|
|
4035
|
+
const numerator1 = (line.b.x - line.a.x) * a - (line.b.y - line.a.y) * b;
|
|
4036
|
+
const numerator2 = (this.b.x - this.a.x) * a - (this.b.y - this.a.y) * b;
|
|
3798
4037
|
a = numerator1 / denominator; // NaN if parallel lines
|
|
3799
4038
|
b = numerator2 / denominator;
|
|
3800
4039
|
// Catch NaN?
|
|
3801
|
-
const x = this.a.x +
|
|
3802
|
-
const y = this.a.y +
|
|
4040
|
+
const x = this.a.x + a * (this.b.x - this.a.x);
|
|
4041
|
+
const y = this.a.y + a * (this.b.y - this.a.y);
|
|
3803
4042
|
if (isNaN(a) || isNaN(x) || isNaN(y)) {
|
|
3804
4043
|
return undefined;
|
|
3805
4044
|
}
|
|
3806
4045
|
// if we cast these lines infinitely in both directions, they intersect here:
|
|
3807
4046
|
return new Vertex(x, y);
|
|
3808
4047
|
}
|
|
3809
|
-
;
|
|
3810
4048
|
/**
|
|
3811
4049
|
* Create an SVG representation of this line.
|
|
3812
4050
|
*
|
|
@@ -3819,19 +4057,20 @@ class Line extends VertTuple {
|
|
|
3819
4057
|
* @memberof Line
|
|
3820
4058
|
**/
|
|
3821
4059
|
toSVGString(options) {
|
|
3822
|
-
options = options || {};
|
|
3823
|
-
var buffer = [];
|
|
3824
|
-
buffer.push('<line');
|
|
3825
|
-
if
|
|
3826
|
-
|
|
3827
|
-
buffer.push(' x1="' + this.a.x + '"');
|
|
3828
|
-
buffer.push(' y1="' + this.a.y + '"');
|
|
3829
|
-
buffer.push(' x2="' + this.b.x + '"');
|
|
3830
|
-
buffer.push(' y2="' + this.b.y + '"');
|
|
3831
|
-
buffer.push(' />');
|
|
3832
|
-
return buffer.join('');
|
|
4060
|
+
// options = options || {};
|
|
4061
|
+
// var buffer = [];
|
|
4062
|
+
// buffer.push( '<line' );
|
|
4063
|
+
// if( options.className )
|
|
4064
|
+
// buffer.push( ' class="' + options.className + '"' );
|
|
4065
|
+
// buffer.push( ' x1="' + this.a.x + '"' );
|
|
4066
|
+
// buffer.push( ' y1="' + this.a.y + '"' );
|
|
4067
|
+
// buffer.push( ' x2="' + this.b.x + '"' );
|
|
4068
|
+
// buffer.push( ' y2="' + this.b.y + '"' );
|
|
4069
|
+
// buffer.push( ' />' );
|
|
4070
|
+
// return buffer.join('');
|
|
4071
|
+
console.warn("[Deprecation] Warning: the Line.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
4072
|
+
return "";
|
|
3833
4073
|
}
|
|
3834
|
-
;
|
|
3835
4074
|
}
|
|
3836
4075
|
|
|
3837
4076
|
/**
|
|
@@ -3843,7 +4082,9 @@ class Line extends VertTuple {
|
|
|
3843
4082
|
* @modified 2020-09-07 Changed the vertAt function by switching sin and cos! The old version did not return the correct vertex (by angle) accoring to the assumed circle math.
|
|
3844
4083
|
* @modified 2020-10-16 Added the containsCircle(...) function.
|
|
3845
4084
|
* @modified 2021-01-20 Added UID.
|
|
3846
|
-
* @
|
|
4085
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
4086
|
+
* @modified 2022-02-02 Cleared the `toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
4087
|
+
* @version 1.3.0
|
|
3847
4088
|
**/
|
|
3848
4089
|
/**
|
|
3849
4090
|
* @classdesc A simple circle: center point and radius.
|
|
@@ -3874,7 +4115,6 @@ class Circle {
|
|
|
3874
4115
|
this.center = center;
|
|
3875
4116
|
this.radius = radius;
|
|
3876
4117
|
}
|
|
3877
|
-
;
|
|
3878
4118
|
/**
|
|
3879
4119
|
* Check if the given circle is fully contained inside this circle.
|
|
3880
4120
|
*
|
|
@@ -3887,7 +4127,6 @@ class Circle {
|
|
|
3887
4127
|
containsCircle(circle) {
|
|
3888
4128
|
return this.center.distance(circle.center) + circle.radius < this.radius;
|
|
3889
4129
|
}
|
|
3890
|
-
;
|
|
3891
4130
|
/**
|
|
3892
4131
|
* Calculate the distance from this circle to the given line.
|
|
3893
4132
|
*
|
|
@@ -3906,7 +4145,6 @@ class Circle {
|
|
|
3906
4145
|
const closestPointOnLine = line.getClosestPoint(this.center);
|
|
3907
4146
|
return closestPointOnLine.distance(this.center) - this.radius;
|
|
3908
4147
|
}
|
|
3909
|
-
;
|
|
3910
4148
|
/**
|
|
3911
4149
|
* Get the vertex on the this circle for the given angle.
|
|
3912
4150
|
*
|
|
@@ -3920,7 +4158,6 @@ class Circle {
|
|
|
3920
4158
|
// Find the point on the circle respective the angle. Then move relative to center.
|
|
3921
4159
|
return Circle.circleUtils.vertAt(angle, this.radius).add(this.center);
|
|
3922
4160
|
}
|
|
3923
|
-
;
|
|
3924
4161
|
/**
|
|
3925
4162
|
* Get a tangent line of this circle for a given angle.
|
|
3926
4163
|
*
|
|
@@ -3937,7 +4174,6 @@ class Circle {
|
|
|
3937
4174
|
// Construct the perpendicular of the line in point a. Then move relative to center.
|
|
3938
4175
|
return new Vector(pointA, new Vertex(0, 0)).add(this.center).perp();
|
|
3939
4176
|
}
|
|
3940
|
-
;
|
|
3941
4177
|
/**
|
|
3942
4178
|
* Calculate the intersection points (if exists) with the given circle.
|
|
3943
4179
|
*
|
|
@@ -3977,48 +4213,56 @@ class Circle {
|
|
|
3977
4213
|
// x4 = P2.x - h*(P1.y - P0.y)/d;
|
|
3978
4214
|
// y4 = P2.y + h*(P1.x - P0.x)/d;
|
|
3979
4215
|
// return pair<Point, Point>(Point(x3, y3), Point(x4, y4));
|
|
3980
|
-
// }
|
|
4216
|
+
// }
|
|
3981
4217
|
var p0 = this.center;
|
|
3982
4218
|
var p1 = circle.center;
|
|
3983
4219
|
var d = p0.distance(p1);
|
|
3984
4220
|
var a = (this.radius * this.radius - circle.radius * circle.radius + d * d) / (2 * d);
|
|
3985
4221
|
var h = Math.sqrt(this.radius * this.radius - a * a);
|
|
3986
4222
|
var p2 = p1.clone().scale(a / d, p0);
|
|
3987
|
-
var x3 = p2.x + h * (p1.y - p0.y) / d;
|
|
3988
|
-
var y3 = p2.y - h * (p1.x - p0.x) / d;
|
|
3989
|
-
var x4 = p2.x - h * (p1.y - p0.y) / d;
|
|
3990
|
-
var y4 = p2.y + h * (p1.x - p0.x) / d;
|
|
4223
|
+
var x3 = p2.x + (h * (p1.y - p0.y)) / d;
|
|
4224
|
+
var y3 = p2.y - (h * (p1.x - p0.x)) / d;
|
|
4225
|
+
var x4 = p2.x - (h * (p1.y - p0.y)) / d;
|
|
4226
|
+
var y4 = p2.y + (h * (p1.x - p0.x)) / d;
|
|
3991
4227
|
return new Line(new Vertex(x3, y3), new Vertex(x4, y4));
|
|
3992
4228
|
}
|
|
3993
|
-
;
|
|
3994
4229
|
/**
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4230
|
+
* Create an SVG representation of this circle.
|
|
4231
|
+
*
|
|
4232
|
+
* @deprecated DEPRECATION Please use the drawutilssvg library and an XMLSerializer instead.
|
|
4233
|
+
* @method toSVGString
|
|
4234
|
+
* @param {object=} options - An optional set of options, like 'className'.
|
|
4235
|
+
* @return {string} A string representing the SVG code for this vertex.
|
|
4236
|
+
* @instance
|
|
4237
|
+
* @memberof Circle
|
|
4238
|
+
*/
|
|
4004
4239
|
toSVGString(options) {
|
|
4005
|
-
options = options || {};
|
|
4006
|
-
var buffer = [];
|
|
4007
|
-
buffer.push(
|
|
4008
|
-
if (options.className)
|
|
4009
|
-
|
|
4010
|
-
buffer.push('
|
|
4011
|
-
buffer.push('
|
|
4012
|
-
buffer.push(
|
|
4013
|
-
buffer.
|
|
4014
|
-
return
|
|
4240
|
+
// options = options || {};
|
|
4241
|
+
// var buffer: Array<string> = [];
|
|
4242
|
+
// buffer.push("<circle");
|
|
4243
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
4244
|
+
// buffer.push(' cx="' + this.center.x + '"');
|
|
4245
|
+
// buffer.push(' cy="' + this.center.y + '"');
|
|
4246
|
+
// buffer.push(' r="' + this.radius + '"');
|
|
4247
|
+
// buffer.push(" />");
|
|
4248
|
+
// return buffer.join("");
|
|
4249
|
+
console.warn("[Deprecation] Warning: the Circle.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
4250
|
+
return "";
|
|
4251
|
+
}
|
|
4252
|
+
/**
|
|
4253
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
4254
|
+
* After calling this function the object might not hold valid data any more and
|
|
4255
|
+
* should not be used.
|
|
4256
|
+
*/
|
|
4257
|
+
destroy() {
|
|
4258
|
+
this.center.destroy();
|
|
4259
|
+
this.isDestroyed = true;
|
|
4015
4260
|
}
|
|
4016
|
-
;
|
|
4017
4261
|
} // END class
|
|
4018
4262
|
Circle.circleUtils = {
|
|
4019
4263
|
vertAt: (angle, radius) => {
|
|
4020
4264
|
/* return new Vertex( Math.sin(angle) * radius,
|
|
4021
|
-
|
|
4265
|
+
Math.cos(angle) * radius ); */
|
|
4022
4266
|
return new Vertex(Math.cos(angle) * radius, Math.sin(angle) * radius);
|
|
4023
4267
|
}
|
|
4024
4268
|
};
|
|
@@ -4059,27 +4303,42 @@ class CircleSector {
|
|
|
4059
4303
|
this.startAngle = startAngle;
|
|
4060
4304
|
this.endAngle = endAngle;
|
|
4061
4305
|
}
|
|
4062
|
-
;
|
|
4063
4306
|
/**
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4307
|
+
* Create an SVG representation of this circle.
|
|
4308
|
+
*
|
|
4309
|
+
* @deprecated DEPRECATION Please use the drawutilssvg library and an XMLSerializer instead.
|
|
4310
|
+
* @method toSVGString
|
|
4311
|
+
* @param {object=} options - An optional set of options, like 'className'.
|
|
4312
|
+
* @return {string} A string representing the SVG code for this vertex.
|
|
4313
|
+
* @instance
|
|
4314
|
+
* @memberof Circle
|
|
4315
|
+
*/
|
|
4072
4316
|
toSVGString(options) {
|
|
4073
|
-
options = options || {};
|
|
4074
|
-
var buffer = [];
|
|
4075
|
-
buffer.push(
|
|
4076
|
-
if (options.className)
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4317
|
+
// options = options || {};
|
|
4318
|
+
// var buffer: Array<string> = [];
|
|
4319
|
+
// buffer.push("<path ");
|
|
4320
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
4321
|
+
// const data: SVGPathParams = CircleSector.circleSectorUtils.describeSVGArc(
|
|
4322
|
+
// this.circle.center.x,
|
|
4323
|
+
// this.circle.center.y,
|
|
4324
|
+
// this.circle.radius,
|
|
4325
|
+
// this.startAngle,
|
|
4326
|
+
// this.endAngle
|
|
4327
|
+
// );
|
|
4328
|
+
// buffer.push(' d="' + data.join(" ") + '" />');
|
|
4329
|
+
// return buffer.join("");
|
|
4330
|
+
console.warn("[Deprecation] Warning: the CircleSector.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
4331
|
+
return "";
|
|
4332
|
+
}
|
|
4333
|
+
/**
|
|
4334
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
4335
|
+
* After calling this function the object might not hold valid data any more and
|
|
4336
|
+
* should not be used.
|
|
4337
|
+
*/
|
|
4338
|
+
destroy() {
|
|
4339
|
+
this.circle.destroy();
|
|
4340
|
+
this.isDestroyed = true;
|
|
4081
4341
|
}
|
|
4082
|
-
;
|
|
4083
4342
|
} // END class
|
|
4084
4343
|
CircleSector.circleSectorUtils = {
|
|
4085
4344
|
/**
|
|
@@ -4088,11 +4347,11 @@ CircleSector.circleSectorUtils = {
|
|
|
4088
4347
|
* TODO: generalize for ellipses (two radii).
|
|
4089
4348
|
*
|
|
4090
4349
|
* @param {number} angle - The angle in radians.
|
|
4091
|
-
|
|
4350
|
+
*/
|
|
4092
4351
|
polarToCartesian: (centerX, centerY, radius, angle) => {
|
|
4093
4352
|
return {
|
|
4094
|
-
x: centerX +
|
|
4095
|
-
y: centerY +
|
|
4353
|
+
x: centerX + radius * Math.cos(angle),
|
|
4354
|
+
y: centerY + radius * Math.sin(angle)
|
|
4096
4355
|
};
|
|
4097
4356
|
},
|
|
4098
4357
|
/**
|
|
@@ -4105,7 +4364,7 @@ CircleSector.circleSectorUtils = {
|
|
|
4105
4364
|
* @return [ 'A', radiusx, radiusy, rotation=0, largeArcFlag=1|0, sweepFlag=0, endx, endy ]
|
|
4106
4365
|
*/
|
|
4107
4366
|
describeSVGArc: (x, y, radius, startAngle, endAngle, options) => {
|
|
4108
|
-
if (typeof options ===
|
|
4367
|
+
if (typeof options === "undefined")
|
|
4109
4368
|
options = { moveToStart: true };
|
|
4110
4369
|
const end = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, endAngle);
|
|
4111
4370
|
const start = CircleSector.circleSectorUtils.polarToCartesian(x, y, radius, startAngle);
|
|
@@ -4130,7 +4389,7 @@ CircleSector.circleSectorUtils = {
|
|
|
4130
4389
|
}
|
|
4131
4390
|
const pathData = [];
|
|
4132
4391
|
if (options.moveToStart) {
|
|
4133
|
-
pathData.push(
|
|
4392
|
+
pathData.push("M", start.x, start.y);
|
|
4134
4393
|
}
|
|
4135
4394
|
pathData.push("A", radius, radius, 0, largeArcFlag, sweepFlag, end.x, end.y);
|
|
4136
4395
|
return pathData;
|
|
@@ -4165,8 +4424,12 @@ CircleSector.circleSectorUtils = {
|
|
|
4165
4424
|
* @modified 2021-03-31 Added 'ellipseSector' the the class names.
|
|
4166
4425
|
* @modified 2021-03-31 Implemented buffering using a buffer <g> node and the beginDrawCycle and endDrawCycle methods.
|
|
4167
4426
|
* @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.
|
|
4168
|
-
* @
|
|
4427
|
+
* @modified 2021-11-15 Adding more parameters tot the `text()` function: fontSize, textAlign, fontFamily, lineHeight.
|
|
4428
|
+
* @modified 2021-11-19 Fixing the `label(text,x,y)` position.
|
|
4429
|
+
* @modified 2021-11-19 Added the `color` param to the `label(...)` function.
|
|
4430
|
+
* @version 1.4.0
|
|
4169
4431
|
**/
|
|
4432
|
+
const RAD_TO_DEG = 180 / Math.PI;
|
|
4170
4433
|
/**
|
|
4171
4434
|
* @classdesc A helper class for basic SVG drawing operations. This class should
|
|
4172
4435
|
* be compatible to the default 'draw' class.
|
|
@@ -4226,7 +4489,8 @@ class drawutilssvg {
|
|
|
4226
4489
|
"vertex": "Vertex",
|
|
4227
4490
|
"line": "Line",
|
|
4228
4491
|
"vector": "Vector",
|
|
4229
|
-
"image": "Image"
|
|
4492
|
+
"image": "Image",
|
|
4493
|
+
"text": "Text"
|
|
4230
4494
|
};
|
|
4231
4495
|
// Question: why isn't this working if the svgNode is created dynamically? (nodeStyle.sheet is null)
|
|
4232
4496
|
const rules = [];
|
|
@@ -5006,27 +5270,65 @@ class drawutilssvg {
|
|
|
5006
5270
|
if (!isOpen)
|
|
5007
5271
|
d.push("Z");
|
|
5008
5272
|
node.setAttribute("d", d.join(" "));
|
|
5009
|
-
return this._bindFillDraw(node, "
|
|
5273
|
+
return this._bindFillDraw(node, "polygon", color, lineWidth || 1);
|
|
5010
5274
|
}
|
|
5011
5275
|
/**
|
|
5012
|
-
* Draw a text
|
|
5276
|
+
* Draw a text at the given relative position.
|
|
5013
5277
|
*
|
|
5014
|
-
* @method
|
|
5278
|
+
* @method text
|
|
5015
5279
|
* @param {string} text - The text to draw.
|
|
5016
5280
|
* @param {number} x - The x-position to draw the text at.
|
|
5017
5281
|
* @param {number} y - The y-position to draw the text at.
|
|
5018
|
-
* @param {
|
|
5282
|
+
* @param {string=} options.color - The Color to use.
|
|
5283
|
+
* @param {string=} options.fontFamily - The font family to use.
|
|
5284
|
+
* @param {number=} options.fontSize - The font size (in pixels) to use.
|
|
5285
|
+
* @param {FontStyle=} options.fontStyle - The font style to use.
|
|
5286
|
+
* @param {FontWeight=} options.fontWeight - The font weight to use.
|
|
5287
|
+
* @param {number=} options.lineHeight - The line height (in pixels) to use.
|
|
5288
|
+
* @param {number=} options.rotation - The (optional) rotation in radians.
|
|
5289
|
+
* @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `"left" || "right" || "center" || "start" || "end"`.
|
|
5019
5290
|
* @return {void}
|
|
5020
5291
|
* @instance
|
|
5021
|
-
* @memberof
|
|
5292
|
+
* @memberof drawutils
|
|
5022
5293
|
*/
|
|
5023
5294
|
text(text, x, y, options) {
|
|
5295
|
+
var _a, _b;
|
|
5024
5296
|
options = options || {};
|
|
5025
5297
|
const color = options.color || "black";
|
|
5026
|
-
const
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5298
|
+
const lineHeight = ((_b = (_a = options.lineHeight) !== null && _a !== void 0 ? _a : options.fontSize) !== null && _b !== void 0 ? _b : 0) * this.scale.x;
|
|
5299
|
+
// https://www.w3.org/TR/SVG/text.html#TextAnchorProperty
|
|
5300
|
+
// start | middle | end
|
|
5301
|
+
const textAlign = options.textAlign === "left" || options.textAlign === "start"
|
|
5302
|
+
? "start"
|
|
5303
|
+
: options.textAlign === "center"
|
|
5304
|
+
? "middle"
|
|
5305
|
+
: options.textAlign === "right" || options.textAlign === "end"
|
|
5306
|
+
? "end"
|
|
5307
|
+
: "start";
|
|
5308
|
+
const transformOrigin = `${this._x(x)}px ${this._y(y)}px`;
|
|
5309
|
+
const translate = `translate(${this._x(x)} ${this._y(y) + lineHeight / 2})`;
|
|
5310
|
+
// Safari has a transform-origin/rotation bug.
|
|
5311
|
+
// It's essential to use rotate(r,x,y) here. "rotate(r)"" with transform-origin(x,y) won't do the job.
|
|
5312
|
+
// And rotate and translate cannot be used is combination on a text object.
|
|
5313
|
+
// So wrap the text inside a <g>, translate the <g>, and rotate the text inside.
|
|
5314
|
+
const rotate = options.rotation ? `rotate(${options.rotation * RAD_TO_DEG} 0 0)` : ``;
|
|
5315
|
+
const node = this.makeNode("g");
|
|
5316
|
+
const curId = this.curId;
|
|
5317
|
+
this.curId = curId + "_text";
|
|
5318
|
+
const textNode = this.makeNode("text");
|
|
5319
|
+
node.appendChild(textNode);
|
|
5320
|
+
textNode.setAttribute("font-family", options.fontFamily); // May be undefined
|
|
5321
|
+
textNode.setAttribute("font-size", options.fontSize ? `${options.fontSize * this.scale.x}` : null);
|
|
5322
|
+
textNode.setAttribute("font-style", options.fontStyle ? `${options.fontStyle}` : null);
|
|
5323
|
+
textNode.setAttribute("font-weight", options.fontWeight ? `${options.fontWeight}` : null);
|
|
5324
|
+
textNode.setAttribute("text-anchor", textAlign);
|
|
5325
|
+
textNode.setAttribute("transform-origin", "0 0");
|
|
5326
|
+
textNode.setAttribute("transform", rotate);
|
|
5327
|
+
node.setAttribute("transform-origin", transformOrigin);
|
|
5328
|
+
node.setAttribute("transform", translate);
|
|
5329
|
+
textNode.innerHTML = text;
|
|
5330
|
+
// Restore old ID
|
|
5331
|
+
this.curId = curId;
|
|
5030
5332
|
return this._bindFillDraw(node, "text", color, 1);
|
|
5031
5333
|
}
|
|
5032
5334
|
/**
|
|
@@ -5037,16 +5339,21 @@ class drawutilssvg {
|
|
|
5037
5339
|
* @param {number} x - The x-position to draw the text at.
|
|
5038
5340
|
* @param {number} y - The y-position to draw the text at.
|
|
5039
5341
|
* @param {number=} rotation - The (optional) rotation in radians.
|
|
5342
|
+
* @param {string="black"} color - The color to use (default is black).
|
|
5040
5343
|
* @return {void}
|
|
5041
5344
|
* @instance
|
|
5042
5345
|
* @memberof drawutilssvg
|
|
5043
5346
|
*/
|
|
5044
|
-
label(text, x, y, rotation) {
|
|
5347
|
+
label(text, x, y, rotation, color) {
|
|
5045
5348
|
const node = this.makeNode("text");
|
|
5046
5349
|
// For some strange reason SVG rotation transforms use degrees instead of radians
|
|
5047
|
-
node.setAttribute("transform", `translate(${
|
|
5350
|
+
node.setAttribute("transform", `translate(${x},${y}), rotate(${((rotation || 0) / Math.PI) * 180})`);
|
|
5351
|
+
node.setAttribute("font-family", "Arial");
|
|
5352
|
+
node.setAttribute("font-size", "9pt");
|
|
5353
|
+
node.setAttribute("font-style", "normal");
|
|
5354
|
+
node.setAttribute("font-weight", "lighter");
|
|
5048
5355
|
node.innerHTML = text;
|
|
5049
|
-
return this._bindFillDraw(node, "label", "black", null);
|
|
5356
|
+
return this._bindFillDraw(node, "label", color || "black", null);
|
|
5050
5357
|
}
|
|
5051
5358
|
/**
|
|
5052
5359
|
* Draw an SVG-like path given by the specified path data.
|
|
@@ -5355,7 +5662,9 @@ drawutilssvg.HEAD_XML = [
|
|
|
5355
5662
|
* @modified 2021-02-22 Added the `path` drawing function to draw SVG path data.
|
|
5356
5663
|
* @modified 2021-03-31 Added the `endDrawCycle` function from `DrawLib`.
|
|
5357
5664
|
* @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.
|
|
5358
|
-
* @
|
|
5665
|
+
* @modified 2021-11-12 Adding more parameters tot the `text()` function: fontSize, textAlign, fontFamily, lineHeight.
|
|
5666
|
+
* @modified 2021-11-19 Added the `color` param to the `label(...)` function.
|
|
5667
|
+
* @version 1.10.0
|
|
5359
5668
|
**/
|
|
5360
5669
|
// Todo: rename this class to Drawutils?
|
|
5361
5670
|
/**
|
|
@@ -6010,20 +6319,62 @@ class drawutils {
|
|
|
6010
6319
|
this.ctx.setLineDash([]);
|
|
6011
6320
|
this.ctx.restore();
|
|
6012
6321
|
}
|
|
6322
|
+
/**
|
|
6323
|
+
* Draw a text at the given relative position.
|
|
6324
|
+
*
|
|
6325
|
+
* @method text
|
|
6326
|
+
* @param {string} text - The text to draw.
|
|
6327
|
+
* @param {number} x - The x-position to draw the text at.
|
|
6328
|
+
* @param {number} y - The y-position to draw the text at.
|
|
6329
|
+
* @param {string=} options.color - The Color to use.
|
|
6330
|
+
* @param {string=} options.fontFamily - The font family to use.
|
|
6331
|
+
* @param {number=} options.fontSize - The font size (in pixels) to use.
|
|
6332
|
+
* @param {FontStyle=} options.fontStyle - The font style to use.
|
|
6333
|
+
* @param {FontWeight=} options.fontWeight - The font weight to use.
|
|
6334
|
+
* @param {number=} options.lineHeight - The line height (in pixels) to use.
|
|
6335
|
+
* @param {number=} options.rotation - The (optional) rotation in radians.
|
|
6336
|
+
* @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `"left" || "right" || "center" || "start" || "end"`.
|
|
6337
|
+
* @return {void}
|
|
6338
|
+
* @instance
|
|
6339
|
+
* @memberof drawutils
|
|
6340
|
+
*/
|
|
6013
6341
|
text(text, x, y, options) {
|
|
6342
|
+
// See https://stackoverflow.com/a/23523697
|
|
6343
|
+
var _a, _b, _c;
|
|
6014
6344
|
options = options || {};
|
|
6015
6345
|
this.ctx.save();
|
|
6016
|
-
|
|
6017
|
-
|
|
6346
|
+
let relX = this.offset.x + x * this.scale.x;
|
|
6347
|
+
let relY = this.offset.y + y * this.scale.y;
|
|
6018
6348
|
const color = options.color || "black";
|
|
6349
|
+
if (options.fontSize || options.fontFamily) {
|
|
6350
|
+
// Scaling of text only works in uniform mode
|
|
6351
|
+
this.ctx.font =
|
|
6352
|
+
(options.fontWeight ? options.fontWeight + " " : "") +
|
|
6353
|
+
(options.fontStyle ? options.fontStyle + " " : "") +
|
|
6354
|
+
(options.fontSize ? options.fontSize * this.scale.x + "px " : " ") +
|
|
6355
|
+
(options.fontFamily
|
|
6356
|
+
? options.fontFamily.indexOf(" ") === -1
|
|
6357
|
+
? options.fontFamily
|
|
6358
|
+
: `"${options.fontFamily}"`
|
|
6359
|
+
: "Arial");
|
|
6360
|
+
}
|
|
6361
|
+
if (options.textAlign) {
|
|
6362
|
+
this.ctx.textAlign = options.textAlign;
|
|
6363
|
+
}
|
|
6364
|
+
const rotation = (_a = options.rotation) !== null && _a !== void 0 ? _a : 0.0;
|
|
6365
|
+
const lineHeight = ((_c = (_b = options.lineHeight) !== null && _b !== void 0 ? _b : options.fontSize) !== null && _c !== void 0 ? _c : 0) * this.scale.x;
|
|
6366
|
+
this.ctx.translate(relX, relY);
|
|
6367
|
+
this.ctx.rotate(rotation);
|
|
6019
6368
|
if (this.fillShapes) {
|
|
6020
6369
|
this.ctx.fillStyle = color;
|
|
6021
|
-
this.ctx.fillText(text,
|
|
6370
|
+
this.ctx.fillText(text, 0, lineHeight / 2);
|
|
6022
6371
|
}
|
|
6023
6372
|
else {
|
|
6024
6373
|
this.ctx.strokeStyle = color;
|
|
6025
|
-
this.ctx.strokeText(text,
|
|
6374
|
+
this.ctx.strokeText(text, 0, lineHeight / 2);
|
|
6026
6375
|
}
|
|
6376
|
+
// this.ctx.translate(-relX, -relY);
|
|
6377
|
+
// this.ctx.rotate(-rotation); // is this necessary before 'restore()'?
|
|
6027
6378
|
this.ctx.restore();
|
|
6028
6379
|
}
|
|
6029
6380
|
/**
|
|
@@ -6043,8 +6394,9 @@ class drawutils {
|
|
|
6043
6394
|
*/
|
|
6044
6395
|
label(text, x, y, rotation, color) {
|
|
6045
6396
|
this.ctx.save();
|
|
6397
|
+
this.ctx.font = "lighter 9pt Arial";
|
|
6046
6398
|
this.ctx.translate(x, y);
|
|
6047
|
-
if (typeof rotation
|
|
6399
|
+
if (typeof rotation !== "undefined")
|
|
6048
6400
|
this.ctx.rotate(rotation);
|
|
6049
6401
|
this.ctx.fillStyle = color || "black";
|
|
6050
6402
|
if (this.fillShapes) {
|
|
@@ -6653,6 +7005,25 @@ class drawutilsgl {
|
|
|
6653
7005
|
polyline(vertices, isOpen, color, lineWidth) {
|
|
6654
7006
|
// NOT YET IMPLEMENTED
|
|
6655
7007
|
}
|
|
7008
|
+
/**
|
|
7009
|
+
* Draw a text at the given relative position.
|
|
7010
|
+
*
|
|
7011
|
+
* @method text
|
|
7012
|
+
* @param {string} text - The text to draw.
|
|
7013
|
+
* @param {number} x - The x-position to draw the text at.
|
|
7014
|
+
* @param {number} y - The y-position to draw the text at.
|
|
7015
|
+
* @param {string=} options.color - The Color to use.
|
|
7016
|
+
* @param {string=} options.fontFamily - The font family to use.
|
|
7017
|
+
* @param {number=} options.fontSize - The font size (in pixels) to use.
|
|
7018
|
+
* @param {FontStyle=} options.fontStyle - The font style to use.
|
|
7019
|
+
* @param {FontWeight=} options.fontWeight - The font weight to use.
|
|
7020
|
+
* @param {number=} options.lineHeight - The line height (in pixels) to use.
|
|
7021
|
+
* @param {number=} options.rotation - The (optional) rotation in radians.
|
|
7022
|
+
* @param {string=} options.textAlign - The text align to use. According to the specifiactions (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign) valid values are `"left" || "right" || "center" || "start" || "end"`.
|
|
7023
|
+
* @return {void}
|
|
7024
|
+
* @instance
|
|
7025
|
+
* @memberof drawutils
|
|
7026
|
+
*/
|
|
6656
7027
|
text(text, x, y, options) {
|
|
6657
7028
|
// NOT YET IMPLEMENTED
|
|
6658
7029
|
}
|
|
@@ -6664,14 +7035,12 @@ class drawutilsgl {
|
|
|
6664
7035
|
* @param {number} x - The x-position to draw the text at.
|
|
6665
7036
|
* @param {number} y - The y-position to draw the text at.
|
|
6666
7037
|
* @param {number=} rotation - The (aoptional) rotation in radians.
|
|
7038
|
+
* @param {string="black"} color - The color to use (default is black).
|
|
6667
7039
|
* @return {void}
|
|
6668
7040
|
* @instance
|
|
6669
7041
|
* @memberof drawutils
|
|
6670
7042
|
*/
|
|
6671
|
-
|
|
6672
|
-
// | Draw a non-scaling text label at the given position.
|
|
6673
|
-
// +-------------------------------
|
|
6674
|
-
label(text, x, y, rotation) {
|
|
7043
|
+
label(text, x, y, rotation, color) {
|
|
6675
7044
|
// NOT YET IMPLEMENTED
|
|
6676
7045
|
}
|
|
6677
7046
|
/**
|
|
@@ -6810,7 +7179,9 @@ class GLU {
|
|
|
6810
7179
|
* @modified 2020-12-28 Added the `getArea` function.
|
|
6811
7180
|
* @modified 2021-01-20 Added UID.
|
|
6812
7181
|
* @modified 2021-01-22 Always updating circumcircle when retieving it.
|
|
6813
|
-
* @
|
|
7182
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
7183
|
+
* @modified 2022-02-02 Cleared the `Triangle.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
7184
|
+
* @version 2.6.0
|
|
6814
7185
|
*
|
|
6815
7186
|
* @file Triangle
|
|
6816
7187
|
* @fileoverview A simple triangle class: three vertices.
|
|
@@ -6871,7 +7242,6 @@ class Triangle {
|
|
|
6871
7242
|
throw `Cannot create triangle from array with less than three vertices (${arr.length})`;
|
|
6872
7243
|
return new Triangle(arr[0], arr[1], arr[2]);
|
|
6873
7244
|
}
|
|
6874
|
-
;
|
|
6875
7245
|
/**
|
|
6876
7246
|
* Get the area of this triangle. The returned area is never negative.
|
|
6877
7247
|
*
|
|
@@ -6887,7 +7257,6 @@ class Triangle {
|
|
|
6887
7257
|
getArea() {
|
|
6888
7258
|
return Math.abs(Triangle.utils.signedArea(this.a.x, this.a.y, this.b.x, this.b.y, this.c.x, this.c.y));
|
|
6889
7259
|
}
|
|
6890
|
-
;
|
|
6891
7260
|
/**
|
|
6892
7261
|
* Get the centroid of this triangle.
|
|
6893
7262
|
*
|
|
@@ -6901,7 +7270,6 @@ class Triangle {
|
|
|
6901
7270
|
getCentroid() {
|
|
6902
7271
|
return new Vertex((this.a.x + this.b.x + this.c.x) / 3, (this.a.y + this.b.y + this.c.y) / 3);
|
|
6903
7272
|
}
|
|
6904
|
-
;
|
|
6905
7273
|
/**
|
|
6906
7274
|
* Scale the triangle towards its centroid.
|
|
6907
7275
|
*
|
|
@@ -6918,7 +7286,6 @@ class Triangle {
|
|
|
6918
7286
|
this.c.scale(factor, centroid);
|
|
6919
7287
|
return this;
|
|
6920
7288
|
}
|
|
6921
|
-
;
|
|
6922
7289
|
/**
|
|
6923
7290
|
* Get the circumcircle of this triangle.
|
|
6924
7291
|
*
|
|
@@ -6935,11 +7302,10 @@ class Triangle {
|
|
|
6935
7302
|
* @memberof Triangle
|
|
6936
7303
|
*/
|
|
6937
7304
|
getCircumcircle() {
|
|
6938
|
-
// if( !this.center || !this.radius )
|
|
7305
|
+
// if( !this.center || !this.radius )
|
|
6939
7306
|
this.calcCircumcircle();
|
|
6940
7307
|
return new Circle(this.center.clone(), this.radius);
|
|
6941
7308
|
}
|
|
6942
|
-
;
|
|
6943
7309
|
/**
|
|
6944
7310
|
* Check if this triangle and the passed triangle share an
|
|
6945
7311
|
* adjacent edge.
|
|
@@ -6959,7 +7325,6 @@ class Triangle {
|
|
|
6959
7325
|
var c = this.c.equals(tri.a) || this.c.equals(tri.b) || this.c.equals(tri.c);
|
|
6960
7326
|
return (a && b) || (a && c) || (b && c);
|
|
6961
7327
|
}
|
|
6962
|
-
;
|
|
6963
7328
|
/**
|
|
6964
7329
|
* Get that vertex of this triangle (a,b,c) that is not vert1 nor vert2 of
|
|
6965
7330
|
* the passed two.
|
|
@@ -6972,14 +7337,13 @@ class Triangle {
|
|
|
6972
7337
|
* @memberof Triangle
|
|
6973
7338
|
*/
|
|
6974
7339
|
getThirdVertex(vert1, vert2) {
|
|
6975
|
-
if (this.a.equals(vert1) && this.b.equals(vert2) || this.a.equals(vert2) && this.b.equals(vert1))
|
|
7340
|
+
if ((this.a.equals(vert1) && this.b.equals(vert2)) || (this.a.equals(vert2) && this.b.equals(vert1)))
|
|
6976
7341
|
return this.c;
|
|
6977
|
-
if (this.b.equals(vert1) && this.c.equals(vert2) || this.b.equals(vert2) && this.c.equals(vert1))
|
|
7342
|
+
if ((this.b.equals(vert1) && this.c.equals(vert2)) || (this.b.equals(vert2) && this.c.equals(vert1)))
|
|
6978
7343
|
return this.a;
|
|
6979
7344
|
//if( this.c.equals(vert1) && this.a.equals(vert2) || this.c.equals(vert2) && this.a.equals(vert1) )
|
|
6980
7345
|
return this.b;
|
|
6981
7346
|
}
|
|
6982
|
-
;
|
|
6983
7347
|
/**
|
|
6984
7348
|
* Re-compute the circumcircle of this triangle (if the vertices
|
|
6985
7349
|
* have changed).
|
|
@@ -7019,8 +7383,7 @@ class Triangle {
|
|
|
7019
7383
|
}
|
|
7020
7384
|
this.radius_squared = dx * dx + dy * dy;
|
|
7021
7385
|
this.radius = Math.sqrt(this.radius_squared);
|
|
7022
|
-
}
|
|
7023
|
-
; // END calcCircumcircle
|
|
7386
|
+
} // END calcCircumcircle
|
|
7024
7387
|
/**
|
|
7025
7388
|
* Check if the passed vertex is inside this triangle's
|
|
7026
7389
|
* circumcircle.
|
|
@@ -7035,9 +7398,8 @@ class Triangle {
|
|
|
7035
7398
|
const dx = this.center.x - v.x;
|
|
7036
7399
|
const dy = this.center.y - v.y;
|
|
7037
7400
|
const dist_squared = dx * dx + dy * dy;
|
|
7038
|
-
return
|
|
7401
|
+
return dist_squared <= this.radius_squared;
|
|
7039
7402
|
}
|
|
7040
|
-
;
|
|
7041
7403
|
/**
|
|
7042
7404
|
* Get the rectangular bounds for this triangle.
|
|
7043
7405
|
*
|
|
@@ -7049,7 +7411,6 @@ class Triangle {
|
|
|
7049
7411
|
bounds() {
|
|
7050
7412
|
return new Bounds(new Vertex(Triangle.utils.min3(this.a.x, this.b.x, this.c.x), Triangle.utils.min3(this.a.y, this.b.y, this.c.y)), new Vertex(Triangle.utils.max3(this.a.x, this.b.x, this.c.x), Triangle.utils.max3(this.a.y, this.b.y, this.c.y)));
|
|
7051
7413
|
}
|
|
7052
|
-
;
|
|
7053
7414
|
/**
|
|
7054
7415
|
* Convert this triangle to a polygon instance.
|
|
7055
7416
|
*
|
|
@@ -7063,7 +7424,6 @@ class Triangle {
|
|
|
7063
7424
|
toPolygon() {
|
|
7064
7425
|
return new Polygon([this.a, this.b, this.c]);
|
|
7065
7426
|
}
|
|
7066
|
-
;
|
|
7067
7427
|
/**
|
|
7068
7428
|
* Get the determinant of this triangle.
|
|
7069
7429
|
*
|
|
@@ -7076,7 +7436,6 @@ class Triangle {
|
|
|
7076
7436
|
// (b.y - a.y)*(c.x - b.x) - (c.y - b.y)*(b.x - a.x);
|
|
7077
7437
|
return (this.b.y - this.a.y) * (this.c.x - this.b.x) - (this.c.y - this.b.y) * (this.b.x - this.a.x);
|
|
7078
7438
|
}
|
|
7079
|
-
;
|
|
7080
7439
|
/**
|
|
7081
7440
|
* Checks if the passed vertex (p) is inside this triangle.
|
|
7082
7441
|
*
|
|
@@ -7091,7 +7450,6 @@ class Triangle {
|
|
|
7091
7450
|
containsPoint(p) {
|
|
7092
7451
|
return Triangle.utils.pointIsInTriangle(p.x, p.y, this.a.x, this.a.y, this.b.x, this.b.y, this.c.x, this.c.y);
|
|
7093
7452
|
}
|
|
7094
|
-
;
|
|
7095
7453
|
/**
|
|
7096
7454
|
* Get that inner triangle which defines the maximal incircle.
|
|
7097
7455
|
*
|
|
@@ -7110,7 +7468,6 @@ class Triangle {
|
|
|
7110
7468
|
const circleIntersC = lineC.getClosestPoint(intersection);
|
|
7111
7469
|
return new Triangle(circleIntersA, circleIntersB, circleIntersC);
|
|
7112
7470
|
}
|
|
7113
|
-
;
|
|
7114
7471
|
/**
|
|
7115
7472
|
* Get the incircle of this triangle. That is the circle that touches each side
|
|
7116
7473
|
* of this triangle in exactly one point.
|
|
@@ -7122,7 +7479,6 @@ class Triangle {
|
|
|
7122
7479
|
getIncircle() {
|
|
7123
7480
|
return this.getIncircularTriangle().getCircumcircle();
|
|
7124
7481
|
}
|
|
7125
|
-
;
|
|
7126
7482
|
/**
|
|
7127
7483
|
* Get the incenter of this triangle (which is the center of the circumcircle).
|
|
7128
7484
|
*
|
|
@@ -7136,7 +7492,6 @@ class Triangle {
|
|
|
7136
7492
|
this.calcCircumcircle();
|
|
7137
7493
|
return this.center.clone();
|
|
7138
7494
|
}
|
|
7139
|
-
;
|
|
7140
7495
|
/**
|
|
7141
7496
|
* Converts this triangle into a human-readable string.
|
|
7142
7497
|
*
|
|
@@ -7146,9 +7501,8 @@ class Triangle {
|
|
|
7146
7501
|
* @memberof Triangle
|
|
7147
7502
|
*/
|
|
7148
7503
|
toString() {
|
|
7149
|
-
return
|
|
7504
|
+
return "{ a : " + this.a.toString() + ", b : " + this.b.toString() + ", c : " + this.c.toString() + "}";
|
|
7150
7505
|
}
|
|
7151
|
-
;
|
|
7152
7506
|
/**
|
|
7153
7507
|
* Create an SVG representation of this triangle.
|
|
7154
7508
|
*
|
|
@@ -7160,32 +7514,43 @@ class Triangle {
|
|
|
7160
7514
|
* @memberof Triangle
|
|
7161
7515
|
**/
|
|
7162
7516
|
toSVGString(options) {
|
|
7163
|
-
options = options || {};
|
|
7164
|
-
var buffer = [];
|
|
7165
|
-
buffer.push(
|
|
7166
|
-
if (options.className)
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
buffer.
|
|
7186
|
-
return
|
|
7517
|
+
// options = options || {};
|
|
7518
|
+
// var buffer = [];
|
|
7519
|
+
// buffer.push("<path");
|
|
7520
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
7521
|
+
// buffer.push(' d="');
|
|
7522
|
+
// var vertices = [this.a, this.b, this.c];
|
|
7523
|
+
// if (vertices.length > 0) {
|
|
7524
|
+
// buffer.push("M ");
|
|
7525
|
+
// buffer.push(vertices[0].x);
|
|
7526
|
+
// buffer.push(" ");
|
|
7527
|
+
// buffer.push(vertices[0].y);
|
|
7528
|
+
// for (var i = 1; i < vertices.length; i++) {
|
|
7529
|
+
// buffer.push(" L ");
|
|
7530
|
+
// buffer.push(vertices[i].x);
|
|
7531
|
+
// buffer.push(" ");
|
|
7532
|
+
// buffer.push(vertices[i].y);
|
|
7533
|
+
// }
|
|
7534
|
+
// //if( !this.isOpen ) {
|
|
7535
|
+
// buffer.push(" Z");
|
|
7536
|
+
// //}
|
|
7537
|
+
// }
|
|
7538
|
+
// buffer.push('" />');
|
|
7539
|
+
// return buffer.join("");
|
|
7540
|
+
console.warn("[Deprecation] Warning: the Triangle.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
7541
|
+
return "";
|
|
7542
|
+
}
|
|
7543
|
+
/**
|
|
7544
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
7545
|
+
* After calling this function the object might not hold valid data any more and
|
|
7546
|
+
* should not be used.
|
|
7547
|
+
*/
|
|
7548
|
+
destroy() {
|
|
7549
|
+
this.a.destroy();
|
|
7550
|
+
this.b.destroy();
|
|
7551
|
+
this.c.destroy();
|
|
7552
|
+
this.isDestroyed = true;
|
|
7187
7553
|
}
|
|
7188
|
-
;
|
|
7189
7554
|
}
|
|
7190
7555
|
/**
|
|
7191
7556
|
* An epsilon for comparison.
|
|
@@ -7197,10 +7562,10 @@ Triangle.EPSILON = 1.0e-6;
|
|
|
7197
7562
|
Triangle.utils = {
|
|
7198
7563
|
// Used in the bounds() function.
|
|
7199
7564
|
max3(a, b, c) {
|
|
7200
|
-
return
|
|
7565
|
+
return a >= b && a >= c ? a : b >= a && b >= c ? b : c;
|
|
7201
7566
|
},
|
|
7202
7567
|
min3(a, b, c) {
|
|
7203
|
-
return
|
|
7568
|
+
return a <= b && a <= c ? a : b <= a && b <= c ? b : c;
|
|
7204
7569
|
},
|
|
7205
7570
|
signedArea(p0x, p0y, p1x, p1y, p2x, p2y) {
|
|
7206
7571
|
return 0.5 * (-p1y * p2x + p0y * (-p1x + p2x) + p0x * (p1y - p2y) + p1x * p2y);
|
|
@@ -7216,9 +7581,9 @@ Triangle.utils = {
|
|
|
7216
7581
|
// http://stackoverflow.com/questions/2049582/how-to-determine-a-point-in-a-2d-triangle
|
|
7217
7582
|
// var area : number = 1/2*(-p1y*p2x + p0y*(-p1x + p2x) + p0x*(p1y - p2y) + p1x*p2y);
|
|
7218
7583
|
var area = Triangle.utils.signedArea(p0x, p0y, p1x, p1y, p2x, p2y);
|
|
7219
|
-
var s = 1 / (2 * area) * (p0y * p2x - p0x * p2y + (p2y - p0y) * px + (p0x - p2x) * py);
|
|
7220
|
-
var t = 1 / (2 * area) * (p0x * p1y - p0y * p1x + (p0y - p1y) * px + (p1x - p0x) * py);
|
|
7221
|
-
return s > 0 && t > 0 &&
|
|
7584
|
+
var s = (1 / (2 * area)) * (p0y * p2x - p0x * p2y + (p2y - p0y) * px + (p0x - p2x) * py);
|
|
7585
|
+
var t = (1 / (2 * area)) * (p0x * p1y - p0y * p1x + (p0y - p1y) * px + (p1x - p0x) * py);
|
|
7586
|
+
return s > 0 && t > 0 && 1 - s - t > 0;
|
|
7222
7587
|
}
|
|
7223
7588
|
};
|
|
7224
7589
|
|
|
@@ -7389,7 +7754,8 @@ Grid.utils = {
|
|
|
7389
7754
|
* @modified 2020-07-28 Changed the `delete` key code from 8 to 46.
|
|
7390
7755
|
* @modified 2020-10-04 Changed `window` to `globalThis`.
|
|
7391
7756
|
* @modified 2020-10-04 Added extended JSDoc.
|
|
7392
|
-
* @
|
|
7757
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
7758
|
+
* @version 1.1.0
|
|
7393
7759
|
*
|
|
7394
7760
|
* @file KeyHandler
|
|
7395
7761
|
* @public
|
|
@@ -7420,7 +7786,7 @@ class KeyHandler {
|
|
|
7420
7786
|
* @memberof KeyHandler
|
|
7421
7787
|
* @param {HTMLElement} options.element (optional) The HTML element to listen on; if null then 'window' will be used.
|
|
7422
7788
|
* @param {boolean} options.trackAll (optional) Set to true if you want to keep track of _all_ keys (keyStatus).
|
|
7423
|
-
|
|
7789
|
+
**/
|
|
7424
7790
|
constructor(options) {
|
|
7425
7791
|
this.downListeners = [];
|
|
7426
7792
|
this.pressListeners = [];
|
|
@@ -7439,7 +7805,6 @@ class KeyHandler {
|
|
|
7439
7805
|
// Install the listeners
|
|
7440
7806
|
this.installListeners();
|
|
7441
7807
|
}
|
|
7442
|
-
;
|
|
7443
7808
|
/**
|
|
7444
7809
|
* A helper function to fire key events from this KeyHandler.
|
|
7445
7810
|
*
|
|
@@ -7457,7 +7822,6 @@ class KeyHandler {
|
|
|
7457
7822
|
}
|
|
7458
7823
|
return hasListener;
|
|
7459
7824
|
}
|
|
7460
|
-
;
|
|
7461
7825
|
/**
|
|
7462
7826
|
* Internal function to fire a new keydown event to all listeners.
|
|
7463
7827
|
* You should not call this function on your own unless you know what you do.
|
|
@@ -7473,10 +7837,9 @@ class KeyHandler {
|
|
|
7473
7837
|
fireDownEvent(e, handler) {
|
|
7474
7838
|
if (handler.fireEvent(e, handler.downListeners) || handler.trackAllKeys) {
|
|
7475
7839
|
// Down event has listeners. Update key state.
|
|
7476
|
-
handler.keyStates[e.keyCode] =
|
|
7840
|
+
handler.keyStates[e.keyCode] = "down";
|
|
7477
7841
|
}
|
|
7478
7842
|
}
|
|
7479
|
-
;
|
|
7480
7843
|
/**
|
|
7481
7844
|
* Internal function to fire a new keypress event to all listeners.
|
|
7482
7845
|
* You should not call this function on your own unless you know what you do.
|
|
@@ -7492,7 +7855,6 @@ class KeyHandler {
|
|
|
7492
7855
|
firePressEvent(e, handler) {
|
|
7493
7856
|
handler.fireEvent(e, handler.pressListeners);
|
|
7494
7857
|
}
|
|
7495
|
-
;
|
|
7496
7858
|
/**
|
|
7497
7859
|
* Internal function to fire a new keyup event to all listeners.
|
|
7498
7860
|
* You should not call this function on your own unless you know what you do.
|
|
@@ -7511,20 +7873,18 @@ class KeyHandler {
|
|
|
7511
7873
|
delete handler.keyStates[e.keyCode];
|
|
7512
7874
|
}
|
|
7513
7875
|
}
|
|
7514
|
-
;
|
|
7515
7876
|
/**
|
|
7516
7877
|
* Resolve the key/name code.
|
|
7517
7878
|
*/
|
|
7518
7879
|
static key2code(key) {
|
|
7519
|
-
if (typeof key ==
|
|
7880
|
+
if (typeof key == "number")
|
|
7520
7881
|
return key;
|
|
7521
|
-
if (typeof key !=
|
|
7882
|
+
if (typeof key != "string")
|
|
7522
7883
|
throw "Unknown key name or key type (should be a string or integer): " + key;
|
|
7523
7884
|
if (KeyHandler.KEY_CODES[key])
|
|
7524
7885
|
return KeyHandler.KEY_CODES[key];
|
|
7525
7886
|
throw "Unknown key (cannot resolve key code): " + key;
|
|
7526
7887
|
}
|
|
7527
|
-
;
|
|
7528
7888
|
/**
|
|
7529
7889
|
* Install the required listeners into the initially passed element.
|
|
7530
7890
|
*
|
|
@@ -7533,20 +7893,24 @@ class KeyHandler {
|
|
|
7533
7893
|
*/
|
|
7534
7894
|
installListeners() {
|
|
7535
7895
|
var _self = this;
|
|
7536
|
-
this.element.addEventListener(
|
|
7537
|
-
|
|
7538
|
-
|
|
7896
|
+
this.element.addEventListener("keydown", (this._keyDownListener = (e) => {
|
|
7897
|
+
_self.fireDownEvent(e, _self);
|
|
7898
|
+
}));
|
|
7899
|
+
this.element.addEventListener("keypress", (this._keyPressListener = (e) => {
|
|
7900
|
+
_self.firePressEvent(e, _self);
|
|
7901
|
+
}));
|
|
7902
|
+
this.element.addEventListener("keyup", (this._keyUpListener = (e) => {
|
|
7903
|
+
_self.fireUpEvent(e, _self);
|
|
7904
|
+
}));
|
|
7539
7905
|
}
|
|
7540
|
-
;
|
|
7541
7906
|
/**
|
|
7542
7907
|
* Remove all installed event listeners from the underlying element.
|
|
7543
7908
|
*/
|
|
7544
7909
|
releaseListeners() {
|
|
7545
|
-
this.element.removeEventListener(
|
|
7546
|
-
this.element.removeEventListener(
|
|
7547
|
-
this.element.removeEventListener(
|
|
7910
|
+
this.element.removeEventListener("keydown", this._keyDownListener);
|
|
7911
|
+
this.element.removeEventListener("keypress", this._keyPressListener);
|
|
7912
|
+
this.element.removeEventListener("keyup", this._keyUpListener);
|
|
7548
7913
|
}
|
|
7549
|
-
;
|
|
7550
7914
|
/**
|
|
7551
7915
|
* Listen for key down. This function allows chaining.
|
|
7552
7916
|
*
|
|
@@ -7563,7 +7927,6 @@ class KeyHandler {
|
|
|
7563
7927
|
this.downListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });
|
|
7564
7928
|
return this;
|
|
7565
7929
|
}
|
|
7566
|
-
;
|
|
7567
7930
|
/**
|
|
7568
7931
|
* Listen for key press.
|
|
7569
7932
|
*
|
|
@@ -7580,7 +7943,6 @@ class KeyHandler {
|
|
|
7580
7943
|
this.pressListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });
|
|
7581
7944
|
return this;
|
|
7582
7945
|
}
|
|
7583
|
-
;
|
|
7584
7946
|
/**
|
|
7585
7947
|
* Listen for key up.
|
|
7586
7948
|
*
|
|
@@ -7597,23 +7959,31 @@ class KeyHandler {
|
|
|
7597
7959
|
this.upListeners.push({ key: key, keyCode: KeyHandler.key2code(key), listener: listener });
|
|
7598
7960
|
return this;
|
|
7599
7961
|
}
|
|
7600
|
-
;
|
|
7601
7962
|
/**
|
|
7602
7963
|
* Check if a specific key is currently held pressed.
|
|
7603
7964
|
*
|
|
7604
7965
|
* @param {string|number} key - Any key identifier, key code or one from the KEY_CODES list.
|
|
7605
7966
|
*/
|
|
7606
7967
|
isDown(key) {
|
|
7607
|
-
if (typeof key ==
|
|
7968
|
+
if (typeof key == "number")
|
|
7608
7969
|
return this.keyStates[key] ? true : false;
|
|
7609
7970
|
else
|
|
7610
7971
|
return this.keyStates[KeyHandler.key2code(key)] ? true : false;
|
|
7611
7972
|
}
|
|
7973
|
+
/**
|
|
7974
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
7975
|
+
* After calling this function the object might not hold valid data any more and
|
|
7976
|
+
* should not be used any more.
|
|
7977
|
+
*/
|
|
7978
|
+
destroy() {
|
|
7979
|
+
this.releaseListeners();
|
|
7980
|
+
}
|
|
7612
7981
|
}
|
|
7613
7982
|
/**
|
|
7614
7983
|
* Source:
|
|
7615
7984
|
* https://keycode.info/
|
|
7616
7985
|
*/
|
|
7986
|
+
// prettier-ignore
|
|
7617
7987
|
KeyHandler.KEY_CODES = {
|
|
7618
7988
|
'break': 3,
|
|
7619
7989
|
'backspace': 8,
|
|
@@ -7930,41 +8300,41 @@ class MouseHandler {
|
|
|
7930
8300
|
// | drag offset, ...) to the callbacks.
|
|
7931
8301
|
// +-------------------------------------------------
|
|
7932
8302
|
const _self = this;
|
|
7933
|
-
this.handlers[
|
|
8303
|
+
this.handlers["mousemove"] = (e) => {
|
|
7934
8304
|
if (_self.listeners.mousemove)
|
|
7935
|
-
_self.listeners.mousemove(_self.mkParams(e,
|
|
8305
|
+
_self.listeners.mousemove(_self.mkParams(e, "mousemove"));
|
|
7936
8306
|
if (_self.mouseDragPos && _self.listeners.drag)
|
|
7937
|
-
_self.listeners.drag(_self.mkParams(e,
|
|
8307
|
+
_self.listeners.drag(_self.mkParams(e, "drag"));
|
|
7938
8308
|
if (_self.mouseDownPos)
|
|
7939
8309
|
_self.mouseDragPos = _self.relPos(e);
|
|
7940
8310
|
};
|
|
7941
|
-
this.handlers[
|
|
8311
|
+
this.handlers["mouseup"] = (e) => {
|
|
7942
8312
|
if (_self.listeners.mouseup)
|
|
7943
|
-
_self.listeners.mouseup(_self.mkParams(e,
|
|
8313
|
+
_self.listeners.mouseup(_self.mkParams(e, "mouseup"));
|
|
7944
8314
|
_self.mouseDragPos = undefined;
|
|
7945
8315
|
_self.mouseDownPos = undefined;
|
|
7946
8316
|
_self.mouseButton = -1;
|
|
7947
8317
|
};
|
|
7948
|
-
this.handlers[
|
|
8318
|
+
this.handlers["mousedown"] = (e) => {
|
|
7949
8319
|
_self.mouseDragPos = _self.relPos(e);
|
|
7950
8320
|
_self.mouseDownPos = _self.relPos(e);
|
|
7951
8321
|
_self.mouseButton = e.button;
|
|
7952
8322
|
if (_self.listeners.mousedown)
|
|
7953
|
-
_self.listeners.mousedown(_self.mkParams(e,
|
|
8323
|
+
_self.listeners.mousedown(_self.mkParams(e, "mousedown"));
|
|
7954
8324
|
};
|
|
7955
|
-
this.handlers[
|
|
8325
|
+
this.handlers["click"] = (e) => {
|
|
7956
8326
|
if (_self.listeners.click)
|
|
7957
|
-
_self.listeners.click(_self.mkParams(e,
|
|
8327
|
+
_self.listeners.click(_self.mkParams(e, "click"));
|
|
7958
8328
|
};
|
|
7959
|
-
this.handlers[
|
|
8329
|
+
this.handlers["wheel"] = (e) => {
|
|
7960
8330
|
if (_self.listeners.wheel)
|
|
7961
|
-
_self.listeners.wheel(_self.mkParams(e,
|
|
8331
|
+
_self.listeners.wheel(_self.mkParams(e, "wheel"));
|
|
7962
8332
|
};
|
|
7963
|
-
this.element.addEventListener(
|
|
7964
|
-
this.element.addEventListener(
|
|
7965
|
-
this.element.addEventListener(
|
|
7966
|
-
this.element.addEventListener(
|
|
7967
|
-
this.element.addEventListener(
|
|
8333
|
+
this.element.addEventListener("mousemove", this.handlers["mousemove"]);
|
|
8334
|
+
this.element.addEventListener("mouseup", this.handlers["mouseup"]);
|
|
8335
|
+
this.element.addEventListener("mousedown", this.handlers["mousedown"]);
|
|
8336
|
+
this.element.addEventListener("click", this.handlers["click"]);
|
|
8337
|
+
this.element.addEventListener("wheel", this.handlers["wheel"]);
|
|
7968
8338
|
}
|
|
7969
8339
|
/**
|
|
7970
8340
|
* Get relative position from the given MouseEvent.
|
|
@@ -7977,11 +8347,8 @@ class MouseHandler {
|
|
|
7977
8347
|
* @return {XYCoords} The relative mouse coordinates.
|
|
7978
8348
|
*/
|
|
7979
8349
|
relPos(e) {
|
|
7980
|
-
return { x: e.offsetX,
|
|
7981
|
-
y: e.offsetY
|
|
7982
|
-
};
|
|
8350
|
+
return { x: e.offsetX, y: e.offsetY };
|
|
7983
8351
|
}
|
|
7984
|
-
;
|
|
7985
8352
|
/**
|
|
7986
8353
|
* Build the extended event params.
|
|
7987
8354
|
*
|
|
@@ -8007,8 +8374,8 @@ class MouseHandler {
|
|
|
8007
8374
|
rightButton: this.mouseButton == 2,
|
|
8008
8375
|
mouseDownPos: this.mouseDownPos,
|
|
8009
8376
|
draggedFrom: this.mouseDragPos,
|
|
8010
|
-
wasDragged:
|
|
8011
|
-
dragAmount:
|
|
8377
|
+
wasDragged: this.mouseDownPos != null && (this.mouseDownPos.x != rel.x || this.mouseDownPos.y != rel.y),
|
|
8378
|
+
dragAmount: this.mouseDownPos != null ? { x: rel.x - this.mouseDragPos.x, y: rel.y - this.mouseDragPos.y } : { x: 0, y: 0 }
|
|
8012
8379
|
};
|
|
8013
8380
|
return xEvent;
|
|
8014
8381
|
}
|
|
@@ -8059,14 +8426,13 @@ class MouseHandler {
|
|
|
8059
8426
|
*/
|
|
8060
8427
|
drag(callback) {
|
|
8061
8428
|
if (this.listeners.drag)
|
|
8062
|
-
this.throwAlreadyInstalled(
|
|
8429
|
+
this.throwAlreadyInstalled("drag");
|
|
8063
8430
|
this.listeners.drag = callback;
|
|
8064
|
-
this.listenFor(
|
|
8065
|
-
this.listenFor(
|
|
8066
|
-
this.listenFor(
|
|
8431
|
+
this.listenFor("mousedown");
|
|
8432
|
+
this.listenFor("mousemove");
|
|
8433
|
+
this.listenFor("mouseup");
|
|
8067
8434
|
return this;
|
|
8068
8435
|
}
|
|
8069
|
-
;
|
|
8070
8436
|
/**
|
|
8071
8437
|
* Installer function to listen for a specific event: mouse-move.
|
|
8072
8438
|
* Pass your callbacks here.
|
|
@@ -8081,12 +8447,11 @@ class MouseHandler {
|
|
|
8081
8447
|
*/
|
|
8082
8448
|
move(callback) {
|
|
8083
8449
|
if (this.listeners.mousemove)
|
|
8084
|
-
this.throwAlreadyInstalled(
|
|
8085
|
-
this.listenFor(
|
|
8450
|
+
this.throwAlreadyInstalled("mousemove");
|
|
8451
|
+
this.listenFor("mousemove");
|
|
8086
8452
|
this.listeners.mousemove = callback;
|
|
8087
8453
|
return this;
|
|
8088
8454
|
}
|
|
8089
|
-
;
|
|
8090
8455
|
/**
|
|
8091
8456
|
* Installer function to listen for a specific event: mouse-up.
|
|
8092
8457
|
* Pass your callbacks here.
|
|
@@ -8101,12 +8466,11 @@ class MouseHandler {
|
|
|
8101
8466
|
*/
|
|
8102
8467
|
up(callback) {
|
|
8103
8468
|
if (this.listeners.mouseup)
|
|
8104
|
-
this.throwAlreadyInstalled(
|
|
8105
|
-
this.listenFor(
|
|
8469
|
+
this.throwAlreadyInstalled("mouseup");
|
|
8470
|
+
this.listenFor("mouseup");
|
|
8106
8471
|
this.listeners.mouseup = callback;
|
|
8107
8472
|
return this;
|
|
8108
8473
|
}
|
|
8109
|
-
;
|
|
8110
8474
|
/**
|
|
8111
8475
|
* Installer function to listen for a specific event: mouse-down.
|
|
8112
8476
|
* Pass your callbacks here.
|
|
@@ -8121,12 +8485,11 @@ class MouseHandler {
|
|
|
8121
8485
|
*/
|
|
8122
8486
|
down(callback) {
|
|
8123
8487
|
if (this.listeners.mousedown)
|
|
8124
|
-
this.throwAlreadyInstalled(
|
|
8125
|
-
this.listenFor(
|
|
8488
|
+
this.throwAlreadyInstalled("mousedown");
|
|
8489
|
+
this.listenFor("mousedown");
|
|
8126
8490
|
this.listeners.mousedown = callback;
|
|
8127
8491
|
return this;
|
|
8128
8492
|
}
|
|
8129
|
-
;
|
|
8130
8493
|
/**
|
|
8131
8494
|
* Installer function to listen for a specific event: mouse-click.
|
|
8132
8495
|
* Pass your callbacks here.
|
|
@@ -8141,12 +8504,11 @@ class MouseHandler {
|
|
|
8141
8504
|
*/
|
|
8142
8505
|
click(callback) {
|
|
8143
8506
|
if (this.listeners.click)
|
|
8144
|
-
this.throwAlreadyInstalled(
|
|
8145
|
-
this.listenFor(
|
|
8507
|
+
this.throwAlreadyInstalled("click");
|
|
8508
|
+
this.listenFor("click");
|
|
8146
8509
|
this.listeners.click = callback;
|
|
8147
8510
|
return this;
|
|
8148
8511
|
}
|
|
8149
|
-
;
|
|
8150
8512
|
/**
|
|
8151
8513
|
* Installer function to listen for a specific event: mouse-wheel.
|
|
8152
8514
|
* Pass your callbacks here.
|
|
@@ -8161,12 +8523,11 @@ class MouseHandler {
|
|
|
8161
8523
|
*/
|
|
8162
8524
|
wheel(callback) {
|
|
8163
8525
|
if (this.listeners.wheel)
|
|
8164
|
-
this.throwAlreadyInstalled(
|
|
8165
|
-
this.listenFor(
|
|
8526
|
+
this.throwAlreadyInstalled("wheel");
|
|
8527
|
+
this.listenFor("wheel");
|
|
8166
8528
|
this.listeners.wheel = callback;
|
|
8167
8529
|
return this;
|
|
8168
8530
|
}
|
|
8169
|
-
;
|
|
8170
8531
|
/**
|
|
8171
8532
|
* An internal function to throw events.
|
|
8172
8533
|
*
|
|
@@ -8180,7 +8541,6 @@ class MouseHandler {
|
|
|
8180
8541
|
throwAlreadyInstalled(name) {
|
|
8181
8542
|
throw `This MouseHandler already has a '${name}' callback. To keep the code simple there is only room for one.`;
|
|
8182
8543
|
}
|
|
8183
|
-
;
|
|
8184
8544
|
/**
|
|
8185
8545
|
* Call this when your work is done.
|
|
8186
8546
|
*
|
|
@@ -8193,16 +8553,16 @@ class MouseHandler {
|
|
|
8193
8553
|
* @return {void}
|
|
8194
8554
|
*/
|
|
8195
8555
|
destroy() {
|
|
8196
|
-
this.unlistenFor(
|
|
8197
|
-
this.unlistenFor(
|
|
8198
|
-
this.unlistenFor(
|
|
8199
|
-
this.unlistenFor(
|
|
8200
|
-
this.unlistenFor(
|
|
8201
|
-
this.element.removeEventListener(
|
|
8202
|
-
this.element.removeEventListener(
|
|
8203
|
-
this.element.removeEventListener(
|
|
8204
|
-
this.element.removeEventListener(
|
|
8205
|
-
this.element.removeEventListener(
|
|
8556
|
+
this.unlistenFor("mousedown");
|
|
8557
|
+
this.unlistenFor("mousemove");
|
|
8558
|
+
this.unlistenFor("moseup");
|
|
8559
|
+
this.unlistenFor("click");
|
|
8560
|
+
this.unlistenFor("wheel");
|
|
8561
|
+
this.element.removeEventListener("mousemove", this.handlers["mousemove"]);
|
|
8562
|
+
this.element.removeEventListener("mouseup", this.handlers["mousedown"]);
|
|
8563
|
+
this.element.removeEventListener("mousedown", this.handlers["mousedown"]);
|
|
8564
|
+
this.element.removeEventListener("click", this.handlers["click"]);
|
|
8565
|
+
this.element.removeEventListener("wheel", this.handlers["wheel"]);
|
|
8206
8566
|
}
|
|
8207
8567
|
}
|
|
8208
8568
|
|
|
@@ -8212,7 +8572,9 @@ class MouseHandler {
|
|
|
8212
8572
|
* @modified 2019-03-23 Added JSDoc tags.
|
|
8213
8573
|
* @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.
|
|
8214
8574
|
* @modified 2021-01-20 Added UID.
|
|
8215
|
-
* @
|
|
8575
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
8576
|
+
* @modified 2022-02-02 Cleared the `PBImage.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
8577
|
+
* @version 1.2.0
|
|
8216
8578
|
*
|
|
8217
8579
|
* @file PBImage
|
|
8218
8580
|
* @fileoverview As native Image objects have only a position and with
|
|
@@ -8247,7 +8609,6 @@ class PBImage {
|
|
|
8247
8609
|
this.upperLeft = upperLeft;
|
|
8248
8610
|
this.lowerRight = lowerRight;
|
|
8249
8611
|
}
|
|
8250
|
-
;
|
|
8251
8612
|
/**
|
|
8252
8613
|
* Convert this vertex to SVG code.
|
|
8253
8614
|
*
|
|
@@ -8262,9 +8623,87 @@ class PBImage {
|
|
|
8262
8623
|
console.warn("PBImage is not yet SVG serializable. Returning empty SVG string.");
|
|
8263
8624
|
return "";
|
|
8264
8625
|
}
|
|
8265
|
-
|
|
8626
|
+
/**
|
|
8627
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
8628
|
+
* After calling this function the object might not hold valid data any more and
|
|
8629
|
+
* should not be used.
|
|
8630
|
+
*/
|
|
8631
|
+
destroy() {
|
|
8632
|
+
this.upperLeft.destroy();
|
|
8633
|
+
this.lowerRight.destroy();
|
|
8634
|
+
this.isDestroyed = true;
|
|
8635
|
+
}
|
|
8266
8636
|
}
|
|
8267
8637
|
|
|
8638
|
+
/**
|
|
8639
|
+
* @author Ikaros Kappler
|
|
8640
|
+
* @date 2021-11-16
|
|
8641
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
8642
|
+
* @version 1.1.0
|
|
8643
|
+
**/
|
|
8644
|
+
/**
|
|
8645
|
+
* @classdesc A simple text element: position, fontSize, fontFamily, color, textAlign, lineHeight and rotation.
|
|
8646
|
+
*
|
|
8647
|
+
* @requires FontOptions
|
|
8648
|
+
* @requires FontSize
|
|
8649
|
+
* @requires FontStyle
|
|
8650
|
+
* @requires FontWeight
|
|
8651
|
+
* @requires Vertex
|
|
8652
|
+
* @requires SVGSerializale
|
|
8653
|
+
* @requires UID
|
|
8654
|
+
* @requires UIDGenerator
|
|
8655
|
+
**/
|
|
8656
|
+
class PBText {
|
|
8657
|
+
/**
|
|
8658
|
+
* Create a new circle with given center point and radius.
|
|
8659
|
+
*
|
|
8660
|
+
* @constructor
|
|
8661
|
+
* @name Circle
|
|
8662
|
+
* @param {Vertex} center - The center point of the circle.
|
|
8663
|
+
* @param {number} radius - The radius of the circle.
|
|
8664
|
+
*/
|
|
8665
|
+
constructor(text, anchor, options) {
|
|
8666
|
+
/**
|
|
8667
|
+
* Required to generate proper CSS classes and other class related IDs.
|
|
8668
|
+
**/
|
|
8669
|
+
this.className = "PBText";
|
|
8670
|
+
this.uid = UIDGenerator.next();
|
|
8671
|
+
this.text = text;
|
|
8672
|
+
this.anchor = anchor !== null && anchor !== void 0 ? anchor : new Vertex();
|
|
8673
|
+
this.color = options.color;
|
|
8674
|
+
this.fontFamily = options.fontFamily;
|
|
8675
|
+
this.fontSize = options.fontSize;
|
|
8676
|
+
this.fontStyle = options.fontStyle;
|
|
8677
|
+
this.fontWeight = options.fontWeight;
|
|
8678
|
+
this.lineHeight = options.lineHeight;
|
|
8679
|
+
this.textAlign = options.textAlign;
|
|
8680
|
+
this.rotation = options.rotation;
|
|
8681
|
+
}
|
|
8682
|
+
/**
|
|
8683
|
+
* Create an SVG representation of this circle.
|
|
8684
|
+
*
|
|
8685
|
+
* @deprecated DEPRECATION Please use the drawutilssvg library and an XMLSerializer instead.
|
|
8686
|
+
* @method toSVGString
|
|
8687
|
+
* @param {object=} options - An optional set of options, like 'className'.
|
|
8688
|
+
* @return {string} A string representing the SVG code for this vertex.
|
|
8689
|
+
* @instance
|
|
8690
|
+
* @memberof Circle
|
|
8691
|
+
*/
|
|
8692
|
+
toSVGString(options) {
|
|
8693
|
+
console.warn("[PBText.toSVGString()] This function is not implemented as it defines a deprecated method. Use the 'drawutilssvg.text()' method instead.");
|
|
8694
|
+
return "";
|
|
8695
|
+
}
|
|
8696
|
+
/**
|
|
8697
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
8698
|
+
* After calling this function the object might not hold valid data any more and
|
|
8699
|
+
* should not be used.
|
|
8700
|
+
*/
|
|
8701
|
+
destroy() {
|
|
8702
|
+
this.anchor.destroy();
|
|
8703
|
+
this.isDestroyed = true;
|
|
8704
|
+
}
|
|
8705
|
+
} // END class
|
|
8706
|
+
|
|
8268
8707
|
/* Port from AlloyFinger v0.1.15
|
|
8269
8708
|
* Original by dntzhang
|
|
8270
8709
|
* Typescript port by Ikaros Kappler
|
|
@@ -8666,7 +9105,9 @@ class AlloyFinger {
|
|
|
8666
9105
|
* @modified 2021-03-10 Added the `toCubicBezier` method.
|
|
8667
9106
|
* @modified 2021-03-15 Added `VEllipse.quarterSegmentCount` and `VEllipse.scale` functions.
|
|
8668
9107
|
* @modified 2021-03-19 Added the `VEllipse.rotate` function.
|
|
8669
|
-
* @
|
|
9108
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
9109
|
+
* @modified 2022-02-02 Cleared the `VEllipse.toSVGString` function (deprecated). Use `drawutilssvg` instead.
|
|
9110
|
+
* @version 1.3.0
|
|
8670
9111
|
*
|
|
8671
9112
|
* @file VEllipse
|
|
8672
9113
|
* @fileoverview Ellipses with a center and an x- and a y-axis (stored as a vertex).
|
|
@@ -8992,17 +9433,28 @@ class VEllipse {
|
|
|
8992
9433
|
* @return string The SVG string
|
|
8993
9434
|
*/
|
|
8994
9435
|
toSVGString(options) {
|
|
8995
|
-
options = options || {};
|
|
8996
|
-
var buffer = [];
|
|
8997
|
-
buffer.push("<ellipse");
|
|
8998
|
-
if (options.className)
|
|
8999
|
-
|
|
9000
|
-
buffer.push('
|
|
9001
|
-
buffer.push('
|
|
9002
|
-
buffer.push('
|
|
9003
|
-
buffer.push(
|
|
9004
|
-
buffer.
|
|
9005
|
-
return
|
|
9436
|
+
// options = options || {};
|
|
9437
|
+
// var buffer: Array<string> = [];
|
|
9438
|
+
// buffer.push("<ellipse");
|
|
9439
|
+
// if (options.className) buffer.push(' class="' + options.className + '"');
|
|
9440
|
+
// buffer.push(' cx="' + this.center.x + '"');
|
|
9441
|
+
// buffer.push(' cy="' + this.center.y + '"');
|
|
9442
|
+
// buffer.push(' rx="' + this.axis.x + '"');
|
|
9443
|
+
// buffer.push(' ry="' + this.axis.y + '"');
|
|
9444
|
+
// buffer.push(" />");
|
|
9445
|
+
// return buffer.join("");
|
|
9446
|
+
console.warn("[Deprecation] Warning: the VEllipse.toSVGString method is deprecated and does not return and valid SVG data any more. Please use `drawutilssvg` instead.");
|
|
9447
|
+
return "";
|
|
9448
|
+
}
|
|
9449
|
+
/**
|
|
9450
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
9451
|
+
* After calling this function the object might not hold valid data any more and
|
|
9452
|
+
* should not be used.
|
|
9453
|
+
*/
|
|
9454
|
+
destroy() {
|
|
9455
|
+
this.center.destroy();
|
|
9456
|
+
this.axis.destroy();
|
|
9457
|
+
this.isDestroyed = true;
|
|
9006
9458
|
}
|
|
9007
9459
|
}
|
|
9008
9460
|
/**
|
|
@@ -9069,7 +9521,8 @@ VEllipse.utils = {
|
|
|
9069
9521
|
*
|
|
9070
9522
|
* @author Ikaros Kappler
|
|
9071
9523
|
* @date 2021-02-26
|
|
9072
|
-
* @
|
|
9524
|
+
* @modified 2022-02-02 Added the `destroy` method.
|
|
9525
|
+
* @version 1.1.0
|
|
9073
9526
|
*/
|
|
9074
9527
|
/**
|
|
9075
9528
|
* @classdesc A class for elliptic sectors.
|
|
@@ -9155,6 +9608,15 @@ class VEllipseSector {
|
|
|
9155
9608
|
}
|
|
9156
9609
|
return curves;
|
|
9157
9610
|
}
|
|
9611
|
+
/**
|
|
9612
|
+
* This function should invalidate any installed listeners and invalidate this object.
|
|
9613
|
+
* After calling this function the object might not hold valid data any more and
|
|
9614
|
+
* should not be used.
|
|
9615
|
+
*/
|
|
9616
|
+
destroy() {
|
|
9617
|
+
this.ellipse.destroy();
|
|
9618
|
+
this.isDestroyed = true;
|
|
9619
|
+
}
|
|
9158
9620
|
}
|
|
9159
9621
|
VEllipseSector.ellipseSectorUtils = {
|
|
9160
9622
|
/**
|
|
@@ -9394,7 +9856,8 @@ VEllipseSector.ellipseSectorUtils = {
|
|
|
9394
9856
|
* @modified 2021-03-03 Added the `VEllipseSector` drawable.
|
|
9395
9857
|
* @modified 2021-03-29 Clearing `currentClassName` and `currentId` after drawing each drawable.
|
|
9396
9858
|
* @modified 2021-04-25 Extending `remove` to accept arrays of drawables.
|
|
9397
|
-
* @
|
|
9859
|
+
* @modified 2021-11-16 Adding the `PBText` drawable.
|
|
9860
|
+
* @version 1.15.0
|
|
9398
9861
|
*
|
|
9399
9862
|
* @file PlotBoilerplate
|
|
9400
9863
|
* @fileoverview The main class.
|
|
@@ -9639,6 +10102,12 @@ class PlotBoilerplate {
|
|
|
9639
10102
|
image: {
|
|
9640
10103
|
color: "#a8a8a8",
|
|
9641
10104
|
lineWidth: 1
|
|
10105
|
+
},
|
|
10106
|
+
text: {
|
|
10107
|
+
color: "rgba(192,0,128,0.5)",
|
|
10108
|
+
lineWidth: 1,
|
|
10109
|
+
fill: true,
|
|
10110
|
+
anchor: true
|
|
9642
10111
|
}
|
|
9643
10112
|
}; // END drawConfig
|
|
9644
10113
|
// +---------------------------------------------------------------------------------
|
|
@@ -9760,7 +10229,7 @@ class PlotBoilerplate {
|
|
|
9760
10229
|
var blob = new Blob([svgCode], { type: "image/svg;charset=utf-8" });
|
|
9761
10230
|
// See documentation for FileSaver.js for usage.
|
|
9762
10231
|
// https://github.com/eligrey/FileSaver.js
|
|
9763
|
-
if (typeof globalThis["saveAs"]
|
|
10232
|
+
if (typeof globalThis["saveAs"] !== "function")
|
|
9764
10233
|
throw "Cannot save file; did you load the ./utils/savefile helper function and the eligrey/SaveFile library?";
|
|
9765
10234
|
var _saveAs = globalThis["saveAs"];
|
|
9766
10235
|
_saveAs(blob, "plotboilerplate.svg");
|
|
@@ -9866,7 +10335,6 @@ class PlotBoilerplate {
|
|
|
9866
10335
|
add(drawable, redraw) {
|
|
9867
10336
|
if (Array.isArray(drawable)) {
|
|
9868
10337
|
const arr = drawable;
|
|
9869
|
-
// for( var i in arr )
|
|
9870
10338
|
for (var i = 0; i < arr.length; i++) {
|
|
9871
10339
|
this.add(arr[i], false);
|
|
9872
10340
|
}
|
|
@@ -9912,9 +10380,9 @@ class PlotBoilerplate {
|
|
|
9912
10380
|
}
|
|
9913
10381
|
else if (drawable instanceof Polygon) {
|
|
9914
10382
|
this.drawables.push(drawable);
|
|
9915
|
-
|
|
9916
|
-
for (var i = 0; i < drawable.vertices.length; i++)
|
|
10383
|
+
for (var i = 0; i < drawable.vertices.length; i++) {
|
|
9917
10384
|
this.vertices.push(drawable.vertices[i]);
|
|
10385
|
+
}
|
|
9918
10386
|
}
|
|
9919
10387
|
else if (drawable instanceof Triangle) {
|
|
9920
10388
|
this.drawables.push(drawable);
|
|
@@ -9926,8 +10394,9 @@ class PlotBoilerplate {
|
|
|
9926
10394
|
this.drawables.push(drawable);
|
|
9927
10395
|
const bezierPath = drawable;
|
|
9928
10396
|
for (var i = 0; i < bezierPath.bezierCurves.length; i++) {
|
|
9929
|
-
if (!drawable.adjustCircular && i == 0)
|
|
10397
|
+
if (!drawable.adjustCircular && i == 0) {
|
|
9930
10398
|
this.vertices.push(bezierPath.bezierCurves[i].startPoint);
|
|
10399
|
+
}
|
|
9931
10400
|
this.vertices.push(bezierPath.bezierCurves[i].endPoint);
|
|
9932
10401
|
this.vertices.push(bezierPath.bezierCurves[i].startControlPoint);
|
|
9933
10402
|
this.vertices.push(bezierPath.bezierCurves[i].endControlPoint);
|
|
@@ -9946,6 +10415,11 @@ class PlotBoilerplate {
|
|
|
9946
10415
|
});
|
|
9947
10416
|
drawable.lowerRight.attr.selectable = false;
|
|
9948
10417
|
}
|
|
10418
|
+
else if (drawable instanceof PBText) {
|
|
10419
|
+
this.vertices.push(drawable.anchor);
|
|
10420
|
+
this.drawables.push(drawable);
|
|
10421
|
+
drawable.anchor.attr.selectable = false;
|
|
10422
|
+
}
|
|
9949
10423
|
else {
|
|
9950
10424
|
throw "Cannot add drawable of unrecognized type: " + typeof drawable + ".";
|
|
9951
10425
|
}
|
|
@@ -9993,7 +10467,7 @@ class PlotBoilerplate {
|
|
|
9993
10467
|
}
|
|
9994
10468
|
}
|
|
9995
10469
|
for (var i = 0; i < this.drawables.length; i++) {
|
|
9996
|
-
if (this.drawables[i] === drawable) {
|
|
10470
|
+
if (this.drawables[i] === drawable || this.drawables[i].uid === drawable.uid) {
|
|
9997
10471
|
this.drawables.splice(i, 1);
|
|
9998
10472
|
if (removeWithVertices) {
|
|
9999
10473
|
// Check if some listeners need to be removed
|
|
@@ -10044,6 +10518,9 @@ class PlotBoilerplate {
|
|
|
10044
10518
|
this.removeVertex(drawable.upperLeft, false);
|
|
10045
10519
|
this.removeVertex(drawable.lowerRight, false);
|
|
10046
10520
|
}
|
|
10521
|
+
else if (drawable instanceof PBText) {
|
|
10522
|
+
this.removeVertex(drawable.anchor, false);
|
|
10523
|
+
}
|
|
10047
10524
|
} // END removeWithVertices
|
|
10048
10525
|
if (redraw) {
|
|
10049
10526
|
this.redraw();
|
|
@@ -10065,8 +10542,9 @@ class PlotBoilerplate {
|
|
|
10065
10542
|
for (var i = 0; i < this.vertices.length; i++) {
|
|
10066
10543
|
if (this.vertices[i] === vert) {
|
|
10067
10544
|
this.vertices.splice(i, 1);
|
|
10068
|
-
if (redraw)
|
|
10545
|
+
if (redraw) {
|
|
10069
10546
|
this.redraw();
|
|
10547
|
+
}
|
|
10070
10548
|
return;
|
|
10071
10549
|
}
|
|
10072
10550
|
}
|
|
@@ -10101,8 +10579,9 @@ class PlotBoilerplate {
|
|
|
10101
10579
|
**/
|
|
10102
10580
|
getVertexNear(pixelPosition, pixelTolerance) {
|
|
10103
10581
|
var p = this.locatePointNear(this.transformMousePosition(pixelPosition.x, pixelPosition.y), pixelTolerance / Math.min(this.config.cssScaleX, this.config.cssScaleY));
|
|
10104
|
-
if (p && p.typeName == "vertex")
|
|
10582
|
+
if (p && p.typeName == "vertex") {
|
|
10105
10583
|
return this.vertices[p.vindex];
|
|
10584
|
+
}
|
|
10106
10585
|
return undefined;
|
|
10107
10586
|
}
|
|
10108
10587
|
/**
|
|
@@ -10369,6 +10848,16 @@ class PlotBoilerplate {
|
|
|
10369
10848
|
d.lowerRight.attr.renderTime = renderTime;
|
|
10370
10849
|
}
|
|
10371
10850
|
}
|
|
10851
|
+
else if (d instanceof PBText) {
|
|
10852
|
+
fill.setCurrentId(d.uid);
|
|
10853
|
+
fill.text(d.text, d.anchor.x, d.anchor.y, d);
|
|
10854
|
+
if (this.drawConfig.text.anchor) {
|
|
10855
|
+
draw.setCurrentId(`${d.uid}_a0`);
|
|
10856
|
+
draw.setCurrentClassName(`${d.className}-anchor`);
|
|
10857
|
+
(this.drawConfig.text.fill ? fill : draw).point(d.anchor, this.drawConfig.text.color);
|
|
10858
|
+
}
|
|
10859
|
+
d.anchor.attr.renderTime = renderTime;
|
|
10860
|
+
}
|
|
10372
10861
|
else {
|
|
10373
10862
|
console.error("Cannot draw object. Unknown class.");
|
|
10374
10863
|
}
|
|
@@ -10647,7 +11136,6 @@ class PlotBoilerplate {
|
|
|
10647
11136
|
// Apply the zoom (the tolerant area should not shrink or grow when zooming)
|
|
10648
11137
|
tolerance /= _self.draw.scale.x;
|
|
10649
11138
|
// Search in vertices
|
|
10650
|
-
// for( var vindex in _self.vertices ) {
|
|
10651
11139
|
for (var vindex = 0; vindex < _self.vertices.length; vindex++) {
|
|
10652
11140
|
var vert = _self.vertices[vindex];
|
|
10653
11141
|
if ((vert.attr.draggable || vert.attr.selectable) && vert.distance(point) < tolerance) {
|
|
@@ -10667,10 +11155,7 @@ class PlotBoilerplate {
|
|
|
10667
11155
|
* @return {void}
|
|
10668
11156
|
**/
|
|
10669
11157
|
handleClick(e) {
|
|
10670
|
-
// x:number,y:number) {
|
|
10671
11158
|
const _self = this;
|
|
10672
|
-
// const x:number = e.params.pos.x;
|
|
10673
|
-
//const y:number = e.params.pos.y;
|
|
10674
11159
|
var p = this.locatePointNear(_self.transformMousePosition(e.params.pos.x, e.params.pos.y), PlotBoilerplate.DEFAULT_CLICK_TOLERANCE / Math.min(_self.config.cssScaleX, _self.config.cssScaleY));
|
|
10675
11160
|
if (p) {
|
|
10676
11161
|
_self.vertices[p.vindex].listeners.fireClickEvent(e);
|
|
@@ -10687,7 +11172,7 @@ class PlotBoilerplate {
|
|
|
10687
11172
|
}
|
|
10688
11173
|
_self.redraw();
|
|
10689
11174
|
}
|
|
10690
|
-
else if (this.keyHandler.isDown("y")
|
|
11175
|
+
else if (this.keyHandler.isDown("y")) {
|
|
10691
11176
|
_self.vertices[p.vindex].attr.bezierAutoAdjust = !_self.vertices[p.vindex].attr.bezierAutoAdjust;
|
|
10692
11177
|
_self.redraw();
|
|
10693
11178
|
}
|
|
@@ -10985,6 +11470,7 @@ class PlotBoilerplate {
|
|
|
10985
11470
|
_self.draggedElements = [];
|
|
10986
11471
|
};
|
|
10987
11472
|
const afProps = {
|
|
11473
|
+
// touchStart: (evt: TouchEvent) => {
|
|
10988
11474
|
touchStart: (evt) => {
|
|
10989
11475
|
if (evt.touches.length == 1) {
|
|
10990
11476
|
touchMovePos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));
|
|
@@ -11087,10 +11573,13 @@ class PlotBoilerplate {
|
|
|
11087
11573
|
_self.redraw();
|
|
11088
11574
|
}
|
|
11089
11575
|
}; // END afProps
|
|
11090
|
-
if (window["createAlloyFinger"])
|
|
11576
|
+
if (window["createAlloyFinger"]) {
|
|
11091
11577
|
window["createAlloyFinger"](this.eventCatcher ? this.eventCatcher : this.canvas, afProps);
|
|
11092
|
-
|
|
11578
|
+
}
|
|
11579
|
+
else {
|
|
11580
|
+
/* tslint:disable-next-line */
|
|
11093
11581
|
new AlloyFinger(this.eventCatcher ? this.eventCatcher : this.canvas, afProps);
|
|
11582
|
+
}
|
|
11094
11583
|
}
|
|
11095
11584
|
catch (e) {
|
|
11096
11585
|
console.error("Failed to initialize AlloyFinger!");
|
|
@@ -11453,5 +11942,5 @@ class SVGBuilder {
|
|
|
11453
11942
|
;
|
|
11454
11943
|
}
|
|
11455
11944
|
|
|
11456
|
-
export { BezierPath, Bounds, Circle, CircleSector, CubicBezierCurve, Grid, KeyHandler, Line, MouseHandler, PBImage, PlotBoilerplate, Polygon, SVGBuilder, Triangle, UIDGenerator, VEllipse, VEllipseSector, Vector, VertTuple, Vertex, VertexAttr, VertexListeners, XMouseEvent, XWheelEvent, drawutils, drawutilsgl, drawutilssvg, geomutils };
|
|
11945
|
+
export { BezierPath, Bounds, Circle, CircleSector, CubicBezierCurve, Grid, KeyHandler, Line, MouseHandler, PBImage, PBText, PlotBoilerplate, Polygon, SVGBuilder, Triangle, UIDGenerator, VEllipse, VEllipseSector, Vector, VertTuple, Vertex, VertexAttr, VertexListeners, XMouseEvent, XWheelEvent, drawutils, drawutilsgl, drawutilssvg, geomutils };
|
|
11457
11946
|
//# sourceMappingURL=index.esm.js.map
|