pts 0.11.5 → 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 +31 -27
- package/dist/index.js +726 -707
- package/dist/index.mjs +726 -707
- package/dist/pts.js +727 -708
- package/dist/pts.min.js +4 -4
- 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
|
}
|
|
@@ -4300,10 +4300,12 @@ var UIPointerActions = {
|
|
|
4300
4300
|
click: "click",
|
|
4301
4301
|
keydown: "keydown",
|
|
4302
4302
|
keyup: "keyup",
|
|
4303
|
+
pointerdown: "pointerdown",
|
|
4304
|
+
pointerup: "pointerup",
|
|
4303
4305
|
contextmenu: "contextmenu",
|
|
4304
4306
|
all: "all"
|
|
4305
4307
|
};
|
|
4306
|
-
var _UI = class {
|
|
4308
|
+
var _UI = class _UI {
|
|
4307
4309
|
/**
|
|
4308
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).
|
|
4309
4311
|
* @param group a Group or an Iterable<PtLike> that defines the UI's appearance
|
|
@@ -4539,8 +4541,8 @@ var _UI = class {
|
|
|
4539
4541
|
}
|
|
4540
4542
|
}
|
|
4541
4543
|
};
|
|
4544
|
+
_UI._counter = 0;
|
|
4542
4545
|
var UI = _UI;
|
|
4543
|
-
UI._counter = 0;
|
|
4544
4546
|
var UIButton = class extends UI {
|
|
4545
4547
|
/**
|
|
4546
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).
|
|
@@ -4565,7 +4567,7 @@ var UIButton = class extends UI {
|
|
|
4565
4567
|
if (hover && !this._states.hover) {
|
|
4566
4568
|
this.state("hover", true);
|
|
4567
4569
|
UI._trigger(this._actions[UA.enter], this, pt, UA.enter, evt);
|
|
4568
|
-
|
|
4570
|
+
let _capID = this.hold(UA.move);
|
|
4569
4571
|
this._hoverID = this.on(UA.move, (t, p) => {
|
|
4570
4572
|
if (!this._within(p) && !this.state("dragging")) {
|
|
4571
4573
|
this.state("hover", false);
|
|
@@ -4616,7 +4618,7 @@ var UIButton = class extends UI {
|
|
|
4616
4618
|
* @returns id numbers that refer to enter/leave handlers, for use in [`UIButton.offHover`](#link) or [`UI.off`](#link).
|
|
4617
4619
|
*/
|
|
4618
4620
|
onHover(enter, leave) {
|
|
4619
|
-
|
|
4621
|
+
let ids = [void 0, void 0];
|
|
4620
4622
|
if (enter)
|
|
4621
4623
|
ids[0] = this.on(UIPointerActions.enter, enter);
|
|
4622
4624
|
if (leave)
|
|
@@ -4630,7 +4632,7 @@ var UIButton = class extends UI {
|
|
|
4630
4632
|
* @returns an array of booleans indicating whether the handlers were removed successfully
|
|
4631
4633
|
*/
|
|
4632
4634
|
offHover(enterID, leaveID) {
|
|
4633
|
-
|
|
4635
|
+
let s = [false, false];
|
|
4634
4636
|
if (enterID === void 0 || enterID >= 0)
|
|
4635
4637
|
s[0] = this.off(UIPointerActions.enter, enterID);
|
|
4636
4638
|
if (leaveID === void 0 || leaveID >= 0)
|
|
@@ -4773,9 +4775,9 @@ var Space = class {
|
|
|
4773
4775
|
* @param player an [`IPlayer`](#link) object with animate function, or a callback function `fn(time, ftime)`.
|
|
4774
4776
|
*/
|
|
4775
4777
|
add(p) {
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4778
|
+
const player = typeof p == "function" ? { animate: p } : p;
|
|
4779
|
+
const k = this.playerCount++;
|
|
4780
|
+
const pid = player.animateID || this.id + k;
|
|
4779
4781
|
this.players[pid] = player;
|
|
4780
4782
|
player.animateID = pid;
|
|
4781
4783
|
if (player.resize && this.bound.inited)
|
|
@@ -4842,7 +4844,7 @@ var Space = class {
|
|
|
4842
4844
|
if (this._refresh)
|
|
4843
4845
|
this.clear();
|
|
4844
4846
|
if (this._isReady) {
|
|
4845
|
-
for (
|
|
4847
|
+
for (const k in this.players) {
|
|
4846
4848
|
if (this.players[k].animate)
|
|
4847
4849
|
this.players[k].animate(time, this._time.diff, this);
|
|
4848
4850
|
}
|
|
@@ -4960,7 +4962,7 @@ var MultiTouchSpace = class extends Space {
|
|
|
4960
4962
|
* Get the mouse or touch pointer that stores the last action.
|
|
4961
4963
|
*/
|
|
4962
4964
|
get pointer() {
|
|
4963
|
-
|
|
4965
|
+
const p = this._pointer.clone();
|
|
4964
4966
|
p.id = this._pointer.id;
|
|
4965
4967
|
return p;
|
|
4966
4968
|
}
|
|
@@ -5012,9 +5014,13 @@ var MultiTouchSpace = class extends Space {
|
|
|
5012
5014
|
this._mouseOut = this._mouseOut.bind(this);
|
|
5013
5015
|
this._mouseMove = this._mouseMove.bind(this);
|
|
5014
5016
|
this._mouseClick = this._mouseClick.bind(this);
|
|
5017
|
+
this._pointerDown = this._pointerDown.bind(this);
|
|
5018
|
+
this._pointerUp = this._pointerUp.bind(this);
|
|
5015
5019
|
this._contextMenu = this._contextMenu.bind(this);
|
|
5016
5020
|
this.bindCanvas("mousedown", this._mouseDown, {}, customTarget);
|
|
5021
|
+
this.bindCanvas("pointerdown", this._pointerDown, {}, customTarget);
|
|
5017
5022
|
this.bindCanvas("mouseup", this._mouseUp, {}, customTarget);
|
|
5023
|
+
this.bindCanvas("pointerup", this._pointerUp, {}, customTarget);
|
|
5018
5024
|
this.bindCanvas("mouseover", this._mouseOver, {}, customTarget);
|
|
5019
5025
|
this.bindCanvas("mouseout", this._mouseOut, {}, customTarget);
|
|
5020
5026
|
this.bindCanvas("mousemove", this._mouseMove, {}, customTarget);
|
|
@@ -5023,7 +5029,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5023
5029
|
this._hasMouse = true;
|
|
5024
5030
|
} else {
|
|
5025
5031
|
this.unbindCanvas("mousedown", this._mouseDown, {}, customTarget);
|
|
5032
|
+
this.unbindCanvas("pointerdown", this._pointerDown, {}, customTarget);
|
|
5026
5033
|
this.unbindCanvas("mouseup", this._mouseUp, {}, customTarget);
|
|
5034
|
+
this.unbindCanvas("pointerup", this._pointerUp, {}, customTarget);
|
|
5027
5035
|
this.unbindCanvas("mouseover", this._mouseOver, {}, customTarget);
|
|
5028
5036
|
this.unbindCanvas("mouseout", this._mouseOut, {}, customTarget);
|
|
5029
5037
|
this.unbindCanvas("mousemove", this._mouseMove, {}, customTarget);
|
|
@@ -5081,9 +5089,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5081
5089
|
touchesToPoints(evt, which = "touches") {
|
|
5082
5090
|
if (!evt || !evt[which])
|
|
5083
5091
|
return [];
|
|
5084
|
-
|
|
5085
|
-
for (
|
|
5086
|
-
|
|
5092
|
+
const ts = [];
|
|
5093
|
+
for (let i = 0; i < evt[which].length; i++) {
|
|
5094
|
+
const t = evt[which].item(i);
|
|
5087
5095
|
ts.push(new Pt(t.pageX - this.bound.topLeft.x, t.pageY - this.bound.topLeft.y));
|
|
5088
5096
|
}
|
|
5089
5097
|
return ts;
|
|
@@ -5099,9 +5107,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5099
5107
|
return;
|
|
5100
5108
|
let px = 0, py = 0;
|
|
5101
5109
|
if (evt instanceof MouseEvent) {
|
|
5102
|
-
for (
|
|
5110
|
+
for (const k in this.players) {
|
|
5103
5111
|
if (this.players.hasOwnProperty(k)) {
|
|
5104
|
-
|
|
5112
|
+
const v = this.players[k];
|
|
5105
5113
|
px = evt.pageX - this.outerBound.x;
|
|
5106
5114
|
py = evt.pageY - this.outerBound.y;
|
|
5107
5115
|
if (v.action)
|
|
@@ -5109,11 +5117,11 @@ var MultiTouchSpace = class extends Space {
|
|
|
5109
5117
|
}
|
|
5110
5118
|
}
|
|
5111
5119
|
} else {
|
|
5112
|
-
for (
|
|
5120
|
+
for (const k in this.players) {
|
|
5113
5121
|
if (this.players.hasOwnProperty(k)) {
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5122
|
+
const v = this.players[k];
|
|
5123
|
+
const c = evt.changedTouches && evt.changedTouches.length > 0;
|
|
5124
|
+
const touch = evt.changedTouches.item(0);
|
|
5117
5125
|
px = c ? touch.pageX - this.outerBound.x : 0;
|
|
5118
5126
|
py = c ? touch.pageY - this.outerBound.y : 0;
|
|
5119
5127
|
if (v.action)
|
|
@@ -5135,6 +5143,13 @@ var MultiTouchSpace = class extends Space {
|
|
|
5135
5143
|
this._pressed = true;
|
|
5136
5144
|
return false;
|
|
5137
5145
|
}
|
|
5146
|
+
_pointerDown(evt) {
|
|
5147
|
+
this._mouseAction(UIPointerActions.pointerdown, evt);
|
|
5148
|
+
if (evt.target instanceof Element) {
|
|
5149
|
+
evt.target.setPointerCapture(evt.pointerId);
|
|
5150
|
+
}
|
|
5151
|
+
return false;
|
|
5152
|
+
}
|
|
5138
5153
|
/**
|
|
5139
5154
|
* MouseUp handler.
|
|
5140
5155
|
* @param evt
|
|
@@ -5149,6 +5164,16 @@ var MultiTouchSpace = class extends Space {
|
|
|
5149
5164
|
this._dragged = false;
|
|
5150
5165
|
return false;
|
|
5151
5166
|
}
|
|
5167
|
+
_pointerUp(evt) {
|
|
5168
|
+
this._mouseAction(UIPointerActions.pointerup, evt);
|
|
5169
|
+
if (evt.target instanceof Element) {
|
|
5170
|
+
evt.target.releasePointerCapture(evt.pointerId);
|
|
5171
|
+
if (this._dragged)
|
|
5172
|
+
this._mouseAction(UIPointerActions.drop, evt);
|
|
5173
|
+
this._dragged = false;
|
|
5174
|
+
}
|
|
5175
|
+
return false;
|
|
5176
|
+
}
|
|
5152
5177
|
/**
|
|
5153
5178
|
* MouseMove handler.
|
|
5154
5179
|
* @param evt
|
|
@@ -5227,9 +5252,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5227
5252
|
_keyboardAction(type, evt) {
|
|
5228
5253
|
if (!this.isPlaying)
|
|
5229
5254
|
return;
|
|
5230
|
-
for (
|
|
5255
|
+
for (const k in this.players) {
|
|
5231
5256
|
if (this.players.hasOwnProperty(k)) {
|
|
5232
|
-
|
|
5257
|
+
const v = this.players[k];
|
|
5233
5258
|
if (v.action)
|
|
5234
5259
|
v.action(type, evt.shiftKey ? 1 : 0, evt.altKey ? 1 : 0, evt);
|
|
5235
5260
|
}
|
|
@@ -5478,7 +5503,7 @@ var Typography = class {
|
|
|
5478
5503
|
};
|
|
5479
5504
|
|
|
5480
5505
|
// src/Image.ts
|
|
5481
|
-
var Img = class {
|
|
5506
|
+
var Img = class _Img {
|
|
5482
5507
|
/**
|
|
5483
5508
|
* Create an Img
|
|
5484
5509
|
* @param editable Specify if you want to manipulate pixels of this image. Default is `false`.
|
|
@@ -5503,7 +5528,7 @@ var Img = class {
|
|
|
5503
5528
|
* @param ready An optional ready callback function
|
|
5504
5529
|
*/
|
|
5505
5530
|
static load(src, editable = false, space, ready) {
|
|
5506
|
-
const img = new
|
|
5531
|
+
const img = new _Img(editable, space);
|
|
5507
5532
|
img.load(src).then((res) => {
|
|
5508
5533
|
if (ready)
|
|
5509
5534
|
ready(res);
|
|
@@ -5519,7 +5544,7 @@ var Img = class {
|
|
|
5519
5544
|
*/
|
|
5520
5545
|
static loadAsync(src, editable = false, space) {
|
|
5521
5546
|
return __async(this, null, function* () {
|
|
5522
|
-
const img = yield new
|
|
5547
|
+
const img = yield new _Img(editable, space).load(src);
|
|
5523
5548
|
return img;
|
|
5524
5549
|
});
|
|
5525
5550
|
}
|
|
@@ -5533,7 +5558,7 @@ var Img = class {
|
|
|
5533
5558
|
*/
|
|
5534
5559
|
static loadPattern(src, space, repeat = "repeat", editable = false) {
|
|
5535
5560
|
return __async(this, null, function* () {
|
|
5536
|
-
const img = yield
|
|
5561
|
+
const img = yield _Img.loadAsync(src, editable, space);
|
|
5537
5562
|
return img.pattern(repeat);
|
|
5538
5563
|
});
|
|
5539
5564
|
}
|
|
@@ -5544,7 +5569,7 @@ var Img = class {
|
|
|
5544
5569
|
* @param scale Optionally set a specific pixel scale (density) of the image canvas.
|
|
5545
5570
|
*/
|
|
5546
5571
|
static blank(size, space, scale) {
|
|
5547
|
-
let img = new
|
|
5572
|
+
let img = new _Img(true, space);
|
|
5548
5573
|
const s = scale ? scale : space.pixelScale;
|
|
5549
5574
|
img.initCanvas(size[0], size[1], s);
|
|
5550
5575
|
return img;
|
|
@@ -5650,7 +5675,7 @@ var Img = class {
|
|
|
5650
5675
|
*/
|
|
5651
5676
|
pixel(p, rescale = true) {
|
|
5652
5677
|
const s = typeof rescale == "number" ? rescale : rescale ? this._scale : 1;
|
|
5653
|
-
return
|
|
5678
|
+
return _Img.getPixel(this._data, [p[0] * s, p[1] * s]);
|
|
5654
5679
|
}
|
|
5655
5680
|
/**
|
|
5656
5681
|
* Given an ImaegData object and a position, return the RGBA pixel value at that position.
|
|
@@ -5715,7 +5740,7 @@ var Img = class {
|
|
|
5715
5740
|
*/
|
|
5716
5741
|
static fromBlob(blob, editable = false, space) {
|
|
5717
5742
|
let url = URL.createObjectURL(blob);
|
|
5718
|
-
return new
|
|
5743
|
+
return new _Img(editable, space).load(url);
|
|
5719
5744
|
}
|
|
5720
5745
|
/**
|
|
5721
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.
|
|
@@ -5843,8 +5868,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5843
5868
|
this._bgcolor = "#e1e9f0";
|
|
5844
5869
|
this._offscreen = false;
|
|
5845
5870
|
this._initialResize = false;
|
|
5846
|
-
|
|
5847
|
-
|
|
5871
|
+
let _selector = null;
|
|
5872
|
+
let _existed = false;
|
|
5848
5873
|
this.id = "pt";
|
|
5849
5874
|
if (elem instanceof Element) {
|
|
5850
5875
|
_selector = elem;
|
|
@@ -5881,7 +5906,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5881
5906
|
* @param id element id attribute
|
|
5882
5907
|
*/
|
|
5883
5908
|
_createElement(elem = "div", id) {
|
|
5884
|
-
|
|
5909
|
+
const d = document.createElement(elem);
|
|
5885
5910
|
d.setAttribute("id", id);
|
|
5886
5911
|
return d;
|
|
5887
5912
|
}
|
|
@@ -5896,7 +5921,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5896
5921
|
this._resizeHandler(null);
|
|
5897
5922
|
this.clear(this._bgcolor);
|
|
5898
5923
|
this._canvas.dispatchEvent(new Event("ready"));
|
|
5899
|
-
for (
|
|
5924
|
+
for (const k in this.players) {
|
|
5900
5925
|
if (this.players.hasOwnProperty(k)) {
|
|
5901
5926
|
if (this.players[k].start)
|
|
5902
5927
|
this.players[k].start(this.bound.clone(), this);
|
|
@@ -5916,8 +5941,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5916
5941
|
this._bgcolor = opt.bgcolor ? opt.bgcolor : "transparent";
|
|
5917
5942
|
this.autoResize = opt.resize != void 0 ? opt.resize : false;
|
|
5918
5943
|
if (opt.retina !== false) {
|
|
5919
|
-
|
|
5920
|
-
|
|
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;
|
|
5921
5946
|
this._pixelScale = Math.max(1, r1 / r2);
|
|
5922
5947
|
}
|
|
5923
5948
|
if (opt.offscreen) {
|
|
@@ -5971,9 +5996,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5971
5996
|
this._offCtx.scale(this._pixelScale, this._pixelScale);
|
|
5972
5997
|
}
|
|
5973
5998
|
}
|
|
5974
|
-
for (
|
|
5999
|
+
for (const k in this.players) {
|
|
5975
6000
|
if (this.players.hasOwnProperty(k)) {
|
|
5976
|
-
|
|
6001
|
+
const p = this.players[k];
|
|
5977
6002
|
if (p.resize)
|
|
5978
6003
|
p.resize(this.bound, evt);
|
|
5979
6004
|
}
|
|
@@ -5990,9 +6015,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5990
6015
|
_resizeHandler(evt) {
|
|
5991
6016
|
if (!window)
|
|
5992
6017
|
return;
|
|
5993
|
-
|
|
6018
|
+
const b = this._autoResize || this._initialResize ? this._container.getBoundingClientRect() : this._canvas.getBoundingClientRect();
|
|
5994
6019
|
if (b) {
|
|
5995
|
-
|
|
6020
|
+
const box = Bound.fromBoundingRect(b);
|
|
5996
6021
|
box.center = box.center.add(window.pageXOffset, window.pageYOffset);
|
|
5997
6022
|
this.resize(box, evt);
|
|
5998
6023
|
}
|
|
@@ -6135,14 +6160,14 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6135
6160
|
* @example `let rec = space.recorder(true); rec.start(); setTimeout( () => rec.stop(), 5000); // record 5s of video and download the file`
|
|
6136
6161
|
*/
|
|
6137
6162
|
recorder(downloadOrCallback, filetype = "webm", bitrate = 15e6) {
|
|
6138
|
-
|
|
6163
|
+
const stream = this._canvas.captureStream();
|
|
6139
6164
|
const recorder = new MediaRecorder(stream, { mimeType: `video/${filetype}`, bitsPerSecond: bitrate });
|
|
6140
6165
|
recorder.ondataavailable = function(d) {
|
|
6141
|
-
|
|
6166
|
+
const url = URL.createObjectURL(new Blob([d.data], { type: `video/${filetype}` }));
|
|
6142
6167
|
if (typeof downloadOrCallback === "function") {
|
|
6143
6168
|
downloadOrCallback(url);
|
|
6144
6169
|
} else if (downloadOrCallback) {
|
|
6145
|
-
|
|
6170
|
+
const a = document.createElement("a");
|
|
6146
6171
|
a.href = url;
|
|
6147
6172
|
a.download = `canvas_video.${filetype}`;
|
|
6148
6173
|
a.click();
|
|
@@ -6152,7 +6177,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6152
6177
|
return recorder;
|
|
6153
6178
|
}
|
|
6154
6179
|
};
|
|
6155
|
-
var CanvasForm = class extends VisualForm {
|
|
6180
|
+
var CanvasForm = class _CanvasForm extends VisualForm {
|
|
6156
6181
|
/**
|
|
6157
6182
|
* Create a new CanvasForm. You may also use [`CanvasSpace.getForm()`](#link) to get the default form.
|
|
6158
6183
|
* @param space an instance of CanvasSpace
|
|
@@ -6229,20 +6254,20 @@ var CanvasForm = class extends VisualForm {
|
|
|
6229
6254
|
}
|
|
6230
6255
|
}
|
|
6231
6256
|
/**
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6257
|
+
* Set current alpha value.
|
|
6258
|
+
* @example `form.alpha(0.6)`
|
|
6259
|
+
* @param a alpha value between 0 and 1
|
|
6260
|
+
*/
|
|
6236
6261
|
alpha(a) {
|
|
6237
6262
|
this._ctx.globalAlpha = a;
|
|
6238
6263
|
this._style.globalAlpha = a;
|
|
6239
6264
|
return this;
|
|
6240
6265
|
}
|
|
6241
6266
|
/**
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
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
|
+
*/
|
|
6246
6271
|
fill(c) {
|
|
6247
6272
|
if (typeof c == "boolean") {
|
|
6248
6273
|
this.filled = c;
|
|
@@ -6254,21 +6279,21 @@ var CanvasForm = class extends VisualForm {
|
|
|
6254
6279
|
return this;
|
|
6255
6280
|
}
|
|
6256
6281
|
/**
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
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
|
+
*/
|
|
6260
6285
|
fillOnly(c) {
|
|
6261
6286
|
this.stroke(false);
|
|
6262
6287
|
return this.fill(c);
|
|
6263
6288
|
}
|
|
6264
6289
|
/**
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
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
|
+
*/
|
|
6272
6297
|
stroke(c, width, linejoin, linecap) {
|
|
6273
6298
|
if (typeof c == "boolean") {
|
|
6274
6299
|
this.stroked = c;
|
|
@@ -6292,24 +6317,24 @@ var CanvasForm = class extends VisualForm {
|
|
|
6292
6317
|
return this;
|
|
6293
6318
|
}
|
|
6294
6319
|
/**
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
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
|
+
*/
|
|
6301
6326
|
strokeOnly(c, width, linejoin, linecap) {
|
|
6302
6327
|
this.fill(false);
|
|
6303
6328
|
return this.stroke(c, width, linejoin, linecap);
|
|
6304
6329
|
}
|
|
6305
6330
|
/**
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
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
|
+
*/
|
|
6313
6338
|
applyFillStroke(filled = true, stroked = true, strokeWidth = 1) {
|
|
6314
6339
|
if (filled) {
|
|
6315
6340
|
if (typeof filled === "string")
|
|
@@ -6324,22 +6349,22 @@ var CanvasForm = class extends VisualForm {
|
|
|
6324
6349
|
return this;
|
|
6325
6350
|
}
|
|
6326
6351
|
/**
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
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
|
+
*/
|
|
6332
6357
|
gradient(stops) {
|
|
6333
|
-
|
|
6358
|
+
const vals = [];
|
|
6334
6359
|
if (stops.length < 2)
|
|
6335
6360
|
stops.push([0.99, "#000"], [1, "#000"]);
|
|
6336
6361
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
6337
|
-
|
|
6338
|
-
|
|
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];
|
|
6339
6364
|
vals.push([t, v]);
|
|
6340
6365
|
}
|
|
6341
6366
|
return (area1, area2) => {
|
|
6342
|
-
|
|
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]);
|
|
6343
6368
|
for (let i = 0, len = vals.length; i < len; i++) {
|
|
6344
6369
|
grad.addColorStop(vals[i][0], vals[i][1]);
|
|
6345
6370
|
}
|
|
@@ -6347,26 +6372,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6347
6372
|
};
|
|
6348
6373
|
}
|
|
6349
6374
|
/**
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
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
|
+
*/
|
|
6353
6378
|
composite(mode = "source-over") {
|
|
6354
6379
|
this._ctx.globalCompositeOperation = mode;
|
|
6355
6380
|
return this;
|
|
6356
6381
|
}
|
|
6357
6382
|
/**
|
|
6358
|
-
|
|
6359
|
-
|
|
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
|
+
*/
|
|
6360
6385
|
clip() {
|
|
6361
6386
|
this._ctx.clip();
|
|
6362
6387
|
return this;
|
|
6363
6388
|
}
|
|
6364
6389
|
/**
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
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
|
+
*/
|
|
6370
6395
|
dash(segments = true, offset = 0) {
|
|
6371
6396
|
if (!segments) {
|
|
6372
6397
|
this._ctx.setLineDash([]);
|
|
@@ -6381,14 +6406,14 @@ var CanvasForm = class extends VisualForm {
|
|
|
6381
6406
|
return this;
|
|
6382
6407
|
}
|
|
6383
6408
|
/**
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
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
|
+
*/
|
|
6392
6417
|
font(sizeOrFont, weight, style, lineHeight, family) {
|
|
6393
6418
|
if (typeof sizeOrFont == "number") {
|
|
6394
6419
|
this._font.size = sizeOrFont;
|
|
@@ -6409,49 +6434,49 @@ var CanvasForm = class extends VisualForm {
|
|
|
6409
6434
|
return this;
|
|
6410
6435
|
}
|
|
6411
6436
|
/**
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
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
|
+
*/
|
|
6415
6440
|
fontWidthEstimate(estimate = true) {
|
|
6416
6441
|
this._estimateTextWidth = estimate ? Typography.textWidthEstimator((c) => this._ctx.measureText(c).width) : void 0;
|
|
6417
6442
|
return this;
|
|
6418
6443
|
}
|
|
6419
6444
|
/**
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
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
|
+
*/
|
|
6423
6448
|
getTextWidth(c) {
|
|
6424
6449
|
return !this._estimateTextWidth ? this._ctx.measureText(c + " .").width : this._estimateTextWidth(c);
|
|
6425
6450
|
}
|
|
6426
6451
|
/**
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
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
|
+
*/
|
|
6432
6457
|
_textTruncate(str, width, tail = "") {
|
|
6433
6458
|
return Typography.truncate(this.getTextWidth.bind(this), str, width, tail);
|
|
6434
6459
|
}
|
|
6435
6460
|
/**
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
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
|
+
*/
|
|
6442
6467
|
_textAlign(box, vertical, offset, center) {
|
|
6443
|
-
|
|
6468
|
+
const _box = Util.iterToArray(box);
|
|
6444
6469
|
if (!Util.arrayCheck(_box))
|
|
6445
6470
|
return;
|
|
6446
6471
|
if (!center)
|
|
6447
6472
|
center = Rectangle.center(_box);
|
|
6448
|
-
|
|
6473
|
+
let px = _box[0][0];
|
|
6449
6474
|
if (this._ctx.textAlign == "end" || this._ctx.textAlign == "right") {
|
|
6450
6475
|
px = _box[1][0];
|
|
6451
6476
|
} else if (this._ctx.textAlign == "center" || this._ctx.textAlign == "middle") {
|
|
6452
6477
|
px = center[0];
|
|
6453
6478
|
}
|
|
6454
|
-
|
|
6479
|
+
let py = center[1];
|
|
6455
6480
|
if (vertical == "top" || vertical == "start") {
|
|
6456
6481
|
py = _box[0][1];
|
|
6457
6482
|
} else if (vertical == "end" || vertical == "bottom") {
|
|
@@ -6460,10 +6485,10 @@ var CanvasForm = class extends VisualForm {
|
|
|
6460
6485
|
return offset ? new Pt(px + offset[0], py + offset[1]) : new Pt(px, py);
|
|
6461
6486
|
}
|
|
6462
6487
|
/**
|
|
6463
|
-
|
|
6464
|
-
|
|
6488
|
+
* Reset the rendering context's common styles to this form's styles. This supports using multiple forms on the same canvas context.
|
|
6489
|
+
*/
|
|
6465
6490
|
reset() {
|
|
6466
|
-
for (
|
|
6491
|
+
for (const k in this._style) {
|
|
6467
6492
|
if (this._style.hasOwnProperty(k)) {
|
|
6468
6493
|
this._ctx[k] = this._style[k];
|
|
6469
6494
|
}
|
|
@@ -6479,38 +6504,38 @@ var CanvasForm = class extends VisualForm {
|
|
|
6479
6504
|
this._ctx.stroke();
|
|
6480
6505
|
}
|
|
6481
6506
|
/**
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
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
|
+
*/
|
|
6489
6514
|
static point(ctx, p, radius = 5, shape = "square") {
|
|
6490
6515
|
if (!p)
|
|
6491
6516
|
return;
|
|
6492
|
-
if (!
|
|
6517
|
+
if (!_CanvasForm[shape])
|
|
6493
6518
|
throw new Error(`${shape} is not a static function of CanvasForm`);
|
|
6494
|
-
|
|
6519
|
+
_CanvasForm[shape](ctx, p, radius);
|
|
6495
6520
|
}
|
|
6496
6521
|
/**
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
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
|
+
*/
|
|
6503
6528
|
point(p, radius = 5, shape = "square") {
|
|
6504
|
-
|
|
6529
|
+
_CanvasForm.point(this._ctx, p, radius, shape);
|
|
6505
6530
|
this._paint();
|
|
6506
6531
|
return this;
|
|
6507
6532
|
}
|
|
6508
6533
|
/**
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
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
|
+
*/
|
|
6514
6539
|
static circle(ctx, pt, radius = 10) {
|
|
6515
6540
|
if (!pt)
|
|
6516
6541
|
return;
|
|
@@ -6519,25 +6544,25 @@ var CanvasForm = class extends VisualForm {
|
|
|
6519
6544
|
ctx.closePath();
|
|
6520
6545
|
}
|
|
6521
6546
|
/**
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
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
|
+
*/
|
|
6525
6550
|
circle(pts) {
|
|
6526
|
-
|
|
6527
|
-
|
|
6551
|
+
const p = Util.iterToArray(pts);
|
|
6552
|
+
_CanvasForm.circle(this._ctx, p[0], p[1][0]);
|
|
6528
6553
|
this._paint();
|
|
6529
6554
|
return this;
|
|
6530
6555
|
}
|
|
6531
6556
|
/**
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
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
|
+
*/
|
|
6541
6566
|
static ellipse(ctx, pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6542
6567
|
if (!pt || !radius)
|
|
6543
6568
|
return;
|
|
@@ -6545,28 +6570,28 @@ var CanvasForm = class extends VisualForm {
|
|
|
6545
6570
|
ctx.ellipse(pt[0], pt[1], radius[0], radius[1], rotation, startAngle, endAngle, cc);
|
|
6546
6571
|
}
|
|
6547
6572
|
/**
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
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
|
+
*/
|
|
6556
6581
|
ellipse(pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6557
|
-
|
|
6582
|
+
_CanvasForm.ellipse(this._ctx, pt, radius, rotation, startAngle, endAngle, cc);
|
|
6558
6583
|
this._paint();
|
|
6559
6584
|
return this;
|
|
6560
6585
|
}
|
|
6561
6586
|
/**
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
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
|
+
*/
|
|
6570
6595
|
static arc(ctx, pt, radius, startAngle, endAngle, cc) {
|
|
6571
6596
|
if (!pt)
|
|
6572
6597
|
return;
|
|
@@ -6574,31 +6599,31 @@ var CanvasForm = class extends VisualForm {
|
|
|
6574
6599
|
ctx.arc(pt[0], pt[1], radius, startAngle, endAngle, cc);
|
|
6575
6600
|
}
|
|
6576
6601
|
/**
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
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
|
+
*/
|
|
6584
6609
|
arc(pt, radius, startAngle, endAngle, cc) {
|
|
6585
|
-
|
|
6610
|
+
_CanvasForm.arc(this._ctx, pt, radius, startAngle, endAngle, cc);
|
|
6586
6611
|
this._paint();
|
|
6587
6612
|
return this;
|
|
6588
6613
|
}
|
|
6589
6614
|
/**
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
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
|
+
*/
|
|
6595
6620
|
static square(ctx, pt, halfsize) {
|
|
6596
6621
|
if (!pt)
|
|
6597
6622
|
return;
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6623
|
+
const x1 = pt[0] - halfsize;
|
|
6624
|
+
const y1 = pt[1] - halfsize;
|
|
6625
|
+
const x2 = pt[0] + halfsize;
|
|
6626
|
+
const y2 = pt[1] + halfsize;
|
|
6602
6627
|
ctx.beginPath();
|
|
6603
6628
|
ctx.moveTo(x1, y1);
|
|
6604
6629
|
ctx.lineTo(x1, y2);
|
|
@@ -6607,26 +6632,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6607
6632
|
ctx.closePath();
|
|
6608
6633
|
}
|
|
6609
6634
|
/**
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6635
|
+
* Draw a square, given a center and its half-size.
|
|
6636
|
+
* @param pt center Pt
|
|
6637
|
+
* @param halfsize half-size
|
|
6638
|
+
*/
|
|
6614
6639
|
square(pt, halfsize) {
|
|
6615
|
-
|
|
6640
|
+
_CanvasForm.square(this._ctx, pt, halfsize);
|
|
6616
6641
|
this._paint();
|
|
6617
6642
|
return this;
|
|
6618
6643
|
}
|
|
6619
6644
|
/**
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
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
|
+
*/
|
|
6624
6649
|
static line(ctx, pts) {
|
|
6625
6650
|
if (!Util.arrayCheck(pts))
|
|
6626
6651
|
return;
|
|
6627
6652
|
let i = 0;
|
|
6628
6653
|
ctx.beginPath();
|
|
6629
|
-
for (
|
|
6654
|
+
for (const it of pts) {
|
|
6630
6655
|
if (it) {
|
|
6631
6656
|
if (i++ > 0) {
|
|
6632
6657
|
ctx.lineTo(it[0], it[1]);
|
|
@@ -6637,41 +6662,41 @@ var CanvasForm = class extends VisualForm {
|
|
|
6637
6662
|
}
|
|
6638
6663
|
}
|
|
6639
6664
|
/**
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6665
|
+
* Draw a line or polyline.
|
|
6666
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6667
|
+
*/
|
|
6643
6668
|
line(pts) {
|
|
6644
|
-
|
|
6669
|
+
_CanvasForm.line(this._ctx, pts);
|
|
6645
6670
|
this._paint();
|
|
6646
6671
|
return this;
|
|
6647
6672
|
}
|
|
6648
6673
|
/**
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
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
|
+
*/
|
|
6653
6678
|
static polygon(ctx, pts) {
|
|
6654
6679
|
if (!Util.arrayCheck(pts))
|
|
6655
6680
|
return;
|
|
6656
|
-
|
|
6681
|
+
_CanvasForm.line(ctx, pts);
|
|
6657
6682
|
ctx.closePath();
|
|
6658
6683
|
}
|
|
6659
6684
|
/**
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6685
|
+
* Draw a polygon.
|
|
6686
|
+
* @param pts a Group or an Iterable<PtLike> representingg a polygon
|
|
6687
|
+
*/
|
|
6663
6688
|
polygon(pts) {
|
|
6664
|
-
|
|
6689
|
+
_CanvasForm.polygon(this._ctx, pts);
|
|
6665
6690
|
this._paint();
|
|
6666
6691
|
return this;
|
|
6667
6692
|
}
|
|
6668
6693
|
/**
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
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
|
+
*/
|
|
6673
6698
|
static rect(ctx, pts) {
|
|
6674
|
-
|
|
6699
|
+
const p = Util.iterToArray(pts);
|
|
6675
6700
|
if (!Util.arrayCheck(p))
|
|
6676
6701
|
return;
|
|
6677
6702
|
ctx.beginPath();
|
|
@@ -6682,29 +6707,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6682
6707
|
ctx.closePath();
|
|
6683
6708
|
}
|
|
6684
6709
|
/**
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
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
|
+
*/
|
|
6688
6713
|
rect(pts) {
|
|
6689
|
-
|
|
6714
|
+
_CanvasForm.rect(this._ctx, pts);
|
|
6690
6715
|
this._paint();
|
|
6691
6716
|
return this;
|
|
6692
6717
|
}
|
|
6693
6718
|
/**
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
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
|
+
*/
|
|
6700
6725
|
static image(ctx, ptOrRect, img, orig) {
|
|
6701
|
-
|
|
6726
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6702
6727
|
let pos;
|
|
6703
6728
|
if (typeof t[0] === "number") {
|
|
6704
6729
|
pos = t;
|
|
6705
6730
|
} else {
|
|
6706
6731
|
if (orig) {
|
|
6707
|
-
|
|
6732
|
+
const o = Util.iterToArray(orig);
|
|
6708
6733
|
pos = [
|
|
6709
6734
|
o[0][0],
|
|
6710
6735
|
o[0][1],
|
|
@@ -6728,29 +6753,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6728
6753
|
}
|
|
6729
6754
|
}
|
|
6730
6755
|
/**
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
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
|
+
*/
|
|
6736
6761
|
image(ptOrRect, img, orig) {
|
|
6737
6762
|
if (img instanceof Img) {
|
|
6738
6763
|
if (img.loaded) {
|
|
6739
|
-
|
|
6764
|
+
_CanvasForm.image(this._ctx, ptOrRect, img.image, orig);
|
|
6740
6765
|
}
|
|
6741
6766
|
} else {
|
|
6742
|
-
|
|
6767
|
+
_CanvasForm.image(this._ctx, ptOrRect, img, orig);
|
|
6743
6768
|
}
|
|
6744
6769
|
return this;
|
|
6745
6770
|
}
|
|
6746
6771
|
/**
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
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
|
+
*/
|
|
6752
6777
|
static imageData(ctx, ptOrRect, img) {
|
|
6753
|
-
|
|
6778
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6754
6779
|
if (typeof t[0] === "number") {
|
|
6755
6780
|
ctx.putImageData(img, t[0], t[1]);
|
|
6756
6781
|
} else {
|
|
@@ -6758,74 +6783,74 @@ var CanvasForm = class extends VisualForm {
|
|
|
6758
6783
|
}
|
|
6759
6784
|
}
|
|
6760
6785
|
/**
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
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
|
+
*/
|
|
6765
6790
|
imageData(ptOrRect, img) {
|
|
6766
|
-
|
|
6791
|
+
_CanvasForm.imageData(this._ctx, ptOrRect, img);
|
|
6767
6792
|
return this;
|
|
6768
6793
|
}
|
|
6769
6794
|
/**
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
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
|
+
*/
|
|
6776
6801
|
static text(ctx, pt, txt, maxWidth) {
|
|
6777
6802
|
if (!pt)
|
|
6778
6803
|
return;
|
|
6779
6804
|
ctx.fillText(txt, pt[0], pt[1], maxWidth);
|
|
6780
6805
|
}
|
|
6781
6806
|
/**
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
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
|
+
*/
|
|
6787
6812
|
text(pt, txt, maxWidth) {
|
|
6788
|
-
|
|
6813
|
+
_CanvasForm.text(this._ctx, pt, txt, maxWidth);
|
|
6789
6814
|
return this;
|
|
6790
6815
|
}
|
|
6791
6816
|
/**
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
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
|
+
*/
|
|
6799
6824
|
textBox(box, txt, verticalAlign = "middle", tail = "", overrideBaseline = true) {
|
|
6800
6825
|
if (overrideBaseline)
|
|
6801
6826
|
this._ctx.textBaseline = verticalAlign;
|
|
6802
|
-
|
|
6803
|
-
|
|
6827
|
+
const size = Rectangle.size(box);
|
|
6828
|
+
const t = this._textTruncate(txt, size[0], tail);
|
|
6804
6829
|
this.text(this._textAlign(box, verticalAlign), t[0]);
|
|
6805
6830
|
return this;
|
|
6806
6831
|
}
|
|
6807
6832
|
/**
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
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
|
+
*/
|
|
6815
6840
|
paragraphBox(box, txt, lineHeight = 1.2, verticalAlign = "top", crop = true) {
|
|
6816
|
-
|
|
6817
|
-
|
|
6841
|
+
const b = Util.iterToArray(box);
|
|
6842
|
+
const size = Rectangle.size(b);
|
|
6818
6843
|
this._ctx.textBaseline = "top";
|
|
6819
|
-
|
|
6820
|
-
|
|
6844
|
+
const lstep = this._font.size * lineHeight;
|
|
6845
|
+
const nextLine = (sub, buffer = [], cc = 0) => {
|
|
6821
6846
|
if (!sub)
|
|
6822
6847
|
return buffer;
|
|
6823
6848
|
if (crop && cc * lstep > size[1] - lstep * 2)
|
|
6824
6849
|
return buffer;
|
|
6825
6850
|
if (cc > 1e4)
|
|
6826
6851
|
throw new Error("max recursion reached (10000)");
|
|
6827
|
-
|
|
6828
|
-
|
|
6852
|
+
const t = this._textTruncate(sub, size[0], "");
|
|
6853
|
+
const newln = t[0].indexOf("\n");
|
|
6829
6854
|
if (newln >= 0) {
|
|
6830
6855
|
buffer.push(t[0].substr(0, newln));
|
|
6831
6856
|
return nextLine(sub.substr(newln + 1), buffer, cc + 1);
|
|
@@ -6833,12 +6858,12 @@ var CanvasForm = class extends VisualForm {
|
|
|
6833
6858
|
let dt = t[0].lastIndexOf(" ") + 1;
|
|
6834
6859
|
if (dt <= 0 || t[1] === sub.length)
|
|
6835
6860
|
dt = void 0;
|
|
6836
|
-
|
|
6861
|
+
const line = t[0].substr(0, dt);
|
|
6837
6862
|
buffer.push(line);
|
|
6838
6863
|
return t[1] <= 0 || t[1] === sub.length ? buffer : nextLine(sub.substr(dt || t[1]), buffer, cc + 1);
|
|
6839
6864
|
};
|
|
6840
|
-
|
|
6841
|
-
|
|
6865
|
+
const lines = nextLine(txt);
|
|
6866
|
+
const lsize = lines.length * lstep;
|
|
6842
6867
|
let lbox = b;
|
|
6843
6868
|
if (verticalAlign == "middle" || verticalAlign == "center") {
|
|
6844
6869
|
let lpad = (size[1] - lsize) / 2;
|
|
@@ -6850,17 +6875,17 @@ var CanvasForm = class extends VisualForm {
|
|
|
6850
6875
|
} else {
|
|
6851
6876
|
lbox = new Group(b[0], b[0].$add(size[0], lsize));
|
|
6852
6877
|
}
|
|
6853
|
-
|
|
6878
|
+
const center = Rectangle.center(lbox);
|
|
6854
6879
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
6855
6880
|
this.text(this._textAlign(lbox, "top", [0, i * lstep], center), lines[i]);
|
|
6856
6881
|
}
|
|
6857
6882
|
return this;
|
|
6858
6883
|
}
|
|
6859
6884
|
/**
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
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
|
+
*/
|
|
6864
6889
|
alignText(alignment = "left", baseline = "alphabetic") {
|
|
6865
6890
|
if (baseline == "center")
|
|
6866
6891
|
baseline = "middle";
|
|
@@ -6871,11 +6896,11 @@ var CanvasForm = class extends VisualForm {
|
|
|
6871
6896
|
return this;
|
|
6872
6897
|
}
|
|
6873
6898
|
/**
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
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
|
+
*/
|
|
6877
6902
|
log(txt) {
|
|
6878
|
-
|
|
6903
|
+
const w = this._ctx.measureText(txt).width + 20;
|
|
6879
6904
|
this.stroke(false).fill("rgba(0,0,0,.4)").rect([[0, 0], [w, 20]]);
|
|
6880
6905
|
this.fill("#fff").text([10, 14], txt);
|
|
6881
6906
|
return this;
|
|
@@ -7338,7 +7363,7 @@ var Noise = class extends Pt {
|
|
|
7338
7363
|
return Num.lerp(Num.lerp(n00, n10, tx), Num.lerp(n01, n11, tx), _fade(y));
|
|
7339
7364
|
}
|
|
7340
7365
|
};
|
|
7341
|
-
var Delaunay = class extends Group {
|
|
7366
|
+
var Delaunay = class _Delaunay extends Group {
|
|
7342
7367
|
constructor() {
|
|
7343
7368
|
super(...arguments);
|
|
7344
7369
|
this._mesh = [];
|
|
@@ -7385,7 +7410,7 @@ var Delaunay = class extends Group {
|
|
|
7385
7410
|
edges.push(circum.i, circum.j, circum.j, circum.k, circum.k, circum.i);
|
|
7386
7411
|
opened.splice(j, 1);
|
|
7387
7412
|
}
|
|
7388
|
-
|
|
7413
|
+
_Delaunay._dedupe(edges);
|
|
7389
7414
|
j = edges.length;
|
|
7390
7415
|
while (j > 1) {
|
|
7391
7416
|
opened.push(this._circum(edges[--j], edges[--j], c, false, pts));
|
|
@@ -7527,7 +7552,7 @@ var Delaunay = class extends Group {
|
|
|
7527
7552
|
};
|
|
7528
7553
|
|
|
7529
7554
|
// src/Color.ts
|
|
7530
|
-
var _Color = class extends Pt {
|
|
7555
|
+
var _Color = class _Color extends Pt {
|
|
7531
7556
|
/**
|
|
7532
7557
|
* Create a Color. Same as creating a Pt. Optionally you may use [`Color.from`](#link) to create a color.
|
|
7533
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
|
|
@@ -7542,8 +7567,8 @@ var _Color = class extends Pt {
|
|
|
7542
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
|
|
7543
7568
|
*/
|
|
7544
7569
|
static from(...args) {
|
|
7545
|
-
|
|
7546
|
-
|
|
7570
|
+
const p = [1, 1, 1, 1];
|
|
7571
|
+
const c = Util.getArgs(args);
|
|
7547
7572
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
7548
7573
|
if (i < c.length)
|
|
7549
7574
|
p[i] = c[i];
|
|
@@ -7558,7 +7583,7 @@ var _Color = class extends Pt {
|
|
|
7558
7583
|
if (hex[0] == "#")
|
|
7559
7584
|
hex = hex.substr(1);
|
|
7560
7585
|
if (hex.length <= 3) {
|
|
7561
|
-
|
|
7586
|
+
const fn = (i) => hex[i] || "F";
|
|
7562
7587
|
hex = `${fn(0)}${fn(0)}${fn(1)}${fn(1)}${fn(2)}${fn(2)}`;
|
|
7563
7588
|
}
|
|
7564
7589
|
let alpha = 1;
|
|
@@ -7566,7 +7591,7 @@ var _Color = class extends Pt {
|
|
|
7566
7591
|
alpha = hex.substr(6) && 255 / 255;
|
|
7567
7592
|
hex = hex.substring(0, 6);
|
|
7568
7593
|
}
|
|
7569
|
-
|
|
7594
|
+
const hexVal = parseInt(hex, 16);
|
|
7570
7595
|
return new _Color(hexVal >> 16, hexVal >> 8 & 255, hexVal & 255, alpha);
|
|
7571
7596
|
}
|
|
7572
7597
|
/**
|
|
@@ -7648,7 +7673,7 @@ var _Color = class extends Pt {
|
|
|
7648
7673
|
* Clone this Color.
|
|
7649
7674
|
*/
|
|
7650
7675
|
clone() {
|
|
7651
|
-
|
|
7676
|
+
const c = new _Color(this);
|
|
7652
7677
|
c.toMode(this._mode);
|
|
7653
7678
|
return c;
|
|
7654
7679
|
}
|
|
@@ -7659,7 +7684,7 @@ var _Color = class extends Pt {
|
|
|
7659
7684
|
*/
|
|
7660
7685
|
toMode(mode, convert = false) {
|
|
7661
7686
|
if (convert) {
|
|
7662
|
-
|
|
7687
|
+
const fname = this._mode.toUpperCase() + "to" + mode.toUpperCase();
|
|
7663
7688
|
if (_Color[fname]) {
|
|
7664
7689
|
this.to(_Color[fname](this, this._isNorm, this._isNorm));
|
|
7665
7690
|
} else {
|
|
@@ -7711,7 +7736,7 @@ var _Color = class extends Pt {
|
|
|
7711
7736
|
return this._mode == "lch" ? this[2] : this[0];
|
|
7712
7737
|
}
|
|
7713
7738
|
set h(n) {
|
|
7714
|
-
|
|
7739
|
+
const i = this._mode == "lch" ? 2 : 0;
|
|
7715
7740
|
this[i] = n;
|
|
7716
7741
|
}
|
|
7717
7742
|
/**
|
|
@@ -7730,7 +7755,7 @@ var _Color = class extends Pt {
|
|
|
7730
7755
|
return this._mode == "hsl" ? this[2] : this[0];
|
|
7731
7756
|
}
|
|
7732
7757
|
set l(n) {
|
|
7733
|
-
|
|
7758
|
+
const i = this._mode == "hsl" ? 2 : 0;
|
|
7734
7759
|
this[i] = n;
|
|
7735
7760
|
}
|
|
7736
7761
|
// lab, lch, luv
|
|
@@ -7796,7 +7821,7 @@ var _Color = class extends Pt {
|
|
|
7796
7821
|
normalize(toNorm = true) {
|
|
7797
7822
|
if (this._isNorm == toNorm)
|
|
7798
7823
|
return this;
|
|
7799
|
-
|
|
7824
|
+
const ranges = _Color.ranges[this._mode];
|
|
7800
7825
|
for (let i = 0; i < 3; i++) {
|
|
7801
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);
|
|
7802
7827
|
}
|
|
@@ -7817,8 +7842,8 @@ var _Color = class extends Pt {
|
|
|
7817
7842
|
*/
|
|
7818
7843
|
toString(format = "mode") {
|
|
7819
7844
|
if (format == "hex") {
|
|
7820
|
-
|
|
7821
|
-
|
|
7845
|
+
const _hex = (n) => {
|
|
7846
|
+
const s = Math.floor(n).toString(16);
|
|
7822
7847
|
return s.length < 2 ? "0" + s : s;
|
|
7823
7848
|
};
|
|
7824
7849
|
return `#${_hex(this[0])}${_hex(this[1])}${_hex(this[2])}`;
|
|
@@ -7838,17 +7863,17 @@ var _Color = class extends Pt {
|
|
|
7838
7863
|
* @returns a new HSL Color
|
|
7839
7864
|
*/
|
|
7840
7865
|
static RGBtoHSL(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
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);
|
|
7844
7869
|
let h = (max + min) / 2;
|
|
7845
7870
|
let s = h;
|
|
7846
|
-
|
|
7871
|
+
const l = h;
|
|
7847
7872
|
if (max == min) {
|
|
7848
7873
|
h = 0;
|
|
7849
7874
|
s = 0;
|
|
7850
7875
|
} else {
|
|
7851
|
-
|
|
7876
|
+
const d = max - min;
|
|
7852
7877
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
7853
7878
|
h = 0;
|
|
7854
7879
|
if (max === r) {
|
|
@@ -7874,9 +7899,9 @@ var _Color = class extends Pt {
|
|
|
7874
7899
|
h = h / 360;
|
|
7875
7900
|
if (s == 0)
|
|
7876
7901
|
return _Color.rgb(l * 255, l * 255, l * 255, hsl.alpha);
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7902
|
+
const q = l <= 0.5 ? l * (1 + s) : l + s - l * s;
|
|
7903
|
+
const p = 2 * l - q;
|
|
7904
|
+
const convert = (t) => {
|
|
7880
7905
|
t = t < 0 ? t + 1 : t > 1 ? t - 1 : t;
|
|
7881
7906
|
if (t * 6 < 1) {
|
|
7882
7907
|
return p + (q - p) * t * 6;
|
|
@@ -7888,7 +7913,7 @@ var _Color = class extends Pt {
|
|
|
7888
7913
|
return p;
|
|
7889
7914
|
}
|
|
7890
7915
|
};
|
|
7891
|
-
|
|
7916
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7892
7917
|
return _Color.rgb(
|
|
7893
7918
|
sc * convert(h + 1 / 3),
|
|
7894
7919
|
sc * convert(h),
|
|
@@ -7904,13 +7929,13 @@ var _Color = class extends Pt {
|
|
|
7904
7929
|
* @returns a new HSB Color
|
|
7905
7930
|
*/
|
|
7906
7931
|
static RGBtoHSB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
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;
|
|
7911
7936
|
let h = 0;
|
|
7912
|
-
|
|
7913
|
-
|
|
7937
|
+
const s = max === 0 ? 0 : d / max;
|
|
7938
|
+
const v = max;
|
|
7914
7939
|
if (max != min) {
|
|
7915
7940
|
if (max === r) {
|
|
7916
7941
|
h = (g - b) / d + (g < b ? 6 : 0);
|
|
@@ -7933,12 +7958,12 @@ var _Color = class extends Pt {
|
|
|
7933
7958
|
let [h, s, v] = hsb;
|
|
7934
7959
|
if (!normalizedInput)
|
|
7935
7960
|
h = h / 360;
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
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 = [
|
|
7942
7967
|
[v, t, p],
|
|
7943
7968
|
[q, v, p],
|
|
7944
7969
|
[p, v, t],
|
|
@@ -7946,8 +7971,8 @@ var _Color = class extends Pt {
|
|
|
7946
7971
|
[t, p, v],
|
|
7947
7972
|
[v, p, q]
|
|
7948
7973
|
];
|
|
7949
|
-
|
|
7950
|
-
|
|
7974
|
+
const c = pick[i % 6];
|
|
7975
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7951
7976
|
return _Color.rgb(
|
|
7952
7977
|
sc * c[0],
|
|
7953
7978
|
sc * c[1],
|
|
@@ -7963,7 +7988,7 @@ var _Color = class extends Pt {
|
|
|
7963
7988
|
* @returns a new LAB Color
|
|
7964
7989
|
*/
|
|
7965
7990
|
static RGBtoLAB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7966
|
-
|
|
7991
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7967
7992
|
return _Color.XYZtoLAB(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
7968
7993
|
}
|
|
7969
7994
|
/**
|
|
@@ -7974,7 +7999,7 @@ var _Color = class extends Pt {
|
|
|
7974
7999
|
* @returns a new RGB Color
|
|
7975
8000
|
*/
|
|
7976
8001
|
static LABtoRGB(lab, normalizedInput = false, normalizedOutput = false) {
|
|
7977
|
-
|
|
8002
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
7978
8003
|
return _Color.XYZtoRGB(_Color.LABtoXYZ(c), false, normalizedOutput);
|
|
7979
8004
|
}
|
|
7980
8005
|
/**
|
|
@@ -7985,7 +8010,7 @@ var _Color = class extends Pt {
|
|
|
7985
8010
|
* @returns a new LCH Color
|
|
7986
8011
|
*/
|
|
7987
8012
|
static RGBtoLCH(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7988
|
-
|
|
8013
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7989
8014
|
return _Color.LABtoLCH(_Color.RGBtoLAB(c), false, normalizedOutput);
|
|
7990
8015
|
}
|
|
7991
8016
|
/**
|
|
@@ -7996,7 +8021,7 @@ var _Color = class extends Pt {
|
|
|
7996
8021
|
* @returns a new RGB Color
|
|
7997
8022
|
*/
|
|
7998
8023
|
static LCHtoRGB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
7999
|
-
|
|
8024
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8000
8025
|
return _Color.LABtoRGB(_Color.LCHtoLAB(c), false, normalizedOutput);
|
|
8001
8026
|
}
|
|
8002
8027
|
/**
|
|
@@ -8007,7 +8032,7 @@ var _Color = class extends Pt {
|
|
|
8007
8032
|
* @returns a new LUV Color
|
|
8008
8033
|
*/
|
|
8009
8034
|
static RGBtoLUV(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8010
|
-
|
|
8035
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
8011
8036
|
return _Color.XYZtoLUV(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
8012
8037
|
}
|
|
8013
8038
|
/**
|
|
@@ -8018,7 +8043,7 @@ var _Color = class extends Pt {
|
|
|
8018
8043
|
* @returns a new RGB Color
|
|
8019
8044
|
*/
|
|
8020
8045
|
static LUVtoRGB(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8021
|
-
|
|
8046
|
+
const c = normalizedInput ? luv.$normalize(false) : luv;
|
|
8022
8047
|
return _Color.XYZtoRGB(_Color.LUVtoXYZ(c), false, normalizedOutput);
|
|
8023
8048
|
}
|
|
8024
8049
|
/**
|
|
@@ -8029,13 +8054,13 @@ var _Color = class extends Pt {
|
|
|
8029
8054
|
* @returns a new XYZ Color
|
|
8030
8055
|
*/
|
|
8031
8056
|
static RGBtoXYZ(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8032
|
-
|
|
8057
|
+
const c = !normalizedInput ? rgb.$normalize() : rgb.clone();
|
|
8033
8058
|
for (let i = 0; i < 3; i++) {
|
|
8034
8059
|
c[i] = c[i] > 0.04045 ? Math.pow((c[i] + 0.055) / 1.055, 2.4) : c[i] / 12.92;
|
|
8035
8060
|
if (!normalizedOutput)
|
|
8036
8061
|
c[i] = c[i] * 100;
|
|
8037
8062
|
}
|
|
8038
|
-
|
|
8063
|
+
const cc = _Color.xyz(
|
|
8039
8064
|
c[0] * 0.4124564 + c[1] * 0.3575761 + c[2] * 0.1804375,
|
|
8040
8065
|
c[0] * 0.2126729 + c[1] * 0.7151522 + c[2] * 0.072175,
|
|
8041
8066
|
c[0] * 0.0193339 + c[1] * 0.119192 + c[2] * 0.9503041,
|
|
@@ -8051,8 +8076,8 @@ var _Color = class extends Pt {
|
|
|
8051
8076
|
* @returns a new RGB Color
|
|
8052
8077
|
*/
|
|
8053
8078
|
static XYZtoRGB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8054
|
-
|
|
8055
|
-
|
|
8079
|
+
const [x, y, z] = !normalizedInput ? xyz.$normalize() : xyz;
|
|
8080
|
+
const rgb = [
|
|
8056
8081
|
x * 3.2406254773200533 + y * -1.5372079722103187 + z * -0.4986285986982479,
|
|
8057
8082
|
x * -0.9689307147293197 + y * 1.8757560608852415 + z * 0.041517523842953964,
|
|
8058
8083
|
x * 0.055710120445510616 + y * -0.2040210505984867 + z * 1.0569959422543882
|
|
@@ -8063,7 +8088,7 @@ var _Color = class extends Pt {
|
|
|
8063
8088
|
if (!normalizedOutput)
|
|
8064
8089
|
rgb[i] = Math.round(rgb[i] * 255);
|
|
8065
8090
|
}
|
|
8066
|
-
|
|
8091
|
+
const cc = _Color.rgb(rgb[0], rgb[1], rgb[2], xyz.alpha);
|
|
8067
8092
|
return normalizedOutput ? cc.normalize() : cc;
|
|
8068
8093
|
}
|
|
8069
8094
|
/**
|
|
@@ -8074,13 +8099,13 @@ var _Color = class extends Pt {
|
|
|
8074
8099
|
* @returns a new LAB Color
|
|
8075
8100
|
*/
|
|
8076
8101
|
static XYZtoLAB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8077
|
-
|
|
8102
|
+
const c = normalizedInput ? xyz.$normalize(false) : xyz.clone();
|
|
8078
8103
|
const eps = 0.00885645167;
|
|
8079
8104
|
const kap = 903.296296296;
|
|
8080
8105
|
c.divide(_Color.D65);
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
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(
|
|
8084
8109
|
116 * cy - 16,
|
|
8085
8110
|
500 * (fn(c[0]) - cy),
|
|
8086
8111
|
200 * (cy - fn(c[2])),
|
|
@@ -8096,16 +8121,16 @@ var _Color = class extends Pt {
|
|
|
8096
8121
|
* @returns a new XYZ Color
|
|
8097
8122
|
*/
|
|
8098
8123
|
static LABtoXYZ(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
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;
|
|
8103
8128
|
const eps = 0.00885645167;
|
|
8104
8129
|
const kap = 903.296296296;
|
|
8105
|
-
|
|
8130
|
+
const d = _Color.D65;
|
|
8106
8131
|
const xxx = Math.pow(x, 3);
|
|
8107
8132
|
const zzz = Math.pow(z, 3);
|
|
8108
|
-
|
|
8133
|
+
const cc = _Color.xyz(
|
|
8109
8134
|
d[0] * (xxx > eps ? xxx : (116 * x - 16) / kap),
|
|
8110
8135
|
d[1] * (c[0] > kap * eps ? Math.pow((c[0] + 16) / 116, 3) : c[0] / kap),
|
|
8111
8136
|
d[2] * (zzz > eps ? zzz : (116 * z - 16) / kap),
|
|
@@ -8122,13 +8147,13 @@ var _Color = class extends Pt {
|
|
|
8122
8147
|
*/
|
|
8123
8148
|
static XYZtoLUV(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8124
8149
|
let [x, y, z] = normalizedInput ? xyz.$normalize(false) : xyz;
|
|
8125
|
-
|
|
8126
|
-
|
|
8150
|
+
const u = 4 * x / (x + 15 * y + 3 * z);
|
|
8151
|
+
const v = 9 * y / (x + 15 * y + 3 * z);
|
|
8127
8152
|
y = y / 100;
|
|
8128
8153
|
y = y > 8856e-6 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
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;
|
|
8132
8157
|
return _Color.luv(
|
|
8133
8158
|
L,
|
|
8134
8159
|
13 * L * (u - refU),
|
|
@@ -8146,15 +8171,15 @@ var _Color = class extends Pt {
|
|
|
8146
8171
|
static LUVtoXYZ(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8147
8172
|
let [l, u, v] = normalizedInput ? luv.$normalize(false) : luv;
|
|
8148
8173
|
let y = (l + 16) / 116;
|
|
8149
|
-
|
|
8174
|
+
const cubeY = y * y * y;
|
|
8150
8175
|
y = cubeY > 8856e-6 ? cubeY : (y - 16 / 116) / 7.787;
|
|
8151
|
-
|
|
8152
|
-
|
|
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]);
|
|
8153
8178
|
u = u / (13 * l) + refU;
|
|
8154
8179
|
v = v / (13 * l) + refV;
|
|
8155
8180
|
y = y * 100;
|
|
8156
|
-
|
|
8157
|
-
|
|
8181
|
+
const x = -1 * (9 * y * u) / ((u - 4) * v - u * v);
|
|
8182
|
+
const z = (9 * y - 15 * v * y - v * x) / (3 * v);
|
|
8158
8183
|
return _Color.xyz(x, y, z, luv.alpha);
|
|
8159
8184
|
}
|
|
8160
8185
|
/**
|
|
@@ -8165,8 +8190,8 @@ var _Color = class extends Pt {
|
|
|
8165
8190
|
* @returns a new LCH Color
|
|
8166
8191
|
*/
|
|
8167
8192
|
static LABtoLCH(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8168
|
-
|
|
8169
|
-
|
|
8193
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8194
|
+
const h = Geom.toDegree(Geom.boundRadian(Math.atan2(c[2], c[1])));
|
|
8170
8195
|
return _Color.lch(
|
|
8171
8196
|
c[0],
|
|
8172
8197
|
Math.sqrt(c[1] * c[1] + c[2] * c[2]),
|
|
@@ -8182,8 +8207,8 @@ var _Color = class extends Pt {
|
|
|
8182
8207
|
* @returns a new LAB Color
|
|
8183
8208
|
*/
|
|
8184
8209
|
static LCHtoLAB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
8185
|
-
|
|
8186
|
-
|
|
8210
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8211
|
+
const rad = Geom.toRadian(c[2]);
|
|
8187
8212
|
return _Color.lab(
|
|
8188
8213
|
c[0],
|
|
8189
8214
|
Math.cos(rad) * c[1],
|
|
@@ -8192,13 +8217,12 @@ var _Color = class extends Pt {
|
|
|
8192
8217
|
);
|
|
8193
8218
|
}
|
|
8194
8219
|
};
|
|
8195
|
-
var Color = _Color;
|
|
8196
8220
|
// XYZ property for Standard Observer 2deg, Daylight/sRGB illuminant D65
|
|
8197
|
-
|
|
8221
|
+
_Color.D65 = new Pt(95.047, 100, 108.883, 1);
|
|
8198
8222
|
/**
|
|
8199
8223
|
* Value range for each color space
|
|
8200
8224
|
*/
|
|
8201
|
-
|
|
8225
|
+
_Color.ranges = {
|
|
8202
8226
|
rgb: new Group(new Pt(0, 255), new Pt(0, 255), new Pt(0, 255)),
|
|
8203
8227
|
hsl: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
8204
8228
|
hsb: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
@@ -8207,9 +8231,10 @@ Color.ranges = {
|
|
|
8207
8231
|
luv: new Group(new Pt(0, 100), new Pt(-134, 220), new Pt(-140, 122)),
|
|
8208
8232
|
xyz: new Group(new Pt(0, 100), new Pt(0, 100), new Pt(0, 100))
|
|
8209
8233
|
};
|
|
8234
|
+
var Color = _Color;
|
|
8210
8235
|
|
|
8211
8236
|
// src/Dom.ts
|
|
8212
|
-
var DOMSpace = class extends MultiTouchSpace {
|
|
8237
|
+
var DOMSpace = class _DOMSpace extends MultiTouchSpace {
|
|
8213
8238
|
/**
|
|
8214
8239
|
* Create a DOMSpace for HTML DOM elements
|
|
8215
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.
|
|
@@ -8222,8 +8247,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8222
8247
|
this._autoResize = true;
|
|
8223
8248
|
this._bgcolor = "#e1e9f0";
|
|
8224
8249
|
this._css = {};
|
|
8225
|
-
|
|
8226
|
-
|
|
8250
|
+
let _selector = null;
|
|
8251
|
+
let _existed = false;
|
|
8227
8252
|
this.id = "pts";
|
|
8228
8253
|
if (elem instanceof Element) {
|
|
8229
8254
|
_selector = elem;
|
|
@@ -8234,8 +8259,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8234
8259
|
this.id = elem.substr(1);
|
|
8235
8260
|
}
|
|
8236
8261
|
if (!_selector) {
|
|
8237
|
-
this._container =
|
|
8238
|
-
this._canvas =
|
|
8262
|
+
this._container = _DOMSpace.createElement("div", "pts_container");
|
|
8263
|
+
this._canvas = _DOMSpace.createElement("div", "pts_element");
|
|
8239
8264
|
this._container.appendChild(this._canvas);
|
|
8240
8265
|
document.body.appendChild(this._container);
|
|
8241
8266
|
_existed = false;
|
|
@@ -8497,7 +8522,7 @@ var HTMLSpace = class extends DOMSpace {
|
|
|
8497
8522
|
return super.removeAll();
|
|
8498
8523
|
}
|
|
8499
8524
|
};
|
|
8500
|
-
var _HTMLForm = class extends VisualForm {
|
|
8525
|
+
var _HTMLForm = class _HTMLForm extends VisualForm {
|
|
8501
8526
|
/**
|
|
8502
8527
|
* Create a new `HTMLForm`. Alternatively, you can use [`HTMLSpace.getForm`](#link) function to get an instance of HTMLForm.
|
|
8503
8528
|
* @param space the space to use
|
|
@@ -8916,12 +8941,12 @@ var _HTMLForm = class extends VisualForm {
|
|
|
8916
8941
|
return this;
|
|
8917
8942
|
}
|
|
8918
8943
|
};
|
|
8944
|
+
_HTMLForm.groupID = 0;
|
|
8945
|
+
_HTMLForm.domID = 0;
|
|
8919
8946
|
var HTMLForm = _HTMLForm;
|
|
8920
|
-
HTMLForm.groupID = 0;
|
|
8921
|
-
HTMLForm.domID = 0;
|
|
8922
8947
|
|
|
8923
8948
|
// src/Svg.ts
|
|
8924
|
-
var SVGSpace = class extends DOMSpace {
|
|
8949
|
+
var SVGSpace = class _SVGSpace extends DOMSpace {
|
|
8925
8950
|
/**
|
|
8926
8951
|
* Create a SVGSpace which represents a Space for SVG elements.
|
|
8927
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.
|
|
@@ -8932,7 +8957,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8932
8957
|
super(elem, callback);
|
|
8933
8958
|
this._bgcolor = "#999";
|
|
8934
8959
|
if (this._canvas.nodeName.toLowerCase() != "svg") {
|
|
8935
|
-
let s =
|
|
8960
|
+
let s = _SVGSpace.svgElement(this._canvas, "svg", `${this.id}_svg`);
|
|
8936
8961
|
this._container = this._canvas;
|
|
8937
8962
|
this._canvas = s;
|
|
8938
8963
|
}
|
|
@@ -8958,7 +8983,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8958
8983
|
*/
|
|
8959
8984
|
resize(b, evt) {
|
|
8960
8985
|
super.resize(b, evt);
|
|
8961
|
-
|
|
8986
|
+
_SVGSpace.setAttr(this.element, {
|
|
8962
8987
|
"viewBox": `0 0 ${this.bound.width} ${this.bound.height}`,
|
|
8963
8988
|
"width": `${this.bound.width}`,
|
|
8964
8989
|
"height": `${this.bound.height}`,
|
|
@@ -9003,7 +9028,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
9003
9028
|
return super.removeAll();
|
|
9004
9029
|
}
|
|
9005
9030
|
};
|
|
9006
|
-
var _SVGForm = class extends VisualForm {
|
|
9031
|
+
var _SVGForm = class _SVGForm extends VisualForm {
|
|
9007
9032
|
/**
|
|
9008
9033
|
* Create a new SVGForm. You may also use [`SVGSpace.getForm`](#link) to get a default form directly.
|
|
9009
9034
|
* @param space an instance of SVGSpace
|
|
@@ -9497,12 +9522,12 @@ var _SVGForm = class extends VisualForm {
|
|
|
9497
9522
|
return this;
|
|
9498
9523
|
}
|
|
9499
9524
|
};
|
|
9525
|
+
_SVGForm.groupID = 0;
|
|
9526
|
+
_SVGForm.domID = 0;
|
|
9500
9527
|
var SVGForm = _SVGForm;
|
|
9501
|
-
SVGForm.groupID = 0;
|
|
9502
|
-
SVGForm.domID = 0;
|
|
9503
9528
|
|
|
9504
9529
|
// src/Physics.ts
|
|
9505
|
-
var World = class {
|
|
9530
|
+
var World = class _World {
|
|
9506
9531
|
/**
|
|
9507
9532
|
* Create a `World` for 2D physics simulation.
|
|
9508
9533
|
* @param bound a Group or an Iterable<Pt> representing a rectangular bounding box
|
|
@@ -9590,13 +9615,10 @@ var World = class {
|
|
|
9590
9615
|
* @returns a Body, or undefined if not found
|
|
9591
9616
|
*/
|
|
9592
9617
|
body(id) {
|
|
9593
|
-
let idx = id;
|
|
9594
9618
|
if (typeof id === "string" && id.length > 0) {
|
|
9595
|
-
|
|
9619
|
+
return this._bodies[this._bnames.indexOf(id)];
|
|
9596
9620
|
}
|
|
9597
|
-
|
|
9598
|
-
return void 0;
|
|
9599
|
-
return this._bodies[idx];
|
|
9621
|
+
return typeof id === "number" && id >= 0 ? this._bodies[id] : void 0;
|
|
9600
9622
|
}
|
|
9601
9623
|
/**
|
|
9602
9624
|
* Get a particle in this world by index or string id.
|
|
@@ -9604,13 +9626,10 @@ var World = class {
|
|
|
9604
9626
|
* @returns a Particle, or undefined if not found
|
|
9605
9627
|
*/
|
|
9606
9628
|
particle(id) {
|
|
9607
|
-
let idx = id;
|
|
9608
9629
|
if (typeof id === "string" && id.length > 0) {
|
|
9609
|
-
|
|
9630
|
+
return this._particles[this._pnames.indexOf(id)];
|
|
9610
9631
|
}
|
|
9611
|
-
|
|
9612
|
-
return void 0;
|
|
9613
|
-
return this._particles[idx];
|
|
9632
|
+
return typeof id === "number" && id >= 0 ? this._particles[id] : void 0;
|
|
9614
9633
|
}
|
|
9615
9634
|
/**
|
|
9616
9635
|
* Given a body's name, return its index in the bodies array, or -1 if not found.
|
|
@@ -9757,7 +9776,7 @@ var World = class {
|
|
|
9757
9776
|
for (let i = 0, len = this._particles.length; i < len; i++) {
|
|
9758
9777
|
let p = this._particles[i];
|
|
9759
9778
|
this.integrate(p, dt, this._lastTime);
|
|
9760
|
-
|
|
9779
|
+
_World.boundConstraint(p, this._bound, this._damping);
|
|
9761
9780
|
for (let k = i + 1; k < len; k++) {
|
|
9762
9781
|
if (i !== k) {
|
|
9763
9782
|
let p2 = this._particles[k];
|
|
@@ -9778,7 +9797,7 @@ var World = class {
|
|
|
9778
9797
|
if (bds) {
|
|
9779
9798
|
for (let k = 0, klen = bds.length; k < klen; k++) {
|
|
9780
9799
|
let bk = bds[k];
|
|
9781
|
-
|
|
9800
|
+
_World.boundConstraint(bk, this._bound, this._damping);
|
|
9782
9801
|
this.integrate(bk, dt, this._lastTime);
|
|
9783
9802
|
}
|
|
9784
9803
|
for (let k = i + 1; k < len; k++) {
|
|
@@ -9961,7 +9980,7 @@ var Particle = class extends Pt {
|
|
|
9961
9980
|
return `Particle: ${this[0]} ${this[1]} | previous ${this._prev[0]} ${this._prev[1]} | mass ${this._mass}`;
|
|
9962
9981
|
}
|
|
9963
9982
|
};
|
|
9964
|
-
var Body = class extends Group {
|
|
9983
|
+
var Body = class _Body extends Group {
|
|
9965
9984
|
/**
|
|
9966
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.
|
|
9967
9986
|
*/
|
|
@@ -9980,7 +9999,7 @@ var Body = class extends Group {
|
|
|
9980
9999
|
* @param autoMass Automatically calculate the mass based on the area of the polygon. Default is true.
|
|
9981
10000
|
*/
|
|
9982
10001
|
static fromGroup(body, stiff = 1, autoLink = true, autoMass = true) {
|
|
9983
|
-
let b = new
|
|
10002
|
+
let b = new _Body().init(body);
|
|
9984
10003
|
if (autoLink)
|
|
9985
10004
|
b.linkAll(stiff);
|
|
9986
10005
|
if (autoMass)
|
|
@@ -10135,7 +10154,7 @@ var Body = class extends Group {
|
|
|
10135
10154
|
};
|
|
10136
10155
|
|
|
10137
10156
|
// src/Play.ts
|
|
10138
|
-
var Tempo = class {
|
|
10157
|
+
var Tempo = class _Tempo {
|
|
10139
10158
|
/**
|
|
10140
10159
|
* Construct a new Tempo instance by beats-per-minute. Alternatively, you can use [`Tempo.fromBeat`](#link) to create from milliseconds.
|
|
10141
10160
|
* @param bpm beats per minute
|
|
@@ -10151,7 +10170,7 @@ var Tempo = class {
|
|
|
10151
10170
|
* @param ms milliseconds per beat
|
|
10152
10171
|
*/
|
|
10153
10172
|
static fromBeat(ms) {
|
|
10154
|
-
return new
|
|
10173
|
+
return new _Tempo(6e4 / ms);
|
|
10155
10174
|
}
|
|
10156
10175
|
/**
|
|
10157
10176
|
* Beats-per-minute value
|
|
@@ -10193,16 +10212,16 @@ var Tempo = class {
|
|
|
10193
10212
|
* @returns an object with chainable functions
|
|
10194
10213
|
*/
|
|
10195
10214
|
every(beats) {
|
|
10196
|
-
|
|
10197
|
-
|
|
10215
|
+
const self = this;
|
|
10216
|
+
const p = Array.isArray(beats) ? beats[0] : beats;
|
|
10198
10217
|
return {
|
|
10199
10218
|
start: function(fn, offset = 0, name) {
|
|
10200
|
-
|
|
10219
|
+
const id = name || self._createID(fn);
|
|
10201
10220
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: false, fn };
|
|
10202
10221
|
return this;
|
|
10203
10222
|
},
|
|
10204
10223
|
progress: function(fn, offset = 0, name) {
|
|
10205
|
-
|
|
10224
|
+
const id = name || self._createID(fn);
|
|
10206
10225
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: true, fn };
|
|
10207
10226
|
return this;
|
|
10208
10227
|
}
|
|
@@ -10214,11 +10233,11 @@ var Tempo = class {
|
|
|
10214
10233
|
* @param time current time in milliseconds
|
|
10215
10234
|
*/
|
|
10216
10235
|
track(time) {
|
|
10217
|
-
for (
|
|
10236
|
+
for (const k in this._listeners) {
|
|
10218
10237
|
if (this._listeners.hasOwnProperty(k)) {
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10238
|
+
const li = this._listeners[k];
|
|
10239
|
+
const _t = li.offset ? time + li.offset : time;
|
|
10240
|
+
const ms = li.period * this._ms;
|
|
10222
10241
|
let isStart = false;
|
|
10223
10242
|
if (_t > li.duration + ms) {
|
|
10224
10243
|
li.duration = _t - _t % this._ms;
|
|
@@ -10228,10 +10247,10 @@ var Tempo = class {
|
|
|
10228
10247
|
}
|
|
10229
10248
|
isStart = true;
|
|
10230
10249
|
}
|
|
10231
|
-
|
|
10232
|
-
|
|
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];
|
|
10233
10252
|
if (li.continuous || isStart) {
|
|
10234
|
-
|
|
10253
|
+
const done = li.fn.apply(li, params);
|
|
10235
10254
|
if (done)
|
|
10236
10255
|
delete this._listeners[li.name];
|
|
10237
10256
|
}
|
|
@@ -10265,7 +10284,7 @@ var Tempo = class {
|
|
|
10265
10284
|
return;
|
|
10266
10285
|
}
|
|
10267
10286
|
};
|
|
10268
|
-
var Sound = class {
|
|
10287
|
+
var Sound = class _Sound {
|
|
10269
10288
|
// Tracking play time against ctx.currentTime
|
|
10270
10289
|
/**
|
|
10271
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).
|
|
@@ -10280,7 +10299,7 @@ var Sound = class {
|
|
|
10280
10299
|
* Create an AudioContext instance. This is called internally only.
|
|
10281
10300
|
*/
|
|
10282
10301
|
_createAudioContext() {
|
|
10283
|
-
|
|
10302
|
+
const _ctx = window.AudioContext;
|
|
10284
10303
|
if (!_ctx)
|
|
10285
10304
|
throw new Error("Your browser doesn't support Web Audio. (No AudioContext)");
|
|
10286
10305
|
this._ctx = _ctx ? new _ctx() : void 0;
|
|
@@ -10294,7 +10313,7 @@ var Sound = class {
|
|
|
10294
10313
|
* @returns a `Sound` instance
|
|
10295
10314
|
*/
|
|
10296
10315
|
static from(node, ctx, type = "gen", stream) {
|
|
10297
|
-
|
|
10316
|
+
const s = new _Sound(type);
|
|
10298
10317
|
s._node = node;
|
|
10299
10318
|
s._ctx = ctx;
|
|
10300
10319
|
if (stream)
|
|
@@ -10310,7 +10329,7 @@ var Sound = class {
|
|
|
10310
10329
|
*/
|
|
10311
10330
|
static load(source, crossOrigin = "anonymous") {
|
|
10312
10331
|
return new Promise((resolve, reject) => {
|
|
10313
|
-
|
|
10332
|
+
const s = new _Sound("file");
|
|
10314
10333
|
s._source = typeof source === "string" ? new Audio(source) : source;
|
|
10315
10334
|
s._source.autoplay = false;
|
|
10316
10335
|
s._source.crossOrigin = crossOrigin;
|
|
@@ -10335,10 +10354,10 @@ var Sound = class {
|
|
|
10335
10354
|
*/
|
|
10336
10355
|
static loadAsBuffer(url) {
|
|
10337
10356
|
return new Promise((resolve, reject) => {
|
|
10338
|
-
|
|
10357
|
+
const request = new XMLHttpRequest();
|
|
10339
10358
|
request.open("GET", url, true);
|
|
10340
10359
|
request.responseType = "arraybuffer";
|
|
10341
|
-
|
|
10360
|
+
const s = new _Sound("file");
|
|
10342
10361
|
request.onload = function() {
|
|
10343
10362
|
s._ctx.decodeAudioData(request.response, function(buffer) {
|
|
10344
10363
|
s.createBuffer(buffer);
|
|
@@ -10370,13 +10389,13 @@ var Sound = class {
|
|
|
10370
10389
|
* @example `Sound.generate( 'sine', 120 )`
|
|
10371
10390
|
*/
|
|
10372
10391
|
static generate(type, val) {
|
|
10373
|
-
|
|
10392
|
+
const s = new _Sound("gen");
|
|
10374
10393
|
return s._gen(type, val);
|
|
10375
10394
|
}
|
|
10376
10395
|
// Create the oscillator
|
|
10377
10396
|
_gen(type, val) {
|
|
10378
10397
|
this._node = this._ctx.createOscillator();
|
|
10379
|
-
|
|
10398
|
+
const osc = this._node;
|
|
10380
10399
|
osc.type = type;
|
|
10381
10400
|
if (type === "custom") {
|
|
10382
10401
|
osc.setPeriodicWave(val);
|
|
@@ -10394,7 +10413,7 @@ var Sound = class {
|
|
|
10394
10413
|
static input(constraint) {
|
|
10395
10414
|
return __async(this, null, function* () {
|
|
10396
10415
|
try {
|
|
10397
|
-
|
|
10416
|
+
const s = new _Sound("input");
|
|
10398
10417
|
if (!s)
|
|
10399
10418
|
return void 0;
|
|
10400
10419
|
const c = constraint ? constraint : { audio: true, video: false };
|
|
@@ -10464,7 +10483,7 @@ var Sound = class {
|
|
|
10464
10483
|
get progress() {
|
|
10465
10484
|
let dur = 0;
|
|
10466
10485
|
let curr = 0;
|
|
10467
|
-
if (
|
|
10486
|
+
if (this._buffer) {
|
|
10468
10487
|
dur = this._buffer.duration;
|
|
10469
10488
|
curr = this._timestamp ? this._ctx.currentTime - this._timestamp : 0;
|
|
10470
10489
|
} else {
|
|
@@ -10536,7 +10555,7 @@ var Sound = class {
|
|
|
10536
10555
|
* @param smooth Optional smoothing value (corresponds to `AnalyserNode.smoothingTimeConstant`)
|
|
10537
10556
|
*/
|
|
10538
10557
|
analyze(size = 256, minDb = -100, maxDb = -30, smooth = 0.8) {
|
|
10539
|
-
|
|
10558
|
+
const a = this._ctx.createAnalyser();
|
|
10540
10559
|
a.fftSize = size * 2;
|
|
10541
10560
|
a.minDecibels = minDb;
|
|
10542
10561
|
a.maxDecibels = maxDb;
|
|
@@ -10563,8 +10582,8 @@ var Sound = class {
|
|
|
10563
10582
|
}
|
|
10564
10583
|
// Map domain data to another range
|
|
10565
10584
|
_domainTo(time, size, position = [0, 0], trim = [0, 0]) {
|
|
10566
|
-
|
|
10567
|
-
|
|
10585
|
+
const data = time ? this.timeDomain() : this.freqDomain();
|
|
10586
|
+
const g = new Group();
|
|
10568
10587
|
for (let i = trim[0], len = data.length - trim[1]; i < len; i++) {
|
|
10569
10588
|
g.push(new Pt(position[0] + size[0] * i / len, position[1] + size[1] * data[i] / 255));
|
|
10570
10589
|
}
|
|
@@ -10623,7 +10642,7 @@ var Sound = class {
|
|
|
10623
10642
|
this._ctx.resume();
|
|
10624
10643
|
}
|
|
10625
10644
|
if (this._type === "file") {
|
|
10626
|
-
if (
|
|
10645
|
+
if (this._buffer) {
|
|
10627
10646
|
this._node.start(timeAt);
|
|
10628
10647
|
this._timestamp = this._ctx.currentTime + timeAt;
|
|
10629
10648
|
} else {
|
|
@@ -10648,7 +10667,7 @@ var Sound = class {
|
|
|
10648
10667
|
if (this._playing)
|
|
10649
10668
|
(this._outputNode || this._node).disconnect(this._ctx.destination);
|
|
10650
10669
|
if (this._type === "file") {
|
|
10651
|
-
if (
|
|
10670
|
+
if (this._buffer) {
|
|
10652
10671
|
if (this.progress < 1)
|
|
10653
10672
|
this._node.stop();
|
|
10654
10673
|
} else {
|