pts 0.11.6 → 0.12.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/.eslintignore +5 -0
- package/.eslintrc.js +52 -0
- package/dist/index.d.mts +1380 -0
- package/dist/index.d.ts +26 -26
- package/dist/index.js +701 -707
- package/dist/index.mjs +701 -707
- package/dist/pts.js +701 -707
- package/dist/pts.min.js +3 -3
- package/dist/pts.min.js.map +1 -1
- package/package.json +10 -5
package/dist/index.js
CHANGED
|
@@ -88,7 +88,7 @@ __export(module_exports, {
|
|
|
88
88
|
module.exports = __toCommonJS(module_exports);
|
|
89
89
|
|
|
90
90
|
// src/LinearAlgebra.ts
|
|
91
|
-
var Vec = class {
|
|
91
|
+
var Vec = class _Vec {
|
|
92
92
|
/**
|
|
93
93
|
* Add `b` to vector `a`.
|
|
94
94
|
* @returns vector `a`
|
|
@@ -181,44 +181,44 @@ var Vec = class {
|
|
|
181
181
|
* Magnitude of `a`.
|
|
182
182
|
*/
|
|
183
183
|
static magnitude(a) {
|
|
184
|
-
return Math.sqrt(
|
|
184
|
+
return Math.sqrt(_Vec.dot(a, a));
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
187
|
* Unit vector of `a`. If magnitude of `a` is already known, pass it in the second paramter to optimize calculation.
|
|
188
188
|
*/
|
|
189
189
|
static unit(a, magnitude = void 0) {
|
|
190
|
-
|
|
190
|
+
const m = magnitude === void 0 ? _Vec.magnitude(a) : magnitude;
|
|
191
191
|
if (m === 0)
|
|
192
192
|
return Pt.make(a.length);
|
|
193
|
-
return
|
|
193
|
+
return _Vec.divide(a, m);
|
|
194
194
|
}
|
|
195
195
|
/**
|
|
196
196
|
* Set `a` to its absolute value in each dimension.
|
|
197
197
|
* @returns vector `a`
|
|
198
198
|
*/
|
|
199
199
|
static abs(a) {
|
|
200
|
-
return
|
|
200
|
+
return _Vec.map(a, Math.abs);
|
|
201
201
|
}
|
|
202
202
|
/**
|
|
203
203
|
* Set `a` to its floor value in each dimension.
|
|
204
204
|
* @returns vector `a`
|
|
205
205
|
*/
|
|
206
206
|
static floor(a) {
|
|
207
|
-
return
|
|
207
|
+
return _Vec.map(a, Math.floor);
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
210
|
* Set `a` to its ceiling value in each dimension.
|
|
211
211
|
* @returns vector `a`
|
|
212
212
|
*/
|
|
213
213
|
static ceil(a) {
|
|
214
|
-
return
|
|
214
|
+
return _Vec.map(a, Math.ceil);
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
217
|
* Set `a` to its rounded value in each dimension.
|
|
218
218
|
* @returns vector `a`
|
|
219
219
|
*/
|
|
220
220
|
static round(a) {
|
|
221
|
-
return
|
|
221
|
+
return _Vec.map(a, Math.round);
|
|
222
222
|
}
|
|
223
223
|
/**
|
|
224
224
|
* Find the max value within a vector's dimensions.
|
|
@@ -268,7 +268,7 @@ var Vec = class {
|
|
|
268
268
|
return a;
|
|
269
269
|
}
|
|
270
270
|
};
|
|
271
|
-
var Mat = class {
|
|
271
|
+
var Mat = class _Mat {
|
|
272
272
|
constructor() {
|
|
273
273
|
this.reset();
|
|
274
274
|
}
|
|
@@ -282,13 +282,13 @@ var Mat = class {
|
|
|
282
282
|
* Convert the value of its stored 3x3 matrix to a 2D [`DOMMatrix`](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix) instance
|
|
283
283
|
*/
|
|
284
284
|
get domMatrix() {
|
|
285
|
-
return new DOMMatrix(
|
|
285
|
+
return new DOMMatrix(_Mat.toDOMMatrix(this._33));
|
|
286
286
|
}
|
|
287
287
|
/**
|
|
288
288
|
* Reset the internal 3x3 matrix to its identity
|
|
289
289
|
*/
|
|
290
290
|
reset() {
|
|
291
|
-
this._33 =
|
|
291
|
+
this._33 = _Mat.scale2DMatrix(1, 1);
|
|
292
292
|
}
|
|
293
293
|
/**
|
|
294
294
|
* Scale the internal 3x3 matrix. You can chain this function with other related functions.
|
|
@@ -296,8 +296,8 @@ var Mat = class {
|
|
|
296
296
|
* @param at Optional origin location to scale from.
|
|
297
297
|
*/
|
|
298
298
|
scale2D(val, at = [0, 0]) {
|
|
299
|
-
const m =
|
|
300
|
-
this._33 =
|
|
299
|
+
const m = _Mat.scaleAt2DMatrix(val[0] || 1, val[1] || 1, at);
|
|
300
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
301
301
|
return this;
|
|
302
302
|
}
|
|
303
303
|
/**
|
|
@@ -306,8 +306,8 @@ var Mat = class {
|
|
|
306
306
|
* @param at Optional origin location to rotate from.
|
|
307
307
|
*/
|
|
308
308
|
rotate2D(ang, at = [0, 0]) {
|
|
309
|
-
const m =
|
|
310
|
-
this._33 =
|
|
309
|
+
const m = _Mat.rotateAt2DMatrix(Math.cos(ang), Math.sin(ang), at);
|
|
310
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
311
311
|
return this;
|
|
312
312
|
}
|
|
313
313
|
/**
|
|
@@ -315,8 +315,8 @@ var Mat = class {
|
|
|
315
315
|
* @param val [x, y] offset values
|
|
316
316
|
*/
|
|
317
317
|
translate2D(val) {
|
|
318
|
-
const m =
|
|
319
|
-
this._33 =
|
|
318
|
+
const m = _Mat.translate2DMatrix(val[0] || 0, val[1] || 0);
|
|
319
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
320
320
|
return this;
|
|
321
321
|
}
|
|
322
322
|
/**
|
|
@@ -325,8 +325,8 @@ var Mat = class {
|
|
|
325
325
|
* @param at Optional origin location to scale from.
|
|
326
326
|
*/
|
|
327
327
|
shear2D(val, at = [0, 0]) {
|
|
328
|
-
const m =
|
|
329
|
-
this._33 =
|
|
328
|
+
const m = _Mat.shearAt2DMatrix(Math.tan(val[0] || 0), Math.tan(val[1] || 1), at);
|
|
329
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
330
330
|
return this;
|
|
331
331
|
}
|
|
332
332
|
/**
|
|
@@ -342,8 +342,8 @@ var Mat = class {
|
|
|
342
342
|
if (a.length != b.length)
|
|
343
343
|
throw new Error("Cannot add matrix if rows' and columns' size don't match.");
|
|
344
344
|
}
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
const g = new Group();
|
|
346
|
+
const isNum = typeof b == "number";
|
|
347
347
|
for (let i = 0, len = a.length; i < len; i++) {
|
|
348
348
|
g.push(a[i].$add(isNum ? b : b[i]));
|
|
349
349
|
}
|
|
@@ -358,7 +358,7 @@ var Mat = class {
|
|
|
358
358
|
* @returns If not elementwise, this will return a new group with M Pt, each with N dimensions (M-rows, N-columns).
|
|
359
359
|
*/
|
|
360
360
|
static multiply(a, b, transposed = false, elementwise = false) {
|
|
361
|
-
|
|
361
|
+
const g = new Group();
|
|
362
362
|
if (typeof b != "number") {
|
|
363
363
|
if (elementwise) {
|
|
364
364
|
if (a.length != b.length)
|
|
@@ -372,9 +372,9 @@ var Mat = class {
|
|
|
372
372
|
if (transposed && a[0].length != b[0].length)
|
|
373
373
|
throw new Error("Cannot multiply matrix if transposed and the columns in both matrices don't match.");
|
|
374
374
|
if (!transposed)
|
|
375
|
-
b =
|
|
375
|
+
b = _Mat.transpose(b);
|
|
376
376
|
for (let ai = 0, alen = a.length; ai < alen; ai++) {
|
|
377
|
-
|
|
377
|
+
const p = Pt.make(b.length, 0);
|
|
378
378
|
for (let bi = 0, blen = b.length; bi < blen; bi++) {
|
|
379
379
|
p[bi] = Vec.dot(a[ai], b[bi]);
|
|
380
380
|
}
|
|
@@ -395,7 +395,7 @@ var Mat = class {
|
|
|
395
395
|
* @param defaultValue a default value to fill if index out of bound. If not provided, it will throw an error instead.
|
|
396
396
|
*/
|
|
397
397
|
static zipSlice(g, index, defaultValue = false) {
|
|
398
|
-
|
|
398
|
+
const z = [];
|
|
399
399
|
for (let i = 0, len = g.length; i < len; i++) {
|
|
400
400
|
if (g[i].length - 1 < index && defaultValue === false)
|
|
401
401
|
throw `Index ${index} is out of bounds`;
|
|
@@ -410,10 +410,10 @@ var Mat = class {
|
|
|
410
410
|
* @param useLongest If true, find the longest list of values in a Pt and use its length for zipping. Default is false, which uses the first item's length for zipping.
|
|
411
411
|
*/
|
|
412
412
|
static zip(g, defaultValue = false, useLongest = false) {
|
|
413
|
-
|
|
414
|
-
|
|
413
|
+
const ps = new Group();
|
|
414
|
+
const len = useLongest ? g.reduce((a, b) => Math.max(a, b.length), 0) : g[0].length;
|
|
415
415
|
for (let i = 0; i < len; i++) {
|
|
416
|
-
ps.push(
|
|
416
|
+
ps.push(_Mat.zipSlice(g, i, defaultValue));
|
|
417
417
|
}
|
|
418
418
|
return ps;
|
|
419
419
|
}
|
|
@@ -421,7 +421,7 @@ var Mat = class {
|
|
|
421
421
|
* Same as `zip` function.
|
|
422
422
|
*/
|
|
423
423
|
static transpose(g, defaultValue = false, useLongest = false) {
|
|
424
|
-
return
|
|
424
|
+
return _Mat.zip(g, defaultValue, useLongest);
|
|
425
425
|
}
|
|
426
426
|
static toDOMMatrix(m) {
|
|
427
427
|
return [m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1]];
|
|
@@ -433,8 +433,8 @@ var Mat = class {
|
|
|
433
433
|
* @returns a new transformed Pt
|
|
434
434
|
*/
|
|
435
435
|
static transform2D(pt, m) {
|
|
436
|
-
|
|
437
|
-
|
|
436
|
+
const x = pt[0] * m[0][0] + pt[1] * m[1][0] + m[2][0];
|
|
437
|
+
const y = pt[0] * m[0][1] + pt[1] * m[1][1] + m[2][1];
|
|
438
438
|
return new Pt(x, y);
|
|
439
439
|
}
|
|
440
440
|
/**
|
|
@@ -481,7 +481,7 @@ var Mat = class {
|
|
|
481
481
|
* Get a matrix to scale a point from an origin point. For use in `transform2D`.
|
|
482
482
|
*/
|
|
483
483
|
static scaleAt2DMatrix(sx, sy, at) {
|
|
484
|
-
|
|
484
|
+
const m = _Mat.scale2DMatrix(sx, sy);
|
|
485
485
|
m[2][0] = -at[0] * sx + at[0];
|
|
486
486
|
m[2][1] = -at[1] * sy + at[1];
|
|
487
487
|
return m;
|
|
@@ -490,7 +490,7 @@ var Mat = class {
|
|
|
490
490
|
* Get a matrix to rotate a point from an origin point. For use in `transform2D`.
|
|
491
491
|
*/
|
|
492
492
|
static rotateAt2DMatrix(cosA, sinA, at) {
|
|
493
|
-
|
|
493
|
+
const m = _Mat.rotate2DMatrix(cosA, sinA);
|
|
494
494
|
m[2][0] = at[0] * (1 - cosA) + at[1] * sinA;
|
|
495
495
|
m[2][1] = at[1] * (1 - cosA) - at[0] * sinA;
|
|
496
496
|
return m;
|
|
@@ -499,7 +499,7 @@ var Mat = class {
|
|
|
499
499
|
* Get a matrix to shear a point from an origin point. For use in `transform2D`.
|
|
500
500
|
*/
|
|
501
501
|
static shearAt2DMatrix(tanX, tanY, at) {
|
|
502
|
-
|
|
502
|
+
const m = _Mat.shear2DMatrix(tanX, tanY);
|
|
503
503
|
m[2][0] = -at[1] * tanY;
|
|
504
504
|
m[2][1] = -at[0] * tanX;
|
|
505
505
|
return m;
|
|
@@ -510,7 +510,7 @@ var Mat = class {
|
|
|
510
510
|
* @param p1 second end point to define the reflection line
|
|
511
511
|
*/
|
|
512
512
|
static reflectAt2DMatrix(p1, p2) {
|
|
513
|
-
|
|
513
|
+
const intercept = Line.intercept(p1, p2);
|
|
514
514
|
if (intercept == void 0) {
|
|
515
515
|
return [
|
|
516
516
|
new Pt([-1, 0, 0]),
|
|
@@ -518,10 +518,10 @@ var Mat = class {
|
|
|
518
518
|
new Pt([p1[0] + p2[0], 0, 1])
|
|
519
519
|
];
|
|
520
520
|
} else {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
521
|
+
const yi = intercept.yi;
|
|
522
|
+
const ang2 = Math.atan(intercept.slope) * 2;
|
|
523
|
+
const cosA = Math.cos(ang2);
|
|
524
|
+
const sinA = Math.sin(ang2);
|
|
525
525
|
return [
|
|
526
526
|
new Pt([cosA, sinA, 0]),
|
|
527
527
|
new Pt([sinA, -cosA, 0]),
|
|
@@ -534,7 +534,7 @@ var Mat = class {
|
|
|
534
534
|
// src/Op.ts
|
|
535
535
|
var _errorLength = (obj, param = "expected") => Util.warn("Group's length is less than " + param, obj);
|
|
536
536
|
var _errorOutofBound = (obj, param = "") => Util.warn(`Index ${param} is out of bound in Group`, obj);
|
|
537
|
-
var Line = class {
|
|
537
|
+
var Line = class _Line {
|
|
538
538
|
/**
|
|
539
539
|
* Create a line that originates from an anchor point, given an angle and a magnitude.
|
|
540
540
|
* @param anchor an anchor Pt
|
|
@@ -632,7 +632,7 @@ var Line = class {
|
|
|
632
632
|
*/
|
|
633
633
|
static distanceFromPt(line, pt) {
|
|
634
634
|
let _line = Util.iterToArray(line);
|
|
635
|
-
let projectionVector =
|
|
635
|
+
let projectionVector = _Line.perpendicularFromPt(_line, pt, true);
|
|
636
636
|
if (projectionVector) {
|
|
637
637
|
return projectionVector.magnitude();
|
|
638
638
|
} else {
|
|
@@ -648,8 +648,8 @@ var Line = class {
|
|
|
648
648
|
static intersectRay2D(la, lb) {
|
|
649
649
|
let _la = Util.iterToArray(la);
|
|
650
650
|
let _lb = Util.iterToArray(lb);
|
|
651
|
-
let a =
|
|
652
|
-
let b =
|
|
651
|
+
let a = _Line.intercept(_la[0], _la[1]);
|
|
652
|
+
let b = _Line.intercept(_lb[0], _lb[1]);
|
|
653
653
|
let pa = _la[0];
|
|
654
654
|
let pb = _lb[0];
|
|
655
655
|
if (a == void 0) {
|
|
@@ -683,7 +683,7 @@ var Line = class {
|
|
|
683
683
|
static intersectLine2D(la, lb) {
|
|
684
684
|
let _la = Util.iterToArray(la);
|
|
685
685
|
let _lb = Util.iterToArray(lb);
|
|
686
|
-
let pt =
|
|
686
|
+
let pt = _Line.intersectRay2D(_la, _lb);
|
|
687
687
|
return pt && Geom.withinBound(pt, _la[0], _la[1]) && Geom.withinBound(pt, _lb[0], _lb[1]) ? pt : void 0;
|
|
688
688
|
}
|
|
689
689
|
/**
|
|
@@ -695,7 +695,7 @@ var Line = class {
|
|
|
695
695
|
static intersectLineWithRay2D(line, ray) {
|
|
696
696
|
let _line = Util.iterToArray(line);
|
|
697
697
|
let _ray = Util.iterToArray(ray);
|
|
698
|
-
let pt =
|
|
698
|
+
let pt = _Line.intersectRay2D(_line, _ray);
|
|
699
699
|
return pt && Geom.withinBound(pt, _line[0], _line[1]) ? pt : void 0;
|
|
700
700
|
}
|
|
701
701
|
/**
|
|
@@ -707,7 +707,7 @@ var Line = class {
|
|
|
707
707
|
static intersectPolygon2D(lineOrRay, poly, sourceIsRay = false) {
|
|
708
708
|
let _lineOrRay = Util.iterToArray(lineOrRay);
|
|
709
709
|
let _poly = Util.iterToArray(poly);
|
|
710
|
-
let fn = sourceIsRay ?
|
|
710
|
+
let fn = sourceIsRay ? _Line.intersectLineWithRay2D : _Line.intersectLine2D;
|
|
711
711
|
let pts = new Group();
|
|
712
712
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
713
713
|
let next = i === len - 1 ? 0 : i + 1;
|
|
@@ -725,7 +725,7 @@ var Line = class {
|
|
|
725
725
|
*/
|
|
726
726
|
static intersectLines2D(lines1, lines2, isRay = false) {
|
|
727
727
|
let group = new Group();
|
|
728
|
-
let fn = isRay ?
|
|
728
|
+
let fn = isRay ? _Line.intersectLineWithRay2D : _Line.intersectLine2D;
|
|
729
729
|
for (let l1 of lines1) {
|
|
730
730
|
for (let l2 of lines2) {
|
|
731
731
|
let _ip = fn(l1, l2);
|
|
@@ -743,7 +743,7 @@ var Line = class {
|
|
|
743
743
|
*/
|
|
744
744
|
static intersectGridWithRay2D(ray, gridPt) {
|
|
745
745
|
let _ray = Util.iterToArray(ray);
|
|
746
|
-
let t =
|
|
746
|
+
let t = _Line.intercept(new Pt(_ray[0]).subtract(gridPt), new Pt(_ray[1]).subtract(gridPt));
|
|
747
747
|
let g = new Group();
|
|
748
748
|
if (t && t.xi)
|
|
749
749
|
g.push(new Pt(gridPt[0] + t.xi, gridPt[1]));
|
|
@@ -759,7 +759,7 @@ var Line = class {
|
|
|
759
759
|
*/
|
|
760
760
|
static intersectGridWithLine2D(line, gridPt) {
|
|
761
761
|
let _line = Util.iterToArray(line);
|
|
762
|
-
let g =
|
|
762
|
+
let g = _Line.intersectGridWithRay2D(_line, gridPt);
|
|
763
763
|
let gg = new Group();
|
|
764
764
|
for (let i = 0, len = g.length; i < len; i++) {
|
|
765
765
|
if (Geom.withinBound(g[i], _line[0], _line[1]))
|
|
@@ -779,7 +779,7 @@ var Line = class {
|
|
|
779
779
|
let box = Geom.boundingBox(Group.fromPtArray(_line));
|
|
780
780
|
if (!Rectangle.hasIntersectRect2D(box, _rect))
|
|
781
781
|
return new Group();
|
|
782
|
-
return
|
|
782
|
+
return _Line.intersectLines2D([_line], Rectangle.sides(_rect));
|
|
783
783
|
}
|
|
784
784
|
/**
|
|
785
785
|
* Get evenly distributed points on a line. Similar to [`Create.distributeLinear`](#link) but excluding end points.
|
|
@@ -820,7 +820,7 @@ var Line = class {
|
|
|
820
820
|
} else {
|
|
821
821
|
sideIdx = ls[0] < 0 ? 3 : 1;
|
|
822
822
|
}
|
|
823
|
-
return
|
|
823
|
+
return _Line.intersectRay2D(sides[sideIdx], _line);
|
|
824
824
|
}
|
|
825
825
|
}
|
|
826
826
|
/**
|
|
@@ -856,7 +856,7 @@ var Line = class {
|
|
|
856
856
|
return new Group(_line[0].$min(_line[1]), _line[0].$max(_line[1]));
|
|
857
857
|
}
|
|
858
858
|
};
|
|
859
|
-
var Rectangle = class {
|
|
859
|
+
var Rectangle = class _Rectangle {
|
|
860
860
|
/**
|
|
861
861
|
* Create a rectangle from top-left anchor point. Same as [`Rectangle.fromTopLeft`](#link).
|
|
862
862
|
* @param topLeft top-left point
|
|
@@ -865,7 +865,7 @@ var Rectangle = class {
|
|
|
865
865
|
* @returns a Group of 2 Pts representing a rectangle
|
|
866
866
|
*/
|
|
867
867
|
static from(topLeft, widthOrSize, height) {
|
|
868
|
-
return
|
|
868
|
+
return _Rectangle.fromTopLeft(topLeft, widthOrSize, height);
|
|
869
869
|
}
|
|
870
870
|
/**
|
|
871
871
|
* Create a rectangle given a top-left position and a size.
|
|
@@ -906,9 +906,9 @@ var Rectangle = class {
|
|
|
906
906
|
*/
|
|
907
907
|
static toSquare(pts, enclose = false) {
|
|
908
908
|
let _pts = Util.iterToArray(pts);
|
|
909
|
-
let s =
|
|
909
|
+
let s = _Rectangle.size(_pts);
|
|
910
910
|
let m = enclose ? s.maxValue().value : s.minValue().value;
|
|
911
|
-
return
|
|
911
|
+
return _Rectangle.fromCenter(_Rectangle.center(_pts), m, m);
|
|
912
912
|
}
|
|
913
913
|
/**
|
|
914
914
|
* Get the size of this rectangle as a Pt.
|
|
@@ -944,7 +944,7 @@ var Rectangle = class {
|
|
|
944
944
|
* @returns an array of 4 Groups, each of which represents a line segment
|
|
945
945
|
*/
|
|
946
946
|
static sides(rect) {
|
|
947
|
-
let [p0, p1, p2, p3] =
|
|
947
|
+
let [p0, p1, p2, p3] = _Rectangle.corners(rect);
|
|
948
948
|
return [
|
|
949
949
|
new Group(p0, p1),
|
|
950
950
|
new Group(p1, p2),
|
|
@@ -978,7 +978,7 @@ var Rectangle = class {
|
|
|
978
978
|
* @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle
|
|
979
979
|
*/
|
|
980
980
|
static polygon(rect) {
|
|
981
|
-
return
|
|
981
|
+
return _Rectangle.corners(rect);
|
|
982
982
|
}
|
|
983
983
|
/**
|
|
984
984
|
* Subdivide a rectangle into 4 rectangles, one for each quadrant.
|
|
@@ -987,8 +987,8 @@ var Rectangle = class {
|
|
|
987
987
|
*/
|
|
988
988
|
static quadrants(rect, center) {
|
|
989
989
|
let _rect = Util.iterToArray(rect);
|
|
990
|
-
let corners =
|
|
991
|
-
let _center = center != void 0 ? new Pt(center) :
|
|
990
|
+
let corners = _Rectangle.corners(_rect);
|
|
991
|
+
let _center = center != void 0 ? new Pt(center) : _Rectangle.center(_rect);
|
|
992
992
|
return corners.map((c) => new Group(c, _center).boundingBox());
|
|
993
993
|
}
|
|
994
994
|
/**
|
|
@@ -1041,12 +1041,12 @@ var Rectangle = class {
|
|
|
1041
1041
|
static intersectRect2D(rect1, rect2) {
|
|
1042
1042
|
let _rect1 = Util.iterToArray(rect1);
|
|
1043
1043
|
let _rect2 = Util.iterToArray(rect2);
|
|
1044
|
-
if (!
|
|
1044
|
+
if (!_Rectangle.hasIntersectRect2D(_rect1, _rect2))
|
|
1045
1045
|
return new Group();
|
|
1046
|
-
return Line.intersectLines2D(
|
|
1046
|
+
return Line.intersectLines2D(_Rectangle.sides(_rect1), _Rectangle.sides(_rect2));
|
|
1047
1047
|
}
|
|
1048
1048
|
};
|
|
1049
|
-
var Circle = class {
|
|
1049
|
+
var Circle = class _Circle {
|
|
1050
1050
|
/**
|
|
1051
1051
|
* Create a circle that either fits within, or encloses, a rectangle.
|
|
1052
1052
|
* @param pts a Group or an Iterable<PtLike> with 2 Pt representing a rectangle
|
|
@@ -1137,7 +1137,7 @@ var Circle = class {
|
|
|
1137
1137
|
static intersectLine2D(circle, line) {
|
|
1138
1138
|
let _pts = Util.iterToArray(circle);
|
|
1139
1139
|
let _line = Util.iterToArray(line);
|
|
1140
|
-
let ps =
|
|
1140
|
+
let ps = _Circle.intersectRay2D(_pts, _line);
|
|
1141
1141
|
let g = new Group();
|
|
1142
1142
|
if (ps.length > 0) {
|
|
1143
1143
|
for (let i = 0, len = ps.length; i < len; i++) {
|
|
@@ -1190,7 +1190,7 @@ var Circle = class {
|
|
|
1190
1190
|
let sides = Rectangle.sides(_rect);
|
|
1191
1191
|
let g = [];
|
|
1192
1192
|
for (let i = 0, len = sides.length; i < len; i++) {
|
|
1193
|
-
let ps =
|
|
1193
|
+
let ps = _Circle.intersectLine2D(_pts, sides[i]);
|
|
1194
1194
|
if (ps.length > 0)
|
|
1195
1195
|
g.push(ps);
|
|
1196
1196
|
}
|
|
@@ -1233,7 +1233,7 @@ var Circle = class {
|
|
|
1233
1233
|
}
|
|
1234
1234
|
}
|
|
1235
1235
|
};
|
|
1236
|
-
var Triangle = class {
|
|
1236
|
+
var Triangle = class _Triangle {
|
|
1237
1237
|
/**
|
|
1238
1238
|
* Create a triangle from a rectangle. The triangle will be isosceles, with the bottom of the rectangle as its base.
|
|
1239
1239
|
* @param rect a Group or an Iterable<Pt> with 2 Pt representing a rectangle
|
|
@@ -1259,7 +1259,7 @@ var Triangle = class {
|
|
|
1259
1259
|
* @param size size is the magnitude of lines from center to the triangle's vertices, like a "radius".
|
|
1260
1260
|
*/
|
|
1261
1261
|
static fromCenter(pt, size) {
|
|
1262
|
-
return
|
|
1262
|
+
return _Triangle.fromCircle(Circle.fromCenter(pt, size));
|
|
1263
1263
|
}
|
|
1264
1264
|
/**
|
|
1265
1265
|
* Get the medial, which is an inner triangle formed by connecting the midpoints of this triangle's sides.
|
|
@@ -1298,7 +1298,7 @@ var Triangle = class {
|
|
|
1298
1298
|
*/
|
|
1299
1299
|
static altitude(tri, index) {
|
|
1300
1300
|
let _pts = Util.iterToArray(tri);
|
|
1301
|
-
let opp =
|
|
1301
|
+
let opp = _Triangle.oppositeSide(_pts, index);
|
|
1302
1302
|
if (opp.length > 1) {
|
|
1303
1303
|
return new Group(_pts[index], Line.perpendicularFromPt(opp, _pts[index]));
|
|
1304
1304
|
} else {
|
|
@@ -1314,8 +1314,8 @@ var Triangle = class {
|
|
|
1314
1314
|
let _pts = Util.iterToArray(tri);
|
|
1315
1315
|
if (_pts.length < 3)
|
|
1316
1316
|
return _errorLength(void 0, 3);
|
|
1317
|
-
let a =
|
|
1318
|
-
let b =
|
|
1317
|
+
let a = _Triangle.altitude(_pts, 0);
|
|
1318
|
+
let b = _Triangle.altitude(_pts, 1);
|
|
1319
1319
|
return Line.intersectRay2D(a, b);
|
|
1320
1320
|
}
|
|
1321
1321
|
/**
|
|
@@ -1338,7 +1338,7 @@ var Triangle = class {
|
|
|
1338
1338
|
*/
|
|
1339
1339
|
static incircle(tri, center) {
|
|
1340
1340
|
let _pts = Util.iterToArray(tri);
|
|
1341
|
-
let c = center ? center :
|
|
1341
|
+
let c = center ? center : _Triangle.incenter(_pts);
|
|
1342
1342
|
let area = Polygon.area(_pts);
|
|
1343
1343
|
let perim = Polygon.perimeter(_pts, true);
|
|
1344
1344
|
let r = 2 * area / perim.total;
|
|
@@ -1351,7 +1351,7 @@ var Triangle = class {
|
|
|
1351
1351
|
*/
|
|
1352
1352
|
static circumcenter(tri) {
|
|
1353
1353
|
let _pts = Util.iterToArray(tri);
|
|
1354
|
-
let md =
|
|
1354
|
+
let md = _Triangle.medial(_pts);
|
|
1355
1355
|
let a = [md[0], Geom.perpendicular(_pts[0].$subtract(md[0])).p1.$add(md[0])];
|
|
1356
1356
|
let b = [md[1], Geom.perpendicular(_pts[1].$subtract(md[1])).p1.$add(md[1])];
|
|
1357
1357
|
return Line.intersectRay2D(a, b);
|
|
@@ -1363,12 +1363,12 @@ var Triangle = class {
|
|
|
1363
1363
|
*/
|
|
1364
1364
|
static circumcircle(tri, center) {
|
|
1365
1365
|
let _pts = Util.iterToArray(tri);
|
|
1366
|
-
let c = center ? center :
|
|
1366
|
+
let c = center ? center : _Triangle.circumcenter(_pts);
|
|
1367
1367
|
let r = _pts[0].$subtract(c).magnitude();
|
|
1368
1368
|
return Circle.fromCenter(c, r);
|
|
1369
1369
|
}
|
|
1370
1370
|
};
|
|
1371
|
-
var Polygon = class {
|
|
1371
|
+
var Polygon = class _Polygon {
|
|
1372
1372
|
/**
|
|
1373
1373
|
* Get the centroid of a polygon, which is the average of all its points.
|
|
1374
1374
|
* @param pts a Group or an Iterable<PtLike> representing a polygon
|
|
@@ -1432,7 +1432,7 @@ var Polygon = class {
|
|
|
1432
1432
|
* @param t a value between 0 to 1 for interpolation. Default to 0.5 which will get the middle point.
|
|
1433
1433
|
*/
|
|
1434
1434
|
static midpoints(poly, closePath = false, t = 0.5) {
|
|
1435
|
-
let sides =
|
|
1435
|
+
let sides = _Polygon.lines(poly, closePath);
|
|
1436
1436
|
let mids = sides.map((s) => Geom.interpolate(s[0], s[1], t));
|
|
1437
1437
|
return mids;
|
|
1438
1438
|
}
|
|
@@ -1469,7 +1469,7 @@ var Polygon = class {
|
|
|
1469
1469
|
* @returns a bisector Pt that's a normalized unit vector
|
|
1470
1470
|
*/
|
|
1471
1471
|
static bisector(poly, index) {
|
|
1472
|
-
let sides =
|
|
1472
|
+
let sides = _Polygon.adjacentSides(poly, index, true);
|
|
1473
1473
|
if (sides.length >= 2) {
|
|
1474
1474
|
let a = sides[0][1].$subtract(sides[0][0]).unit();
|
|
1475
1475
|
let b = sides[1][1].$subtract(sides[1][0]).unit();
|
|
@@ -1485,7 +1485,7 @@ var Polygon = class {
|
|
|
1485
1485
|
* @returns an object with `total` length, and `segments` which is a Pt that stores each segment's length
|
|
1486
1486
|
*/
|
|
1487
1487
|
static perimeter(poly, closePath = false) {
|
|
1488
|
-
let lines =
|
|
1488
|
+
let lines = _Polygon.lines(poly, closePath);
|
|
1489
1489
|
let mag = 0;
|
|
1490
1490
|
let p = Pt.make(lines.length, 0);
|
|
1491
1491
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
@@ -1625,8 +1625,8 @@ var Polygon = class {
|
|
|
1625
1625
|
* @param unitAxis unit axis
|
|
1626
1626
|
*/
|
|
1627
1627
|
static _axisOverlap(poly1, poly2, unitAxis) {
|
|
1628
|
-
let pa =
|
|
1629
|
-
let pb =
|
|
1628
|
+
let pa = _Polygon.projectAxis(poly1, unitAxis);
|
|
1629
|
+
let pb = _Polygon.projectAxis(poly2, unitAxis);
|
|
1630
1630
|
return pa[0] < pb[0] ? pb[0] - pa[1] : pa[0] - pb[1];
|
|
1631
1631
|
}
|
|
1632
1632
|
/**
|
|
@@ -1638,7 +1638,7 @@ var Polygon = class {
|
|
|
1638
1638
|
let _poly = Util.iterToArray(poly);
|
|
1639
1639
|
let c = false;
|
|
1640
1640
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
1641
|
-
let ln =
|
|
1641
|
+
let ln = _Polygon.lineAt(_poly, i);
|
|
1642
1642
|
if (ln[0][1] > pt[1] != ln[1][1] > pt[1] && pt[0] < (ln[1][0] - ln[0][0]) * (pt[1] - ln[0][1]) / (ln[1][1] - ln[0][1]) + ln[0][0]) {
|
|
1643
1643
|
c = !c;
|
|
1644
1644
|
}
|
|
@@ -1669,10 +1669,10 @@ var Polygon = class {
|
|
|
1669
1669
|
let r = _circle[1][0];
|
|
1670
1670
|
let minDist = Number.MAX_SAFE_INTEGER;
|
|
1671
1671
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
1672
|
-
let edge =
|
|
1672
|
+
let edge = _Polygon.lineAt(_poly, i);
|
|
1673
1673
|
let axis = new Pt(edge[0].y - edge[1].y, edge[1].x - edge[0].x).unit();
|
|
1674
1674
|
let poly2 = new Group(c.$add(axis.$multiply(r)), c.$subtract(axis.$multiply(r)));
|
|
1675
|
-
let dist =
|
|
1675
|
+
let dist = _Polygon._axisOverlap(_poly, poly2, axis);
|
|
1676
1676
|
if (dist > 0) {
|
|
1677
1677
|
return null;
|
|
1678
1678
|
} else if (Math.abs(dist) < minDist) {
|
|
@@ -1687,7 +1687,7 @@ var Polygon = class {
|
|
|
1687
1687
|
}
|
|
1688
1688
|
if (!info.edge)
|
|
1689
1689
|
return null;
|
|
1690
|
-
let dir = c.$subtract(
|
|
1690
|
+
let dir = c.$subtract(_Polygon.centroid(_poly)).dot(info.normal);
|
|
1691
1691
|
if (dir < 0)
|
|
1692
1692
|
info.normal.multiply(-1);
|
|
1693
1693
|
info.dist = minDist;
|
|
@@ -1716,9 +1716,9 @@ var Polygon = class {
|
|
|
1716
1716
|
};
|
|
1717
1717
|
let minDist = Number.MAX_SAFE_INTEGER;
|
|
1718
1718
|
for (let i = 0, plen = _poly1.length + _poly2.length; i < plen; i++) {
|
|
1719
|
-
let edge = i < _poly1.length ?
|
|
1719
|
+
let edge = i < _poly1.length ? _Polygon.lineAt(_poly1, i) : _Polygon.lineAt(_poly2, i - _poly1.length);
|
|
1720
1720
|
let axis = new Pt(edge[0].y - edge[1].y, edge[1].x - edge[0].x).unit();
|
|
1721
|
-
let dist =
|
|
1721
|
+
let dist = _Polygon._axisOverlap(_poly1, _poly2, axis);
|
|
1722
1722
|
if (dist > 0) {
|
|
1723
1723
|
return null;
|
|
1724
1724
|
} else if (Math.abs(dist) < minDist) {
|
|
@@ -1731,8 +1731,8 @@ var Polygon = class {
|
|
|
1731
1731
|
info.dist = minDist;
|
|
1732
1732
|
let b1 = info.which === 0 ? _poly2 : _poly1;
|
|
1733
1733
|
let b2 = info.which === 0 ? _poly1 : _poly2;
|
|
1734
|
-
let c1 =
|
|
1735
|
-
let c2 =
|
|
1734
|
+
let c1 = _Polygon.centroid(b1);
|
|
1735
|
+
let c2 = _Polygon.centroid(b2);
|
|
1736
1736
|
let dir = c1.$subtract(c2).dot(info.normal);
|
|
1737
1737
|
if (dir < 0)
|
|
1738
1738
|
info.normal.multiply(-1);
|
|
@@ -1754,7 +1754,7 @@ var Polygon = class {
|
|
|
1754
1754
|
static intersectPolygon2D(poly1, poly2) {
|
|
1755
1755
|
let _poly1 = Util.iterToArray(poly1);
|
|
1756
1756
|
let _poly2 = Util.iterToArray(poly2);
|
|
1757
|
-
let lp =
|
|
1757
|
+
let lp = _Polygon.lines(_poly1);
|
|
1758
1758
|
let g = [];
|
|
1759
1759
|
for (let i = 0, len = lp.length; i < len; i++) {
|
|
1760
1760
|
let ins = Line.intersectPolygon2D(lp[i], _poly2, false);
|
|
@@ -1777,7 +1777,7 @@ var Polygon = class {
|
|
|
1777
1777
|
return boxes;
|
|
1778
1778
|
}
|
|
1779
1779
|
};
|
|
1780
|
-
var Curve = class {
|
|
1780
|
+
var Curve = class _Curve {
|
|
1781
1781
|
/**
|
|
1782
1782
|
* Get a precalculated coefficients per step.
|
|
1783
1783
|
* @param steps number of steps
|
|
@@ -1836,17 +1836,17 @@ var Curve = class {
|
|
|
1836
1836
|
if (_pts.length < 2)
|
|
1837
1837
|
return new Group();
|
|
1838
1838
|
let ps = new Group();
|
|
1839
|
-
let ts =
|
|
1840
|
-
let c =
|
|
1839
|
+
let ts = _Curve.getSteps(steps);
|
|
1840
|
+
let c = _Curve.controlPoints(_pts, 0, true);
|
|
1841
1841
|
for (let i = 0; i <= steps; i++) {
|
|
1842
|
-
ps.push(
|
|
1842
|
+
ps.push(_Curve.catmullRomStep(ts[i], c));
|
|
1843
1843
|
}
|
|
1844
1844
|
let k = 0;
|
|
1845
1845
|
while (k < _pts.length - 2) {
|
|
1846
|
-
let cp =
|
|
1846
|
+
let cp = _Curve.controlPoints(_pts, k);
|
|
1847
1847
|
if (cp.length > 0) {
|
|
1848
1848
|
for (let i = 0; i <= steps; i++) {
|
|
1849
|
-
ps.push(
|
|
1849
|
+
ps.push(_Curve.catmullRomStep(ts[i], cp));
|
|
1850
1850
|
}
|
|
1851
1851
|
k++;
|
|
1852
1852
|
}
|
|
@@ -1866,7 +1866,7 @@ var Curve = class {
|
|
|
1866
1866
|
new Pt(-1.5, 2, 0.5, 0),
|
|
1867
1867
|
new Pt(0.5, -0.5, 0, 0)
|
|
1868
1868
|
);
|
|
1869
|
-
return
|
|
1869
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
1870
1870
|
}
|
|
1871
1871
|
/**
|
|
1872
1872
|
* Create a Cardinal curve.
|
|
@@ -1880,17 +1880,17 @@ var Curve = class {
|
|
|
1880
1880
|
if (_pts.length < 2)
|
|
1881
1881
|
return new Group();
|
|
1882
1882
|
let ps = new Group();
|
|
1883
|
-
let ts =
|
|
1884
|
-
let c =
|
|
1883
|
+
let ts = _Curve.getSteps(steps);
|
|
1884
|
+
let c = _Curve.controlPoints(_pts, 0, true);
|
|
1885
1885
|
for (let i = 0; i <= steps; i++) {
|
|
1886
|
-
ps.push(
|
|
1886
|
+
ps.push(_Curve.cardinalStep(ts[i], c, tension));
|
|
1887
1887
|
}
|
|
1888
1888
|
let k = 0;
|
|
1889
1889
|
while (k < _pts.length - 2) {
|
|
1890
|
-
let cp =
|
|
1890
|
+
let cp = _Curve.controlPoints(_pts, k);
|
|
1891
1891
|
if (cp.length > 0) {
|
|
1892
1892
|
for (let i = 0; i <= steps; i++) {
|
|
1893
|
-
ps.push(
|
|
1893
|
+
ps.push(_Curve.cardinalStep(ts[i], cp, tension));
|
|
1894
1894
|
}
|
|
1895
1895
|
k++;
|
|
1896
1896
|
}
|
|
@@ -1914,7 +1914,7 @@ var Curve = class {
|
|
|
1914
1914
|
let h = Mat.multiply([step], m, true)[0].multiply(tension);
|
|
1915
1915
|
let h2 = 2 * step[0] - 3 * step[1] + 1;
|
|
1916
1916
|
let h3 = -2 * step[0] + 3 * step[1];
|
|
1917
|
-
let pt =
|
|
1917
|
+
let pt = _Curve._calcPt(ctrls, h);
|
|
1918
1918
|
pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;
|
|
1919
1919
|
pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;
|
|
1920
1920
|
if (pt.length > 2)
|
|
@@ -1932,13 +1932,13 @@ var Curve = class {
|
|
|
1932
1932
|
if (_pts.length < 4)
|
|
1933
1933
|
return new Group();
|
|
1934
1934
|
let ps = new Group();
|
|
1935
|
-
let ts =
|
|
1935
|
+
let ts = _Curve.getSteps(steps);
|
|
1936
1936
|
let k = 0;
|
|
1937
1937
|
while (k < _pts.length - 3) {
|
|
1938
|
-
let c =
|
|
1938
|
+
let c = _Curve.controlPoints(_pts, k);
|
|
1939
1939
|
if (c.length > 0) {
|
|
1940
1940
|
for (let i = 0; i <= steps; i++) {
|
|
1941
|
-
ps.push(
|
|
1941
|
+
ps.push(_Curve.bezierStep(ts[i], c));
|
|
1942
1942
|
}
|
|
1943
1943
|
k += 3;
|
|
1944
1944
|
}
|
|
@@ -1958,7 +1958,7 @@ var Curve = class {
|
|
|
1958
1958
|
new Pt(-3, 3, 0, 0),
|
|
1959
1959
|
new Pt(1, 0, 0, 0)
|
|
1960
1960
|
);
|
|
1961
|
-
return
|
|
1961
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
1962
1962
|
}
|
|
1963
1963
|
/**
|
|
1964
1964
|
* Create a basis spline (NURBS) curve.
|
|
@@ -1972,18 +1972,18 @@ var Curve = class {
|
|
|
1972
1972
|
if (_pts.length < 2)
|
|
1973
1973
|
return new Group();
|
|
1974
1974
|
let ps = new Group();
|
|
1975
|
-
let ts =
|
|
1975
|
+
let ts = _Curve.getSteps(steps);
|
|
1976
1976
|
let k = 0;
|
|
1977
1977
|
while (k < _pts.length - 3) {
|
|
1978
|
-
let c =
|
|
1978
|
+
let c = _Curve.controlPoints(_pts, k);
|
|
1979
1979
|
if (c.length > 0) {
|
|
1980
1980
|
if (tension !== 1) {
|
|
1981
1981
|
for (let i = 0; i <= steps; i++) {
|
|
1982
|
-
ps.push(
|
|
1982
|
+
ps.push(_Curve.bsplineTensionStep(ts[i], c, tension));
|
|
1983
1983
|
}
|
|
1984
1984
|
} else {
|
|
1985
1985
|
for (let i = 0; i <= steps; i++) {
|
|
1986
|
-
ps.push(
|
|
1986
|
+
ps.push(_Curve.bsplineStep(ts[i], c));
|
|
1987
1987
|
}
|
|
1988
1988
|
}
|
|
1989
1989
|
k++;
|
|
@@ -2004,7 +2004,7 @@ var Curve = class {
|
|
|
2004
2004
|
new Pt(-0.5, 0.5, 0.5, 0.16666666666666666),
|
|
2005
2005
|
new Pt(0.16666666666666666, 0, 0, 0)
|
|
2006
2006
|
);
|
|
2007
|
-
return
|
|
2007
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
2008
2008
|
}
|
|
2009
2009
|
/**
|
|
2010
2010
|
* Interpolate to get a point on a basis spline curve with tension.
|
|
@@ -2023,7 +2023,7 @@ var Curve = class {
|
|
|
2023
2023
|
let h = Mat.multiply([step], m, true)[0].multiply(tension);
|
|
2024
2024
|
let h2 = 2 * step[0] - 3 * step[1] + 1;
|
|
2025
2025
|
let h3 = -2 * step[0] + 3 * step[1];
|
|
2026
|
-
let pt =
|
|
2026
|
+
let pt = _Curve._calcPt(ctrls, h);
|
|
2027
2027
|
pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;
|
|
2028
2028
|
pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;
|
|
2029
2029
|
if (pt.length > 2)
|
|
@@ -2034,13 +2034,13 @@ var Curve = class {
|
|
|
2034
2034
|
|
|
2035
2035
|
// src/uheprng.ts
|
|
2036
2036
|
function Mash() {
|
|
2037
|
-
|
|
2038
|
-
|
|
2037
|
+
let n = 4022871197;
|
|
2038
|
+
let mash = function(data) {
|
|
2039
2039
|
if (data) {
|
|
2040
2040
|
data = data.toString();
|
|
2041
|
-
for (
|
|
2041
|
+
for (let i = 0; i < data.length; i++) {
|
|
2042
2042
|
n += data.charCodeAt(i);
|
|
2043
|
-
|
|
2043
|
+
let h = 0.02519603282416938 * n;
|
|
2044
2044
|
n = h >>> 0;
|
|
2045
2045
|
h -= n;
|
|
2046
2046
|
h *= n;
|
|
@@ -2055,12 +2055,12 @@ function Mash() {
|
|
|
2055
2055
|
return mash;
|
|
2056
2056
|
}
|
|
2057
2057
|
function uheprng_default(seed) {
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2058
|
+
let o = 48;
|
|
2059
|
+
let c = 1;
|
|
2060
|
+
let p = o;
|
|
2061
|
+
let s = new Array(o);
|
|
2062
|
+
let i, j, k = 0;
|
|
2063
|
+
let mash = Mash();
|
|
2064
2064
|
for (i = 0; i < o; i++)
|
|
2065
2065
|
s[i] = mash(Math.random().toString());
|
|
2066
2066
|
function initState() {
|
|
@@ -2092,24 +2092,24 @@ function uheprng_default(seed) {
|
|
|
2092
2092
|
hashString(seed);
|
|
2093
2093
|
return {
|
|
2094
2094
|
/**
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2095
|
+
* this (not anymore) PRIVATE (internal access only) function is the heart of the multiply-with-carry
|
|
2096
|
+
* (MWC) PRNG algorithm. When called it returns a pseudo-random number in the form of a
|
|
2097
|
+
* 32-bit JavaScript fraction (0.0 to <1.0) it is a PRIVATE function used by the default
|
|
2098
|
+
* [0-1] return function, and by the random 'string(n)' function which returns 'n'
|
|
2099
|
+
* characters from 33 to 126.
|
|
2100
|
+
* @returns a number between 0.0 and 1.0
|
|
2101
|
+
*/
|
|
2102
2102
|
random() {
|
|
2103
2103
|
if (++p >= o)
|
|
2104
2104
|
p = 0;
|
|
2105
|
-
|
|
2105
|
+
let t = 1768863 * s[p] + c * 23283064365386963e-26;
|
|
2106
2106
|
return s[p] = t - (c = t | 0);
|
|
2107
2107
|
}
|
|
2108
2108
|
};
|
|
2109
2109
|
}
|
|
2110
2110
|
|
|
2111
2111
|
// src/Num.ts
|
|
2112
|
-
var Num = class {
|
|
2112
|
+
var Num = class _Num {
|
|
2113
2113
|
/**
|
|
2114
2114
|
* Check if two numbers are equal or almost equal within a threshold.
|
|
2115
2115
|
* @param a number a
|
|
@@ -2145,7 +2145,7 @@ var Num = class {
|
|
|
2145
2145
|
* @example `boundValue(361, 0, 360)` will return 1
|
|
2146
2146
|
*/
|
|
2147
2147
|
static boundValue(val, min, max) {
|
|
2148
|
-
|
|
2148
|
+
const len = Math.abs(max - min);
|
|
2149
2149
|
let a = val % len;
|
|
2150
2150
|
if (a > max)
|
|
2151
2151
|
a -= len;
|
|
@@ -2168,8 +2168,8 @@ var Num = class {
|
|
|
2168
2168
|
* @param b range value 2
|
|
2169
2169
|
*/
|
|
2170
2170
|
static randomRange(a, b = 0) {
|
|
2171
|
-
|
|
2172
|
-
return a +
|
|
2171
|
+
const r = a > b ? a - b : b - a;
|
|
2172
|
+
return a + _Num.random() * r;
|
|
2173
2173
|
}
|
|
2174
2174
|
/**
|
|
2175
2175
|
* Get a random Pt within the range defined by either 1 or 2 Pt
|
|
@@ -2177,11 +2177,11 @@ var Num = class {
|
|
|
2177
2177
|
* @param b optional Pt to define the end of the range
|
|
2178
2178
|
*/
|
|
2179
2179
|
static randomPt(a, b) {
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2180
|
+
const p = new Pt(a.length);
|
|
2181
|
+
const range = b ? Vec.subtract(b.slice(), a) : a;
|
|
2182
|
+
const start = b ? a : new Pt(a.length).fill(0);
|
|
2183
2183
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
2184
|
-
p[i] =
|
|
2184
|
+
p[i] = _Num.random() * range[i] + start[i];
|
|
2185
2185
|
}
|
|
2186
2186
|
return p;
|
|
2187
2187
|
}
|
|
@@ -2192,8 +2192,8 @@ var Num = class {
|
|
|
2192
2192
|
* @param b range value 1
|
|
2193
2193
|
*/
|
|
2194
2194
|
static normalizeValue(n, a, b) {
|
|
2195
|
-
|
|
2196
|
-
|
|
2195
|
+
const min = Math.min(a, b);
|
|
2196
|
+
const max = Math.max(a, b);
|
|
2197
2197
|
return (n - min) / (max - min);
|
|
2198
2198
|
}
|
|
2199
2199
|
/**
|
|
@@ -2202,8 +2202,8 @@ var Num = class {
|
|
|
2202
2202
|
* @returns a Pt of the dimensional sums
|
|
2203
2203
|
*/
|
|
2204
2204
|
static sum(pts) {
|
|
2205
|
-
|
|
2206
|
-
|
|
2205
|
+
const _pts = Util.iterToArray(pts);
|
|
2206
|
+
const c = new Pt(_pts[0]);
|
|
2207
2207
|
for (let i = 1, len = _pts.length; i < len; i++) {
|
|
2208
2208
|
Vec.add(c, _pts[i]);
|
|
2209
2209
|
}
|
|
@@ -2215,8 +2215,8 @@ var Num = class {
|
|
|
2215
2215
|
* @returns a Pt of averages
|
|
2216
2216
|
*/
|
|
2217
2217
|
static average(pts) {
|
|
2218
|
-
|
|
2219
|
-
return
|
|
2218
|
+
const _pts = Util.iterToArray(pts);
|
|
2219
|
+
return _Num.sum(_pts).divide(_pts.length);
|
|
2220
2220
|
}
|
|
2221
2221
|
/**
|
|
2222
2222
|
* Given a value between 0 to 1, returns a value that cycles between 0 -> 1 -> 0 using the provided shaping method.
|
|
@@ -2239,9 +2239,9 @@ var Num = class {
|
|
|
2239
2239
|
static mapToRange(n, currA, currB, targetA, targetB) {
|
|
2240
2240
|
if (currA == currB)
|
|
2241
2241
|
throw new Error("[currMin, currMax] must define a range that is not zero");
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
return
|
|
2242
|
+
const min = Math.min(targetA, targetB);
|
|
2243
|
+
const max = Math.max(targetA, targetB);
|
|
2244
|
+
return _Num.normalizeValue(n, currA, currB) * (max - min) + min;
|
|
2245
2245
|
}
|
|
2246
2246
|
/**
|
|
2247
2247
|
* Seed the pseudorandom generator.
|
|
@@ -2259,7 +2259,7 @@ var Num = class {
|
|
|
2259
2259
|
return this.generator ? this.generator.random() : Math.random();
|
|
2260
2260
|
}
|
|
2261
2261
|
};
|
|
2262
|
-
var Geom = class {
|
|
2262
|
+
var Geom = class _Geom {
|
|
2263
2263
|
/**
|
|
2264
2264
|
* Bound an angle between 0 to 360 degrees.
|
|
2265
2265
|
* @param angle angle value
|
|
@@ -2295,7 +2295,7 @@ var Geom = class {
|
|
|
2295
2295
|
*/
|
|
2296
2296
|
static boundingBox(pts) {
|
|
2297
2297
|
let minPt, maxPt;
|
|
2298
|
-
for (
|
|
2298
|
+
for (const p of pts) {
|
|
2299
2299
|
if (minPt == void 0) {
|
|
2300
2300
|
minPt = p.clone();
|
|
2301
2301
|
maxPt = p.clone();
|
|
@@ -2321,9 +2321,9 @@ var Geom = class {
|
|
|
2321
2321
|
* @param direction a string either "to" (subtract all Pt with this anchor base), or "from" (add all Pt from this anchor base)
|
|
2322
2322
|
*/
|
|
2323
2323
|
static anchor(pts, ptOrIndex = 0, direction = "to") {
|
|
2324
|
-
|
|
2324
|
+
const method = direction == "to" ? "subtract" : "add";
|
|
2325
2325
|
let i = 0;
|
|
2326
|
-
for (
|
|
2326
|
+
for (const p of pts) {
|
|
2327
2327
|
if (typeof ptOrIndex == "number") {
|
|
2328
2328
|
if (ptOrIndex !== i)
|
|
2329
2329
|
p[method](pts[ptOrIndex]);
|
|
@@ -2341,8 +2341,8 @@ var Geom = class {
|
|
|
2341
2341
|
* @returns interpolated point as a new Pt
|
|
2342
2342
|
*/
|
|
2343
2343
|
static interpolate(a, b, t = 0.5) {
|
|
2344
|
-
|
|
2345
|
-
|
|
2344
|
+
const len = Math.min(a.length, b.length);
|
|
2345
|
+
const d = Pt.make(len);
|
|
2346
2346
|
for (let i = 0; i < len; i++) {
|
|
2347
2347
|
d[i] = a[i] * (1 - t) + b[i] * t;
|
|
2348
2348
|
}
|
|
@@ -2354,13 +2354,13 @@ var Geom = class {
|
|
|
2354
2354
|
* @returns an array of two Pt that are perpendicular to this Pt
|
|
2355
2355
|
*/
|
|
2356
2356
|
static perpendicular(pt, axis = Const.xy) {
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2357
|
+
const y = axis[1];
|
|
2358
|
+
const x = axis[0];
|
|
2359
|
+
const p = new Pt(pt);
|
|
2360
|
+
const pa = new Pt(p);
|
|
2361
2361
|
pa[x] = -p[y];
|
|
2362
2362
|
pa[y] = p[x];
|
|
2363
|
-
|
|
2363
|
+
const pb = new Pt(p);
|
|
2364
2364
|
pb[x] = p[y];
|
|
2365
2365
|
pb[y] = -p[x];
|
|
2366
2366
|
return new Group(pa, pb);
|
|
@@ -2389,14 +2389,14 @@ var Geom = class {
|
|
|
2389
2389
|
* @param pts a Group or an Iterable<Pt>
|
|
2390
2390
|
*/
|
|
2391
2391
|
static sortEdges(pts) {
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2392
|
+
const _pts = Util.iterToArray(pts);
|
|
2393
|
+
const bounds = _Geom.boundingBox(_pts);
|
|
2394
|
+
const center = bounds[1].add(bounds[0]).divide(2);
|
|
2395
|
+
const fn = (a, b) => {
|
|
2396
2396
|
if (a.length < 2 || b.length < 2)
|
|
2397
2397
|
throw new Error("Pt dimension cannot be less than 2");
|
|
2398
|
-
|
|
2399
|
-
|
|
2398
|
+
const da = a.$subtract(center);
|
|
2399
|
+
const db = b.$subtract(center);
|
|
2400
2400
|
if (da[0] >= 0 && db[0] < 0)
|
|
2401
2401
|
return 1;
|
|
2402
2402
|
if (da[0] < 0 && db[0] >= 0)
|
|
@@ -2406,7 +2406,7 @@ var Geom = class {
|
|
|
2406
2406
|
return da[1] > db[1] ? 1 : -1;
|
|
2407
2407
|
return db[1] > da[1] ? 1 : -1;
|
|
2408
2408
|
}
|
|
2409
|
-
|
|
2409
|
+
const det = da.$cross2D(db);
|
|
2410
2410
|
if (det < 0)
|
|
2411
2411
|
return 1;
|
|
2412
2412
|
if (det > 0)
|
|
@@ -2422,17 +2422,17 @@ var Geom = class {
|
|
|
2422
2422
|
* @param anchor optional anchor point to scale from
|
|
2423
2423
|
*/
|
|
2424
2424
|
static scale(ps, scale, anchor) {
|
|
2425
|
-
|
|
2426
|
-
|
|
2425
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2426
|
+
const scs = typeof scale == "number" ? Pt.make(pts[0].length, scale) : scale;
|
|
2427
2427
|
if (!anchor)
|
|
2428
2428
|
anchor = Pt.make(pts[0].length, 0);
|
|
2429
2429
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2430
|
-
|
|
2430
|
+
const p = pts[i];
|
|
2431
2431
|
for (let k = 0, lenP = p.length; k < lenP; k++) {
|
|
2432
2432
|
p[k] = anchor && anchor[k] ? anchor[k] + (p[k] - anchor[k]) * scs[k] : p[k] * scs[k];
|
|
2433
2433
|
}
|
|
2434
2434
|
}
|
|
2435
|
-
return
|
|
2435
|
+
return _Geom;
|
|
2436
2436
|
}
|
|
2437
2437
|
/**
|
|
2438
2438
|
* Rotate a Pt or a Group of Pts in 2D space. You may also use [`Pt.rotate2D`](#link) instance method.
|
|
@@ -2442,14 +2442,14 @@ var Geom = class {
|
|
|
2442
2442
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2443
2443
|
*/
|
|
2444
2444
|
static rotate2D(ps, angle, anchor, axis) {
|
|
2445
|
-
|
|
2446
|
-
|
|
2445
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2446
|
+
const fn = anchor ? Mat.rotateAt2DMatrix : Mat.rotate2DMatrix;
|
|
2447
2447
|
if (!anchor)
|
|
2448
2448
|
anchor = Pt.make(pts[0].length, 0);
|
|
2449
|
-
|
|
2450
|
-
|
|
2449
|
+
const cos = Math.cos(angle);
|
|
2450
|
+
const sin = Math.sin(angle);
|
|
2451
2451
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2452
|
-
|
|
2452
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2453
2453
|
p.to(Mat.transform2D(p, fn(cos, sin, anchor)));
|
|
2454
2454
|
if (axis) {
|
|
2455
2455
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2457,7 +2457,7 @@ var Geom = class {
|
|
|
2457
2457
|
}
|
|
2458
2458
|
}
|
|
2459
2459
|
}
|
|
2460
|
-
return
|
|
2460
|
+
return _Geom;
|
|
2461
2461
|
}
|
|
2462
2462
|
/**
|
|
2463
2463
|
* Shear a Pt or a Group of Pts in 2D space. You may also use [`Pt.shear2D`](#link) instance method.
|
|
@@ -2467,15 +2467,15 @@ var Geom = class {
|
|
|
2467
2467
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2468
2468
|
*/
|
|
2469
2469
|
static shear2D(ps, scale, anchor, axis) {
|
|
2470
|
-
|
|
2471
|
-
|
|
2470
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2471
|
+
const s = typeof scale == "number" ? [scale, scale] : scale;
|
|
2472
2472
|
if (!anchor)
|
|
2473
2473
|
anchor = Pt.make(pts[0].length, 0);
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2474
|
+
const fn = anchor ? Mat.shearAt2DMatrix : Mat.shear2DMatrix;
|
|
2475
|
+
const tanx = Math.tan(s[0]);
|
|
2476
|
+
const tany = Math.tan(s[1]);
|
|
2477
2477
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2478
|
-
|
|
2478
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2479
2479
|
p.to(Mat.transform2D(p, fn(tanx, tany, anchor)));
|
|
2480
2480
|
if (axis) {
|
|
2481
2481
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2483,7 +2483,7 @@ var Geom = class {
|
|
|
2483
2483
|
}
|
|
2484
2484
|
}
|
|
2485
2485
|
}
|
|
2486
|
-
return
|
|
2486
|
+
return _Geom;
|
|
2487
2487
|
}
|
|
2488
2488
|
/**
|
|
2489
2489
|
* Reflect a Pt or a Group of Pts along a 2D line. You may also use [`Pt.reflect2D`](#link) instance method.
|
|
@@ -2492,11 +2492,11 @@ var Geom = class {
|
|
|
2492
2492
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2493
2493
|
*/
|
|
2494
2494
|
static reflect2D(ps, line, axis) {
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2495
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2496
|
+
const _line = Util.iterToArray(line);
|
|
2497
|
+
const mat = Mat.reflectAt2DMatrix(_line[0], _line[1]);
|
|
2498
2498
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2499
|
-
|
|
2499
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2500
2500
|
p.to(Mat.transform2D(p, mat));
|
|
2501
2501
|
if (axis) {
|
|
2502
2502
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2504,17 +2504,17 @@ var Geom = class {
|
|
|
2504
2504
|
}
|
|
2505
2505
|
}
|
|
2506
2506
|
}
|
|
2507
|
-
return
|
|
2507
|
+
return _Geom;
|
|
2508
2508
|
}
|
|
2509
2509
|
/**
|
|
2510
2510
|
* Generate a cosine lookup table.
|
|
2511
2511
|
* @returns an object with a cosine tables (array of 360 values) and a function to get cosine given a radian input.
|
|
2512
2512
|
*/
|
|
2513
2513
|
static cosTable() {
|
|
2514
|
-
|
|
2514
|
+
const cos = new Float64Array(360);
|
|
2515
2515
|
for (let i = 0; i < 360; i++)
|
|
2516
2516
|
cos[i] = Math.cos(i * Math.PI / 180);
|
|
2517
|
-
|
|
2517
|
+
const find = (rad) => cos[Math.floor(_Geom.boundAngle(_Geom.toDegree(rad)))];
|
|
2518
2518
|
return { table: cos, cos: find };
|
|
2519
2519
|
}
|
|
2520
2520
|
/**
|
|
@@ -2522,14 +2522,14 @@ var Geom = class {
|
|
|
2522
2522
|
* @returns an object with a sine tables (array of 360 values) and a function to get sine value given a radian input.
|
|
2523
2523
|
*/
|
|
2524
2524
|
static sinTable() {
|
|
2525
|
-
|
|
2525
|
+
const sin = new Float64Array(360);
|
|
2526
2526
|
for (let i = 0; i < 360; i++)
|
|
2527
2527
|
sin[i] = Math.sin(i * Math.PI / 180);
|
|
2528
|
-
|
|
2528
|
+
const find = (rad) => sin[Math.floor(_Geom.boundAngle(_Geom.toDegree(rad)))];
|
|
2529
2529
|
return { table: sin, sin: find };
|
|
2530
2530
|
}
|
|
2531
2531
|
};
|
|
2532
|
-
var Shaping = class {
|
|
2532
|
+
var Shaping = class _Shaping {
|
|
2533
2533
|
/**
|
|
2534
2534
|
* Linear mapping.
|
|
2535
2535
|
* @param t a value between 0 to 1
|
|
@@ -2560,7 +2560,7 @@ var Shaping = class {
|
|
|
2560
2560
|
* @param c the value to shape, default is 1
|
|
2561
2561
|
*/
|
|
2562
2562
|
static quadraticInOut(t, c = 1) {
|
|
2563
|
-
|
|
2563
|
+
const dt = t * 2;
|
|
2564
2564
|
return t < 0.5 ? c / 2 * t * t * 4 : -c / 2 * ((dt - 1) * (dt - 3) - 1);
|
|
2565
2565
|
}
|
|
2566
2566
|
/**
|
|
@@ -2577,7 +2577,7 @@ var Shaping = class {
|
|
|
2577
2577
|
* @param c the value to shape, default is 1
|
|
2578
2578
|
*/
|
|
2579
2579
|
static cubicOut(t, c = 1) {
|
|
2580
|
-
|
|
2580
|
+
const dt = t - 1;
|
|
2581
2581
|
return c * (dt * dt * dt + 1);
|
|
2582
2582
|
}
|
|
2583
2583
|
/**
|
|
@@ -2586,7 +2586,7 @@ var Shaping = class {
|
|
|
2586
2586
|
* @param c the value to shape, default is 1
|
|
2587
2587
|
*/
|
|
2588
2588
|
static cubicInOut(t, c = 1) {
|
|
2589
|
-
|
|
2589
|
+
const dt = t * 2;
|
|
2590
2590
|
return t < 0.5 ? c / 2 * dt * dt * dt : c / 2 * ((dt - 2) * (dt - 2) * (dt - 2) + 2);
|
|
2591
2591
|
}
|
|
2592
2592
|
/**
|
|
@@ -2637,9 +2637,9 @@ var Shaping = class {
|
|
|
2637
2637
|
* @param c the value to shape, default is 1
|
|
2638
2638
|
*/
|
|
2639
2639
|
static cosineApprox(t, c = 1) {
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2640
|
+
const t2 = t * t;
|
|
2641
|
+
const t4 = t2 * t2;
|
|
2642
|
+
const t6 = t4 * t2;
|
|
2643
2643
|
return c * (4 * t6 / 9 - 17 * t4 / 9 + 22 * t2 / 9);
|
|
2644
2644
|
}
|
|
2645
2645
|
/**
|
|
@@ -2656,7 +2656,7 @@ var Shaping = class {
|
|
|
2656
2656
|
* @param c the value to shape, default is 1
|
|
2657
2657
|
*/
|
|
2658
2658
|
static circularOut(t, c = 1) {
|
|
2659
|
-
|
|
2659
|
+
const dt = t - 1;
|
|
2660
2660
|
return c * Math.sqrt(1 - dt * dt);
|
|
2661
2661
|
}
|
|
2662
2662
|
/**
|
|
@@ -2665,7 +2665,7 @@ var Shaping = class {
|
|
|
2665
2665
|
* @param c the value to shape, default is 1
|
|
2666
2666
|
*/
|
|
2667
2667
|
static circularInOut(t, c = 1) {
|
|
2668
|
-
|
|
2668
|
+
const dt = t * 2;
|
|
2669
2669
|
return t < 0.5 ? -c / 2 * (Math.sqrt(1 - dt * dt) - 1) : c / 2 * (Math.sqrt(1 - (dt - 2) * (dt - 2)) + 1);
|
|
2670
2670
|
}
|
|
2671
2671
|
/**
|
|
@@ -2675,8 +2675,8 @@ var Shaping = class {
|
|
|
2675
2675
|
* @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.
|
|
2676
2676
|
*/
|
|
2677
2677
|
static elasticIn(t, c = 1, p = 0.7) {
|
|
2678
|
-
|
|
2679
|
-
|
|
2678
|
+
const dt = t - 1;
|
|
2679
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2680
2680
|
return c * (-Math.pow(2, 10 * dt) * Math.sin((dt - s) * Const.two_pi / p));
|
|
2681
2681
|
}
|
|
2682
2682
|
/**
|
|
@@ -2686,7 +2686,7 @@ var Shaping = class {
|
|
|
2686
2686
|
* @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.
|
|
2687
2687
|
*/
|
|
2688
2688
|
static elasticOut(t, c = 1, p = 0.7) {
|
|
2689
|
-
|
|
2689
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2690
2690
|
return c * (Math.pow(2, -10 * t) * Math.sin((t - s) * Const.two_pi / p)) + c;
|
|
2691
2691
|
}
|
|
2692
2692
|
/**
|
|
@@ -2697,7 +2697,7 @@ var Shaping = class {
|
|
|
2697
2697
|
*/
|
|
2698
2698
|
static elasticInOut(t, c = 1, p = 0.6) {
|
|
2699
2699
|
let dt = t * 2;
|
|
2700
|
-
|
|
2700
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2701
2701
|
if (t < 0.5) {
|
|
2702
2702
|
dt -= 1;
|
|
2703
2703
|
return c * (-0.5 * (Math.pow(2, 10 * dt) * Math.sin((dt - s) * Const.two_pi / p)));
|
|
@@ -2712,7 +2712,7 @@ var Shaping = class {
|
|
|
2712
2712
|
* @param c the value to shape, default is 1
|
|
2713
2713
|
*/
|
|
2714
2714
|
static bounceIn(t, c = 1) {
|
|
2715
|
-
return c -
|
|
2715
|
+
return c - _Shaping.bounceOut(1 - t, c);
|
|
2716
2716
|
}
|
|
2717
2717
|
/**
|
|
2718
2718
|
* Bounce out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).
|
|
@@ -2739,7 +2739,7 @@ var Shaping = class {
|
|
|
2739
2739
|
* @param c the value to shape, default is 1
|
|
2740
2740
|
*/
|
|
2741
2741
|
static bounceInOut(t, c = 1) {
|
|
2742
|
-
return t < 0.5 ?
|
|
2742
|
+
return t < 0.5 ? _Shaping.bounceIn(t * 2, c) / 2 : _Shaping.bounceOut(t * 2 - 1, c) / 2 + c / 2;
|
|
2743
2743
|
}
|
|
2744
2744
|
/**
|
|
2745
2745
|
* Sigmoid curve changes its shape adapted from the input value, but always returns a value between 0 to 1.
|
|
@@ -2748,7 +2748,7 @@ var Shaping = class {
|
|
|
2748
2748
|
* @param p the larger the value, the "steeper" the curve will be. Default is 10.
|
|
2749
2749
|
*/
|
|
2750
2750
|
static sigmoid(t, c = 1, p = 10) {
|
|
2751
|
-
|
|
2751
|
+
const d = p * (t - 0.5);
|
|
2752
2752
|
return c / (1 + Math.exp(-d));
|
|
2753
2753
|
}
|
|
2754
2754
|
/**
|
|
@@ -2760,9 +2760,9 @@ var Shaping = class {
|
|
|
2760
2760
|
static logSigmoid(t, c = 1, p = 0.7) {
|
|
2761
2761
|
p = Math.max(Const.epsilon, Math.min(1 - Const.epsilon, p));
|
|
2762
2762
|
p = 1 / (1 - p);
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2763
|
+
const A = 1 / (1 + Math.exp((t - 0.5) * p * -2));
|
|
2764
|
+
const B = 1 / (1 + Math.exp(p));
|
|
2765
|
+
const C = 1 / (1 + Math.exp(-p));
|
|
2766
2766
|
return c * (A - B) / (C - B);
|
|
2767
2767
|
}
|
|
2768
2768
|
/**
|
|
@@ -2785,13 +2785,13 @@ var Shaping = class {
|
|
|
2785
2785
|
* @param p1 a Pt object specifying the first control Pt, or a value specifying the control Pt's x position (its y position will default to 0.5). Default is `Pt(0.95, 0.95)
|
|
2786
2786
|
*/
|
|
2787
2787
|
static quadraticBezier(t, c = 1, p = [0.05, 0.95]) {
|
|
2788
|
-
|
|
2789
|
-
|
|
2788
|
+
const a = typeof p != "number" ? p[0] : p;
|
|
2789
|
+
const b = typeof p != "number" ? p[1] : 0.5;
|
|
2790
2790
|
let om2a = 1 - 2 * a;
|
|
2791
2791
|
if (om2a === 0) {
|
|
2792
2792
|
om2a = Const.epsilon;
|
|
2793
2793
|
}
|
|
2794
|
-
|
|
2794
|
+
const d = (Math.sqrt(a * a + om2a * t) - a) / om2a;
|
|
2795
2795
|
return c * ((1 - 2 * b) * (d * d) + 2 * b * d);
|
|
2796
2796
|
}
|
|
2797
2797
|
/**
|
|
@@ -2802,7 +2802,7 @@ var Shaping = class {
|
|
|
2802
2802
|
* @param p2` a Pt object specifying the second control Pt. Default is `Pt(0.9, 0.2).
|
|
2803
2803
|
*/
|
|
2804
2804
|
static cubicBezier(t, c = 1, p1 = [0.1, 0.7], p2 = [0.9, 0.2]) {
|
|
2805
|
-
|
|
2805
|
+
const curve = new Group(new Pt(0, 0), new Pt(p1), new Pt(p2), new Pt(1, 1));
|
|
2806
2806
|
return c * Curve.bezierStep(new Pt(t * t * t, t * t, t, 1), Curve.controlPoints(curve)).y;
|
|
2807
2807
|
}
|
|
2808
2808
|
/**
|
|
@@ -2812,11 +2812,11 @@ var Shaping = class {
|
|
|
2812
2812
|
* @param p1` a Pt object specifying the Pt to pass through. Default is `Pt(0.2, 0.35)
|
|
2813
2813
|
*/
|
|
2814
2814
|
static quadraticTarget(t, c = 1, p1 = [0.2, 0.35]) {
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2815
|
+
const a = Math.min(1 - Const.epsilon, Math.max(Const.epsilon, p1[0]));
|
|
2816
|
+
const b = Math.min(1, Math.max(0, p1[1]));
|
|
2817
|
+
const A = (1 - b) / (1 - a) - b / a;
|
|
2818
|
+
const B = (A * (a * a) - b) / a;
|
|
2819
|
+
const y = A * (t * t) - B * t;
|
|
2820
2820
|
return c * Math.min(1, Math.max(0, y));
|
|
2821
2821
|
}
|
|
2822
2822
|
/**
|
|
@@ -2837,8 +2837,8 @@ var Shaping = class {
|
|
|
2837
2837
|
* @param args optional paramters to pass to original function
|
|
2838
2838
|
*/
|
|
2839
2839
|
static step(fn, steps, t, c, ...args) {
|
|
2840
|
-
|
|
2841
|
-
|
|
2840
|
+
const s = 1 / steps;
|
|
2841
|
+
const tt = Math.floor(t / s) * s;
|
|
2842
2842
|
return fn(tt, c, ...args);
|
|
2843
2843
|
}
|
|
2844
2844
|
};
|
|
@@ -2876,16 +2876,16 @@ var Range = class {
|
|
|
2876
2876
|
calc() {
|
|
2877
2877
|
if (!this._source)
|
|
2878
2878
|
return;
|
|
2879
|
-
|
|
2879
|
+
const dims = this._source[0].length;
|
|
2880
2880
|
this._dims = dims;
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2881
|
+
const max = new Pt(dims);
|
|
2882
|
+
const min = new Pt(dims);
|
|
2883
|
+
const mag = new Pt(dims);
|
|
2884
2884
|
for (let i = 0; i < dims; i++) {
|
|
2885
2885
|
max[i] = Const.min;
|
|
2886
2886
|
min[i] = Const.max;
|
|
2887
2887
|
mag[i] = 0;
|
|
2888
|
-
|
|
2888
|
+
const s = this._source.zipSlice(i);
|
|
2889
2889
|
for (let k = 0, len = s.length; k < len; k++) {
|
|
2890
2890
|
max[i] = Math.max(max[i], s[k]);
|
|
2891
2891
|
min[i] = Math.min(min[i], s[k]);
|
|
@@ -2904,10 +2904,10 @@ var Range = class {
|
|
|
2904
2904
|
* @param exclude Optional boolean array where `true` means excluding the conversion in that specific dimension.
|
|
2905
2905
|
*/
|
|
2906
2906
|
mapTo(min, max, exclude) {
|
|
2907
|
-
|
|
2907
|
+
const target = new Group();
|
|
2908
2908
|
for (let i = 0, len = this._source.length; i < len; i++) {
|
|
2909
|
-
|
|
2910
|
-
|
|
2909
|
+
const g = this._source[i];
|
|
2910
|
+
const n = new Pt(this._dims);
|
|
2911
2911
|
for (let k = 0; k < this._dims; k++) {
|
|
2912
2912
|
n[k] = exclude && exclude[k] ? g[k] : Num.mapToRange(g[k], this._min[k], this._max[k], min, max);
|
|
2913
2913
|
}
|
|
@@ -2921,7 +2921,7 @@ var Range = class {
|
|
|
2921
2921
|
* @param update Optional. Set the parameter to `false` if you want to append without immediately updating this Range's min and max values. Default is `true`.
|
|
2922
2922
|
*/
|
|
2923
2923
|
append(pts, update = true) {
|
|
2924
|
-
|
|
2924
|
+
const _pts = Util.iterToArray(pts);
|
|
2925
2925
|
if (_pts[0].length !== this._dims)
|
|
2926
2926
|
throw new Error(`Dimensions don't match. ${this._dims} dimensions in Range and ${_pts[0].length} provided in parameter. `);
|
|
2927
2927
|
this._source = this._source.concat(_pts);
|
|
@@ -2934,9 +2934,9 @@ var Range = class {
|
|
|
2934
2934
|
* @param count number of subdivision. For example, 10 subdivision will return 11 tick values, which include first(min) and last(max) values.
|
|
2935
2935
|
*/
|
|
2936
2936
|
ticks(count) {
|
|
2937
|
-
|
|
2937
|
+
const g = new Group();
|
|
2938
2938
|
for (let i = 0; i <= count; i++) {
|
|
2939
|
-
|
|
2939
|
+
const p = new Pt(this._dims);
|
|
2940
2940
|
for (let k = 0, len = this._max.length; k < len; k++) {
|
|
2941
2941
|
p[k] = Num.lerp(this._min[k], this._max[k], i / count);
|
|
2942
2942
|
}
|
|
@@ -3005,7 +3005,7 @@ var Const = {
|
|
|
3005
3005
|
/** Gaussian constant (1 / Math.sqrt(2 * Math.PI)) */
|
|
3006
3006
|
gaussian: 0.3989422804014327
|
|
3007
3007
|
};
|
|
3008
|
-
var _Util = class {
|
|
3008
|
+
var _Util = class _Util {
|
|
3009
3009
|
/**
|
|
3010
3010
|
* Set a global warning level setting. If no parameter is passed, this will return the current warn-level. See [`Util.warn`](#link).
|
|
3011
3011
|
* @param lv a [`WarningType`](#link) option, where "error" will throw an error, "warn" will log in console, and "mute" will ignore the error.
|
|
@@ -3100,7 +3100,7 @@ var _Util = class {
|
|
|
3100
3100
|
* @param flattenAsGroup a boolean to specify whether the return type should be a Group or Array. Default is `true` which returns a Group.
|
|
3101
3101
|
*/
|
|
3102
3102
|
static flatten(pts, flattenAsGroup = true) {
|
|
3103
|
-
let arr = flattenAsGroup ? new Group() :
|
|
3103
|
+
let arr = flattenAsGroup ? new Group() : [];
|
|
3104
3104
|
return arr.concat.apply(arr, pts);
|
|
3105
3105
|
}
|
|
3106
3106
|
/**
|
|
@@ -3173,7 +3173,7 @@ var _Util = class {
|
|
|
3173
3173
|
* @param callback a function to capture the data. It receives two parameters: a `response` as string, and a `success` status as boolean.
|
|
3174
3174
|
*/
|
|
3175
3175
|
static load(url, callback) {
|
|
3176
|
-
|
|
3176
|
+
let request = new XMLHttpRequest();
|
|
3177
3177
|
request.open("GET", url, true);
|
|
3178
3178
|
request.onload = function() {
|
|
3179
3179
|
if (request.status >= 200 && request.status < 400) {
|
|
@@ -3251,11 +3251,11 @@ var _Util = class {
|
|
|
3251
3251
|
return /iPhone|iPad|Android/i.test(navigator.userAgent);
|
|
3252
3252
|
}
|
|
3253
3253
|
};
|
|
3254
|
+
_Util._warnLevel = "mute";
|
|
3254
3255
|
var Util = _Util;
|
|
3255
|
-
Util._warnLevel = "mute";
|
|
3256
3256
|
|
|
3257
3257
|
// src/Pt.ts
|
|
3258
|
-
var Pt = class extends Float32Array {
|
|
3258
|
+
var Pt = class _Pt extends Float32Array {
|
|
3259
3259
|
/**
|
|
3260
3260
|
* Create a Pt. If no parameter is provided, this will instantiate a Pt with 2 dimensions [0, 0].
|
|
3261
3261
|
* Note that `new Pt(3)` will only instantiate Pt with length of 3 (ie, same as `new Float32Array(3)` ). If you need a Pt with 1 dimension of value 3, use `new Pt([3])`.
|
|
@@ -3278,7 +3278,7 @@ var Pt = class extends Float32Array {
|
|
|
3278
3278
|
* @param randomize if `true`, randomize the value between 0 to default value
|
|
3279
3279
|
*/
|
|
3280
3280
|
static make(dimensions, defaultValue = 0, randomize = false) {
|
|
3281
|
-
|
|
3281
|
+
const p = new Float32Array(dimensions);
|
|
3282
3282
|
if (defaultValue)
|
|
3283
3283
|
p.fill(defaultValue);
|
|
3284
3284
|
if (randomize) {
|
|
@@ -3286,7 +3286,7 @@ var Pt = class extends Float32Array {
|
|
|
3286
3286
|
p[i] = p[i] * Num.random();
|
|
3287
3287
|
}
|
|
3288
3288
|
}
|
|
3289
|
-
return new
|
|
3289
|
+
return new _Pt(p);
|
|
3290
3290
|
}
|
|
3291
3291
|
/**
|
|
3292
3292
|
* ID string of this Pt
|
|
@@ -3337,7 +3337,7 @@ var Pt = class extends Float32Array {
|
|
|
3337
3337
|
* Clone this Pt and return it as a new Pt.
|
|
3338
3338
|
*/
|
|
3339
3339
|
clone() {
|
|
3340
|
-
return new
|
|
3340
|
+
return new _Pt(this);
|
|
3341
3341
|
}
|
|
3342
3342
|
/**
|
|
3343
3343
|
* Check if another Pt is equal to this Pt, within a threshold.
|
|
@@ -3356,7 +3356,7 @@ var Pt = class extends Float32Array {
|
|
|
3356
3356
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3357
3357
|
*/
|
|
3358
3358
|
to(...args) {
|
|
3359
|
-
|
|
3359
|
+
const p = Util.getArgs(args);
|
|
3360
3360
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3361
3361
|
this[i] = p[i];
|
|
3362
3362
|
}
|
|
@@ -3376,8 +3376,8 @@ var Pt = class extends Float32Array {
|
|
|
3376
3376
|
* @param anchorFromPt If `true`, add it from this Pt's current position. Default is `false` which update the position from origin (0,0). See also [`Geom.rotate2D`](#link) for rotating a point from another anchor point.
|
|
3377
3377
|
*/
|
|
3378
3378
|
toAngle(radian, magnitude, anchorFromPt = false) {
|
|
3379
|
-
|
|
3380
|
-
|
|
3379
|
+
const m = magnitude != void 0 ? magnitude : this.magnitude();
|
|
3380
|
+
const change = [Math.cos(radian) * m, Math.sin(radian) * m];
|
|
3381
3381
|
return anchorFromPt ? this.add(change) : this.to(change);
|
|
3382
3382
|
}
|
|
3383
3383
|
/**
|
|
@@ -3387,7 +3387,7 @@ var Pt = class extends Float32Array {
|
|
|
3387
3387
|
* @returns a resulting function that takes other parameters required in `fn`
|
|
3388
3388
|
*/
|
|
3389
3389
|
op(fn) {
|
|
3390
|
-
|
|
3390
|
+
const self = this;
|
|
3391
3391
|
return (...params) => {
|
|
3392
3392
|
return fn(self, ...params);
|
|
3393
3393
|
};
|
|
@@ -3399,7 +3399,7 @@ var Pt = class extends Float32Array {
|
|
|
3399
3399
|
* @returns an array of resulting functions
|
|
3400
3400
|
*/
|
|
3401
3401
|
ops(fns) {
|
|
3402
|
-
|
|
3402
|
+
const _ops = [];
|
|
3403
3403
|
for (let i = 0, len = fns.length; i < len; i++) {
|
|
3404
3404
|
_ops.push(this.op(fns[i]));
|
|
3405
3405
|
}
|
|
@@ -3410,18 +3410,18 @@ var Pt = class extends Float32Array {
|
|
|
3410
3410
|
* @param axis a string such as "xy" (use Const.xy) or an array to specify indices
|
|
3411
3411
|
*/
|
|
3412
3412
|
$take(axis) {
|
|
3413
|
-
|
|
3413
|
+
const p = [];
|
|
3414
3414
|
for (let i = 0, len = axis.length; i < len; i++) {
|
|
3415
3415
|
p.push(this[axis[i]] || 0);
|
|
3416
3416
|
}
|
|
3417
|
-
return new
|
|
3417
|
+
return new _Pt(p);
|
|
3418
3418
|
}
|
|
3419
3419
|
/**
|
|
3420
3420
|
* Concatenate this Pt with addition dimensional values and return as a new Pt.
|
|
3421
3421
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3422
3422
|
*/
|
|
3423
3423
|
$concat(...args) {
|
|
3424
|
-
return new
|
|
3424
|
+
return new _Pt(this.toArray().concat(Util.getArgs(args)));
|
|
3425
3425
|
}
|
|
3426
3426
|
/**
|
|
3427
3427
|
* Add scalar or vector values to this Pt.
|
|
@@ -3616,8 +3616,8 @@ var Pt = class extends Float32Array {
|
|
|
3616
3616
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3617
3617
|
*/
|
|
3618
3618
|
$min(...args) {
|
|
3619
|
-
|
|
3620
|
-
|
|
3619
|
+
const p = Util.getArgs(args);
|
|
3620
|
+
const m = this.clone();
|
|
3621
3621
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3622
3622
|
m[i] = Math.min(this[i], p[i]);
|
|
3623
3623
|
}
|
|
@@ -3628,8 +3628,8 @@ var Pt = class extends Float32Array {
|
|
|
3628
3628
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3629
3629
|
*/
|
|
3630
3630
|
$max(...args) {
|
|
3631
|
-
|
|
3632
|
-
|
|
3631
|
+
const p = Util.getArgs(args);
|
|
3632
|
+
const m = this.clone();
|
|
3633
3633
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3634
3634
|
m[i] = Math.max(this[i], p[i]);
|
|
3635
3635
|
}
|
|
@@ -3656,7 +3656,7 @@ var Pt = class extends Float32Array {
|
|
|
3656
3656
|
* @param anchor optional anchor point to scale from
|
|
3657
3657
|
*/
|
|
3658
3658
|
scale(scale, anchor) {
|
|
3659
|
-
Geom.scale(this, scale, anchor ||
|
|
3659
|
+
Geom.scale(this, scale, anchor || _Pt.make(this.length, 0));
|
|
3660
3660
|
return this;
|
|
3661
3661
|
}
|
|
3662
3662
|
/**
|
|
@@ -3666,7 +3666,7 @@ var Pt = class extends Float32Array {
|
|
|
3666
3666
|
* @param axis optional string such as "yz" to specify a 2D plane
|
|
3667
3667
|
*/
|
|
3668
3668
|
rotate2D(angle, anchor, axis) {
|
|
3669
|
-
Geom.rotate2D(this, angle, anchor ||
|
|
3669
|
+
Geom.rotate2D(this, angle, anchor || _Pt.make(this.length, 0), axis);
|
|
3670
3670
|
return this;
|
|
3671
3671
|
}
|
|
3672
3672
|
/**
|
|
@@ -3676,7 +3676,7 @@ var Pt = class extends Float32Array {
|
|
|
3676
3676
|
* @param axis optional string such as "yz" to specify a 2D plane
|
|
3677
3677
|
*/
|
|
3678
3678
|
shear2D(scale, anchor, axis) {
|
|
3679
|
-
Geom.shear2D(this, scale, anchor ||
|
|
3679
|
+
Geom.shear2D(this, scale, anchor || _Pt.make(this.length, 0), axis);
|
|
3680
3680
|
return this;
|
|
3681
3681
|
}
|
|
3682
3682
|
/**
|
|
@@ -3704,16 +3704,16 @@ var Pt = class extends Float32Array {
|
|
|
3704
3704
|
* Convert this Pt to a Group as new Group([0,...], pt)
|
|
3705
3705
|
*/
|
|
3706
3706
|
toGroup() {
|
|
3707
|
-
return new Group(
|
|
3707
|
+
return new Group(_Pt.make(this.length), this.clone());
|
|
3708
3708
|
}
|
|
3709
3709
|
/**
|
|
3710
3710
|
* Convert this Pt to a Bound as new Group([0,...], pt)
|
|
3711
3711
|
*/
|
|
3712
3712
|
toBound() {
|
|
3713
|
-
return new Bound(
|
|
3713
|
+
return new Bound(_Pt.make(this.length), this.clone());
|
|
3714
3714
|
}
|
|
3715
3715
|
};
|
|
3716
|
-
var Group = class extends Array {
|
|
3716
|
+
var Group = class _Group extends Array {
|
|
3717
3717
|
/**
|
|
3718
3718
|
* Create a Group by passing an array of [`Pt`](#link). You may also create a Group using [`Group.fromArray`](#link) or [`Group.fromPtArray`](#link).
|
|
3719
3719
|
* @param args an array of Pts
|
|
@@ -3782,7 +3782,7 @@ var Group = class extends Array {
|
|
|
3782
3782
|
* Depp clone this group and its Pts.
|
|
3783
3783
|
*/
|
|
3784
3784
|
clone() {
|
|
3785
|
-
|
|
3785
|
+
const group = new _Group();
|
|
3786
3786
|
for (let i = 0, len = this.length; i < len; i++) {
|
|
3787
3787
|
group.push(this[i].clone());
|
|
3788
3788
|
}
|
|
@@ -3794,9 +3794,9 @@ var Group = class extends Array {
|
|
|
3794
3794
|
* @example `Group.fromArray( [[1,2], [3,4], [5,6]] )`
|
|
3795
3795
|
*/
|
|
3796
3796
|
static fromArray(list) {
|
|
3797
|
-
|
|
3798
|
-
for (
|
|
3799
|
-
|
|
3797
|
+
const g = new _Group();
|
|
3798
|
+
for (const li of list) {
|
|
3799
|
+
const p = li instanceof Pt ? li : new Pt(li);
|
|
3800
3800
|
g.push(p);
|
|
3801
3801
|
}
|
|
3802
3802
|
return g;
|
|
@@ -3806,7 +3806,7 @@ var Group = class extends Array {
|
|
|
3806
3806
|
* @param list an Iterable<Pt>
|
|
3807
3807
|
*/
|
|
3808
3808
|
static fromPtArray(list) {
|
|
3809
|
-
return
|
|
3809
|
+
return _Group.from(list);
|
|
3810
3810
|
}
|
|
3811
3811
|
/**
|
|
3812
3812
|
* Split this Group into an array of sub-groups.
|
|
@@ -3815,7 +3815,7 @@ var Group = class extends Array {
|
|
|
3815
3815
|
* @param loopBack if `true`, always go through the array till the end and loop back to the beginning to complete the segments if needed
|
|
3816
3816
|
*/
|
|
3817
3817
|
split(chunkSize, stride, loopBack = false) {
|
|
3818
|
-
|
|
3818
|
+
const sp = Util.split(this, chunkSize, stride, loopBack);
|
|
3819
3819
|
return sp;
|
|
3820
3820
|
}
|
|
3821
3821
|
/**
|
|
@@ -3824,7 +3824,7 @@ var Group = class extends Array {
|
|
|
3824
3824
|
* @param index the index position to insert into
|
|
3825
3825
|
*/
|
|
3826
3826
|
insert(pts, index = 0) {
|
|
3827
|
-
|
|
3827
|
+
_Group.prototype.splice.apply(this, [index, 0, ...pts]);
|
|
3828
3828
|
return this;
|
|
3829
3829
|
}
|
|
3830
3830
|
/**
|
|
@@ -3834,8 +3834,8 @@ var Group = class extends Array {
|
|
|
3834
3834
|
* @returns The items that are removed.
|
|
3835
3835
|
*/
|
|
3836
3836
|
remove(index = 0, count = 1) {
|
|
3837
|
-
|
|
3838
|
-
return
|
|
3837
|
+
const param = index < 0 ? [index * -1 - 1, count] : [index, count];
|
|
3838
|
+
return _Group.prototype.splice.apply(this, param);
|
|
3839
3839
|
}
|
|
3840
3840
|
/**
|
|
3841
3841
|
* Split this group into an array of sub-group segments.
|
|
@@ -3886,7 +3886,7 @@ var Group = class extends Array {
|
|
|
3886
3886
|
* @returns a resulting function that takes other parameters required in `fn`
|
|
3887
3887
|
*/
|
|
3888
3888
|
op(fn) {
|
|
3889
|
-
|
|
3889
|
+
const self = this;
|
|
3890
3890
|
return (...params) => {
|
|
3891
3891
|
return fn(self, ...params);
|
|
3892
3892
|
};
|
|
@@ -3898,7 +3898,7 @@ var Group = class extends Array {
|
|
|
3898
3898
|
* @returns an array of resulting functions
|
|
3899
3899
|
*/
|
|
3900
3900
|
ops(fns) {
|
|
3901
|
-
|
|
3901
|
+
const _ops = [];
|
|
3902
3902
|
for (let i = 0, len = fns.length; i < len; i++) {
|
|
3903
3903
|
_ops.push(this.op(fns[i]));
|
|
3904
3904
|
}
|
|
@@ -3910,9 +3910,9 @@ var Group = class extends Array {
|
|
|
3910
3910
|
*/
|
|
3911
3911
|
interpolate(t) {
|
|
3912
3912
|
t = Num.clamp(t, 0, 1);
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3913
|
+
const chunk = this.length - 1;
|
|
3914
|
+
const tc = 1 / (this.length - 1);
|
|
3915
|
+
const idx = Math.floor(t / tc);
|
|
3916
3916
|
return Geom.interpolate(this[idx], this[Math.min(this.length - 1, idx + 1)], (t - idx * tc) * chunk);
|
|
3917
3917
|
}
|
|
3918
3918
|
/**
|
|
@@ -3927,7 +3927,7 @@ var Group = class extends Array {
|
|
|
3927
3927
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3928
3928
|
*/
|
|
3929
3929
|
moveTo(...args) {
|
|
3930
|
-
|
|
3930
|
+
const d = new Pt(Util.getArgs(args)).subtract(this[0]);
|
|
3931
3931
|
this.moveBy(d);
|
|
3932
3932
|
return this;
|
|
3933
3933
|
}
|
|
@@ -4075,7 +4075,7 @@ var Group = class extends Array {
|
|
|
4075
4075
|
return "Group[ " + this.reduce((p, c) => p + c.toString() + " ", "") + " ]";
|
|
4076
4076
|
}
|
|
4077
4077
|
};
|
|
4078
|
-
var Bound = class extends Group {
|
|
4078
|
+
var Bound = class _Bound extends Group {
|
|
4079
4079
|
/**
|
|
4080
4080
|
* Create a Bound. This is similar to the Group constructor. You can also create a Bound via the static function [`Bound.fromGroup`](#link), or alternatively via the [Group.toBound](#link) function.
|
|
4081
4081
|
* @param args a list of Pt as parameters
|
|
@@ -4096,7 +4096,7 @@ var Bound = class extends Group {
|
|
|
4096
4096
|
* @returns a Bound object
|
|
4097
4097
|
*/
|
|
4098
4098
|
static fromBoundingRect(rect) {
|
|
4099
|
-
|
|
4099
|
+
const b = new _Bound(new Pt(rect.left || 0, rect.top || 0), new Pt(rect.right || 0, rect.bottom || 0));
|
|
4100
4100
|
if (rect.width && rect.height)
|
|
4101
4101
|
b.size = new Pt(rect.width, rect.height);
|
|
4102
4102
|
return b;
|
|
@@ -4106,10 +4106,10 @@ var Bound = class extends Group {
|
|
|
4106
4106
|
* @param g a Group or an Iterable<PtLike>
|
|
4107
4107
|
*/
|
|
4108
4108
|
static fromGroup(g) {
|
|
4109
|
-
|
|
4109
|
+
const _g = Util.iterToArray(g);
|
|
4110
4110
|
if (_g.length < 2)
|
|
4111
4111
|
throw new Error("Cannot create a Bound from a group that has less than 2 Pt");
|
|
4112
|
-
return new
|
|
4112
|
+
return new _Bound(_g[0], _g[_g.length - 1]);
|
|
4113
4113
|
}
|
|
4114
4114
|
/**
|
|
4115
4115
|
* Initiate the bound's properties.
|
|
@@ -4120,8 +4120,8 @@ var Bound = class extends Group {
|
|
|
4120
4120
|
this._inited = true;
|
|
4121
4121
|
}
|
|
4122
4122
|
if (this.p1 && this.p2) {
|
|
4123
|
-
|
|
4124
|
-
|
|
4123
|
+
const a = this.p1;
|
|
4124
|
+
const b = this.p2;
|
|
4125
4125
|
this.topLeft = a.$min(b);
|
|
4126
4126
|
this._bottomRight = a.$max(b);
|
|
4127
4127
|
this._updateSize();
|
|
@@ -4132,7 +4132,7 @@ var Bound = class extends Group {
|
|
|
4132
4132
|
* Clone this bound and return a new one.
|
|
4133
4133
|
*/
|
|
4134
4134
|
clone() {
|
|
4135
|
-
return new
|
|
4135
|
+
return new _Bound(this._topLeft.clone(), this._bottomRight.clone());
|
|
4136
4136
|
}
|
|
4137
4137
|
/**
|
|
4138
4138
|
* Recalculte size and center.
|
|
@@ -4165,7 +4165,7 @@ var Bound = class extends Group {
|
|
|
4165
4165
|
* Recalculate based on center position and size.
|
|
4166
4166
|
*/
|
|
4167
4167
|
_updatePosFromCenter() {
|
|
4168
|
-
|
|
4168
|
+
const half = this._size.$multiply(0.5);
|
|
4169
4169
|
this._topLeft = this._center.$subtract(half);
|
|
4170
4170
|
this._bottomRight = this._center.$add(half);
|
|
4171
4171
|
}
|
|
@@ -4305,7 +4305,7 @@ var UIPointerActions = {
|
|
|
4305
4305
|
contextmenu: "contextmenu",
|
|
4306
4306
|
all: "all"
|
|
4307
4307
|
};
|
|
4308
|
-
var _UI = class {
|
|
4308
|
+
var _UI = class _UI {
|
|
4309
4309
|
/**
|
|
4310
4310
|
* Create an UI element. You may also create a new UI using one of the static helper like [`UI.fromRectangle`](#link) or [`UI.fromCircle`](#link).
|
|
4311
4311
|
* @param group a Group or an Iterable<PtLike> that defines the UI's appearance
|
|
@@ -4541,8 +4541,8 @@ var _UI = class {
|
|
|
4541
4541
|
}
|
|
4542
4542
|
}
|
|
4543
4543
|
};
|
|
4544
|
+
_UI._counter = 0;
|
|
4544
4545
|
var UI = _UI;
|
|
4545
|
-
UI._counter = 0;
|
|
4546
4546
|
var UIButton = class extends UI {
|
|
4547
4547
|
/**
|
|
4548
4548
|
* Create an UIButton. A button has 2 states, "clicks" (number) and "hover" (boolean), which you can access through [`UI.state`](#link) function. You may also create a new UIButton using one of the static helper like [`UI.fromRectangle`](#link) or [`UI.fromCircle`](#link).
|
|
@@ -4567,7 +4567,7 @@ var UIButton = class extends UI {
|
|
|
4567
4567
|
if (hover && !this._states.hover) {
|
|
4568
4568
|
this.state("hover", true);
|
|
4569
4569
|
UI._trigger(this._actions[UA.enter], this, pt, UA.enter, evt);
|
|
4570
|
-
|
|
4570
|
+
let _capID = this.hold(UA.move);
|
|
4571
4571
|
this._hoverID = this.on(UA.move, (t, p) => {
|
|
4572
4572
|
if (!this._within(p) && !this.state("dragging")) {
|
|
4573
4573
|
this.state("hover", false);
|
|
@@ -4618,7 +4618,7 @@ var UIButton = class extends UI {
|
|
|
4618
4618
|
* @returns id numbers that refer to enter/leave handlers, for use in [`UIButton.offHover`](#link) or [`UI.off`](#link).
|
|
4619
4619
|
*/
|
|
4620
4620
|
onHover(enter, leave) {
|
|
4621
|
-
|
|
4621
|
+
let ids = [void 0, void 0];
|
|
4622
4622
|
if (enter)
|
|
4623
4623
|
ids[0] = this.on(UIPointerActions.enter, enter);
|
|
4624
4624
|
if (leave)
|
|
@@ -4632,7 +4632,7 @@ var UIButton = class extends UI {
|
|
|
4632
4632
|
* @returns an array of booleans indicating whether the handlers were removed successfully
|
|
4633
4633
|
*/
|
|
4634
4634
|
offHover(enterID, leaveID) {
|
|
4635
|
-
|
|
4635
|
+
let s = [false, false];
|
|
4636
4636
|
if (enterID === void 0 || enterID >= 0)
|
|
4637
4637
|
s[0] = this.off(UIPointerActions.enter, enterID);
|
|
4638
4638
|
if (leaveID === void 0 || leaveID >= 0)
|
|
@@ -4775,9 +4775,9 @@ var Space = class {
|
|
|
4775
4775
|
* @param player an [`IPlayer`](#link) object with animate function, or a callback function `fn(time, ftime)`.
|
|
4776
4776
|
*/
|
|
4777
4777
|
add(p) {
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4778
|
+
const player = typeof p == "function" ? { animate: p } : p;
|
|
4779
|
+
const k = this.playerCount++;
|
|
4780
|
+
const pid = player.animateID || this.id + k;
|
|
4781
4781
|
this.players[pid] = player;
|
|
4782
4782
|
player.animateID = pid;
|
|
4783
4783
|
if (player.resize && this.bound.inited)
|
|
@@ -4844,7 +4844,7 @@ var Space = class {
|
|
|
4844
4844
|
if (this._refresh)
|
|
4845
4845
|
this.clear();
|
|
4846
4846
|
if (this._isReady) {
|
|
4847
|
-
for (
|
|
4847
|
+
for (const k in this.players) {
|
|
4848
4848
|
if (this.players[k].animate)
|
|
4849
4849
|
this.players[k].animate(time, this._time.diff, this);
|
|
4850
4850
|
}
|
|
@@ -4962,7 +4962,7 @@ var MultiTouchSpace = class extends Space {
|
|
|
4962
4962
|
* Get the mouse or touch pointer that stores the last action.
|
|
4963
4963
|
*/
|
|
4964
4964
|
get pointer() {
|
|
4965
|
-
|
|
4965
|
+
const p = this._pointer.clone();
|
|
4966
4966
|
p.id = this._pointer.id;
|
|
4967
4967
|
return p;
|
|
4968
4968
|
}
|
|
@@ -5089,9 +5089,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5089
5089
|
touchesToPoints(evt, which = "touches") {
|
|
5090
5090
|
if (!evt || !evt[which])
|
|
5091
5091
|
return [];
|
|
5092
|
-
|
|
5093
|
-
for (
|
|
5094
|
-
|
|
5092
|
+
const ts = [];
|
|
5093
|
+
for (let i = 0; i < evt[which].length; i++) {
|
|
5094
|
+
const t = evt[which].item(i);
|
|
5095
5095
|
ts.push(new Pt(t.pageX - this.bound.topLeft.x, t.pageY - this.bound.topLeft.y));
|
|
5096
5096
|
}
|
|
5097
5097
|
return ts;
|
|
@@ -5107,9 +5107,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5107
5107
|
return;
|
|
5108
5108
|
let px = 0, py = 0;
|
|
5109
5109
|
if (evt instanceof MouseEvent) {
|
|
5110
|
-
for (
|
|
5110
|
+
for (const k in this.players) {
|
|
5111
5111
|
if (this.players.hasOwnProperty(k)) {
|
|
5112
|
-
|
|
5112
|
+
const v = this.players[k];
|
|
5113
5113
|
px = evt.pageX - this.outerBound.x;
|
|
5114
5114
|
py = evt.pageY - this.outerBound.y;
|
|
5115
5115
|
if (v.action)
|
|
@@ -5117,11 +5117,11 @@ var MultiTouchSpace = class extends Space {
|
|
|
5117
5117
|
}
|
|
5118
5118
|
}
|
|
5119
5119
|
} else {
|
|
5120
|
-
for (
|
|
5120
|
+
for (const k in this.players) {
|
|
5121
5121
|
if (this.players.hasOwnProperty(k)) {
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5122
|
+
const v = this.players[k];
|
|
5123
|
+
const c = evt.changedTouches && evt.changedTouches.length > 0;
|
|
5124
|
+
const touch = evt.changedTouches.item(0);
|
|
5125
5125
|
px = c ? touch.pageX - this.outerBound.x : 0;
|
|
5126
5126
|
py = c ? touch.pageY - this.outerBound.y : 0;
|
|
5127
5127
|
if (v.action)
|
|
@@ -5252,9 +5252,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5252
5252
|
_keyboardAction(type, evt) {
|
|
5253
5253
|
if (!this.isPlaying)
|
|
5254
5254
|
return;
|
|
5255
|
-
for (
|
|
5255
|
+
for (const k in this.players) {
|
|
5256
5256
|
if (this.players.hasOwnProperty(k)) {
|
|
5257
|
-
|
|
5257
|
+
const v = this.players[k];
|
|
5258
5258
|
if (v.action)
|
|
5259
5259
|
v.action(type, evt.shiftKey ? 1 : 0, evt.altKey ? 1 : 0, evt);
|
|
5260
5260
|
}
|
|
@@ -5503,7 +5503,7 @@ var Typography = class {
|
|
|
5503
5503
|
};
|
|
5504
5504
|
|
|
5505
5505
|
// src/Image.ts
|
|
5506
|
-
var Img = class {
|
|
5506
|
+
var Img = class _Img {
|
|
5507
5507
|
/**
|
|
5508
5508
|
* Create an Img
|
|
5509
5509
|
* @param editable Specify if you want to manipulate pixels of this image. Default is `false`.
|
|
@@ -5528,7 +5528,7 @@ var Img = class {
|
|
|
5528
5528
|
* @param ready An optional ready callback function
|
|
5529
5529
|
*/
|
|
5530
5530
|
static load(src, editable = false, space, ready) {
|
|
5531
|
-
const img = new
|
|
5531
|
+
const img = new _Img(editable, space);
|
|
5532
5532
|
img.load(src).then((res) => {
|
|
5533
5533
|
if (ready)
|
|
5534
5534
|
ready(res);
|
|
@@ -5544,7 +5544,7 @@ var Img = class {
|
|
|
5544
5544
|
*/
|
|
5545
5545
|
static loadAsync(src, editable = false, space) {
|
|
5546
5546
|
return __async(this, null, function* () {
|
|
5547
|
-
const img = yield new
|
|
5547
|
+
const img = yield new _Img(editable, space).load(src);
|
|
5548
5548
|
return img;
|
|
5549
5549
|
});
|
|
5550
5550
|
}
|
|
@@ -5558,7 +5558,7 @@ var Img = class {
|
|
|
5558
5558
|
*/
|
|
5559
5559
|
static loadPattern(src, space, repeat = "repeat", editable = false) {
|
|
5560
5560
|
return __async(this, null, function* () {
|
|
5561
|
-
const img = yield
|
|
5561
|
+
const img = yield _Img.loadAsync(src, editable, space);
|
|
5562
5562
|
return img.pattern(repeat);
|
|
5563
5563
|
});
|
|
5564
5564
|
}
|
|
@@ -5569,7 +5569,7 @@ var Img = class {
|
|
|
5569
5569
|
* @param scale Optionally set a specific pixel scale (density) of the image canvas.
|
|
5570
5570
|
*/
|
|
5571
5571
|
static blank(size, space, scale) {
|
|
5572
|
-
let img = new
|
|
5572
|
+
let img = new _Img(true, space);
|
|
5573
5573
|
const s = scale ? scale : space.pixelScale;
|
|
5574
5574
|
img.initCanvas(size[0], size[1], s);
|
|
5575
5575
|
return img;
|
|
@@ -5675,7 +5675,7 @@ var Img = class {
|
|
|
5675
5675
|
*/
|
|
5676
5676
|
pixel(p, rescale = true) {
|
|
5677
5677
|
const s = typeof rescale == "number" ? rescale : rescale ? this._scale : 1;
|
|
5678
|
-
return
|
|
5678
|
+
return _Img.getPixel(this._data, [p[0] * s, p[1] * s]);
|
|
5679
5679
|
}
|
|
5680
5680
|
/**
|
|
5681
5681
|
* Given an ImaegData object and a position, return the RGBA pixel value at that position.
|
|
@@ -5740,7 +5740,7 @@ var Img = class {
|
|
|
5740
5740
|
*/
|
|
5741
5741
|
static fromBlob(blob, editable = false, space) {
|
|
5742
5742
|
let url = URL.createObjectURL(blob);
|
|
5743
|
-
return new
|
|
5743
|
+
return new _Img(editable, space).load(url);
|
|
5744
5744
|
}
|
|
5745
5745
|
/**
|
|
5746
5746
|
* Convert ImageData object to a Blob, which you can then create an Img instance via [`Img.fromBlob`](#link). Note that the resulting image's dimensions will not account for pixel density.
|
|
@@ -5868,8 +5868,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5868
5868
|
this._bgcolor = "#e1e9f0";
|
|
5869
5869
|
this._offscreen = false;
|
|
5870
5870
|
this._initialResize = false;
|
|
5871
|
-
|
|
5872
|
-
|
|
5871
|
+
let _selector = null;
|
|
5872
|
+
let _existed = false;
|
|
5873
5873
|
this.id = "pt";
|
|
5874
5874
|
if (elem instanceof Element) {
|
|
5875
5875
|
_selector = elem;
|
|
@@ -5906,7 +5906,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5906
5906
|
* @param id element id attribute
|
|
5907
5907
|
*/
|
|
5908
5908
|
_createElement(elem = "div", id) {
|
|
5909
|
-
|
|
5909
|
+
const d = document.createElement(elem);
|
|
5910
5910
|
d.setAttribute("id", id);
|
|
5911
5911
|
return d;
|
|
5912
5912
|
}
|
|
@@ -5921,7 +5921,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5921
5921
|
this._resizeHandler(null);
|
|
5922
5922
|
this.clear(this._bgcolor);
|
|
5923
5923
|
this._canvas.dispatchEvent(new Event("ready"));
|
|
5924
|
-
for (
|
|
5924
|
+
for (const k in this.players) {
|
|
5925
5925
|
if (this.players.hasOwnProperty(k)) {
|
|
5926
5926
|
if (this.players[k].start)
|
|
5927
5927
|
this.players[k].start(this.bound.clone(), this);
|
|
@@ -5941,8 +5941,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5941
5941
|
this._bgcolor = opt.bgcolor ? opt.bgcolor : "transparent";
|
|
5942
5942
|
this.autoResize = opt.resize != void 0 ? opt.resize : false;
|
|
5943
5943
|
if (opt.retina !== false) {
|
|
5944
|
-
|
|
5945
|
-
|
|
5944
|
+
const r1 = window ? window.devicePixelRatio || 1 : 1;
|
|
5945
|
+
const r2 = this._ctx.webkitBackingStorePixelRatio || this._ctx.mozBackingStorePixelRatio || this._ctx.msBackingStorePixelRatio || this._ctx.oBackingStorePixelRatio || this._ctx.backingStorePixelRatio || 1;
|
|
5946
5946
|
this._pixelScale = Math.max(1, r1 / r2);
|
|
5947
5947
|
}
|
|
5948
5948
|
if (opt.offscreen) {
|
|
@@ -5996,9 +5996,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5996
5996
|
this._offCtx.scale(this._pixelScale, this._pixelScale);
|
|
5997
5997
|
}
|
|
5998
5998
|
}
|
|
5999
|
-
for (
|
|
5999
|
+
for (const k in this.players) {
|
|
6000
6000
|
if (this.players.hasOwnProperty(k)) {
|
|
6001
|
-
|
|
6001
|
+
const p = this.players[k];
|
|
6002
6002
|
if (p.resize)
|
|
6003
6003
|
p.resize(this.bound, evt);
|
|
6004
6004
|
}
|
|
@@ -6015,9 +6015,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6015
6015
|
_resizeHandler(evt) {
|
|
6016
6016
|
if (!window)
|
|
6017
6017
|
return;
|
|
6018
|
-
|
|
6018
|
+
const b = this._autoResize || this._initialResize ? this._container.getBoundingClientRect() : this._canvas.getBoundingClientRect();
|
|
6019
6019
|
if (b) {
|
|
6020
|
-
|
|
6020
|
+
const box = Bound.fromBoundingRect(b);
|
|
6021
6021
|
box.center = box.center.add(window.pageXOffset, window.pageYOffset);
|
|
6022
6022
|
this.resize(box, evt);
|
|
6023
6023
|
}
|
|
@@ -6160,14 +6160,14 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6160
6160
|
* @example `let rec = space.recorder(true); rec.start(); setTimeout( () => rec.stop(), 5000); // record 5s of video and download the file`
|
|
6161
6161
|
*/
|
|
6162
6162
|
recorder(downloadOrCallback, filetype = "webm", bitrate = 15e6) {
|
|
6163
|
-
|
|
6163
|
+
const stream = this._canvas.captureStream();
|
|
6164
6164
|
const recorder = new MediaRecorder(stream, { mimeType: `video/${filetype}`, bitsPerSecond: bitrate });
|
|
6165
6165
|
recorder.ondataavailable = function(d) {
|
|
6166
|
-
|
|
6166
|
+
const url = URL.createObjectURL(new Blob([d.data], { type: `video/${filetype}` }));
|
|
6167
6167
|
if (typeof downloadOrCallback === "function") {
|
|
6168
6168
|
downloadOrCallback(url);
|
|
6169
6169
|
} else if (downloadOrCallback) {
|
|
6170
|
-
|
|
6170
|
+
const a = document.createElement("a");
|
|
6171
6171
|
a.href = url;
|
|
6172
6172
|
a.download = `canvas_video.${filetype}`;
|
|
6173
6173
|
a.click();
|
|
@@ -6177,7 +6177,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6177
6177
|
return recorder;
|
|
6178
6178
|
}
|
|
6179
6179
|
};
|
|
6180
|
-
var CanvasForm = class extends VisualForm {
|
|
6180
|
+
var CanvasForm = class _CanvasForm extends VisualForm {
|
|
6181
6181
|
/**
|
|
6182
6182
|
* Create a new CanvasForm. You may also use [`CanvasSpace.getForm()`](#link) to get the default form.
|
|
6183
6183
|
* @param space an instance of CanvasSpace
|
|
@@ -6254,20 +6254,20 @@ var CanvasForm = class extends VisualForm {
|
|
|
6254
6254
|
}
|
|
6255
6255
|
}
|
|
6256
6256
|
/**
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6257
|
+
* Set current alpha value.
|
|
6258
|
+
* @example `form.alpha(0.6)`
|
|
6259
|
+
* @param a alpha value between 0 and 1
|
|
6260
|
+
*/
|
|
6261
6261
|
alpha(a) {
|
|
6262
6262
|
this._ctx.globalAlpha = a;
|
|
6263
6263
|
this._style.globalAlpha = a;
|
|
6264
6264
|
return this;
|
|
6265
6265
|
}
|
|
6266
6266
|
/**
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6267
|
+
* Set current fill style. Provide a valid color string such as `"#FFF"` or `"rgba(255,0,100,0.5)"` or `false` to specify no fill color.
|
|
6268
|
+
* @example `form.fill("#F90")`, `form.fill("rgba(0,0,0,.5")`, `form.fill(false)`
|
|
6269
|
+
* @param c fill color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle))
|
|
6270
|
+
*/
|
|
6271
6271
|
fill(c) {
|
|
6272
6272
|
if (typeof c == "boolean") {
|
|
6273
6273
|
this.filled = c;
|
|
@@ -6279,21 +6279,21 @@ var CanvasForm = class extends VisualForm {
|
|
|
6279
6279
|
return this;
|
|
6280
6280
|
}
|
|
6281
6281
|
/**
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6282
|
+
* Set current fill style and remove stroke style.
|
|
6283
|
+
* @param c fill color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle))
|
|
6284
|
+
*/
|
|
6285
6285
|
fillOnly(c) {
|
|
6286
6286
|
this.stroke(false);
|
|
6287
6287
|
return this.fill(c);
|
|
6288
6288
|
}
|
|
6289
6289
|
/**
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6290
|
+
* Set current stroke style. Provide a valid color string or `false` to specify no stroke color.
|
|
6291
|
+
* @example `form.stroke("#F90")`, `form.stroke("rgba(0,0,0,.5")`, `form.stroke(false)`, `form.stroke("#000", 0.5, 'round', 'square')`
|
|
6292
|
+
* @param c stroke color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle))
|
|
6293
|
+
* @param width Optional value (can be floating point) to set line width
|
|
6294
|
+
* @param linejoin Optional string to set line joint style. Can be "miter", "bevel", or "round".
|
|
6295
|
+
* @param linecap Optional string to set line cap style. Can be "butt", "round", or "square".
|
|
6296
|
+
*/
|
|
6297
6297
|
stroke(c, width, linejoin, linecap) {
|
|
6298
6298
|
if (typeof c == "boolean") {
|
|
6299
6299
|
this.stroked = c;
|
|
@@ -6317,24 +6317,24 @@ var CanvasForm = class extends VisualForm {
|
|
|
6317
6317
|
return this;
|
|
6318
6318
|
}
|
|
6319
6319
|
/**
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6320
|
+
* Set stroke style and remove fill style.
|
|
6321
|
+
* @param c stroke color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle))
|
|
6322
|
+
* @param width Optional value (can be floating point) to set line width
|
|
6323
|
+
* @param linejoin Optional string to set line joint style. Can be "miter", "bevel", or "round".
|
|
6324
|
+
* @param linecap Optional string to set line cap style. Can be "butt", "round", or "square".
|
|
6325
|
+
*/
|
|
6326
6326
|
strokeOnly(c, width, linejoin, linecap) {
|
|
6327
6327
|
this.fill(false);
|
|
6328
6328
|
return this.stroke(c, width, linejoin, linecap);
|
|
6329
6329
|
}
|
|
6330
6330
|
/**
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6331
|
+
* A convenient function to apply fill and/or stroke after custom drawings using canvas context (eg, `form.ctx.ellipse(...)`).
|
|
6332
|
+
* You don't need to call this function if you're using Pts' drawing functions like `form.point` or `form.rect`
|
|
6333
|
+
* @param filled apply fill when set to `true`
|
|
6334
|
+
* @param stroked apply stroke when set to `true`
|
|
6335
|
+
* @param strokeWidth optionally set a stroke width
|
|
6336
|
+
* @example `form.ctx.beginPath(); form.ctx.ellipse(...); form.applyFillStroke();`
|
|
6337
|
+
*/
|
|
6338
6338
|
applyFillStroke(filled = true, stroked = true, strokeWidth = 1) {
|
|
6339
6339
|
if (filled) {
|
|
6340
6340
|
if (typeof filled === "string")
|
|
@@ -6349,22 +6349,22 @@ var CanvasForm = class extends VisualForm {
|
|
|
6349
6349
|
return this;
|
|
6350
6350
|
}
|
|
6351
6351
|
/**
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6352
|
+
* This function takes an array of gradient colors, and returns a function to define the areas of the gradient fill. See demo code in [CanvasForm.gradient](https://ptsjs.org/demo/?name=canvasform.textBox).
|
|
6353
|
+
* @param stops an array of gradient stops. This can be an array of colors `["#f00", "#0f0", ...]` for evenly distributed gradient, or an array of [stop, color] like `[[0.1, "#f00"], [0.7, "#0f0"]]`
|
|
6354
|
+
* @returns a function that takes 1 or 2 `Group` as parameters. Use a single `Group` to specify a rectangular area for linear gradient, or use 2 `Groups` to specify 2 `Circles` for radial gradient.
|
|
6355
|
+
* @example `c1 = Circle.fromCenter(...); grad = form.gradient(["#f00", "#00f"]); form.fill( grad( c1, c2 ) ).circle( c1 )`
|
|
6356
|
+
*/
|
|
6357
6357
|
gradient(stops) {
|
|
6358
|
-
|
|
6358
|
+
const vals = [];
|
|
6359
6359
|
if (stops.length < 2)
|
|
6360
6360
|
stops.push([0.99, "#000"], [1, "#000"]);
|
|
6361
6361
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
6362
|
-
|
|
6363
|
-
|
|
6362
|
+
const t = typeof stops[i] === "string" ? i * (1 / (stops.length - 1)) : stops[i][0];
|
|
6363
|
+
const v = typeof stops[i] === "string" ? stops[i] : stops[i][1];
|
|
6364
6364
|
vals.push([t, v]);
|
|
6365
6365
|
}
|
|
6366
6366
|
return (area1, area2) => {
|
|
6367
|
-
|
|
6367
|
+
const grad = area2 ? this._ctx.createRadialGradient(area1[0][0], area1[0][1], Math.abs(area1[1][0]), area2[0][0], area2[0][1], Math.abs(area2[1][0])) : this._ctx.createLinearGradient(area1[0][0], area1[0][1], area1[1][0], area1[1][1]);
|
|
6368
6368
|
for (let i = 0, len = vals.length; i < len; i++) {
|
|
6369
6369
|
grad.addColorStop(vals[i][0], vals[i][1]);
|
|
6370
6370
|
}
|
|
@@ -6372,26 +6372,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6372
6372
|
};
|
|
6373
6373
|
}
|
|
6374
6374
|
/**
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6375
|
+
* Set composite operation (also known as blend mode). You can also call this function without parameters to get back to default 'source-over' mode. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation) for the full list of operations you can use.
|
|
6376
|
+
* @param mode a composite operation such as 'lighten', 'multiply', 'overlay', and 'color-burn'.
|
|
6377
|
+
*/
|
|
6378
6378
|
composite(mode = "source-over") {
|
|
6379
6379
|
this._ctx.globalCompositeOperation = mode;
|
|
6380
6380
|
return this;
|
|
6381
6381
|
}
|
|
6382
6382
|
/**
|
|
6383
|
-
|
|
6384
|
-
|
|
6383
|
+
* Create a clipping mask from the current path. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip) for details.
|
|
6384
|
+
*/
|
|
6385
6385
|
clip() {
|
|
6386
6386
|
this._ctx.clip();
|
|
6387
6387
|
return this;
|
|
6388
6388
|
}
|
|
6389
6389
|
/**
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6390
|
+
* Activate dashed stroke and set dash style. You can customize the segments and offset.
|
|
6391
|
+
* @example `form.dash()`, `form.dash([5, 10])`, `form.dash([5, 5], 5)`, `form.dash(false)`
|
|
6392
|
+
* @param segments Dash segments. Defaults to `true` which corresponds to `[5, 5]`. Pass `false` to deactivate dashes. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash))
|
|
6393
|
+
* @param offset Dash offset. Defaults to 0. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)
|
|
6394
|
+
*/
|
|
6395
6395
|
dash(segments = true, offset = 0) {
|
|
6396
6396
|
if (!segments) {
|
|
6397
6397
|
this._ctx.setLineDash([]);
|
|
@@ -6406,14 +6406,14 @@ var CanvasForm = class extends VisualForm {
|
|
|
6406
6406
|
return this;
|
|
6407
6407
|
}
|
|
6408
6408
|
/**
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6409
|
+
* Set the current font.
|
|
6410
|
+
* @param sizeOrFont either a number to specify font-size, or a `Font` object to specify all font properties
|
|
6411
|
+
* @param weight Optional font-weight string such as "bold"
|
|
6412
|
+
* @param style Optional font-style string such as "italic"
|
|
6413
|
+
* @param lineHeight Optional line-height number suchas 1.5
|
|
6414
|
+
* @param family Optional font-family such as "Helvetica, sans-serif"
|
|
6415
|
+
* @example `form.font( myFont )`, `form.font(14, "bold")`
|
|
6416
|
+
*/
|
|
6417
6417
|
font(sizeOrFont, weight, style, lineHeight, family) {
|
|
6418
6418
|
if (typeof sizeOrFont == "number") {
|
|
6419
6419
|
this._font.size = sizeOrFont;
|
|
@@ -6434,49 +6434,49 @@ var CanvasForm = class extends VisualForm {
|
|
|
6434
6434
|
return this;
|
|
6435
6435
|
}
|
|
6436
6436
|
/**
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6437
|
+
* Set whether to use html canvas' [`measureText`](#link) function, or a faster but less accurate heuristic function.
|
|
6438
|
+
* @param estimate `true` to use heuristic function, or `false` to use ctx.measureText
|
|
6439
|
+
*/
|
|
6440
6440
|
fontWidthEstimate(estimate = true) {
|
|
6441
6441
|
this._estimateTextWidth = estimate ? Typography.textWidthEstimator((c) => this._ctx.measureText(c).width) : void 0;
|
|
6442
6442
|
return this;
|
|
6443
6443
|
}
|
|
6444
6444
|
/**
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6445
|
+
* Get the width of this text. It will return an actual measurement or an estimate based on [`fontWidthEstimate`](#link) setting. Default is an actual measurement using canvas context's measureText.
|
|
6446
|
+
* @param c a string of text contents
|
|
6447
|
+
*/
|
|
6448
6448
|
getTextWidth(c) {
|
|
6449
6449
|
return !this._estimateTextWidth ? this._ctx.measureText(c + " .").width : this._estimateTextWidth(c);
|
|
6450
6450
|
}
|
|
6451
6451
|
/**
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6452
|
+
* Truncate text to fit width.
|
|
6453
|
+
* @param str text to truncate
|
|
6454
|
+
* @param width width to fit
|
|
6455
|
+
* @param tail text to indicate overflow such as "...". Default is empty "".
|
|
6456
|
+
*/
|
|
6457
6457
|
_textTruncate(str, width, tail = "") {
|
|
6458
6458
|
return Typography.truncate(this.getTextWidth.bind(this), str, width, tail);
|
|
6459
6459
|
}
|
|
6460
6460
|
/**
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6461
|
+
* Align text within a rectangle box.
|
|
6462
|
+
* @param box a Group or an Iterable<PtLike> that defines a rectangular box
|
|
6463
|
+
* @param vertical a string that specifies the vertical alignment in the box: "top", "bottom", "middle", "start", "end"
|
|
6464
|
+
* @param offset Optional offset from the edge (like padding)
|
|
6465
|
+
* @param center Optional center position
|
|
6466
|
+
*/
|
|
6467
6467
|
_textAlign(box, vertical, offset, center) {
|
|
6468
|
-
|
|
6468
|
+
const _box = Util.iterToArray(box);
|
|
6469
6469
|
if (!Util.arrayCheck(_box))
|
|
6470
6470
|
return;
|
|
6471
6471
|
if (!center)
|
|
6472
6472
|
center = Rectangle.center(_box);
|
|
6473
|
-
|
|
6473
|
+
let px = _box[0][0];
|
|
6474
6474
|
if (this._ctx.textAlign == "end" || this._ctx.textAlign == "right") {
|
|
6475
6475
|
px = _box[1][0];
|
|
6476
6476
|
} else if (this._ctx.textAlign == "center" || this._ctx.textAlign == "middle") {
|
|
6477
6477
|
px = center[0];
|
|
6478
6478
|
}
|
|
6479
|
-
|
|
6479
|
+
let py = center[1];
|
|
6480
6480
|
if (vertical == "top" || vertical == "start") {
|
|
6481
6481
|
py = _box[0][1];
|
|
6482
6482
|
} else if (vertical == "end" || vertical == "bottom") {
|
|
@@ -6485,10 +6485,10 @@ var CanvasForm = class extends VisualForm {
|
|
|
6485
6485
|
return offset ? new Pt(px + offset[0], py + offset[1]) : new Pt(px, py);
|
|
6486
6486
|
}
|
|
6487
6487
|
/**
|
|
6488
|
-
|
|
6489
|
-
|
|
6488
|
+
* Reset the rendering context's common styles to this form's styles. This supports using multiple forms on the same canvas context.
|
|
6489
|
+
*/
|
|
6490
6490
|
reset() {
|
|
6491
|
-
for (
|
|
6491
|
+
for (const k in this._style) {
|
|
6492
6492
|
if (this._style.hasOwnProperty(k)) {
|
|
6493
6493
|
this._ctx[k] = this._style[k];
|
|
6494
6494
|
}
|
|
@@ -6504,38 +6504,38 @@ var CanvasForm = class extends VisualForm {
|
|
|
6504
6504
|
this._ctx.stroke();
|
|
6505
6505
|
}
|
|
6506
6506
|
/**
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6507
|
+
* A static function to draw a point.
|
|
6508
|
+
* @param ctx canvas rendering context
|
|
6509
|
+
* @param p a Pt object
|
|
6510
|
+
* @param radius radius of the point. Default is 5.
|
|
6511
|
+
* @param shape The shape of the point. Defaults to "square", but it can be "circle" or a custom shape function in your own implementation.
|
|
6512
|
+
* @example `form.point( p )`, `form.point( p, 10, "circle" )`
|
|
6513
|
+
*/
|
|
6514
6514
|
static point(ctx, p, radius = 5, shape = "square") {
|
|
6515
6515
|
if (!p)
|
|
6516
6516
|
return;
|
|
6517
|
-
if (!
|
|
6517
|
+
if (!_CanvasForm[shape])
|
|
6518
6518
|
throw new Error(`${shape} is not a static function of CanvasForm`);
|
|
6519
|
-
|
|
6519
|
+
_CanvasForm[shape](ctx, p, radius);
|
|
6520
6520
|
}
|
|
6521
6521
|
/**
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6522
|
+
* Draws a point.
|
|
6523
|
+
* @param p a Pt object
|
|
6524
|
+
* @param radius radius of the point. Default is 5.
|
|
6525
|
+
* @param shape The shape of the point. Defaults to "square", but it can be "circle" or a custom shape function in your own implementation.
|
|
6526
|
+
* @example `form.point( p )`, `form.point( p, 10, "circle" )`
|
|
6527
|
+
*/
|
|
6528
6528
|
point(p, radius = 5, shape = "square") {
|
|
6529
|
-
|
|
6529
|
+
_CanvasForm.point(this._ctx, p, radius, shape);
|
|
6530
6530
|
this._paint();
|
|
6531
6531
|
return this;
|
|
6532
6532
|
}
|
|
6533
6533
|
/**
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6534
|
+
* A static function to draw a circle.
|
|
6535
|
+
* @param ctx canvas rendering context
|
|
6536
|
+
* @param pt center position of the circle
|
|
6537
|
+
* @param radius radius of the circle
|
|
6538
|
+
*/
|
|
6539
6539
|
static circle(ctx, pt, radius = 10) {
|
|
6540
6540
|
if (!pt)
|
|
6541
6541
|
return;
|
|
@@ -6544,25 +6544,25 @@ var CanvasForm = class extends VisualForm {
|
|
|
6544
6544
|
ctx.closePath();
|
|
6545
6545
|
}
|
|
6546
6546
|
/**
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6547
|
+
* Draw a circle. See also [`Circle.fromCenter`](#link)
|
|
6548
|
+
* @param pts usually a Group or an Iterable<PtLike> with 2 Pt, but it can also take an array of two numeric arrays [ [position], [size] ]
|
|
6549
|
+
*/
|
|
6550
6550
|
circle(pts) {
|
|
6551
|
-
|
|
6552
|
-
|
|
6551
|
+
const p = Util.iterToArray(pts);
|
|
6552
|
+
_CanvasForm.circle(this._ctx, p[0], p[1][0]);
|
|
6553
6553
|
this._paint();
|
|
6554
6554
|
return this;
|
|
6555
6555
|
}
|
|
6556
6556
|
/**
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6557
|
+
* A static function to draw an ellipse.
|
|
6558
|
+
* @param ctx canvas rendering context
|
|
6559
|
+
* @param pt center position
|
|
6560
|
+
* @param radius radius [x, y] of the ellipse
|
|
6561
|
+
* @param rotation rotation of the ellipse in radian. Default is 0.
|
|
6562
|
+
* @param startAngle start angle of the ellipse. Default is 0.
|
|
6563
|
+
* @param endAngle end angle of the ellipse. Default is 2 PI.
|
|
6564
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6565
|
+
*/
|
|
6566
6566
|
static ellipse(ctx, pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6567
6567
|
if (!pt || !radius)
|
|
6568
6568
|
return;
|
|
@@ -6570,28 +6570,28 @@ var CanvasForm = class extends VisualForm {
|
|
|
6570
6570
|
ctx.ellipse(pt[0], pt[1], radius[0], radius[1], rotation, startAngle, endAngle, cc);
|
|
6571
6571
|
}
|
|
6572
6572
|
/**
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6573
|
+
* Draw an ellipse.
|
|
6574
|
+
* @param pt center position
|
|
6575
|
+
* @param radius radius [x, y] of the ellipse
|
|
6576
|
+
* @param rotation rotation of the ellipse in radian. Default is 0.
|
|
6577
|
+
* @param startAngle start angle of the ellipse. Default is 0.
|
|
6578
|
+
* @param endAngle end angle of the ellipse. Default is 2 PI.
|
|
6579
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6580
|
+
*/
|
|
6581
6581
|
ellipse(pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6582
|
-
|
|
6582
|
+
_CanvasForm.ellipse(this._ctx, pt, radius, rotation, startAngle, endAngle, cc);
|
|
6583
6583
|
this._paint();
|
|
6584
6584
|
return this;
|
|
6585
6585
|
}
|
|
6586
6586
|
/**
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6587
|
+
* A static function to draw an arc.
|
|
6588
|
+
* @param ctx canvas rendering context
|
|
6589
|
+
* @param pt center position
|
|
6590
|
+
* @param radius radius of the arc circle
|
|
6591
|
+
* @param startAngle start angle of the arc
|
|
6592
|
+
* @param endAngle end angle of the arc
|
|
6593
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6594
|
+
*/
|
|
6595
6595
|
static arc(ctx, pt, radius, startAngle, endAngle, cc) {
|
|
6596
6596
|
if (!pt)
|
|
6597
6597
|
return;
|
|
@@ -6599,31 +6599,31 @@ var CanvasForm = class extends VisualForm {
|
|
|
6599
6599
|
ctx.arc(pt[0], pt[1], radius, startAngle, endAngle, cc);
|
|
6600
6600
|
}
|
|
6601
6601
|
/**
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6602
|
+
* Draw an arc.
|
|
6603
|
+
* @param pt center position
|
|
6604
|
+
* @param radius radius of the arc circle
|
|
6605
|
+
* @param startAngle start angle of the arc
|
|
6606
|
+
* @param endAngle end angle of the arc
|
|
6607
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6608
|
+
*/
|
|
6609
6609
|
arc(pt, radius, startAngle, endAngle, cc) {
|
|
6610
|
-
|
|
6610
|
+
_CanvasForm.arc(this._ctx, pt, radius, startAngle, endAngle, cc);
|
|
6611
6611
|
this._paint();
|
|
6612
6612
|
return this;
|
|
6613
6613
|
}
|
|
6614
6614
|
/**
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6615
|
+
* A static function to draw a square.
|
|
6616
|
+
* @param ctx canvas rendering context
|
|
6617
|
+
* @param pt center position of the square
|
|
6618
|
+
* @param halfsize half size of the square
|
|
6619
|
+
*/
|
|
6620
6620
|
static square(ctx, pt, halfsize) {
|
|
6621
6621
|
if (!pt)
|
|
6622
6622
|
return;
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6623
|
+
const x1 = pt[0] - halfsize;
|
|
6624
|
+
const y1 = pt[1] - halfsize;
|
|
6625
|
+
const x2 = pt[0] + halfsize;
|
|
6626
|
+
const y2 = pt[1] + halfsize;
|
|
6627
6627
|
ctx.beginPath();
|
|
6628
6628
|
ctx.moveTo(x1, y1);
|
|
6629
6629
|
ctx.lineTo(x1, y2);
|
|
@@ -6632,26 +6632,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6632
6632
|
ctx.closePath();
|
|
6633
6633
|
}
|
|
6634
6634
|
/**
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6635
|
+
* Draw a square, given a center and its half-size.
|
|
6636
|
+
* @param pt center Pt
|
|
6637
|
+
* @param halfsize half-size
|
|
6638
|
+
*/
|
|
6639
6639
|
square(pt, halfsize) {
|
|
6640
|
-
|
|
6640
|
+
_CanvasForm.square(this._ctx, pt, halfsize);
|
|
6641
6641
|
this._paint();
|
|
6642
6642
|
return this;
|
|
6643
6643
|
}
|
|
6644
6644
|
/**
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6645
|
+
* A static function to draw a line or polyline.
|
|
6646
|
+
* @param ctx canvas rendering context
|
|
6647
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6648
|
+
*/
|
|
6649
6649
|
static line(ctx, pts) {
|
|
6650
6650
|
if (!Util.arrayCheck(pts))
|
|
6651
6651
|
return;
|
|
6652
6652
|
let i = 0;
|
|
6653
6653
|
ctx.beginPath();
|
|
6654
|
-
for (
|
|
6654
|
+
for (const it of pts) {
|
|
6655
6655
|
if (it) {
|
|
6656
6656
|
if (i++ > 0) {
|
|
6657
6657
|
ctx.lineTo(it[0], it[1]);
|
|
@@ -6662,41 +6662,41 @@ var CanvasForm = class extends VisualForm {
|
|
|
6662
6662
|
}
|
|
6663
6663
|
}
|
|
6664
6664
|
/**
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6665
|
+
* Draw a line or polyline.
|
|
6666
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6667
|
+
*/
|
|
6668
6668
|
line(pts) {
|
|
6669
|
-
|
|
6669
|
+
_CanvasForm.line(this._ctx, pts);
|
|
6670
6670
|
this._paint();
|
|
6671
6671
|
return this;
|
|
6672
6672
|
}
|
|
6673
6673
|
/**
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6674
|
+
* A static function to draw a polygon.
|
|
6675
|
+
* @param ctx canvas rendering context
|
|
6676
|
+
* @param pts a Group or an Iterable<PtLike> representing a polygon
|
|
6677
|
+
*/
|
|
6678
6678
|
static polygon(ctx, pts) {
|
|
6679
6679
|
if (!Util.arrayCheck(pts))
|
|
6680
6680
|
return;
|
|
6681
|
-
|
|
6681
|
+
_CanvasForm.line(ctx, pts);
|
|
6682
6682
|
ctx.closePath();
|
|
6683
6683
|
}
|
|
6684
6684
|
/**
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6685
|
+
* Draw a polygon.
|
|
6686
|
+
* @param pts a Group or an Iterable<PtLike> representingg a polygon
|
|
6687
|
+
*/
|
|
6688
6688
|
polygon(pts) {
|
|
6689
|
-
|
|
6689
|
+
_CanvasForm.polygon(this._ctx, pts);
|
|
6690
6690
|
this._paint();
|
|
6691
6691
|
return this;
|
|
6692
6692
|
}
|
|
6693
6693
|
/**
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6694
|
+
* A static function to draw a rectangle.
|
|
6695
|
+
* @param ctx canvas rendering context
|
|
6696
|
+
* @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.
|
|
6697
|
+
*/
|
|
6698
6698
|
static rect(ctx, pts) {
|
|
6699
|
-
|
|
6699
|
+
const p = Util.iterToArray(pts);
|
|
6700
6700
|
if (!Util.arrayCheck(p))
|
|
6701
6701
|
return;
|
|
6702
6702
|
ctx.beginPath();
|
|
@@ -6707,29 +6707,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6707
6707
|
ctx.closePath();
|
|
6708
6708
|
}
|
|
6709
6709
|
/**
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6710
|
+
* Draw a rectangle.
|
|
6711
|
+
* @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.
|
|
6712
|
+
*/
|
|
6713
6713
|
rect(pts) {
|
|
6714
|
-
|
|
6714
|
+
_CanvasForm.rect(this._ctx, pts);
|
|
6715
6715
|
this._paint();
|
|
6716
6716
|
return this;
|
|
6717
6717
|
}
|
|
6718
6718
|
/**
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6719
|
+
* A static function to draw an image.
|
|
6720
|
+
* @param ctx canvas rendering context
|
|
6721
|
+
* @param img either an [Img](#link) instance or an [`CanvasImageSource`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource) instance (eg the image from `<img>`, `<video>` or `<canvas>`)
|
|
6722
|
+
* @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.
|
|
6723
|
+
* @param orig optionally a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a cropping box in the original target.
|
|
6724
|
+
*/
|
|
6725
6725
|
static image(ctx, ptOrRect, img, orig) {
|
|
6726
|
-
|
|
6726
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6727
6727
|
let pos;
|
|
6728
6728
|
if (typeof t[0] === "number") {
|
|
6729
6729
|
pos = t;
|
|
6730
6730
|
} else {
|
|
6731
6731
|
if (orig) {
|
|
6732
|
-
|
|
6732
|
+
const o = Util.iterToArray(orig);
|
|
6733
6733
|
pos = [
|
|
6734
6734
|
o[0][0],
|
|
6735
6735
|
o[0][1],
|
|
@@ -6753,29 +6753,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6753
6753
|
}
|
|
6754
6754
|
}
|
|
6755
6755
|
/**
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6756
|
+
* Draw an image.
|
|
6757
|
+
* @param img either an [Img](#link) instance or an [`CanvasImageSource`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource) instance (eg the image from `<img>`, `<video>` or `<canvas>`)
|
|
6758
|
+
* @param ptOrRect a target area to place the image. Either a PtLike specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left position, bottom-right position) that specifies a bounding box. Default is (0,0) at top-left.
|
|
6759
|
+
* @param orig optionally a Group or an Iterable<PtLike> with 2 Pt (top-left position, bottom-right position) that specifies a cropping box in the original target.
|
|
6760
|
+
*/
|
|
6761
6761
|
image(ptOrRect, img, orig) {
|
|
6762
6762
|
if (img instanceof Img) {
|
|
6763
6763
|
if (img.loaded) {
|
|
6764
|
-
|
|
6764
|
+
_CanvasForm.image(this._ctx, ptOrRect, img.image, orig);
|
|
6765
6765
|
}
|
|
6766
6766
|
} else {
|
|
6767
|
-
|
|
6767
|
+
_CanvasForm.image(this._ctx, ptOrRect, img, orig);
|
|
6768
6768
|
}
|
|
6769
6769
|
return this;
|
|
6770
6770
|
}
|
|
6771
6771
|
/**
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6772
|
+
* A static function to draw ImageData on canvas
|
|
6773
|
+
* @param ctx canvas rendering context
|
|
6774
|
+
* @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.
|
|
6775
|
+
* @param img an ImageData object
|
|
6776
|
+
*/
|
|
6777
6777
|
static imageData(ctx, ptOrRect, img) {
|
|
6778
|
-
|
|
6778
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6779
6779
|
if (typeof t[0] === "number") {
|
|
6780
6780
|
ctx.putImageData(img, t[0], t[1]);
|
|
6781
6781
|
} else {
|
|
@@ -6783,74 +6783,74 @@ var CanvasForm = class extends VisualForm {
|
|
|
6783
6783
|
}
|
|
6784
6784
|
}
|
|
6785
6785
|
/**
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6786
|
+
* Draw ImageData on canvas using ImageData
|
|
6787
|
+
* @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.
|
|
6788
|
+
* @param img an ImageData object
|
|
6789
|
+
*/
|
|
6790
6790
|
imageData(ptOrRect, img) {
|
|
6791
|
-
|
|
6791
|
+
_CanvasForm.imageData(this._ctx, ptOrRect, img);
|
|
6792
6792
|
return this;
|
|
6793
6793
|
}
|
|
6794
6794
|
/**
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6795
|
+
* A static function to draw text.
|
|
6796
|
+
* @param ctx canvas rendering context
|
|
6797
|
+
* @param `pt` a Point object to specify the anchor point
|
|
6798
|
+
* @param `txt` a string of text to draw
|
|
6799
|
+
* @param `maxWidth` specify a maximum width per line
|
|
6800
|
+
*/
|
|
6801
6801
|
static text(ctx, pt, txt, maxWidth) {
|
|
6802
6802
|
if (!pt)
|
|
6803
6803
|
return;
|
|
6804
6804
|
ctx.fillText(txt, pt[0], pt[1], maxWidth);
|
|
6805
6805
|
}
|
|
6806
6806
|
/**
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6807
|
+
* Draw text on canvas.
|
|
6808
|
+
* @param `pt` a Pt or numeric array to specify the anchor point
|
|
6809
|
+
* @param `txt` text
|
|
6810
|
+
* @param `maxWidth` specify a maximum width per line
|
|
6811
|
+
*/
|
|
6812
6812
|
text(pt, txt, maxWidth) {
|
|
6813
|
-
|
|
6813
|
+
_CanvasForm.text(this._ctx, pt, txt, maxWidth);
|
|
6814
6814
|
return this;
|
|
6815
6815
|
}
|
|
6816
6816
|
/**
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6817
|
+
* Fit a single-line text in a rectangular box.
|
|
6818
|
+
* @param box a rectangle box defined by a Group or an Iterable<Pt>
|
|
6819
|
+
* @param txt string of text
|
|
6820
|
+
* @param tail text to indicate overflow such as "...". Default is empty "".
|
|
6821
|
+
* @param verticalAlign "top", "middle", or "bottom" to specify vertical alignment inside the box
|
|
6822
|
+
* @param overrideBaseline If `true`, use the corresponding baseline as verticalAlign. If `false`, use the current canvas context's textBaseline setting. Default is `true`.
|
|
6823
|
+
*/
|
|
6824
6824
|
textBox(box, txt, verticalAlign = "middle", tail = "", overrideBaseline = true) {
|
|
6825
6825
|
if (overrideBaseline)
|
|
6826
6826
|
this._ctx.textBaseline = verticalAlign;
|
|
6827
|
-
|
|
6828
|
-
|
|
6827
|
+
const size = Rectangle.size(box);
|
|
6828
|
+
const t = this._textTruncate(txt, size[0], tail);
|
|
6829
6829
|
this.text(this._textAlign(box, verticalAlign), t[0]);
|
|
6830
6830
|
return this;
|
|
6831
6831
|
}
|
|
6832
6832
|
/**
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6833
|
+
* Fit multi-line text in a rectangular box. Note that this will also set canvas context's textBaseline to "top".
|
|
6834
|
+
* @param box a Group or an Iterable<PtLike> with 2 Pt that represents a bounding box
|
|
6835
|
+
* @param txt string of text
|
|
6836
|
+
* @param lineHeight line height as a ratio of font size. Default is 1.2.
|
|
6837
|
+
* @param verticalAlign "top", "middle", or "bottom" to specify vertical alignment inside the box
|
|
6838
|
+
* @param crop a boolean to specify whether to crop text when overflowing
|
|
6839
|
+
*/
|
|
6840
6840
|
paragraphBox(box, txt, lineHeight = 1.2, verticalAlign = "top", crop = true) {
|
|
6841
|
-
|
|
6842
|
-
|
|
6841
|
+
const b = Util.iterToArray(box);
|
|
6842
|
+
const size = Rectangle.size(b);
|
|
6843
6843
|
this._ctx.textBaseline = "top";
|
|
6844
|
-
|
|
6845
|
-
|
|
6844
|
+
const lstep = this._font.size * lineHeight;
|
|
6845
|
+
const nextLine = (sub, buffer = [], cc = 0) => {
|
|
6846
6846
|
if (!sub)
|
|
6847
6847
|
return buffer;
|
|
6848
6848
|
if (crop && cc * lstep > size[1] - lstep * 2)
|
|
6849
6849
|
return buffer;
|
|
6850
6850
|
if (cc > 1e4)
|
|
6851
6851
|
throw new Error("max recursion reached (10000)");
|
|
6852
|
-
|
|
6853
|
-
|
|
6852
|
+
const t = this._textTruncate(sub, size[0], "");
|
|
6853
|
+
const newln = t[0].indexOf("\n");
|
|
6854
6854
|
if (newln >= 0) {
|
|
6855
6855
|
buffer.push(t[0].substr(0, newln));
|
|
6856
6856
|
return nextLine(sub.substr(newln + 1), buffer, cc + 1);
|
|
@@ -6858,12 +6858,12 @@ var CanvasForm = class extends VisualForm {
|
|
|
6858
6858
|
let dt = t[0].lastIndexOf(" ") + 1;
|
|
6859
6859
|
if (dt <= 0 || t[1] === sub.length)
|
|
6860
6860
|
dt = void 0;
|
|
6861
|
-
|
|
6861
|
+
const line = t[0].substr(0, dt);
|
|
6862
6862
|
buffer.push(line);
|
|
6863
6863
|
return t[1] <= 0 || t[1] === sub.length ? buffer : nextLine(sub.substr(dt || t[1]), buffer, cc + 1);
|
|
6864
6864
|
};
|
|
6865
|
-
|
|
6866
|
-
|
|
6865
|
+
const lines = nextLine(txt);
|
|
6866
|
+
const lsize = lines.length * lstep;
|
|
6867
6867
|
let lbox = b;
|
|
6868
6868
|
if (verticalAlign == "middle" || verticalAlign == "center") {
|
|
6869
6869
|
let lpad = (size[1] - lsize) / 2;
|
|
@@ -6875,17 +6875,17 @@ var CanvasForm = class extends VisualForm {
|
|
|
6875
6875
|
} else {
|
|
6876
6876
|
lbox = new Group(b[0], b[0].$add(size[0], lsize));
|
|
6877
6877
|
}
|
|
6878
|
-
|
|
6878
|
+
const center = Rectangle.center(lbox);
|
|
6879
6879
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
6880
6880
|
this.text(this._textAlign(lbox, "top", [0, i * lstep], center), lines[i]);
|
|
6881
6881
|
}
|
|
6882
6882
|
return this;
|
|
6883
6883
|
}
|
|
6884
6884
|
/**
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6885
|
+
* Set text alignment and baseline (eg, vertical-align).
|
|
6886
|
+
* @param alignment HTML canvas' textAlign option: "left", "right", "center", "start", or "end"
|
|
6887
|
+
* @param baseline HTML canvas' textBaseline option: "top", "hanging", "middle", "alphabetic", "ideographic", "bottom". For convenience, you can also use "center" (same as "middle"), and "baseline" (same as "alphabetic")
|
|
6888
|
+
*/
|
|
6889
6889
|
alignText(alignment = "left", baseline = "alphabetic") {
|
|
6890
6890
|
if (baseline == "center")
|
|
6891
6891
|
baseline = "middle";
|
|
@@ -6896,11 +6896,11 @@ var CanvasForm = class extends VisualForm {
|
|
|
6896
6896
|
return this;
|
|
6897
6897
|
}
|
|
6898
6898
|
/**
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6899
|
+
* A convenient way to draw some text on canvas for logging or debugging. It'll be draw on the top-left of the canvas as an overlay.
|
|
6900
|
+
* @param txt text
|
|
6901
|
+
*/
|
|
6902
6902
|
log(txt) {
|
|
6903
|
-
|
|
6903
|
+
const w = this._ctx.measureText(txt).width + 20;
|
|
6904
6904
|
this.stroke(false).fill("rgba(0,0,0,.4)").rect([[0, 0], [w, 20]]);
|
|
6905
6905
|
this.fill("#fff").text([10, 14], txt);
|
|
6906
6906
|
return this;
|
|
@@ -7363,7 +7363,7 @@ var Noise = class extends Pt {
|
|
|
7363
7363
|
return Num.lerp(Num.lerp(n00, n10, tx), Num.lerp(n01, n11, tx), _fade(y));
|
|
7364
7364
|
}
|
|
7365
7365
|
};
|
|
7366
|
-
var Delaunay = class extends Group {
|
|
7366
|
+
var Delaunay = class _Delaunay extends Group {
|
|
7367
7367
|
constructor() {
|
|
7368
7368
|
super(...arguments);
|
|
7369
7369
|
this._mesh = [];
|
|
@@ -7410,7 +7410,7 @@ var Delaunay = class extends Group {
|
|
|
7410
7410
|
edges.push(circum.i, circum.j, circum.j, circum.k, circum.k, circum.i);
|
|
7411
7411
|
opened.splice(j, 1);
|
|
7412
7412
|
}
|
|
7413
|
-
|
|
7413
|
+
_Delaunay._dedupe(edges);
|
|
7414
7414
|
j = edges.length;
|
|
7415
7415
|
while (j > 1) {
|
|
7416
7416
|
opened.push(this._circum(edges[--j], edges[--j], c, false, pts));
|
|
@@ -7552,7 +7552,7 @@ var Delaunay = class extends Group {
|
|
|
7552
7552
|
};
|
|
7553
7553
|
|
|
7554
7554
|
// src/Color.ts
|
|
7555
|
-
var _Color = class extends Pt {
|
|
7555
|
+
var _Color = class _Color extends Pt {
|
|
7556
7556
|
/**
|
|
7557
7557
|
* Create a Color. Same as creating a Pt. Optionally you may use [`Color.from`](#link) to create a color.
|
|
7558
7558
|
* @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties
|
|
@@ -7567,8 +7567,8 @@ var _Color = class extends Pt {
|
|
|
7567
7567
|
* @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties
|
|
7568
7568
|
*/
|
|
7569
7569
|
static from(...args) {
|
|
7570
|
-
|
|
7571
|
-
|
|
7570
|
+
const p = [1, 1, 1, 1];
|
|
7571
|
+
const c = Util.getArgs(args);
|
|
7572
7572
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
7573
7573
|
if (i < c.length)
|
|
7574
7574
|
p[i] = c[i];
|
|
@@ -7583,7 +7583,7 @@ var _Color = class extends Pt {
|
|
|
7583
7583
|
if (hex[0] == "#")
|
|
7584
7584
|
hex = hex.substr(1);
|
|
7585
7585
|
if (hex.length <= 3) {
|
|
7586
|
-
|
|
7586
|
+
const fn = (i) => hex[i] || "F";
|
|
7587
7587
|
hex = `${fn(0)}${fn(0)}${fn(1)}${fn(1)}${fn(2)}${fn(2)}`;
|
|
7588
7588
|
}
|
|
7589
7589
|
let alpha = 1;
|
|
@@ -7591,7 +7591,7 @@ var _Color = class extends Pt {
|
|
|
7591
7591
|
alpha = hex.substr(6) && 255 / 255;
|
|
7592
7592
|
hex = hex.substring(0, 6);
|
|
7593
7593
|
}
|
|
7594
|
-
|
|
7594
|
+
const hexVal = parseInt(hex, 16);
|
|
7595
7595
|
return new _Color(hexVal >> 16, hexVal >> 8 & 255, hexVal & 255, alpha);
|
|
7596
7596
|
}
|
|
7597
7597
|
/**
|
|
@@ -7673,7 +7673,7 @@ var _Color = class extends Pt {
|
|
|
7673
7673
|
* Clone this Color.
|
|
7674
7674
|
*/
|
|
7675
7675
|
clone() {
|
|
7676
|
-
|
|
7676
|
+
const c = new _Color(this);
|
|
7677
7677
|
c.toMode(this._mode);
|
|
7678
7678
|
return c;
|
|
7679
7679
|
}
|
|
@@ -7684,7 +7684,7 @@ var _Color = class extends Pt {
|
|
|
7684
7684
|
*/
|
|
7685
7685
|
toMode(mode, convert = false) {
|
|
7686
7686
|
if (convert) {
|
|
7687
|
-
|
|
7687
|
+
const fname = this._mode.toUpperCase() + "to" + mode.toUpperCase();
|
|
7688
7688
|
if (_Color[fname]) {
|
|
7689
7689
|
this.to(_Color[fname](this, this._isNorm, this._isNorm));
|
|
7690
7690
|
} else {
|
|
@@ -7736,7 +7736,7 @@ var _Color = class extends Pt {
|
|
|
7736
7736
|
return this._mode == "lch" ? this[2] : this[0];
|
|
7737
7737
|
}
|
|
7738
7738
|
set h(n) {
|
|
7739
|
-
|
|
7739
|
+
const i = this._mode == "lch" ? 2 : 0;
|
|
7740
7740
|
this[i] = n;
|
|
7741
7741
|
}
|
|
7742
7742
|
/**
|
|
@@ -7755,7 +7755,7 @@ var _Color = class extends Pt {
|
|
|
7755
7755
|
return this._mode == "hsl" ? this[2] : this[0];
|
|
7756
7756
|
}
|
|
7757
7757
|
set l(n) {
|
|
7758
|
-
|
|
7758
|
+
const i = this._mode == "hsl" ? 2 : 0;
|
|
7759
7759
|
this[i] = n;
|
|
7760
7760
|
}
|
|
7761
7761
|
// lab, lch, luv
|
|
@@ -7821,7 +7821,7 @@ var _Color = class extends Pt {
|
|
|
7821
7821
|
normalize(toNorm = true) {
|
|
7822
7822
|
if (this._isNorm == toNorm)
|
|
7823
7823
|
return this;
|
|
7824
|
-
|
|
7824
|
+
const ranges = _Color.ranges[this._mode];
|
|
7825
7825
|
for (let i = 0; i < 3; i++) {
|
|
7826
7826
|
this[i] = !toNorm ? Num.mapToRange(this[i], 0, 1, ranges[i][0], ranges[i][1]) : Num.mapToRange(this[i], ranges[i][0], ranges[i][1], 0, 1);
|
|
7827
7827
|
}
|
|
@@ -7842,8 +7842,8 @@ var _Color = class extends Pt {
|
|
|
7842
7842
|
*/
|
|
7843
7843
|
toString(format = "mode") {
|
|
7844
7844
|
if (format == "hex") {
|
|
7845
|
-
|
|
7846
|
-
|
|
7845
|
+
const _hex = (n) => {
|
|
7846
|
+
const s = Math.floor(n).toString(16);
|
|
7847
7847
|
return s.length < 2 ? "0" + s : s;
|
|
7848
7848
|
};
|
|
7849
7849
|
return `#${_hex(this[0])}${_hex(this[1])}${_hex(this[2])}`;
|
|
@@ -7863,17 +7863,17 @@ var _Color = class extends Pt {
|
|
|
7863
7863
|
* @returns a new HSL Color
|
|
7864
7864
|
*/
|
|
7865
7865
|
static RGBtoHSL(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7866
|
+
const [r, g, b] = !normalizedInput ? rgb.$normalize() : rgb;
|
|
7867
|
+
const max = Math.max(r, g, b);
|
|
7868
|
+
const min = Math.min(r, g, b);
|
|
7869
7869
|
let h = (max + min) / 2;
|
|
7870
7870
|
let s = h;
|
|
7871
|
-
|
|
7871
|
+
const l = h;
|
|
7872
7872
|
if (max == min) {
|
|
7873
7873
|
h = 0;
|
|
7874
7874
|
s = 0;
|
|
7875
7875
|
} else {
|
|
7876
|
-
|
|
7876
|
+
const d = max - min;
|
|
7877
7877
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
7878
7878
|
h = 0;
|
|
7879
7879
|
if (max === r) {
|
|
@@ -7899,9 +7899,9 @@ var _Color = class extends Pt {
|
|
|
7899
7899
|
h = h / 360;
|
|
7900
7900
|
if (s == 0)
|
|
7901
7901
|
return _Color.rgb(l * 255, l * 255, l * 255, hsl.alpha);
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7902
|
+
const q = l <= 0.5 ? l * (1 + s) : l + s - l * s;
|
|
7903
|
+
const p = 2 * l - q;
|
|
7904
|
+
const convert = (t) => {
|
|
7905
7905
|
t = t < 0 ? t + 1 : t > 1 ? t - 1 : t;
|
|
7906
7906
|
if (t * 6 < 1) {
|
|
7907
7907
|
return p + (q - p) * t * 6;
|
|
@@ -7913,7 +7913,7 @@ var _Color = class extends Pt {
|
|
|
7913
7913
|
return p;
|
|
7914
7914
|
}
|
|
7915
7915
|
};
|
|
7916
|
-
|
|
7916
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7917
7917
|
return _Color.rgb(
|
|
7918
7918
|
sc * convert(h + 1 / 3),
|
|
7919
7919
|
sc * convert(h),
|
|
@@ -7929,13 +7929,13 @@ var _Color = class extends Pt {
|
|
|
7929
7929
|
* @returns a new HSB Color
|
|
7930
7930
|
*/
|
|
7931
7931
|
static RGBtoHSB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7932
|
+
const [r, g, b] = !normalizedInput ? rgb.$normalize() : rgb;
|
|
7933
|
+
const max = Math.max(r, g, b);
|
|
7934
|
+
const min = Math.min(r, g, b);
|
|
7935
|
+
const d = max - min;
|
|
7936
7936
|
let h = 0;
|
|
7937
|
-
|
|
7938
|
-
|
|
7937
|
+
const s = max === 0 ? 0 : d / max;
|
|
7938
|
+
const v = max;
|
|
7939
7939
|
if (max != min) {
|
|
7940
7940
|
if (max === r) {
|
|
7941
7941
|
h = (g - b) / d + (g < b ? 6 : 0);
|
|
@@ -7958,12 +7958,12 @@ var _Color = class extends Pt {
|
|
|
7958
7958
|
let [h, s, v] = hsb;
|
|
7959
7959
|
if (!normalizedInput)
|
|
7960
7960
|
h = h / 360;
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7961
|
+
const i = Math.floor(h * 6);
|
|
7962
|
+
const f = h * 6 - i;
|
|
7963
|
+
const p = v * (1 - s);
|
|
7964
|
+
const q = v * (1 - f * s);
|
|
7965
|
+
const t = v * (1 - (1 - f) * s);
|
|
7966
|
+
const pick = [
|
|
7967
7967
|
[v, t, p],
|
|
7968
7968
|
[q, v, p],
|
|
7969
7969
|
[p, v, t],
|
|
@@ -7971,8 +7971,8 @@ var _Color = class extends Pt {
|
|
|
7971
7971
|
[t, p, v],
|
|
7972
7972
|
[v, p, q]
|
|
7973
7973
|
];
|
|
7974
|
-
|
|
7975
|
-
|
|
7974
|
+
const c = pick[i % 6];
|
|
7975
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7976
7976
|
return _Color.rgb(
|
|
7977
7977
|
sc * c[0],
|
|
7978
7978
|
sc * c[1],
|
|
@@ -7988,7 +7988,7 @@ var _Color = class extends Pt {
|
|
|
7988
7988
|
* @returns a new LAB Color
|
|
7989
7989
|
*/
|
|
7990
7990
|
static RGBtoLAB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7991
|
-
|
|
7991
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7992
7992
|
return _Color.XYZtoLAB(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
7993
7993
|
}
|
|
7994
7994
|
/**
|
|
@@ -7999,7 +7999,7 @@ var _Color = class extends Pt {
|
|
|
7999
7999
|
* @returns a new RGB Color
|
|
8000
8000
|
*/
|
|
8001
8001
|
static LABtoRGB(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8002
|
-
|
|
8002
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8003
8003
|
return _Color.XYZtoRGB(_Color.LABtoXYZ(c), false, normalizedOutput);
|
|
8004
8004
|
}
|
|
8005
8005
|
/**
|
|
@@ -8010,7 +8010,7 @@ var _Color = class extends Pt {
|
|
|
8010
8010
|
* @returns a new LCH Color
|
|
8011
8011
|
*/
|
|
8012
8012
|
static RGBtoLCH(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8013
|
-
|
|
8013
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
8014
8014
|
return _Color.LABtoLCH(_Color.RGBtoLAB(c), false, normalizedOutput);
|
|
8015
8015
|
}
|
|
8016
8016
|
/**
|
|
@@ -8021,7 +8021,7 @@ var _Color = class extends Pt {
|
|
|
8021
8021
|
* @returns a new RGB Color
|
|
8022
8022
|
*/
|
|
8023
8023
|
static LCHtoRGB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
8024
|
-
|
|
8024
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8025
8025
|
return _Color.LABtoRGB(_Color.LCHtoLAB(c), false, normalizedOutput);
|
|
8026
8026
|
}
|
|
8027
8027
|
/**
|
|
@@ -8032,7 +8032,7 @@ var _Color = class extends Pt {
|
|
|
8032
8032
|
* @returns a new LUV Color
|
|
8033
8033
|
*/
|
|
8034
8034
|
static RGBtoLUV(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8035
|
-
|
|
8035
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
8036
8036
|
return _Color.XYZtoLUV(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
8037
8037
|
}
|
|
8038
8038
|
/**
|
|
@@ -8043,7 +8043,7 @@ var _Color = class extends Pt {
|
|
|
8043
8043
|
* @returns a new RGB Color
|
|
8044
8044
|
*/
|
|
8045
8045
|
static LUVtoRGB(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8046
|
-
|
|
8046
|
+
const c = normalizedInput ? luv.$normalize(false) : luv;
|
|
8047
8047
|
return _Color.XYZtoRGB(_Color.LUVtoXYZ(c), false, normalizedOutput);
|
|
8048
8048
|
}
|
|
8049
8049
|
/**
|
|
@@ -8054,13 +8054,13 @@ var _Color = class extends Pt {
|
|
|
8054
8054
|
* @returns a new XYZ Color
|
|
8055
8055
|
*/
|
|
8056
8056
|
static RGBtoXYZ(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8057
|
-
|
|
8057
|
+
const c = !normalizedInput ? rgb.$normalize() : rgb.clone();
|
|
8058
8058
|
for (let i = 0; i < 3; i++) {
|
|
8059
8059
|
c[i] = c[i] > 0.04045 ? Math.pow((c[i] + 0.055) / 1.055, 2.4) : c[i] / 12.92;
|
|
8060
8060
|
if (!normalizedOutput)
|
|
8061
8061
|
c[i] = c[i] * 100;
|
|
8062
8062
|
}
|
|
8063
|
-
|
|
8063
|
+
const cc = _Color.xyz(
|
|
8064
8064
|
c[0] * 0.4124564 + c[1] * 0.3575761 + c[2] * 0.1804375,
|
|
8065
8065
|
c[0] * 0.2126729 + c[1] * 0.7151522 + c[2] * 0.072175,
|
|
8066
8066
|
c[0] * 0.0193339 + c[1] * 0.119192 + c[2] * 0.9503041,
|
|
@@ -8076,8 +8076,8 @@ var _Color = class extends Pt {
|
|
|
8076
8076
|
* @returns a new RGB Color
|
|
8077
8077
|
*/
|
|
8078
8078
|
static XYZtoRGB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8079
|
-
|
|
8080
|
-
|
|
8079
|
+
const [x, y, z] = !normalizedInput ? xyz.$normalize() : xyz;
|
|
8080
|
+
const rgb = [
|
|
8081
8081
|
x * 3.2406254773200533 + y * -1.5372079722103187 + z * -0.4986285986982479,
|
|
8082
8082
|
x * -0.9689307147293197 + y * 1.8757560608852415 + z * 0.041517523842953964,
|
|
8083
8083
|
x * 0.055710120445510616 + y * -0.2040210505984867 + z * 1.0569959422543882
|
|
@@ -8088,7 +8088,7 @@ var _Color = class extends Pt {
|
|
|
8088
8088
|
if (!normalizedOutput)
|
|
8089
8089
|
rgb[i] = Math.round(rgb[i] * 255);
|
|
8090
8090
|
}
|
|
8091
|
-
|
|
8091
|
+
const cc = _Color.rgb(rgb[0], rgb[1], rgb[2], xyz.alpha);
|
|
8092
8092
|
return normalizedOutput ? cc.normalize() : cc;
|
|
8093
8093
|
}
|
|
8094
8094
|
/**
|
|
@@ -8099,13 +8099,13 @@ var _Color = class extends Pt {
|
|
|
8099
8099
|
* @returns a new LAB Color
|
|
8100
8100
|
*/
|
|
8101
8101
|
static XYZtoLAB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8102
|
-
|
|
8102
|
+
const c = normalizedInput ? xyz.$normalize(false) : xyz.clone();
|
|
8103
8103
|
const eps = 0.00885645167;
|
|
8104
8104
|
const kap = 903.296296296;
|
|
8105
8105
|
c.divide(_Color.D65);
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8106
|
+
const fn = (n) => n > eps ? Math.pow(n, 1 / 3) : (kap * n + 16) / 116;
|
|
8107
|
+
const cy = fn(c[1]);
|
|
8108
|
+
const cc = _Color.lab(
|
|
8109
8109
|
116 * cy - 16,
|
|
8110
8110
|
500 * (fn(c[0]) - cy),
|
|
8111
8111
|
200 * (cy - fn(c[2])),
|
|
@@ -8121,16 +8121,16 @@ var _Color = class extends Pt {
|
|
|
8121
8121
|
* @returns a new XYZ Color
|
|
8122
8122
|
*/
|
|
8123
8123
|
static LABtoXYZ(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8124
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8125
|
+
const y = (c[0] + 16) / 116;
|
|
8126
|
+
const x = c[1] / 500 + y;
|
|
8127
|
+
const z = y - c[2] / 200;
|
|
8128
8128
|
const eps = 0.00885645167;
|
|
8129
8129
|
const kap = 903.296296296;
|
|
8130
|
-
|
|
8130
|
+
const d = _Color.D65;
|
|
8131
8131
|
const xxx = Math.pow(x, 3);
|
|
8132
8132
|
const zzz = Math.pow(z, 3);
|
|
8133
|
-
|
|
8133
|
+
const cc = _Color.xyz(
|
|
8134
8134
|
d[0] * (xxx > eps ? xxx : (116 * x - 16) / kap),
|
|
8135
8135
|
d[1] * (c[0] > kap * eps ? Math.pow((c[0] + 16) / 116, 3) : c[0] / kap),
|
|
8136
8136
|
d[2] * (zzz > eps ? zzz : (116 * z - 16) / kap),
|
|
@@ -8147,13 +8147,13 @@ var _Color = class extends Pt {
|
|
|
8147
8147
|
*/
|
|
8148
8148
|
static XYZtoLUV(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8149
8149
|
let [x, y, z] = normalizedInput ? xyz.$normalize(false) : xyz;
|
|
8150
|
-
|
|
8151
|
-
|
|
8150
|
+
const u = 4 * x / (x + 15 * y + 3 * z);
|
|
8151
|
+
const v = 9 * y / (x + 15 * y + 3 * z);
|
|
8152
8152
|
y = y / 100;
|
|
8153
8153
|
y = y > 8856e-6 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8154
|
+
const refU = 4 * _Color.D65[0] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8155
|
+
const refV = 9 * _Color.D65[1] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8156
|
+
const L = 116 * y - 16;
|
|
8157
8157
|
return _Color.luv(
|
|
8158
8158
|
L,
|
|
8159
8159
|
13 * L * (u - refU),
|
|
@@ -8171,15 +8171,15 @@ var _Color = class extends Pt {
|
|
|
8171
8171
|
static LUVtoXYZ(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8172
8172
|
let [l, u, v] = normalizedInput ? luv.$normalize(false) : luv;
|
|
8173
8173
|
let y = (l + 16) / 116;
|
|
8174
|
-
|
|
8174
|
+
const cubeY = y * y * y;
|
|
8175
8175
|
y = cubeY > 8856e-6 ? cubeY : (y - 16 / 116) / 7.787;
|
|
8176
|
-
|
|
8177
|
-
|
|
8176
|
+
const refU = 4 * _Color.D65[0] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8177
|
+
const refV = 9 * _Color.D65[1] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8178
8178
|
u = u / (13 * l) + refU;
|
|
8179
8179
|
v = v / (13 * l) + refV;
|
|
8180
8180
|
y = y * 100;
|
|
8181
|
-
|
|
8182
|
-
|
|
8181
|
+
const x = -1 * (9 * y * u) / ((u - 4) * v - u * v);
|
|
8182
|
+
const z = (9 * y - 15 * v * y - v * x) / (3 * v);
|
|
8183
8183
|
return _Color.xyz(x, y, z, luv.alpha);
|
|
8184
8184
|
}
|
|
8185
8185
|
/**
|
|
@@ -8190,8 +8190,8 @@ var _Color = class extends Pt {
|
|
|
8190
8190
|
* @returns a new LCH Color
|
|
8191
8191
|
*/
|
|
8192
8192
|
static LABtoLCH(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8193
|
-
|
|
8194
|
-
|
|
8193
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8194
|
+
const h = Geom.toDegree(Geom.boundRadian(Math.atan2(c[2], c[1])));
|
|
8195
8195
|
return _Color.lch(
|
|
8196
8196
|
c[0],
|
|
8197
8197
|
Math.sqrt(c[1] * c[1] + c[2] * c[2]),
|
|
@@ -8207,8 +8207,8 @@ var _Color = class extends Pt {
|
|
|
8207
8207
|
* @returns a new LAB Color
|
|
8208
8208
|
*/
|
|
8209
8209
|
static LCHtoLAB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
8210
|
-
|
|
8211
|
-
|
|
8210
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8211
|
+
const rad = Geom.toRadian(c[2]);
|
|
8212
8212
|
return _Color.lab(
|
|
8213
8213
|
c[0],
|
|
8214
8214
|
Math.cos(rad) * c[1],
|
|
@@ -8217,13 +8217,12 @@ var _Color = class extends Pt {
|
|
|
8217
8217
|
);
|
|
8218
8218
|
}
|
|
8219
8219
|
};
|
|
8220
|
-
var Color = _Color;
|
|
8221
8220
|
// XYZ property for Standard Observer 2deg, Daylight/sRGB illuminant D65
|
|
8222
|
-
|
|
8221
|
+
_Color.D65 = new Pt(95.047, 100, 108.883, 1);
|
|
8223
8222
|
/**
|
|
8224
8223
|
* Value range for each color space
|
|
8225
8224
|
*/
|
|
8226
|
-
|
|
8225
|
+
_Color.ranges = {
|
|
8227
8226
|
rgb: new Group(new Pt(0, 255), new Pt(0, 255), new Pt(0, 255)),
|
|
8228
8227
|
hsl: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
8229
8228
|
hsb: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
@@ -8232,9 +8231,10 @@ Color.ranges = {
|
|
|
8232
8231
|
luv: new Group(new Pt(0, 100), new Pt(-134, 220), new Pt(-140, 122)),
|
|
8233
8232
|
xyz: new Group(new Pt(0, 100), new Pt(0, 100), new Pt(0, 100))
|
|
8234
8233
|
};
|
|
8234
|
+
var Color = _Color;
|
|
8235
8235
|
|
|
8236
8236
|
// src/Dom.ts
|
|
8237
|
-
var DOMSpace = class extends MultiTouchSpace {
|
|
8237
|
+
var DOMSpace = class _DOMSpace extends MultiTouchSpace {
|
|
8238
8238
|
/**
|
|
8239
8239
|
* Create a DOMSpace for HTML DOM elements
|
|
8240
8240
|
* @param elem Specify an element by its "id" attribute as string, or by the element object itself. Use css to customize its appearance if needed.
|
|
@@ -8247,8 +8247,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8247
8247
|
this._autoResize = true;
|
|
8248
8248
|
this._bgcolor = "#e1e9f0";
|
|
8249
8249
|
this._css = {};
|
|
8250
|
-
|
|
8251
|
-
|
|
8250
|
+
let _selector = null;
|
|
8251
|
+
let _existed = false;
|
|
8252
8252
|
this.id = "pts";
|
|
8253
8253
|
if (elem instanceof Element) {
|
|
8254
8254
|
_selector = elem;
|
|
@@ -8259,8 +8259,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8259
8259
|
this.id = elem.substr(1);
|
|
8260
8260
|
}
|
|
8261
8261
|
if (!_selector) {
|
|
8262
|
-
this._container =
|
|
8263
|
-
this._canvas =
|
|
8262
|
+
this._container = _DOMSpace.createElement("div", "pts_container");
|
|
8263
|
+
this._canvas = _DOMSpace.createElement("div", "pts_element");
|
|
8264
8264
|
this._container.appendChild(this._canvas);
|
|
8265
8265
|
document.body.appendChild(this._container);
|
|
8266
8266
|
_existed = false;
|
|
@@ -8522,7 +8522,7 @@ var HTMLSpace = class extends DOMSpace {
|
|
|
8522
8522
|
return super.removeAll();
|
|
8523
8523
|
}
|
|
8524
8524
|
};
|
|
8525
|
-
var _HTMLForm = class extends VisualForm {
|
|
8525
|
+
var _HTMLForm = class _HTMLForm extends VisualForm {
|
|
8526
8526
|
/**
|
|
8527
8527
|
* Create a new `HTMLForm`. Alternatively, you can use [`HTMLSpace.getForm`](#link) function to get an instance of HTMLForm.
|
|
8528
8528
|
* @param space the space to use
|
|
@@ -8941,12 +8941,12 @@ var _HTMLForm = class extends VisualForm {
|
|
|
8941
8941
|
return this;
|
|
8942
8942
|
}
|
|
8943
8943
|
};
|
|
8944
|
+
_HTMLForm.groupID = 0;
|
|
8945
|
+
_HTMLForm.domID = 0;
|
|
8944
8946
|
var HTMLForm = _HTMLForm;
|
|
8945
|
-
HTMLForm.groupID = 0;
|
|
8946
|
-
HTMLForm.domID = 0;
|
|
8947
8947
|
|
|
8948
8948
|
// src/Svg.ts
|
|
8949
|
-
var SVGSpace = class extends DOMSpace {
|
|
8949
|
+
var SVGSpace = class _SVGSpace extends DOMSpace {
|
|
8950
8950
|
/**
|
|
8951
8951
|
* Create a SVGSpace which represents a Space for SVG elements.
|
|
8952
8952
|
* @param elem Specify an element by its "id" attribute as string, or by the element object itself. An element can be an existing `<svg>`, or a `<div>` container in which a new `<svg>` will be created. If left empty, a `<div id="pt_container"><svg id="pt" /></div>` will be added to DOM. Use css to customize its appearance if needed.
|
|
@@ -8957,7 +8957,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8957
8957
|
super(elem, callback);
|
|
8958
8958
|
this._bgcolor = "#999";
|
|
8959
8959
|
if (this._canvas.nodeName.toLowerCase() != "svg") {
|
|
8960
|
-
let s =
|
|
8960
|
+
let s = _SVGSpace.svgElement(this._canvas, "svg", `${this.id}_svg`);
|
|
8961
8961
|
this._container = this._canvas;
|
|
8962
8962
|
this._canvas = s;
|
|
8963
8963
|
}
|
|
@@ -8983,7 +8983,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8983
8983
|
*/
|
|
8984
8984
|
resize(b, evt) {
|
|
8985
8985
|
super.resize(b, evt);
|
|
8986
|
-
|
|
8986
|
+
_SVGSpace.setAttr(this.element, {
|
|
8987
8987
|
"viewBox": `0 0 ${this.bound.width} ${this.bound.height}`,
|
|
8988
8988
|
"width": `${this.bound.width}`,
|
|
8989
8989
|
"height": `${this.bound.height}`,
|
|
@@ -9028,7 +9028,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
9028
9028
|
return super.removeAll();
|
|
9029
9029
|
}
|
|
9030
9030
|
};
|
|
9031
|
-
var _SVGForm = class extends VisualForm {
|
|
9031
|
+
var _SVGForm = class _SVGForm extends VisualForm {
|
|
9032
9032
|
/**
|
|
9033
9033
|
* Create a new SVGForm. You may also use [`SVGSpace.getForm`](#link) to get a default form directly.
|
|
9034
9034
|
* @param space an instance of SVGSpace
|
|
@@ -9522,12 +9522,12 @@ var _SVGForm = class extends VisualForm {
|
|
|
9522
9522
|
return this;
|
|
9523
9523
|
}
|
|
9524
9524
|
};
|
|
9525
|
+
_SVGForm.groupID = 0;
|
|
9526
|
+
_SVGForm.domID = 0;
|
|
9525
9527
|
var SVGForm = _SVGForm;
|
|
9526
|
-
SVGForm.groupID = 0;
|
|
9527
|
-
SVGForm.domID = 0;
|
|
9528
9528
|
|
|
9529
9529
|
// src/Physics.ts
|
|
9530
|
-
var World = class {
|
|
9530
|
+
var World = class _World {
|
|
9531
9531
|
/**
|
|
9532
9532
|
* Create a `World` for 2D physics simulation.
|
|
9533
9533
|
* @param bound a Group or an Iterable<Pt> representing a rectangular bounding box
|
|
@@ -9615,13 +9615,10 @@ var World = class {
|
|
|
9615
9615
|
* @returns a Body, or undefined if not found
|
|
9616
9616
|
*/
|
|
9617
9617
|
body(id) {
|
|
9618
|
-
let idx = id;
|
|
9619
9618
|
if (typeof id === "string" && id.length > 0) {
|
|
9620
|
-
|
|
9619
|
+
return this._bodies[this._bnames.indexOf(id)];
|
|
9621
9620
|
}
|
|
9622
|
-
|
|
9623
|
-
return void 0;
|
|
9624
|
-
return this._bodies[idx];
|
|
9621
|
+
return typeof id === "number" && id >= 0 ? this._bodies[id] : void 0;
|
|
9625
9622
|
}
|
|
9626
9623
|
/**
|
|
9627
9624
|
* Get a particle in this world by index or string id.
|
|
@@ -9629,13 +9626,10 @@ var World = class {
|
|
|
9629
9626
|
* @returns a Particle, or undefined if not found
|
|
9630
9627
|
*/
|
|
9631
9628
|
particle(id) {
|
|
9632
|
-
let idx = id;
|
|
9633
9629
|
if (typeof id === "string" && id.length > 0) {
|
|
9634
|
-
|
|
9630
|
+
return this._particles[this._pnames.indexOf(id)];
|
|
9635
9631
|
}
|
|
9636
|
-
|
|
9637
|
-
return void 0;
|
|
9638
|
-
return this._particles[idx];
|
|
9632
|
+
return typeof id === "number" && id >= 0 ? this._particles[id] : void 0;
|
|
9639
9633
|
}
|
|
9640
9634
|
/**
|
|
9641
9635
|
* Given a body's name, return its index in the bodies array, or -1 if not found.
|
|
@@ -9782,7 +9776,7 @@ var World = class {
|
|
|
9782
9776
|
for (let i = 0, len = this._particles.length; i < len; i++) {
|
|
9783
9777
|
let p = this._particles[i];
|
|
9784
9778
|
this.integrate(p, dt, this._lastTime);
|
|
9785
|
-
|
|
9779
|
+
_World.boundConstraint(p, this._bound, this._damping);
|
|
9786
9780
|
for (let k = i + 1; k < len; k++) {
|
|
9787
9781
|
if (i !== k) {
|
|
9788
9782
|
let p2 = this._particles[k];
|
|
@@ -9803,7 +9797,7 @@ var World = class {
|
|
|
9803
9797
|
if (bds) {
|
|
9804
9798
|
for (let k = 0, klen = bds.length; k < klen; k++) {
|
|
9805
9799
|
let bk = bds[k];
|
|
9806
|
-
|
|
9800
|
+
_World.boundConstraint(bk, this._bound, this._damping);
|
|
9807
9801
|
this.integrate(bk, dt, this._lastTime);
|
|
9808
9802
|
}
|
|
9809
9803
|
for (let k = i + 1; k < len; k++) {
|
|
@@ -9986,7 +9980,7 @@ var Particle = class extends Pt {
|
|
|
9986
9980
|
return `Particle: ${this[0]} ${this[1]} | previous ${this._prev[0]} ${this._prev[1]} | mass ${this._mass}`;
|
|
9987
9981
|
}
|
|
9988
9982
|
};
|
|
9989
|
-
var Body = class extends Group {
|
|
9983
|
+
var Body = class _Body extends Group {
|
|
9990
9984
|
/**
|
|
9991
9985
|
* Create an empty Body, this is usually followed by [`Body.init`](#link) to populate the Body. Alternatively, use static function [`Body.fromGroup`](#link) to create and initate a body directly.
|
|
9992
9986
|
*/
|
|
@@ -10005,7 +9999,7 @@ var Body = class extends Group {
|
|
|
10005
9999
|
* @param autoMass Automatically calculate the mass based on the area of the polygon. Default is true.
|
|
10006
10000
|
*/
|
|
10007
10001
|
static fromGroup(body, stiff = 1, autoLink = true, autoMass = true) {
|
|
10008
|
-
let b = new
|
|
10002
|
+
let b = new _Body().init(body);
|
|
10009
10003
|
if (autoLink)
|
|
10010
10004
|
b.linkAll(stiff);
|
|
10011
10005
|
if (autoMass)
|
|
@@ -10160,7 +10154,7 @@ var Body = class extends Group {
|
|
|
10160
10154
|
};
|
|
10161
10155
|
|
|
10162
10156
|
// src/Play.ts
|
|
10163
|
-
var Tempo = class {
|
|
10157
|
+
var Tempo = class _Tempo {
|
|
10164
10158
|
/**
|
|
10165
10159
|
* Construct a new Tempo instance by beats-per-minute. Alternatively, you can use [`Tempo.fromBeat`](#link) to create from milliseconds.
|
|
10166
10160
|
* @param bpm beats per minute
|
|
@@ -10176,7 +10170,7 @@ var Tempo = class {
|
|
|
10176
10170
|
* @param ms milliseconds per beat
|
|
10177
10171
|
*/
|
|
10178
10172
|
static fromBeat(ms) {
|
|
10179
|
-
return new
|
|
10173
|
+
return new _Tempo(6e4 / ms);
|
|
10180
10174
|
}
|
|
10181
10175
|
/**
|
|
10182
10176
|
* Beats-per-minute value
|
|
@@ -10218,16 +10212,16 @@ var Tempo = class {
|
|
|
10218
10212
|
* @returns an object with chainable functions
|
|
10219
10213
|
*/
|
|
10220
10214
|
every(beats) {
|
|
10221
|
-
|
|
10222
|
-
|
|
10215
|
+
const self = this;
|
|
10216
|
+
const p = Array.isArray(beats) ? beats[0] : beats;
|
|
10223
10217
|
return {
|
|
10224
10218
|
start: function(fn, offset = 0, name) {
|
|
10225
|
-
|
|
10219
|
+
const id = name || self._createID(fn);
|
|
10226
10220
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: false, fn };
|
|
10227
10221
|
return this;
|
|
10228
10222
|
},
|
|
10229
10223
|
progress: function(fn, offset = 0, name) {
|
|
10230
|
-
|
|
10224
|
+
const id = name || self._createID(fn);
|
|
10231
10225
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: true, fn };
|
|
10232
10226
|
return this;
|
|
10233
10227
|
}
|
|
@@ -10239,11 +10233,11 @@ var Tempo = class {
|
|
|
10239
10233
|
* @param time current time in milliseconds
|
|
10240
10234
|
*/
|
|
10241
10235
|
track(time) {
|
|
10242
|
-
for (
|
|
10236
|
+
for (const k in this._listeners) {
|
|
10243
10237
|
if (this._listeners.hasOwnProperty(k)) {
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
|
|
10238
|
+
const li = this._listeners[k];
|
|
10239
|
+
const _t = li.offset ? time + li.offset : time;
|
|
10240
|
+
const ms = li.period * this._ms;
|
|
10247
10241
|
let isStart = false;
|
|
10248
10242
|
if (_t > li.duration + ms) {
|
|
10249
10243
|
li.duration = _t - _t % this._ms;
|
|
@@ -10253,10 +10247,10 @@ var Tempo = class {
|
|
|
10253
10247
|
}
|
|
10254
10248
|
isStart = true;
|
|
10255
10249
|
}
|
|
10256
|
-
|
|
10257
|
-
|
|
10250
|
+
const count = Math.max(0, Math.ceil(Math.floor(li.duration / this._ms) / li.period));
|
|
10251
|
+
const params = li.continuous ? [count, Num.clamp((_t - li.duration) / ms, 0, 1), _t, isStart] : [count];
|
|
10258
10252
|
if (li.continuous || isStart) {
|
|
10259
|
-
|
|
10253
|
+
const done = li.fn.apply(li, params);
|
|
10260
10254
|
if (done)
|
|
10261
10255
|
delete this._listeners[li.name];
|
|
10262
10256
|
}
|
|
@@ -10290,7 +10284,7 @@ var Tempo = class {
|
|
|
10290
10284
|
return;
|
|
10291
10285
|
}
|
|
10292
10286
|
};
|
|
10293
|
-
var Sound = class {
|
|
10287
|
+
var Sound = class _Sound {
|
|
10294
10288
|
// Tracking play time against ctx.currentTime
|
|
10295
10289
|
/**
|
|
10296
10290
|
* Construct a `Sound` instance. Usually, it's more convenient to use one of the static methods like [`Sound.load`](#function_load) or [`Sound.from`](#function_from).
|
|
@@ -10305,7 +10299,7 @@ var Sound = class {
|
|
|
10305
10299
|
* Create an AudioContext instance. This is called internally only.
|
|
10306
10300
|
*/
|
|
10307
10301
|
_createAudioContext() {
|
|
10308
|
-
|
|
10302
|
+
const _ctx = window.AudioContext;
|
|
10309
10303
|
if (!_ctx)
|
|
10310
10304
|
throw new Error("Your browser doesn't support Web Audio. (No AudioContext)");
|
|
10311
10305
|
this._ctx = _ctx ? new _ctx() : void 0;
|
|
@@ -10319,7 +10313,7 @@ var Sound = class {
|
|
|
10319
10313
|
* @returns a `Sound` instance
|
|
10320
10314
|
*/
|
|
10321
10315
|
static from(node, ctx, type = "gen", stream) {
|
|
10322
|
-
|
|
10316
|
+
const s = new _Sound(type);
|
|
10323
10317
|
s._node = node;
|
|
10324
10318
|
s._ctx = ctx;
|
|
10325
10319
|
if (stream)
|
|
@@ -10335,7 +10329,7 @@ var Sound = class {
|
|
|
10335
10329
|
*/
|
|
10336
10330
|
static load(source, crossOrigin = "anonymous") {
|
|
10337
10331
|
return new Promise((resolve, reject) => {
|
|
10338
|
-
|
|
10332
|
+
const s = new _Sound("file");
|
|
10339
10333
|
s._source = typeof source === "string" ? new Audio(source) : source;
|
|
10340
10334
|
s._source.autoplay = false;
|
|
10341
10335
|
s._source.crossOrigin = crossOrigin;
|
|
@@ -10360,10 +10354,10 @@ var Sound = class {
|
|
|
10360
10354
|
*/
|
|
10361
10355
|
static loadAsBuffer(url) {
|
|
10362
10356
|
return new Promise((resolve, reject) => {
|
|
10363
|
-
|
|
10357
|
+
const request = new XMLHttpRequest();
|
|
10364
10358
|
request.open("GET", url, true);
|
|
10365
10359
|
request.responseType = "arraybuffer";
|
|
10366
|
-
|
|
10360
|
+
const s = new _Sound("file");
|
|
10367
10361
|
request.onload = function() {
|
|
10368
10362
|
s._ctx.decodeAudioData(request.response, function(buffer) {
|
|
10369
10363
|
s.createBuffer(buffer);
|
|
@@ -10395,13 +10389,13 @@ var Sound = class {
|
|
|
10395
10389
|
* @example `Sound.generate( 'sine', 120 )`
|
|
10396
10390
|
*/
|
|
10397
10391
|
static generate(type, val) {
|
|
10398
|
-
|
|
10392
|
+
const s = new _Sound("gen");
|
|
10399
10393
|
return s._gen(type, val);
|
|
10400
10394
|
}
|
|
10401
10395
|
// Create the oscillator
|
|
10402
10396
|
_gen(type, val) {
|
|
10403
10397
|
this._node = this._ctx.createOscillator();
|
|
10404
|
-
|
|
10398
|
+
const osc = this._node;
|
|
10405
10399
|
osc.type = type;
|
|
10406
10400
|
if (type === "custom") {
|
|
10407
10401
|
osc.setPeriodicWave(val);
|
|
@@ -10419,7 +10413,7 @@ var Sound = class {
|
|
|
10419
10413
|
static input(constraint) {
|
|
10420
10414
|
return __async(this, null, function* () {
|
|
10421
10415
|
try {
|
|
10422
|
-
|
|
10416
|
+
const s = new _Sound("input");
|
|
10423
10417
|
if (!s)
|
|
10424
10418
|
return void 0;
|
|
10425
10419
|
const c = constraint ? constraint : { audio: true, video: false };
|
|
@@ -10489,7 +10483,7 @@ var Sound = class {
|
|
|
10489
10483
|
get progress() {
|
|
10490
10484
|
let dur = 0;
|
|
10491
10485
|
let curr = 0;
|
|
10492
|
-
if (
|
|
10486
|
+
if (this._buffer) {
|
|
10493
10487
|
dur = this._buffer.duration;
|
|
10494
10488
|
curr = this._timestamp ? this._ctx.currentTime - this._timestamp : 0;
|
|
10495
10489
|
} else {
|
|
@@ -10561,7 +10555,7 @@ var Sound = class {
|
|
|
10561
10555
|
* @param smooth Optional smoothing value (corresponds to `AnalyserNode.smoothingTimeConstant`)
|
|
10562
10556
|
*/
|
|
10563
10557
|
analyze(size = 256, minDb = -100, maxDb = -30, smooth = 0.8) {
|
|
10564
|
-
|
|
10558
|
+
const a = this._ctx.createAnalyser();
|
|
10565
10559
|
a.fftSize = size * 2;
|
|
10566
10560
|
a.minDecibels = minDb;
|
|
10567
10561
|
a.maxDecibels = maxDb;
|
|
@@ -10588,8 +10582,8 @@ var Sound = class {
|
|
|
10588
10582
|
}
|
|
10589
10583
|
// Map domain data to another range
|
|
10590
10584
|
_domainTo(time, size, position = [0, 0], trim = [0, 0]) {
|
|
10591
|
-
|
|
10592
|
-
|
|
10585
|
+
const data = time ? this.timeDomain() : this.freqDomain();
|
|
10586
|
+
const g = new Group();
|
|
10593
10587
|
for (let i = trim[0], len = data.length - trim[1]; i < len; i++) {
|
|
10594
10588
|
g.push(new Pt(position[0] + size[0] * i / len, position[1] + size[1] * data[i] / 255));
|
|
10595
10589
|
}
|
|
@@ -10648,7 +10642,7 @@ var Sound = class {
|
|
|
10648
10642
|
this._ctx.resume();
|
|
10649
10643
|
}
|
|
10650
10644
|
if (this._type === "file") {
|
|
10651
|
-
if (
|
|
10645
|
+
if (this._buffer) {
|
|
10652
10646
|
this._node.start(timeAt);
|
|
10653
10647
|
this._timestamp = this._ctx.currentTime + timeAt;
|
|
10654
10648
|
} else {
|
|
@@ -10673,7 +10667,7 @@ var Sound = class {
|
|
|
10673
10667
|
if (this._playing)
|
|
10674
10668
|
(this._outputNode || this._node).disconnect(this._ctx.destination);
|
|
10675
10669
|
if (this._type === "file") {
|
|
10676
|
-
if (
|
|
10670
|
+
if (this._buffer) {
|
|
10677
10671
|
if (this.progress < 1)
|
|
10678
10672
|
this._node.stop();
|
|
10679
10673
|
} else {
|