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.mjs
CHANGED
|
@@ -20,7 +20,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
// src/LinearAlgebra.ts
|
|
23
|
-
var Vec = class {
|
|
23
|
+
var Vec = class _Vec {
|
|
24
24
|
/**
|
|
25
25
|
* Add `b` to vector `a`.
|
|
26
26
|
* @returns vector `a`
|
|
@@ -113,44 +113,44 @@ var Vec = class {
|
|
|
113
113
|
* Magnitude of `a`.
|
|
114
114
|
*/
|
|
115
115
|
static magnitude(a) {
|
|
116
|
-
return Math.sqrt(
|
|
116
|
+
return Math.sqrt(_Vec.dot(a, a));
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
119
|
* Unit vector of `a`. If magnitude of `a` is already known, pass it in the second paramter to optimize calculation.
|
|
120
120
|
*/
|
|
121
121
|
static unit(a, magnitude = void 0) {
|
|
122
|
-
|
|
122
|
+
const m = magnitude === void 0 ? _Vec.magnitude(a) : magnitude;
|
|
123
123
|
if (m === 0)
|
|
124
124
|
return Pt.make(a.length);
|
|
125
|
-
return
|
|
125
|
+
return _Vec.divide(a, m);
|
|
126
126
|
}
|
|
127
127
|
/**
|
|
128
128
|
* Set `a` to its absolute value in each dimension.
|
|
129
129
|
* @returns vector `a`
|
|
130
130
|
*/
|
|
131
131
|
static abs(a) {
|
|
132
|
-
return
|
|
132
|
+
return _Vec.map(a, Math.abs);
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
135
|
* Set `a` to its floor value in each dimension.
|
|
136
136
|
* @returns vector `a`
|
|
137
137
|
*/
|
|
138
138
|
static floor(a) {
|
|
139
|
-
return
|
|
139
|
+
return _Vec.map(a, Math.floor);
|
|
140
140
|
}
|
|
141
141
|
/**
|
|
142
142
|
* Set `a` to its ceiling value in each dimension.
|
|
143
143
|
* @returns vector `a`
|
|
144
144
|
*/
|
|
145
145
|
static ceil(a) {
|
|
146
|
-
return
|
|
146
|
+
return _Vec.map(a, Math.ceil);
|
|
147
147
|
}
|
|
148
148
|
/**
|
|
149
149
|
* Set `a` to its rounded value in each dimension.
|
|
150
150
|
* @returns vector `a`
|
|
151
151
|
*/
|
|
152
152
|
static round(a) {
|
|
153
|
-
return
|
|
153
|
+
return _Vec.map(a, Math.round);
|
|
154
154
|
}
|
|
155
155
|
/**
|
|
156
156
|
* Find the max value within a vector's dimensions.
|
|
@@ -200,7 +200,7 @@ var Vec = class {
|
|
|
200
200
|
return a;
|
|
201
201
|
}
|
|
202
202
|
};
|
|
203
|
-
var Mat = class {
|
|
203
|
+
var Mat = class _Mat {
|
|
204
204
|
constructor() {
|
|
205
205
|
this.reset();
|
|
206
206
|
}
|
|
@@ -214,13 +214,13 @@ var Mat = class {
|
|
|
214
214
|
* Convert the value of its stored 3x3 matrix to a 2D [`DOMMatrix`](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix) instance
|
|
215
215
|
*/
|
|
216
216
|
get domMatrix() {
|
|
217
|
-
return new DOMMatrix(
|
|
217
|
+
return new DOMMatrix(_Mat.toDOMMatrix(this._33));
|
|
218
218
|
}
|
|
219
219
|
/**
|
|
220
220
|
* Reset the internal 3x3 matrix to its identity
|
|
221
221
|
*/
|
|
222
222
|
reset() {
|
|
223
|
-
this._33 =
|
|
223
|
+
this._33 = _Mat.scale2DMatrix(1, 1);
|
|
224
224
|
}
|
|
225
225
|
/**
|
|
226
226
|
* Scale the internal 3x3 matrix. You can chain this function with other related functions.
|
|
@@ -228,8 +228,8 @@ var Mat = class {
|
|
|
228
228
|
* @param at Optional origin location to scale from.
|
|
229
229
|
*/
|
|
230
230
|
scale2D(val, at = [0, 0]) {
|
|
231
|
-
const m =
|
|
232
|
-
this._33 =
|
|
231
|
+
const m = _Mat.scaleAt2DMatrix(val[0] || 1, val[1] || 1, at);
|
|
232
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
233
233
|
return this;
|
|
234
234
|
}
|
|
235
235
|
/**
|
|
@@ -238,8 +238,8 @@ var Mat = class {
|
|
|
238
238
|
* @param at Optional origin location to rotate from.
|
|
239
239
|
*/
|
|
240
240
|
rotate2D(ang, at = [0, 0]) {
|
|
241
|
-
const m =
|
|
242
|
-
this._33 =
|
|
241
|
+
const m = _Mat.rotateAt2DMatrix(Math.cos(ang), Math.sin(ang), at);
|
|
242
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
243
243
|
return this;
|
|
244
244
|
}
|
|
245
245
|
/**
|
|
@@ -247,8 +247,8 @@ var Mat = class {
|
|
|
247
247
|
* @param val [x, y] offset values
|
|
248
248
|
*/
|
|
249
249
|
translate2D(val) {
|
|
250
|
-
const m =
|
|
251
|
-
this._33 =
|
|
250
|
+
const m = _Mat.translate2DMatrix(val[0] || 0, val[1] || 0);
|
|
251
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
252
252
|
return this;
|
|
253
253
|
}
|
|
254
254
|
/**
|
|
@@ -257,8 +257,8 @@ var Mat = class {
|
|
|
257
257
|
* @param at Optional origin location to scale from.
|
|
258
258
|
*/
|
|
259
259
|
shear2D(val, at = [0, 0]) {
|
|
260
|
-
const m =
|
|
261
|
-
this._33 =
|
|
260
|
+
const m = _Mat.shearAt2DMatrix(Math.tan(val[0] || 0), Math.tan(val[1] || 1), at);
|
|
261
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
262
262
|
return this;
|
|
263
263
|
}
|
|
264
264
|
/**
|
|
@@ -274,8 +274,8 @@ var Mat = class {
|
|
|
274
274
|
if (a.length != b.length)
|
|
275
275
|
throw new Error("Cannot add matrix if rows' and columns' size don't match.");
|
|
276
276
|
}
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
const g = new Group();
|
|
278
|
+
const isNum = typeof b == "number";
|
|
279
279
|
for (let i = 0, len = a.length; i < len; i++) {
|
|
280
280
|
g.push(a[i].$add(isNum ? b : b[i]));
|
|
281
281
|
}
|
|
@@ -290,7 +290,7 @@ var Mat = class {
|
|
|
290
290
|
* @returns If not elementwise, this will return a new group with M Pt, each with N dimensions (M-rows, N-columns).
|
|
291
291
|
*/
|
|
292
292
|
static multiply(a, b, transposed = false, elementwise = false) {
|
|
293
|
-
|
|
293
|
+
const g = new Group();
|
|
294
294
|
if (typeof b != "number") {
|
|
295
295
|
if (elementwise) {
|
|
296
296
|
if (a.length != b.length)
|
|
@@ -304,9 +304,9 @@ var Mat = class {
|
|
|
304
304
|
if (transposed && a[0].length != b[0].length)
|
|
305
305
|
throw new Error("Cannot multiply matrix if transposed and the columns in both matrices don't match.");
|
|
306
306
|
if (!transposed)
|
|
307
|
-
b =
|
|
307
|
+
b = _Mat.transpose(b);
|
|
308
308
|
for (let ai = 0, alen = a.length; ai < alen; ai++) {
|
|
309
|
-
|
|
309
|
+
const p = Pt.make(b.length, 0);
|
|
310
310
|
for (let bi = 0, blen = b.length; bi < blen; bi++) {
|
|
311
311
|
p[bi] = Vec.dot(a[ai], b[bi]);
|
|
312
312
|
}
|
|
@@ -327,7 +327,7 @@ var Mat = class {
|
|
|
327
327
|
* @param defaultValue a default value to fill if index out of bound. If not provided, it will throw an error instead.
|
|
328
328
|
*/
|
|
329
329
|
static zipSlice(g, index, defaultValue = false) {
|
|
330
|
-
|
|
330
|
+
const z = [];
|
|
331
331
|
for (let i = 0, len = g.length; i < len; i++) {
|
|
332
332
|
if (g[i].length - 1 < index && defaultValue === false)
|
|
333
333
|
throw `Index ${index} is out of bounds`;
|
|
@@ -342,10 +342,10 @@ var Mat = class {
|
|
|
342
342
|
* @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.
|
|
343
343
|
*/
|
|
344
344
|
static zip(g, defaultValue = false, useLongest = false) {
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
const ps = new Group();
|
|
346
|
+
const len = useLongest ? g.reduce((a, b) => Math.max(a, b.length), 0) : g[0].length;
|
|
347
347
|
for (let i = 0; i < len; i++) {
|
|
348
|
-
ps.push(
|
|
348
|
+
ps.push(_Mat.zipSlice(g, i, defaultValue));
|
|
349
349
|
}
|
|
350
350
|
return ps;
|
|
351
351
|
}
|
|
@@ -353,7 +353,7 @@ var Mat = class {
|
|
|
353
353
|
* Same as `zip` function.
|
|
354
354
|
*/
|
|
355
355
|
static transpose(g, defaultValue = false, useLongest = false) {
|
|
356
|
-
return
|
|
356
|
+
return _Mat.zip(g, defaultValue, useLongest);
|
|
357
357
|
}
|
|
358
358
|
static toDOMMatrix(m) {
|
|
359
359
|
return [m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1]];
|
|
@@ -365,8 +365,8 @@ var Mat = class {
|
|
|
365
365
|
* @returns a new transformed Pt
|
|
366
366
|
*/
|
|
367
367
|
static transform2D(pt, m) {
|
|
368
|
-
|
|
369
|
-
|
|
368
|
+
const x = pt[0] * m[0][0] + pt[1] * m[1][0] + m[2][0];
|
|
369
|
+
const y = pt[0] * m[0][1] + pt[1] * m[1][1] + m[2][1];
|
|
370
370
|
return new Pt(x, y);
|
|
371
371
|
}
|
|
372
372
|
/**
|
|
@@ -413,7 +413,7 @@ var Mat = class {
|
|
|
413
413
|
* Get a matrix to scale a point from an origin point. For use in `transform2D`.
|
|
414
414
|
*/
|
|
415
415
|
static scaleAt2DMatrix(sx, sy, at) {
|
|
416
|
-
|
|
416
|
+
const m = _Mat.scale2DMatrix(sx, sy);
|
|
417
417
|
m[2][0] = -at[0] * sx + at[0];
|
|
418
418
|
m[2][1] = -at[1] * sy + at[1];
|
|
419
419
|
return m;
|
|
@@ -422,7 +422,7 @@ var Mat = class {
|
|
|
422
422
|
* Get a matrix to rotate a point from an origin point. For use in `transform2D`.
|
|
423
423
|
*/
|
|
424
424
|
static rotateAt2DMatrix(cosA, sinA, at) {
|
|
425
|
-
|
|
425
|
+
const m = _Mat.rotate2DMatrix(cosA, sinA);
|
|
426
426
|
m[2][0] = at[0] * (1 - cosA) + at[1] * sinA;
|
|
427
427
|
m[2][1] = at[1] * (1 - cosA) - at[0] * sinA;
|
|
428
428
|
return m;
|
|
@@ -431,7 +431,7 @@ var Mat = class {
|
|
|
431
431
|
* Get a matrix to shear a point from an origin point. For use in `transform2D`.
|
|
432
432
|
*/
|
|
433
433
|
static shearAt2DMatrix(tanX, tanY, at) {
|
|
434
|
-
|
|
434
|
+
const m = _Mat.shear2DMatrix(tanX, tanY);
|
|
435
435
|
m[2][0] = -at[1] * tanY;
|
|
436
436
|
m[2][1] = -at[0] * tanX;
|
|
437
437
|
return m;
|
|
@@ -442,7 +442,7 @@ var Mat = class {
|
|
|
442
442
|
* @param p1 second end point to define the reflection line
|
|
443
443
|
*/
|
|
444
444
|
static reflectAt2DMatrix(p1, p2) {
|
|
445
|
-
|
|
445
|
+
const intercept = Line.intercept(p1, p2);
|
|
446
446
|
if (intercept == void 0) {
|
|
447
447
|
return [
|
|
448
448
|
new Pt([-1, 0, 0]),
|
|
@@ -450,10 +450,10 @@ var Mat = class {
|
|
|
450
450
|
new Pt([p1[0] + p2[0], 0, 1])
|
|
451
451
|
];
|
|
452
452
|
} else {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
453
|
+
const yi = intercept.yi;
|
|
454
|
+
const ang2 = Math.atan(intercept.slope) * 2;
|
|
455
|
+
const cosA = Math.cos(ang2);
|
|
456
|
+
const sinA = Math.sin(ang2);
|
|
457
457
|
return [
|
|
458
458
|
new Pt([cosA, sinA, 0]),
|
|
459
459
|
new Pt([sinA, -cosA, 0]),
|
|
@@ -466,7 +466,7 @@ var Mat = class {
|
|
|
466
466
|
// src/Op.ts
|
|
467
467
|
var _errorLength = (obj, param = "expected") => Util.warn("Group's length is less than " + param, obj);
|
|
468
468
|
var _errorOutofBound = (obj, param = "") => Util.warn(`Index ${param} is out of bound in Group`, obj);
|
|
469
|
-
var Line = class {
|
|
469
|
+
var Line = class _Line {
|
|
470
470
|
/**
|
|
471
471
|
* Create a line that originates from an anchor point, given an angle and a magnitude.
|
|
472
472
|
* @param anchor an anchor Pt
|
|
@@ -564,7 +564,7 @@ var Line = class {
|
|
|
564
564
|
*/
|
|
565
565
|
static distanceFromPt(line, pt) {
|
|
566
566
|
let _line = Util.iterToArray(line);
|
|
567
|
-
let projectionVector =
|
|
567
|
+
let projectionVector = _Line.perpendicularFromPt(_line, pt, true);
|
|
568
568
|
if (projectionVector) {
|
|
569
569
|
return projectionVector.magnitude();
|
|
570
570
|
} else {
|
|
@@ -580,8 +580,8 @@ var Line = class {
|
|
|
580
580
|
static intersectRay2D(la, lb) {
|
|
581
581
|
let _la = Util.iterToArray(la);
|
|
582
582
|
let _lb = Util.iterToArray(lb);
|
|
583
|
-
let a =
|
|
584
|
-
let b =
|
|
583
|
+
let a = _Line.intercept(_la[0], _la[1]);
|
|
584
|
+
let b = _Line.intercept(_lb[0], _lb[1]);
|
|
585
585
|
let pa = _la[0];
|
|
586
586
|
let pb = _lb[0];
|
|
587
587
|
if (a == void 0) {
|
|
@@ -615,7 +615,7 @@ var Line = class {
|
|
|
615
615
|
static intersectLine2D(la, lb) {
|
|
616
616
|
let _la = Util.iterToArray(la);
|
|
617
617
|
let _lb = Util.iterToArray(lb);
|
|
618
|
-
let pt =
|
|
618
|
+
let pt = _Line.intersectRay2D(_la, _lb);
|
|
619
619
|
return pt && Geom.withinBound(pt, _la[0], _la[1]) && Geom.withinBound(pt, _lb[0], _lb[1]) ? pt : void 0;
|
|
620
620
|
}
|
|
621
621
|
/**
|
|
@@ -627,7 +627,7 @@ var Line = class {
|
|
|
627
627
|
static intersectLineWithRay2D(line, ray) {
|
|
628
628
|
let _line = Util.iterToArray(line);
|
|
629
629
|
let _ray = Util.iterToArray(ray);
|
|
630
|
-
let pt =
|
|
630
|
+
let pt = _Line.intersectRay2D(_line, _ray);
|
|
631
631
|
return pt && Geom.withinBound(pt, _line[0], _line[1]) ? pt : void 0;
|
|
632
632
|
}
|
|
633
633
|
/**
|
|
@@ -639,7 +639,7 @@ var Line = class {
|
|
|
639
639
|
static intersectPolygon2D(lineOrRay, poly, sourceIsRay = false) {
|
|
640
640
|
let _lineOrRay = Util.iterToArray(lineOrRay);
|
|
641
641
|
let _poly = Util.iterToArray(poly);
|
|
642
|
-
let fn = sourceIsRay ?
|
|
642
|
+
let fn = sourceIsRay ? _Line.intersectLineWithRay2D : _Line.intersectLine2D;
|
|
643
643
|
let pts = new Group();
|
|
644
644
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
645
645
|
let next = i === len - 1 ? 0 : i + 1;
|
|
@@ -657,7 +657,7 @@ var Line = class {
|
|
|
657
657
|
*/
|
|
658
658
|
static intersectLines2D(lines1, lines2, isRay = false) {
|
|
659
659
|
let group = new Group();
|
|
660
|
-
let fn = isRay ?
|
|
660
|
+
let fn = isRay ? _Line.intersectLineWithRay2D : _Line.intersectLine2D;
|
|
661
661
|
for (let l1 of lines1) {
|
|
662
662
|
for (let l2 of lines2) {
|
|
663
663
|
let _ip = fn(l1, l2);
|
|
@@ -675,7 +675,7 @@ var Line = class {
|
|
|
675
675
|
*/
|
|
676
676
|
static intersectGridWithRay2D(ray, gridPt) {
|
|
677
677
|
let _ray = Util.iterToArray(ray);
|
|
678
|
-
let t =
|
|
678
|
+
let t = _Line.intercept(new Pt(_ray[0]).subtract(gridPt), new Pt(_ray[1]).subtract(gridPt));
|
|
679
679
|
let g = new Group();
|
|
680
680
|
if (t && t.xi)
|
|
681
681
|
g.push(new Pt(gridPt[0] + t.xi, gridPt[1]));
|
|
@@ -691,7 +691,7 @@ var Line = class {
|
|
|
691
691
|
*/
|
|
692
692
|
static intersectGridWithLine2D(line, gridPt) {
|
|
693
693
|
let _line = Util.iterToArray(line);
|
|
694
|
-
let g =
|
|
694
|
+
let g = _Line.intersectGridWithRay2D(_line, gridPt);
|
|
695
695
|
let gg = new Group();
|
|
696
696
|
for (let i = 0, len = g.length; i < len; i++) {
|
|
697
697
|
if (Geom.withinBound(g[i], _line[0], _line[1]))
|
|
@@ -711,7 +711,7 @@ var Line = class {
|
|
|
711
711
|
let box = Geom.boundingBox(Group.fromPtArray(_line));
|
|
712
712
|
if (!Rectangle.hasIntersectRect2D(box, _rect))
|
|
713
713
|
return new Group();
|
|
714
|
-
return
|
|
714
|
+
return _Line.intersectLines2D([_line], Rectangle.sides(_rect));
|
|
715
715
|
}
|
|
716
716
|
/**
|
|
717
717
|
* Get evenly distributed points on a line. Similar to [`Create.distributeLinear`](#link) but excluding end points.
|
|
@@ -752,7 +752,7 @@ var Line = class {
|
|
|
752
752
|
} else {
|
|
753
753
|
sideIdx = ls[0] < 0 ? 3 : 1;
|
|
754
754
|
}
|
|
755
|
-
return
|
|
755
|
+
return _Line.intersectRay2D(sides[sideIdx], _line);
|
|
756
756
|
}
|
|
757
757
|
}
|
|
758
758
|
/**
|
|
@@ -788,7 +788,7 @@ var Line = class {
|
|
|
788
788
|
return new Group(_line[0].$min(_line[1]), _line[0].$max(_line[1]));
|
|
789
789
|
}
|
|
790
790
|
};
|
|
791
|
-
var Rectangle = class {
|
|
791
|
+
var Rectangle = class _Rectangle {
|
|
792
792
|
/**
|
|
793
793
|
* Create a rectangle from top-left anchor point. Same as [`Rectangle.fromTopLeft`](#link).
|
|
794
794
|
* @param topLeft top-left point
|
|
@@ -797,7 +797,7 @@ var Rectangle = class {
|
|
|
797
797
|
* @returns a Group of 2 Pts representing a rectangle
|
|
798
798
|
*/
|
|
799
799
|
static from(topLeft, widthOrSize, height) {
|
|
800
|
-
return
|
|
800
|
+
return _Rectangle.fromTopLeft(topLeft, widthOrSize, height);
|
|
801
801
|
}
|
|
802
802
|
/**
|
|
803
803
|
* Create a rectangle given a top-left position and a size.
|
|
@@ -838,9 +838,9 @@ var Rectangle = class {
|
|
|
838
838
|
*/
|
|
839
839
|
static toSquare(pts, enclose = false) {
|
|
840
840
|
let _pts = Util.iterToArray(pts);
|
|
841
|
-
let s =
|
|
841
|
+
let s = _Rectangle.size(_pts);
|
|
842
842
|
let m = enclose ? s.maxValue().value : s.minValue().value;
|
|
843
|
-
return
|
|
843
|
+
return _Rectangle.fromCenter(_Rectangle.center(_pts), m, m);
|
|
844
844
|
}
|
|
845
845
|
/**
|
|
846
846
|
* Get the size of this rectangle as a Pt.
|
|
@@ -876,7 +876,7 @@ var Rectangle = class {
|
|
|
876
876
|
* @returns an array of 4 Groups, each of which represents a line segment
|
|
877
877
|
*/
|
|
878
878
|
static sides(rect) {
|
|
879
|
-
let [p0, p1, p2, p3] =
|
|
879
|
+
let [p0, p1, p2, p3] = _Rectangle.corners(rect);
|
|
880
880
|
return [
|
|
881
881
|
new Group(p0, p1),
|
|
882
882
|
new Group(p1, p2),
|
|
@@ -910,7 +910,7 @@ var Rectangle = class {
|
|
|
910
910
|
* @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle
|
|
911
911
|
*/
|
|
912
912
|
static polygon(rect) {
|
|
913
|
-
return
|
|
913
|
+
return _Rectangle.corners(rect);
|
|
914
914
|
}
|
|
915
915
|
/**
|
|
916
916
|
* Subdivide a rectangle into 4 rectangles, one for each quadrant.
|
|
@@ -919,8 +919,8 @@ var Rectangle = class {
|
|
|
919
919
|
*/
|
|
920
920
|
static quadrants(rect, center) {
|
|
921
921
|
let _rect = Util.iterToArray(rect);
|
|
922
|
-
let corners =
|
|
923
|
-
let _center = center != void 0 ? new Pt(center) :
|
|
922
|
+
let corners = _Rectangle.corners(_rect);
|
|
923
|
+
let _center = center != void 0 ? new Pt(center) : _Rectangle.center(_rect);
|
|
924
924
|
return corners.map((c) => new Group(c, _center).boundingBox());
|
|
925
925
|
}
|
|
926
926
|
/**
|
|
@@ -973,12 +973,12 @@ var Rectangle = class {
|
|
|
973
973
|
static intersectRect2D(rect1, rect2) {
|
|
974
974
|
let _rect1 = Util.iterToArray(rect1);
|
|
975
975
|
let _rect2 = Util.iterToArray(rect2);
|
|
976
|
-
if (!
|
|
976
|
+
if (!_Rectangle.hasIntersectRect2D(_rect1, _rect2))
|
|
977
977
|
return new Group();
|
|
978
|
-
return Line.intersectLines2D(
|
|
978
|
+
return Line.intersectLines2D(_Rectangle.sides(_rect1), _Rectangle.sides(_rect2));
|
|
979
979
|
}
|
|
980
980
|
};
|
|
981
|
-
var Circle = class {
|
|
981
|
+
var Circle = class _Circle {
|
|
982
982
|
/**
|
|
983
983
|
* Create a circle that either fits within, or encloses, a rectangle.
|
|
984
984
|
* @param pts a Group or an Iterable<PtLike> with 2 Pt representing a rectangle
|
|
@@ -1069,7 +1069,7 @@ var Circle = class {
|
|
|
1069
1069
|
static intersectLine2D(circle, line) {
|
|
1070
1070
|
let _pts = Util.iterToArray(circle);
|
|
1071
1071
|
let _line = Util.iterToArray(line);
|
|
1072
|
-
let ps =
|
|
1072
|
+
let ps = _Circle.intersectRay2D(_pts, _line);
|
|
1073
1073
|
let g = new Group();
|
|
1074
1074
|
if (ps.length > 0) {
|
|
1075
1075
|
for (let i = 0, len = ps.length; i < len; i++) {
|
|
@@ -1122,7 +1122,7 @@ var Circle = class {
|
|
|
1122
1122
|
let sides = Rectangle.sides(_rect);
|
|
1123
1123
|
let g = [];
|
|
1124
1124
|
for (let i = 0, len = sides.length; i < len; i++) {
|
|
1125
|
-
let ps =
|
|
1125
|
+
let ps = _Circle.intersectLine2D(_pts, sides[i]);
|
|
1126
1126
|
if (ps.length > 0)
|
|
1127
1127
|
g.push(ps);
|
|
1128
1128
|
}
|
|
@@ -1165,7 +1165,7 @@ var Circle = class {
|
|
|
1165
1165
|
}
|
|
1166
1166
|
}
|
|
1167
1167
|
};
|
|
1168
|
-
var Triangle = class {
|
|
1168
|
+
var Triangle = class _Triangle {
|
|
1169
1169
|
/**
|
|
1170
1170
|
* Create a triangle from a rectangle. The triangle will be isosceles, with the bottom of the rectangle as its base.
|
|
1171
1171
|
* @param rect a Group or an Iterable<Pt> with 2 Pt representing a rectangle
|
|
@@ -1191,7 +1191,7 @@ var Triangle = class {
|
|
|
1191
1191
|
* @param size size is the magnitude of lines from center to the triangle's vertices, like a "radius".
|
|
1192
1192
|
*/
|
|
1193
1193
|
static fromCenter(pt, size) {
|
|
1194
|
-
return
|
|
1194
|
+
return _Triangle.fromCircle(Circle.fromCenter(pt, size));
|
|
1195
1195
|
}
|
|
1196
1196
|
/**
|
|
1197
1197
|
* Get the medial, which is an inner triangle formed by connecting the midpoints of this triangle's sides.
|
|
@@ -1230,7 +1230,7 @@ var Triangle = class {
|
|
|
1230
1230
|
*/
|
|
1231
1231
|
static altitude(tri, index) {
|
|
1232
1232
|
let _pts = Util.iterToArray(tri);
|
|
1233
|
-
let opp =
|
|
1233
|
+
let opp = _Triangle.oppositeSide(_pts, index);
|
|
1234
1234
|
if (opp.length > 1) {
|
|
1235
1235
|
return new Group(_pts[index], Line.perpendicularFromPt(opp, _pts[index]));
|
|
1236
1236
|
} else {
|
|
@@ -1246,8 +1246,8 @@ var Triangle = class {
|
|
|
1246
1246
|
let _pts = Util.iterToArray(tri);
|
|
1247
1247
|
if (_pts.length < 3)
|
|
1248
1248
|
return _errorLength(void 0, 3);
|
|
1249
|
-
let a =
|
|
1250
|
-
let b =
|
|
1249
|
+
let a = _Triangle.altitude(_pts, 0);
|
|
1250
|
+
let b = _Triangle.altitude(_pts, 1);
|
|
1251
1251
|
return Line.intersectRay2D(a, b);
|
|
1252
1252
|
}
|
|
1253
1253
|
/**
|
|
@@ -1270,7 +1270,7 @@ var Triangle = class {
|
|
|
1270
1270
|
*/
|
|
1271
1271
|
static incircle(tri, center) {
|
|
1272
1272
|
let _pts = Util.iterToArray(tri);
|
|
1273
|
-
let c = center ? center :
|
|
1273
|
+
let c = center ? center : _Triangle.incenter(_pts);
|
|
1274
1274
|
let area = Polygon.area(_pts);
|
|
1275
1275
|
let perim = Polygon.perimeter(_pts, true);
|
|
1276
1276
|
let r = 2 * area / perim.total;
|
|
@@ -1283,7 +1283,7 @@ var Triangle = class {
|
|
|
1283
1283
|
*/
|
|
1284
1284
|
static circumcenter(tri) {
|
|
1285
1285
|
let _pts = Util.iterToArray(tri);
|
|
1286
|
-
let md =
|
|
1286
|
+
let md = _Triangle.medial(_pts);
|
|
1287
1287
|
let a = [md[0], Geom.perpendicular(_pts[0].$subtract(md[0])).p1.$add(md[0])];
|
|
1288
1288
|
let b = [md[1], Geom.perpendicular(_pts[1].$subtract(md[1])).p1.$add(md[1])];
|
|
1289
1289
|
return Line.intersectRay2D(a, b);
|
|
@@ -1295,12 +1295,12 @@ var Triangle = class {
|
|
|
1295
1295
|
*/
|
|
1296
1296
|
static circumcircle(tri, center) {
|
|
1297
1297
|
let _pts = Util.iterToArray(tri);
|
|
1298
|
-
let c = center ? center :
|
|
1298
|
+
let c = center ? center : _Triangle.circumcenter(_pts);
|
|
1299
1299
|
let r = _pts[0].$subtract(c).magnitude();
|
|
1300
1300
|
return Circle.fromCenter(c, r);
|
|
1301
1301
|
}
|
|
1302
1302
|
};
|
|
1303
|
-
var Polygon = class {
|
|
1303
|
+
var Polygon = class _Polygon {
|
|
1304
1304
|
/**
|
|
1305
1305
|
* Get the centroid of a polygon, which is the average of all its points.
|
|
1306
1306
|
* @param pts a Group or an Iterable<PtLike> representing a polygon
|
|
@@ -1364,7 +1364,7 @@ var Polygon = class {
|
|
|
1364
1364
|
* @param t a value between 0 to 1 for interpolation. Default to 0.5 which will get the middle point.
|
|
1365
1365
|
*/
|
|
1366
1366
|
static midpoints(poly, closePath = false, t = 0.5) {
|
|
1367
|
-
let sides =
|
|
1367
|
+
let sides = _Polygon.lines(poly, closePath);
|
|
1368
1368
|
let mids = sides.map((s) => Geom.interpolate(s[0], s[1], t));
|
|
1369
1369
|
return mids;
|
|
1370
1370
|
}
|
|
@@ -1401,7 +1401,7 @@ var Polygon = class {
|
|
|
1401
1401
|
* @returns a bisector Pt that's a normalized unit vector
|
|
1402
1402
|
*/
|
|
1403
1403
|
static bisector(poly, index) {
|
|
1404
|
-
let sides =
|
|
1404
|
+
let sides = _Polygon.adjacentSides(poly, index, true);
|
|
1405
1405
|
if (sides.length >= 2) {
|
|
1406
1406
|
let a = sides[0][1].$subtract(sides[0][0]).unit();
|
|
1407
1407
|
let b = sides[1][1].$subtract(sides[1][0]).unit();
|
|
@@ -1417,7 +1417,7 @@ var Polygon = class {
|
|
|
1417
1417
|
* @returns an object with `total` length, and `segments` which is a Pt that stores each segment's length
|
|
1418
1418
|
*/
|
|
1419
1419
|
static perimeter(poly, closePath = false) {
|
|
1420
|
-
let lines =
|
|
1420
|
+
let lines = _Polygon.lines(poly, closePath);
|
|
1421
1421
|
let mag = 0;
|
|
1422
1422
|
let p = Pt.make(lines.length, 0);
|
|
1423
1423
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
@@ -1557,8 +1557,8 @@ var Polygon = class {
|
|
|
1557
1557
|
* @param unitAxis unit axis
|
|
1558
1558
|
*/
|
|
1559
1559
|
static _axisOverlap(poly1, poly2, unitAxis) {
|
|
1560
|
-
let pa =
|
|
1561
|
-
let pb =
|
|
1560
|
+
let pa = _Polygon.projectAxis(poly1, unitAxis);
|
|
1561
|
+
let pb = _Polygon.projectAxis(poly2, unitAxis);
|
|
1562
1562
|
return pa[0] < pb[0] ? pb[0] - pa[1] : pa[0] - pb[1];
|
|
1563
1563
|
}
|
|
1564
1564
|
/**
|
|
@@ -1570,7 +1570,7 @@ var Polygon = class {
|
|
|
1570
1570
|
let _poly = Util.iterToArray(poly);
|
|
1571
1571
|
let c = false;
|
|
1572
1572
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
1573
|
-
let ln =
|
|
1573
|
+
let ln = _Polygon.lineAt(_poly, i);
|
|
1574
1574
|
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]) {
|
|
1575
1575
|
c = !c;
|
|
1576
1576
|
}
|
|
@@ -1601,10 +1601,10 @@ var Polygon = class {
|
|
|
1601
1601
|
let r = _circle[1][0];
|
|
1602
1602
|
let minDist = Number.MAX_SAFE_INTEGER;
|
|
1603
1603
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
1604
|
-
let edge =
|
|
1604
|
+
let edge = _Polygon.lineAt(_poly, i);
|
|
1605
1605
|
let axis = new Pt(edge[0].y - edge[1].y, edge[1].x - edge[0].x).unit();
|
|
1606
1606
|
let poly2 = new Group(c.$add(axis.$multiply(r)), c.$subtract(axis.$multiply(r)));
|
|
1607
|
-
let dist =
|
|
1607
|
+
let dist = _Polygon._axisOverlap(_poly, poly2, axis);
|
|
1608
1608
|
if (dist > 0) {
|
|
1609
1609
|
return null;
|
|
1610
1610
|
} else if (Math.abs(dist) < minDist) {
|
|
@@ -1619,7 +1619,7 @@ var Polygon = class {
|
|
|
1619
1619
|
}
|
|
1620
1620
|
if (!info.edge)
|
|
1621
1621
|
return null;
|
|
1622
|
-
let dir = c.$subtract(
|
|
1622
|
+
let dir = c.$subtract(_Polygon.centroid(_poly)).dot(info.normal);
|
|
1623
1623
|
if (dir < 0)
|
|
1624
1624
|
info.normal.multiply(-1);
|
|
1625
1625
|
info.dist = minDist;
|
|
@@ -1648,9 +1648,9 @@ var Polygon = class {
|
|
|
1648
1648
|
};
|
|
1649
1649
|
let minDist = Number.MAX_SAFE_INTEGER;
|
|
1650
1650
|
for (let i = 0, plen = _poly1.length + _poly2.length; i < plen; i++) {
|
|
1651
|
-
let edge = i < _poly1.length ?
|
|
1651
|
+
let edge = i < _poly1.length ? _Polygon.lineAt(_poly1, i) : _Polygon.lineAt(_poly2, i - _poly1.length);
|
|
1652
1652
|
let axis = new Pt(edge[0].y - edge[1].y, edge[1].x - edge[0].x).unit();
|
|
1653
|
-
let dist =
|
|
1653
|
+
let dist = _Polygon._axisOverlap(_poly1, _poly2, axis);
|
|
1654
1654
|
if (dist > 0) {
|
|
1655
1655
|
return null;
|
|
1656
1656
|
} else if (Math.abs(dist) < minDist) {
|
|
@@ -1663,8 +1663,8 @@ var Polygon = class {
|
|
|
1663
1663
|
info.dist = minDist;
|
|
1664
1664
|
let b1 = info.which === 0 ? _poly2 : _poly1;
|
|
1665
1665
|
let b2 = info.which === 0 ? _poly1 : _poly2;
|
|
1666
|
-
let c1 =
|
|
1667
|
-
let c2 =
|
|
1666
|
+
let c1 = _Polygon.centroid(b1);
|
|
1667
|
+
let c2 = _Polygon.centroid(b2);
|
|
1668
1668
|
let dir = c1.$subtract(c2).dot(info.normal);
|
|
1669
1669
|
if (dir < 0)
|
|
1670
1670
|
info.normal.multiply(-1);
|
|
@@ -1686,7 +1686,7 @@ var Polygon = class {
|
|
|
1686
1686
|
static intersectPolygon2D(poly1, poly2) {
|
|
1687
1687
|
let _poly1 = Util.iterToArray(poly1);
|
|
1688
1688
|
let _poly2 = Util.iterToArray(poly2);
|
|
1689
|
-
let lp =
|
|
1689
|
+
let lp = _Polygon.lines(_poly1);
|
|
1690
1690
|
let g = [];
|
|
1691
1691
|
for (let i = 0, len = lp.length; i < len; i++) {
|
|
1692
1692
|
let ins = Line.intersectPolygon2D(lp[i], _poly2, false);
|
|
@@ -1709,7 +1709,7 @@ var Polygon = class {
|
|
|
1709
1709
|
return boxes;
|
|
1710
1710
|
}
|
|
1711
1711
|
};
|
|
1712
|
-
var Curve = class {
|
|
1712
|
+
var Curve = class _Curve {
|
|
1713
1713
|
/**
|
|
1714
1714
|
* Get a precalculated coefficients per step.
|
|
1715
1715
|
* @param steps number of steps
|
|
@@ -1768,17 +1768,17 @@ var Curve = class {
|
|
|
1768
1768
|
if (_pts.length < 2)
|
|
1769
1769
|
return new Group();
|
|
1770
1770
|
let ps = new Group();
|
|
1771
|
-
let ts =
|
|
1772
|
-
let c =
|
|
1771
|
+
let ts = _Curve.getSteps(steps);
|
|
1772
|
+
let c = _Curve.controlPoints(_pts, 0, true);
|
|
1773
1773
|
for (let i = 0; i <= steps; i++) {
|
|
1774
|
-
ps.push(
|
|
1774
|
+
ps.push(_Curve.catmullRomStep(ts[i], c));
|
|
1775
1775
|
}
|
|
1776
1776
|
let k = 0;
|
|
1777
1777
|
while (k < _pts.length - 2) {
|
|
1778
|
-
let cp =
|
|
1778
|
+
let cp = _Curve.controlPoints(_pts, k);
|
|
1779
1779
|
if (cp.length > 0) {
|
|
1780
1780
|
for (let i = 0; i <= steps; i++) {
|
|
1781
|
-
ps.push(
|
|
1781
|
+
ps.push(_Curve.catmullRomStep(ts[i], cp));
|
|
1782
1782
|
}
|
|
1783
1783
|
k++;
|
|
1784
1784
|
}
|
|
@@ -1798,7 +1798,7 @@ var Curve = class {
|
|
|
1798
1798
|
new Pt(-1.5, 2, 0.5, 0),
|
|
1799
1799
|
new Pt(0.5, -0.5, 0, 0)
|
|
1800
1800
|
);
|
|
1801
|
-
return
|
|
1801
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
1802
1802
|
}
|
|
1803
1803
|
/**
|
|
1804
1804
|
* Create a Cardinal curve.
|
|
@@ -1812,17 +1812,17 @@ var Curve = class {
|
|
|
1812
1812
|
if (_pts.length < 2)
|
|
1813
1813
|
return new Group();
|
|
1814
1814
|
let ps = new Group();
|
|
1815
|
-
let ts =
|
|
1816
|
-
let c =
|
|
1815
|
+
let ts = _Curve.getSteps(steps);
|
|
1816
|
+
let c = _Curve.controlPoints(_pts, 0, true);
|
|
1817
1817
|
for (let i = 0; i <= steps; i++) {
|
|
1818
|
-
ps.push(
|
|
1818
|
+
ps.push(_Curve.cardinalStep(ts[i], c, tension));
|
|
1819
1819
|
}
|
|
1820
1820
|
let k = 0;
|
|
1821
1821
|
while (k < _pts.length - 2) {
|
|
1822
|
-
let cp =
|
|
1822
|
+
let cp = _Curve.controlPoints(_pts, k);
|
|
1823
1823
|
if (cp.length > 0) {
|
|
1824
1824
|
for (let i = 0; i <= steps; i++) {
|
|
1825
|
-
ps.push(
|
|
1825
|
+
ps.push(_Curve.cardinalStep(ts[i], cp, tension));
|
|
1826
1826
|
}
|
|
1827
1827
|
k++;
|
|
1828
1828
|
}
|
|
@@ -1846,7 +1846,7 @@ var Curve = class {
|
|
|
1846
1846
|
let h = Mat.multiply([step], m, true)[0].multiply(tension);
|
|
1847
1847
|
let h2 = 2 * step[0] - 3 * step[1] + 1;
|
|
1848
1848
|
let h3 = -2 * step[0] + 3 * step[1];
|
|
1849
|
-
let pt =
|
|
1849
|
+
let pt = _Curve._calcPt(ctrls, h);
|
|
1850
1850
|
pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;
|
|
1851
1851
|
pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;
|
|
1852
1852
|
if (pt.length > 2)
|
|
@@ -1864,13 +1864,13 @@ var Curve = class {
|
|
|
1864
1864
|
if (_pts.length < 4)
|
|
1865
1865
|
return new Group();
|
|
1866
1866
|
let ps = new Group();
|
|
1867
|
-
let ts =
|
|
1867
|
+
let ts = _Curve.getSteps(steps);
|
|
1868
1868
|
let k = 0;
|
|
1869
1869
|
while (k < _pts.length - 3) {
|
|
1870
|
-
let c =
|
|
1870
|
+
let c = _Curve.controlPoints(_pts, k);
|
|
1871
1871
|
if (c.length > 0) {
|
|
1872
1872
|
for (let i = 0; i <= steps; i++) {
|
|
1873
|
-
ps.push(
|
|
1873
|
+
ps.push(_Curve.bezierStep(ts[i], c));
|
|
1874
1874
|
}
|
|
1875
1875
|
k += 3;
|
|
1876
1876
|
}
|
|
@@ -1890,7 +1890,7 @@ var Curve = class {
|
|
|
1890
1890
|
new Pt(-3, 3, 0, 0),
|
|
1891
1891
|
new Pt(1, 0, 0, 0)
|
|
1892
1892
|
);
|
|
1893
|
-
return
|
|
1893
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
1894
1894
|
}
|
|
1895
1895
|
/**
|
|
1896
1896
|
* Create a basis spline (NURBS) curve.
|
|
@@ -1904,18 +1904,18 @@ var Curve = class {
|
|
|
1904
1904
|
if (_pts.length < 2)
|
|
1905
1905
|
return new Group();
|
|
1906
1906
|
let ps = new Group();
|
|
1907
|
-
let ts =
|
|
1907
|
+
let ts = _Curve.getSteps(steps);
|
|
1908
1908
|
let k = 0;
|
|
1909
1909
|
while (k < _pts.length - 3) {
|
|
1910
|
-
let c =
|
|
1910
|
+
let c = _Curve.controlPoints(_pts, k);
|
|
1911
1911
|
if (c.length > 0) {
|
|
1912
1912
|
if (tension !== 1) {
|
|
1913
1913
|
for (let i = 0; i <= steps; i++) {
|
|
1914
|
-
ps.push(
|
|
1914
|
+
ps.push(_Curve.bsplineTensionStep(ts[i], c, tension));
|
|
1915
1915
|
}
|
|
1916
1916
|
} else {
|
|
1917
1917
|
for (let i = 0; i <= steps; i++) {
|
|
1918
|
-
ps.push(
|
|
1918
|
+
ps.push(_Curve.bsplineStep(ts[i], c));
|
|
1919
1919
|
}
|
|
1920
1920
|
}
|
|
1921
1921
|
k++;
|
|
@@ -1936,7 +1936,7 @@ var Curve = class {
|
|
|
1936
1936
|
new Pt(-0.5, 0.5, 0.5, 0.16666666666666666),
|
|
1937
1937
|
new Pt(0.16666666666666666, 0, 0, 0)
|
|
1938
1938
|
);
|
|
1939
|
-
return
|
|
1939
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
1940
1940
|
}
|
|
1941
1941
|
/**
|
|
1942
1942
|
* Interpolate to get a point on a basis spline curve with tension.
|
|
@@ -1955,7 +1955,7 @@ var Curve = class {
|
|
|
1955
1955
|
let h = Mat.multiply([step], m, true)[0].multiply(tension);
|
|
1956
1956
|
let h2 = 2 * step[0] - 3 * step[1] + 1;
|
|
1957
1957
|
let h3 = -2 * step[0] + 3 * step[1];
|
|
1958
|
-
let pt =
|
|
1958
|
+
let pt = _Curve._calcPt(ctrls, h);
|
|
1959
1959
|
pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;
|
|
1960
1960
|
pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;
|
|
1961
1961
|
if (pt.length > 2)
|
|
@@ -1966,13 +1966,13 @@ var Curve = class {
|
|
|
1966
1966
|
|
|
1967
1967
|
// src/uheprng.ts
|
|
1968
1968
|
function Mash() {
|
|
1969
|
-
|
|
1970
|
-
|
|
1969
|
+
let n = 4022871197;
|
|
1970
|
+
let mash = function(data) {
|
|
1971
1971
|
if (data) {
|
|
1972
1972
|
data = data.toString();
|
|
1973
|
-
for (
|
|
1973
|
+
for (let i = 0; i < data.length; i++) {
|
|
1974
1974
|
n += data.charCodeAt(i);
|
|
1975
|
-
|
|
1975
|
+
let h = 0.02519603282416938 * n;
|
|
1976
1976
|
n = h >>> 0;
|
|
1977
1977
|
h -= n;
|
|
1978
1978
|
h *= n;
|
|
@@ -1987,12 +1987,12 @@ function Mash() {
|
|
|
1987
1987
|
return mash;
|
|
1988
1988
|
}
|
|
1989
1989
|
function uheprng_default(seed) {
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1990
|
+
let o = 48;
|
|
1991
|
+
let c = 1;
|
|
1992
|
+
let p = o;
|
|
1993
|
+
let s = new Array(o);
|
|
1994
|
+
let i, j, k = 0;
|
|
1995
|
+
let mash = Mash();
|
|
1996
1996
|
for (i = 0; i < o; i++)
|
|
1997
1997
|
s[i] = mash(Math.random().toString());
|
|
1998
1998
|
function initState() {
|
|
@@ -2024,24 +2024,24 @@ function uheprng_default(seed) {
|
|
|
2024
2024
|
hashString(seed);
|
|
2025
2025
|
return {
|
|
2026
2026
|
/**
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2027
|
+
* this (not anymore) PRIVATE (internal access only) function is the heart of the multiply-with-carry
|
|
2028
|
+
* (MWC) PRNG algorithm. When called it returns a pseudo-random number in the form of a
|
|
2029
|
+
* 32-bit JavaScript fraction (0.0 to <1.0) it is a PRIVATE function used by the default
|
|
2030
|
+
* [0-1] return function, and by the random 'string(n)' function which returns 'n'
|
|
2031
|
+
* characters from 33 to 126.
|
|
2032
|
+
* @returns a number between 0.0 and 1.0
|
|
2033
|
+
*/
|
|
2034
2034
|
random() {
|
|
2035
2035
|
if (++p >= o)
|
|
2036
2036
|
p = 0;
|
|
2037
|
-
|
|
2037
|
+
let t = 1768863 * s[p] + c * 23283064365386963e-26;
|
|
2038
2038
|
return s[p] = t - (c = t | 0);
|
|
2039
2039
|
}
|
|
2040
2040
|
};
|
|
2041
2041
|
}
|
|
2042
2042
|
|
|
2043
2043
|
// src/Num.ts
|
|
2044
|
-
var Num = class {
|
|
2044
|
+
var Num = class _Num {
|
|
2045
2045
|
/**
|
|
2046
2046
|
* Check if two numbers are equal or almost equal within a threshold.
|
|
2047
2047
|
* @param a number a
|
|
@@ -2077,7 +2077,7 @@ var Num = class {
|
|
|
2077
2077
|
* @example `boundValue(361, 0, 360)` will return 1
|
|
2078
2078
|
*/
|
|
2079
2079
|
static boundValue(val, min, max) {
|
|
2080
|
-
|
|
2080
|
+
const len = Math.abs(max - min);
|
|
2081
2081
|
let a = val % len;
|
|
2082
2082
|
if (a > max)
|
|
2083
2083
|
a -= len;
|
|
@@ -2100,8 +2100,8 @@ var Num = class {
|
|
|
2100
2100
|
* @param b range value 2
|
|
2101
2101
|
*/
|
|
2102
2102
|
static randomRange(a, b = 0) {
|
|
2103
|
-
|
|
2104
|
-
return a +
|
|
2103
|
+
const r = a > b ? a - b : b - a;
|
|
2104
|
+
return a + _Num.random() * r;
|
|
2105
2105
|
}
|
|
2106
2106
|
/**
|
|
2107
2107
|
* Get a random Pt within the range defined by either 1 or 2 Pt
|
|
@@ -2109,11 +2109,11 @@ var Num = class {
|
|
|
2109
2109
|
* @param b optional Pt to define the end of the range
|
|
2110
2110
|
*/
|
|
2111
2111
|
static randomPt(a, b) {
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2112
|
+
const p = new Pt(a.length);
|
|
2113
|
+
const range = b ? Vec.subtract(b.slice(), a) : a;
|
|
2114
|
+
const start = b ? a : new Pt(a.length).fill(0);
|
|
2115
2115
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
2116
|
-
p[i] =
|
|
2116
|
+
p[i] = _Num.random() * range[i] + start[i];
|
|
2117
2117
|
}
|
|
2118
2118
|
return p;
|
|
2119
2119
|
}
|
|
@@ -2124,8 +2124,8 @@ var Num = class {
|
|
|
2124
2124
|
* @param b range value 1
|
|
2125
2125
|
*/
|
|
2126
2126
|
static normalizeValue(n, a, b) {
|
|
2127
|
-
|
|
2128
|
-
|
|
2127
|
+
const min = Math.min(a, b);
|
|
2128
|
+
const max = Math.max(a, b);
|
|
2129
2129
|
return (n - min) / (max - min);
|
|
2130
2130
|
}
|
|
2131
2131
|
/**
|
|
@@ -2134,8 +2134,8 @@ var Num = class {
|
|
|
2134
2134
|
* @returns a Pt of the dimensional sums
|
|
2135
2135
|
*/
|
|
2136
2136
|
static sum(pts) {
|
|
2137
|
-
|
|
2138
|
-
|
|
2137
|
+
const _pts = Util.iterToArray(pts);
|
|
2138
|
+
const c = new Pt(_pts[0]);
|
|
2139
2139
|
for (let i = 1, len = _pts.length; i < len; i++) {
|
|
2140
2140
|
Vec.add(c, _pts[i]);
|
|
2141
2141
|
}
|
|
@@ -2147,8 +2147,8 @@ var Num = class {
|
|
|
2147
2147
|
* @returns a Pt of averages
|
|
2148
2148
|
*/
|
|
2149
2149
|
static average(pts) {
|
|
2150
|
-
|
|
2151
|
-
return
|
|
2150
|
+
const _pts = Util.iterToArray(pts);
|
|
2151
|
+
return _Num.sum(_pts).divide(_pts.length);
|
|
2152
2152
|
}
|
|
2153
2153
|
/**
|
|
2154
2154
|
* Given a value between 0 to 1, returns a value that cycles between 0 -> 1 -> 0 using the provided shaping method.
|
|
@@ -2171,9 +2171,9 @@ var Num = class {
|
|
|
2171
2171
|
static mapToRange(n, currA, currB, targetA, targetB) {
|
|
2172
2172
|
if (currA == currB)
|
|
2173
2173
|
throw new Error("[currMin, currMax] must define a range that is not zero");
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
return
|
|
2174
|
+
const min = Math.min(targetA, targetB);
|
|
2175
|
+
const max = Math.max(targetA, targetB);
|
|
2176
|
+
return _Num.normalizeValue(n, currA, currB) * (max - min) + min;
|
|
2177
2177
|
}
|
|
2178
2178
|
/**
|
|
2179
2179
|
* Seed the pseudorandom generator.
|
|
@@ -2191,7 +2191,7 @@ var Num = class {
|
|
|
2191
2191
|
return this.generator ? this.generator.random() : Math.random();
|
|
2192
2192
|
}
|
|
2193
2193
|
};
|
|
2194
|
-
var Geom = class {
|
|
2194
|
+
var Geom = class _Geom {
|
|
2195
2195
|
/**
|
|
2196
2196
|
* Bound an angle between 0 to 360 degrees.
|
|
2197
2197
|
* @param angle angle value
|
|
@@ -2227,7 +2227,7 @@ var Geom = class {
|
|
|
2227
2227
|
*/
|
|
2228
2228
|
static boundingBox(pts) {
|
|
2229
2229
|
let minPt, maxPt;
|
|
2230
|
-
for (
|
|
2230
|
+
for (const p of pts) {
|
|
2231
2231
|
if (minPt == void 0) {
|
|
2232
2232
|
minPt = p.clone();
|
|
2233
2233
|
maxPt = p.clone();
|
|
@@ -2253,9 +2253,9 @@ var Geom = class {
|
|
|
2253
2253
|
* @param direction a string either "to" (subtract all Pt with this anchor base), or "from" (add all Pt from this anchor base)
|
|
2254
2254
|
*/
|
|
2255
2255
|
static anchor(pts, ptOrIndex = 0, direction = "to") {
|
|
2256
|
-
|
|
2256
|
+
const method = direction == "to" ? "subtract" : "add";
|
|
2257
2257
|
let i = 0;
|
|
2258
|
-
for (
|
|
2258
|
+
for (const p of pts) {
|
|
2259
2259
|
if (typeof ptOrIndex == "number") {
|
|
2260
2260
|
if (ptOrIndex !== i)
|
|
2261
2261
|
p[method](pts[ptOrIndex]);
|
|
@@ -2273,8 +2273,8 @@ var Geom = class {
|
|
|
2273
2273
|
* @returns interpolated point as a new Pt
|
|
2274
2274
|
*/
|
|
2275
2275
|
static interpolate(a, b, t = 0.5) {
|
|
2276
|
-
|
|
2277
|
-
|
|
2276
|
+
const len = Math.min(a.length, b.length);
|
|
2277
|
+
const d = Pt.make(len);
|
|
2278
2278
|
for (let i = 0; i < len; i++) {
|
|
2279
2279
|
d[i] = a[i] * (1 - t) + b[i] * t;
|
|
2280
2280
|
}
|
|
@@ -2286,13 +2286,13 @@ var Geom = class {
|
|
|
2286
2286
|
* @returns an array of two Pt that are perpendicular to this Pt
|
|
2287
2287
|
*/
|
|
2288
2288
|
static perpendicular(pt, axis = Const.xy) {
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2289
|
+
const y = axis[1];
|
|
2290
|
+
const x = axis[0];
|
|
2291
|
+
const p = new Pt(pt);
|
|
2292
|
+
const pa = new Pt(p);
|
|
2293
2293
|
pa[x] = -p[y];
|
|
2294
2294
|
pa[y] = p[x];
|
|
2295
|
-
|
|
2295
|
+
const pb = new Pt(p);
|
|
2296
2296
|
pb[x] = p[y];
|
|
2297
2297
|
pb[y] = -p[x];
|
|
2298
2298
|
return new Group(pa, pb);
|
|
@@ -2321,14 +2321,14 @@ var Geom = class {
|
|
|
2321
2321
|
* @param pts a Group or an Iterable<Pt>
|
|
2322
2322
|
*/
|
|
2323
2323
|
static sortEdges(pts) {
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2324
|
+
const _pts = Util.iterToArray(pts);
|
|
2325
|
+
const bounds = _Geom.boundingBox(_pts);
|
|
2326
|
+
const center = bounds[1].add(bounds[0]).divide(2);
|
|
2327
|
+
const fn = (a, b) => {
|
|
2328
2328
|
if (a.length < 2 || b.length < 2)
|
|
2329
2329
|
throw new Error("Pt dimension cannot be less than 2");
|
|
2330
|
-
|
|
2331
|
-
|
|
2330
|
+
const da = a.$subtract(center);
|
|
2331
|
+
const db = b.$subtract(center);
|
|
2332
2332
|
if (da[0] >= 0 && db[0] < 0)
|
|
2333
2333
|
return 1;
|
|
2334
2334
|
if (da[0] < 0 && db[0] >= 0)
|
|
@@ -2338,7 +2338,7 @@ var Geom = class {
|
|
|
2338
2338
|
return da[1] > db[1] ? 1 : -1;
|
|
2339
2339
|
return db[1] > da[1] ? 1 : -1;
|
|
2340
2340
|
}
|
|
2341
|
-
|
|
2341
|
+
const det = da.$cross2D(db);
|
|
2342
2342
|
if (det < 0)
|
|
2343
2343
|
return 1;
|
|
2344
2344
|
if (det > 0)
|
|
@@ -2354,17 +2354,17 @@ var Geom = class {
|
|
|
2354
2354
|
* @param anchor optional anchor point to scale from
|
|
2355
2355
|
*/
|
|
2356
2356
|
static scale(ps, scale, anchor) {
|
|
2357
|
-
|
|
2358
|
-
|
|
2357
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2358
|
+
const scs = typeof scale == "number" ? Pt.make(pts[0].length, scale) : scale;
|
|
2359
2359
|
if (!anchor)
|
|
2360
2360
|
anchor = Pt.make(pts[0].length, 0);
|
|
2361
2361
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2362
|
-
|
|
2362
|
+
const p = pts[i];
|
|
2363
2363
|
for (let k = 0, lenP = p.length; k < lenP; k++) {
|
|
2364
2364
|
p[k] = anchor && anchor[k] ? anchor[k] + (p[k] - anchor[k]) * scs[k] : p[k] * scs[k];
|
|
2365
2365
|
}
|
|
2366
2366
|
}
|
|
2367
|
-
return
|
|
2367
|
+
return _Geom;
|
|
2368
2368
|
}
|
|
2369
2369
|
/**
|
|
2370
2370
|
* Rotate a Pt or a Group of Pts in 2D space. You may also use [`Pt.rotate2D`](#link) instance method.
|
|
@@ -2374,14 +2374,14 @@ var Geom = class {
|
|
|
2374
2374
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2375
2375
|
*/
|
|
2376
2376
|
static rotate2D(ps, angle, anchor, axis) {
|
|
2377
|
-
|
|
2378
|
-
|
|
2377
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2378
|
+
const fn = anchor ? Mat.rotateAt2DMatrix : Mat.rotate2DMatrix;
|
|
2379
2379
|
if (!anchor)
|
|
2380
2380
|
anchor = Pt.make(pts[0].length, 0);
|
|
2381
|
-
|
|
2382
|
-
|
|
2381
|
+
const cos = Math.cos(angle);
|
|
2382
|
+
const sin = Math.sin(angle);
|
|
2383
2383
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2384
|
-
|
|
2384
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2385
2385
|
p.to(Mat.transform2D(p, fn(cos, sin, anchor)));
|
|
2386
2386
|
if (axis) {
|
|
2387
2387
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2389,7 +2389,7 @@ var Geom = class {
|
|
|
2389
2389
|
}
|
|
2390
2390
|
}
|
|
2391
2391
|
}
|
|
2392
|
-
return
|
|
2392
|
+
return _Geom;
|
|
2393
2393
|
}
|
|
2394
2394
|
/**
|
|
2395
2395
|
* Shear a Pt or a Group of Pts in 2D space. You may also use [`Pt.shear2D`](#link) instance method.
|
|
@@ -2399,15 +2399,15 @@ var Geom = class {
|
|
|
2399
2399
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2400
2400
|
*/
|
|
2401
2401
|
static shear2D(ps, scale, anchor, axis) {
|
|
2402
|
-
|
|
2403
|
-
|
|
2402
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2403
|
+
const s = typeof scale == "number" ? [scale, scale] : scale;
|
|
2404
2404
|
if (!anchor)
|
|
2405
2405
|
anchor = Pt.make(pts[0].length, 0);
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2406
|
+
const fn = anchor ? Mat.shearAt2DMatrix : Mat.shear2DMatrix;
|
|
2407
|
+
const tanx = Math.tan(s[0]);
|
|
2408
|
+
const tany = Math.tan(s[1]);
|
|
2409
2409
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2410
|
-
|
|
2410
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2411
2411
|
p.to(Mat.transform2D(p, fn(tanx, tany, anchor)));
|
|
2412
2412
|
if (axis) {
|
|
2413
2413
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2415,7 +2415,7 @@ var Geom = class {
|
|
|
2415
2415
|
}
|
|
2416
2416
|
}
|
|
2417
2417
|
}
|
|
2418
|
-
return
|
|
2418
|
+
return _Geom;
|
|
2419
2419
|
}
|
|
2420
2420
|
/**
|
|
2421
2421
|
* Reflect a Pt or a Group of Pts along a 2D line. You may also use [`Pt.reflect2D`](#link) instance method.
|
|
@@ -2424,11 +2424,11 @@ var Geom = class {
|
|
|
2424
2424
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2425
2425
|
*/
|
|
2426
2426
|
static reflect2D(ps, line, axis) {
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2427
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2428
|
+
const _line = Util.iterToArray(line);
|
|
2429
|
+
const mat = Mat.reflectAt2DMatrix(_line[0], _line[1]);
|
|
2430
2430
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2431
|
-
|
|
2431
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2432
2432
|
p.to(Mat.transform2D(p, mat));
|
|
2433
2433
|
if (axis) {
|
|
2434
2434
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2436,17 +2436,17 @@ var Geom = class {
|
|
|
2436
2436
|
}
|
|
2437
2437
|
}
|
|
2438
2438
|
}
|
|
2439
|
-
return
|
|
2439
|
+
return _Geom;
|
|
2440
2440
|
}
|
|
2441
2441
|
/**
|
|
2442
2442
|
* Generate a cosine lookup table.
|
|
2443
2443
|
* @returns an object with a cosine tables (array of 360 values) and a function to get cosine given a radian input.
|
|
2444
2444
|
*/
|
|
2445
2445
|
static cosTable() {
|
|
2446
|
-
|
|
2446
|
+
const cos = new Float64Array(360);
|
|
2447
2447
|
for (let i = 0; i < 360; i++)
|
|
2448
2448
|
cos[i] = Math.cos(i * Math.PI / 180);
|
|
2449
|
-
|
|
2449
|
+
const find = (rad) => cos[Math.floor(_Geom.boundAngle(_Geom.toDegree(rad)))];
|
|
2450
2450
|
return { table: cos, cos: find };
|
|
2451
2451
|
}
|
|
2452
2452
|
/**
|
|
@@ -2454,14 +2454,14 @@ var Geom = class {
|
|
|
2454
2454
|
* @returns an object with a sine tables (array of 360 values) and a function to get sine value given a radian input.
|
|
2455
2455
|
*/
|
|
2456
2456
|
static sinTable() {
|
|
2457
|
-
|
|
2457
|
+
const sin = new Float64Array(360);
|
|
2458
2458
|
for (let i = 0; i < 360; i++)
|
|
2459
2459
|
sin[i] = Math.sin(i * Math.PI / 180);
|
|
2460
|
-
|
|
2460
|
+
const find = (rad) => sin[Math.floor(_Geom.boundAngle(_Geom.toDegree(rad)))];
|
|
2461
2461
|
return { table: sin, sin: find };
|
|
2462
2462
|
}
|
|
2463
2463
|
};
|
|
2464
|
-
var Shaping = class {
|
|
2464
|
+
var Shaping = class _Shaping {
|
|
2465
2465
|
/**
|
|
2466
2466
|
* Linear mapping.
|
|
2467
2467
|
* @param t a value between 0 to 1
|
|
@@ -2492,7 +2492,7 @@ var Shaping = class {
|
|
|
2492
2492
|
* @param c the value to shape, default is 1
|
|
2493
2493
|
*/
|
|
2494
2494
|
static quadraticInOut(t, c = 1) {
|
|
2495
|
-
|
|
2495
|
+
const dt = t * 2;
|
|
2496
2496
|
return t < 0.5 ? c / 2 * t * t * 4 : -c / 2 * ((dt - 1) * (dt - 3) - 1);
|
|
2497
2497
|
}
|
|
2498
2498
|
/**
|
|
@@ -2509,7 +2509,7 @@ var Shaping = class {
|
|
|
2509
2509
|
* @param c the value to shape, default is 1
|
|
2510
2510
|
*/
|
|
2511
2511
|
static cubicOut(t, c = 1) {
|
|
2512
|
-
|
|
2512
|
+
const dt = t - 1;
|
|
2513
2513
|
return c * (dt * dt * dt + 1);
|
|
2514
2514
|
}
|
|
2515
2515
|
/**
|
|
@@ -2518,7 +2518,7 @@ var Shaping = class {
|
|
|
2518
2518
|
* @param c the value to shape, default is 1
|
|
2519
2519
|
*/
|
|
2520
2520
|
static cubicInOut(t, c = 1) {
|
|
2521
|
-
|
|
2521
|
+
const dt = t * 2;
|
|
2522
2522
|
return t < 0.5 ? c / 2 * dt * dt * dt : c / 2 * ((dt - 2) * (dt - 2) * (dt - 2) + 2);
|
|
2523
2523
|
}
|
|
2524
2524
|
/**
|
|
@@ -2569,9 +2569,9 @@ var Shaping = class {
|
|
|
2569
2569
|
* @param c the value to shape, default is 1
|
|
2570
2570
|
*/
|
|
2571
2571
|
static cosineApprox(t, c = 1) {
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2572
|
+
const t2 = t * t;
|
|
2573
|
+
const t4 = t2 * t2;
|
|
2574
|
+
const t6 = t4 * t2;
|
|
2575
2575
|
return c * (4 * t6 / 9 - 17 * t4 / 9 + 22 * t2 / 9);
|
|
2576
2576
|
}
|
|
2577
2577
|
/**
|
|
@@ -2588,7 +2588,7 @@ var Shaping = class {
|
|
|
2588
2588
|
* @param c the value to shape, default is 1
|
|
2589
2589
|
*/
|
|
2590
2590
|
static circularOut(t, c = 1) {
|
|
2591
|
-
|
|
2591
|
+
const dt = t - 1;
|
|
2592
2592
|
return c * Math.sqrt(1 - dt * dt);
|
|
2593
2593
|
}
|
|
2594
2594
|
/**
|
|
@@ -2597,7 +2597,7 @@ var Shaping = class {
|
|
|
2597
2597
|
* @param c the value to shape, default is 1
|
|
2598
2598
|
*/
|
|
2599
2599
|
static circularInOut(t, c = 1) {
|
|
2600
|
-
|
|
2600
|
+
const dt = t * 2;
|
|
2601
2601
|
return t < 0.5 ? -c / 2 * (Math.sqrt(1 - dt * dt) - 1) : c / 2 * (Math.sqrt(1 - (dt - 2) * (dt - 2)) + 1);
|
|
2602
2602
|
}
|
|
2603
2603
|
/**
|
|
@@ -2607,8 +2607,8 @@ var Shaping = class {
|
|
|
2607
2607
|
* @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.
|
|
2608
2608
|
*/
|
|
2609
2609
|
static elasticIn(t, c = 1, p = 0.7) {
|
|
2610
|
-
|
|
2611
|
-
|
|
2610
|
+
const dt = t - 1;
|
|
2611
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2612
2612
|
return c * (-Math.pow(2, 10 * dt) * Math.sin((dt - s) * Const.two_pi / p));
|
|
2613
2613
|
}
|
|
2614
2614
|
/**
|
|
@@ -2618,7 +2618,7 @@ var Shaping = class {
|
|
|
2618
2618
|
* @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.
|
|
2619
2619
|
*/
|
|
2620
2620
|
static elasticOut(t, c = 1, p = 0.7) {
|
|
2621
|
-
|
|
2621
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2622
2622
|
return c * (Math.pow(2, -10 * t) * Math.sin((t - s) * Const.two_pi / p)) + c;
|
|
2623
2623
|
}
|
|
2624
2624
|
/**
|
|
@@ -2629,7 +2629,7 @@ var Shaping = class {
|
|
|
2629
2629
|
*/
|
|
2630
2630
|
static elasticInOut(t, c = 1, p = 0.6) {
|
|
2631
2631
|
let dt = t * 2;
|
|
2632
|
-
|
|
2632
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2633
2633
|
if (t < 0.5) {
|
|
2634
2634
|
dt -= 1;
|
|
2635
2635
|
return c * (-0.5 * (Math.pow(2, 10 * dt) * Math.sin((dt - s) * Const.two_pi / p)));
|
|
@@ -2644,7 +2644,7 @@ var Shaping = class {
|
|
|
2644
2644
|
* @param c the value to shape, default is 1
|
|
2645
2645
|
*/
|
|
2646
2646
|
static bounceIn(t, c = 1) {
|
|
2647
|
-
return c -
|
|
2647
|
+
return c - _Shaping.bounceOut(1 - t, c);
|
|
2648
2648
|
}
|
|
2649
2649
|
/**
|
|
2650
2650
|
* Bounce out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).
|
|
@@ -2671,7 +2671,7 @@ var Shaping = class {
|
|
|
2671
2671
|
* @param c the value to shape, default is 1
|
|
2672
2672
|
*/
|
|
2673
2673
|
static bounceInOut(t, c = 1) {
|
|
2674
|
-
return t < 0.5 ?
|
|
2674
|
+
return t < 0.5 ? _Shaping.bounceIn(t * 2, c) / 2 : _Shaping.bounceOut(t * 2 - 1, c) / 2 + c / 2;
|
|
2675
2675
|
}
|
|
2676
2676
|
/**
|
|
2677
2677
|
* Sigmoid curve changes its shape adapted from the input value, but always returns a value between 0 to 1.
|
|
@@ -2680,7 +2680,7 @@ var Shaping = class {
|
|
|
2680
2680
|
* @param p the larger the value, the "steeper" the curve will be. Default is 10.
|
|
2681
2681
|
*/
|
|
2682
2682
|
static sigmoid(t, c = 1, p = 10) {
|
|
2683
|
-
|
|
2683
|
+
const d = p * (t - 0.5);
|
|
2684
2684
|
return c / (1 + Math.exp(-d));
|
|
2685
2685
|
}
|
|
2686
2686
|
/**
|
|
@@ -2692,9 +2692,9 @@ var Shaping = class {
|
|
|
2692
2692
|
static logSigmoid(t, c = 1, p = 0.7) {
|
|
2693
2693
|
p = Math.max(Const.epsilon, Math.min(1 - Const.epsilon, p));
|
|
2694
2694
|
p = 1 / (1 - p);
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2695
|
+
const A = 1 / (1 + Math.exp((t - 0.5) * p * -2));
|
|
2696
|
+
const B = 1 / (1 + Math.exp(p));
|
|
2697
|
+
const C = 1 / (1 + Math.exp(-p));
|
|
2698
2698
|
return c * (A - B) / (C - B);
|
|
2699
2699
|
}
|
|
2700
2700
|
/**
|
|
@@ -2717,13 +2717,13 @@ var Shaping = class {
|
|
|
2717
2717
|
* @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)
|
|
2718
2718
|
*/
|
|
2719
2719
|
static quadraticBezier(t, c = 1, p = [0.05, 0.95]) {
|
|
2720
|
-
|
|
2721
|
-
|
|
2720
|
+
const a = typeof p != "number" ? p[0] : p;
|
|
2721
|
+
const b = typeof p != "number" ? p[1] : 0.5;
|
|
2722
2722
|
let om2a = 1 - 2 * a;
|
|
2723
2723
|
if (om2a === 0) {
|
|
2724
2724
|
om2a = Const.epsilon;
|
|
2725
2725
|
}
|
|
2726
|
-
|
|
2726
|
+
const d = (Math.sqrt(a * a + om2a * t) - a) / om2a;
|
|
2727
2727
|
return c * ((1 - 2 * b) * (d * d) + 2 * b * d);
|
|
2728
2728
|
}
|
|
2729
2729
|
/**
|
|
@@ -2734,7 +2734,7 @@ var Shaping = class {
|
|
|
2734
2734
|
* @param p2` a Pt object specifying the second control Pt. Default is `Pt(0.9, 0.2).
|
|
2735
2735
|
*/
|
|
2736
2736
|
static cubicBezier(t, c = 1, p1 = [0.1, 0.7], p2 = [0.9, 0.2]) {
|
|
2737
|
-
|
|
2737
|
+
const curve = new Group(new Pt(0, 0), new Pt(p1), new Pt(p2), new Pt(1, 1));
|
|
2738
2738
|
return c * Curve.bezierStep(new Pt(t * t * t, t * t, t, 1), Curve.controlPoints(curve)).y;
|
|
2739
2739
|
}
|
|
2740
2740
|
/**
|
|
@@ -2744,11 +2744,11 @@ var Shaping = class {
|
|
|
2744
2744
|
* @param p1` a Pt object specifying the Pt to pass through. Default is `Pt(0.2, 0.35)
|
|
2745
2745
|
*/
|
|
2746
2746
|
static quadraticTarget(t, c = 1, p1 = [0.2, 0.35]) {
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2747
|
+
const a = Math.min(1 - Const.epsilon, Math.max(Const.epsilon, p1[0]));
|
|
2748
|
+
const b = Math.min(1, Math.max(0, p1[1]));
|
|
2749
|
+
const A = (1 - b) / (1 - a) - b / a;
|
|
2750
|
+
const B = (A * (a * a) - b) / a;
|
|
2751
|
+
const y = A * (t * t) - B * t;
|
|
2752
2752
|
return c * Math.min(1, Math.max(0, y));
|
|
2753
2753
|
}
|
|
2754
2754
|
/**
|
|
@@ -2769,8 +2769,8 @@ var Shaping = class {
|
|
|
2769
2769
|
* @param args optional paramters to pass to original function
|
|
2770
2770
|
*/
|
|
2771
2771
|
static step(fn, steps, t, c, ...args) {
|
|
2772
|
-
|
|
2773
|
-
|
|
2772
|
+
const s = 1 / steps;
|
|
2773
|
+
const tt = Math.floor(t / s) * s;
|
|
2774
2774
|
return fn(tt, c, ...args);
|
|
2775
2775
|
}
|
|
2776
2776
|
};
|
|
@@ -2808,16 +2808,16 @@ var Range = class {
|
|
|
2808
2808
|
calc() {
|
|
2809
2809
|
if (!this._source)
|
|
2810
2810
|
return;
|
|
2811
|
-
|
|
2811
|
+
const dims = this._source[0].length;
|
|
2812
2812
|
this._dims = dims;
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2813
|
+
const max = new Pt(dims);
|
|
2814
|
+
const min = new Pt(dims);
|
|
2815
|
+
const mag = new Pt(dims);
|
|
2816
2816
|
for (let i = 0; i < dims; i++) {
|
|
2817
2817
|
max[i] = Const.min;
|
|
2818
2818
|
min[i] = Const.max;
|
|
2819
2819
|
mag[i] = 0;
|
|
2820
|
-
|
|
2820
|
+
const s = this._source.zipSlice(i);
|
|
2821
2821
|
for (let k = 0, len = s.length; k < len; k++) {
|
|
2822
2822
|
max[i] = Math.max(max[i], s[k]);
|
|
2823
2823
|
min[i] = Math.min(min[i], s[k]);
|
|
@@ -2836,10 +2836,10 @@ var Range = class {
|
|
|
2836
2836
|
* @param exclude Optional boolean array where `true` means excluding the conversion in that specific dimension.
|
|
2837
2837
|
*/
|
|
2838
2838
|
mapTo(min, max, exclude) {
|
|
2839
|
-
|
|
2839
|
+
const target = new Group();
|
|
2840
2840
|
for (let i = 0, len = this._source.length; i < len; i++) {
|
|
2841
|
-
|
|
2842
|
-
|
|
2841
|
+
const g = this._source[i];
|
|
2842
|
+
const n = new Pt(this._dims);
|
|
2843
2843
|
for (let k = 0; k < this._dims; k++) {
|
|
2844
2844
|
n[k] = exclude && exclude[k] ? g[k] : Num.mapToRange(g[k], this._min[k], this._max[k], min, max);
|
|
2845
2845
|
}
|
|
@@ -2853,7 +2853,7 @@ var Range = class {
|
|
|
2853
2853
|
* @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`.
|
|
2854
2854
|
*/
|
|
2855
2855
|
append(pts, update = true) {
|
|
2856
|
-
|
|
2856
|
+
const _pts = Util.iterToArray(pts);
|
|
2857
2857
|
if (_pts[0].length !== this._dims)
|
|
2858
2858
|
throw new Error(`Dimensions don't match. ${this._dims} dimensions in Range and ${_pts[0].length} provided in parameter. `);
|
|
2859
2859
|
this._source = this._source.concat(_pts);
|
|
@@ -2866,9 +2866,9 @@ var Range = class {
|
|
|
2866
2866
|
* @param count number of subdivision. For example, 10 subdivision will return 11 tick values, which include first(min) and last(max) values.
|
|
2867
2867
|
*/
|
|
2868
2868
|
ticks(count) {
|
|
2869
|
-
|
|
2869
|
+
const g = new Group();
|
|
2870
2870
|
for (let i = 0; i <= count; i++) {
|
|
2871
|
-
|
|
2871
|
+
const p = new Pt(this._dims);
|
|
2872
2872
|
for (let k = 0, len = this._max.length; k < len; k++) {
|
|
2873
2873
|
p[k] = Num.lerp(this._min[k], this._max[k], i / count);
|
|
2874
2874
|
}
|
|
@@ -2937,7 +2937,7 @@ var Const = {
|
|
|
2937
2937
|
/** Gaussian constant (1 / Math.sqrt(2 * Math.PI)) */
|
|
2938
2938
|
gaussian: 0.3989422804014327
|
|
2939
2939
|
};
|
|
2940
|
-
var _Util = class {
|
|
2940
|
+
var _Util = class _Util {
|
|
2941
2941
|
/**
|
|
2942
2942
|
* Set a global warning level setting. If no parameter is passed, this will return the current warn-level. See [`Util.warn`](#link).
|
|
2943
2943
|
* @param lv a [`WarningType`](#link) option, where "error" will throw an error, "warn" will log in console, and "mute" will ignore the error.
|
|
@@ -3032,7 +3032,7 @@ var _Util = class {
|
|
|
3032
3032
|
* @param flattenAsGroup a boolean to specify whether the return type should be a Group or Array. Default is `true` which returns a Group.
|
|
3033
3033
|
*/
|
|
3034
3034
|
static flatten(pts, flattenAsGroup = true) {
|
|
3035
|
-
let arr = flattenAsGroup ? new Group() :
|
|
3035
|
+
let arr = flattenAsGroup ? new Group() : [];
|
|
3036
3036
|
return arr.concat.apply(arr, pts);
|
|
3037
3037
|
}
|
|
3038
3038
|
/**
|
|
@@ -3105,7 +3105,7 @@ var _Util = class {
|
|
|
3105
3105
|
* @param callback a function to capture the data. It receives two parameters: a `response` as string, and a `success` status as boolean.
|
|
3106
3106
|
*/
|
|
3107
3107
|
static load(url, callback) {
|
|
3108
|
-
|
|
3108
|
+
let request = new XMLHttpRequest();
|
|
3109
3109
|
request.open("GET", url, true);
|
|
3110
3110
|
request.onload = function() {
|
|
3111
3111
|
if (request.status >= 200 && request.status < 400) {
|
|
@@ -3183,11 +3183,11 @@ var _Util = class {
|
|
|
3183
3183
|
return /iPhone|iPad|Android/i.test(navigator.userAgent);
|
|
3184
3184
|
}
|
|
3185
3185
|
};
|
|
3186
|
+
_Util._warnLevel = "mute";
|
|
3186
3187
|
var Util = _Util;
|
|
3187
|
-
Util._warnLevel = "mute";
|
|
3188
3188
|
|
|
3189
3189
|
// src/Pt.ts
|
|
3190
|
-
var Pt = class extends Float32Array {
|
|
3190
|
+
var Pt = class _Pt extends Float32Array {
|
|
3191
3191
|
/**
|
|
3192
3192
|
* Create a Pt. If no parameter is provided, this will instantiate a Pt with 2 dimensions [0, 0].
|
|
3193
3193
|
* 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])`.
|
|
@@ -3210,7 +3210,7 @@ var Pt = class extends Float32Array {
|
|
|
3210
3210
|
* @param randomize if `true`, randomize the value between 0 to default value
|
|
3211
3211
|
*/
|
|
3212
3212
|
static make(dimensions, defaultValue = 0, randomize = false) {
|
|
3213
|
-
|
|
3213
|
+
const p = new Float32Array(dimensions);
|
|
3214
3214
|
if (defaultValue)
|
|
3215
3215
|
p.fill(defaultValue);
|
|
3216
3216
|
if (randomize) {
|
|
@@ -3218,7 +3218,7 @@ var Pt = class extends Float32Array {
|
|
|
3218
3218
|
p[i] = p[i] * Num.random();
|
|
3219
3219
|
}
|
|
3220
3220
|
}
|
|
3221
|
-
return new
|
|
3221
|
+
return new _Pt(p);
|
|
3222
3222
|
}
|
|
3223
3223
|
/**
|
|
3224
3224
|
* ID string of this Pt
|
|
@@ -3269,7 +3269,7 @@ var Pt = class extends Float32Array {
|
|
|
3269
3269
|
* Clone this Pt and return it as a new Pt.
|
|
3270
3270
|
*/
|
|
3271
3271
|
clone() {
|
|
3272
|
-
return new
|
|
3272
|
+
return new _Pt(this);
|
|
3273
3273
|
}
|
|
3274
3274
|
/**
|
|
3275
3275
|
* Check if another Pt is equal to this Pt, within a threshold.
|
|
@@ -3288,7 +3288,7 @@ var Pt = class extends Float32Array {
|
|
|
3288
3288
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3289
3289
|
*/
|
|
3290
3290
|
to(...args) {
|
|
3291
|
-
|
|
3291
|
+
const p = Util.getArgs(args);
|
|
3292
3292
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3293
3293
|
this[i] = p[i];
|
|
3294
3294
|
}
|
|
@@ -3308,8 +3308,8 @@ var Pt = class extends Float32Array {
|
|
|
3308
3308
|
* @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.
|
|
3309
3309
|
*/
|
|
3310
3310
|
toAngle(radian, magnitude, anchorFromPt = false) {
|
|
3311
|
-
|
|
3312
|
-
|
|
3311
|
+
const m = magnitude != void 0 ? magnitude : this.magnitude();
|
|
3312
|
+
const change = [Math.cos(radian) * m, Math.sin(radian) * m];
|
|
3313
3313
|
return anchorFromPt ? this.add(change) : this.to(change);
|
|
3314
3314
|
}
|
|
3315
3315
|
/**
|
|
@@ -3319,7 +3319,7 @@ var Pt = class extends Float32Array {
|
|
|
3319
3319
|
* @returns a resulting function that takes other parameters required in `fn`
|
|
3320
3320
|
*/
|
|
3321
3321
|
op(fn) {
|
|
3322
|
-
|
|
3322
|
+
const self = this;
|
|
3323
3323
|
return (...params) => {
|
|
3324
3324
|
return fn(self, ...params);
|
|
3325
3325
|
};
|
|
@@ -3331,7 +3331,7 @@ var Pt = class extends Float32Array {
|
|
|
3331
3331
|
* @returns an array of resulting functions
|
|
3332
3332
|
*/
|
|
3333
3333
|
ops(fns) {
|
|
3334
|
-
|
|
3334
|
+
const _ops = [];
|
|
3335
3335
|
for (let i = 0, len = fns.length; i < len; i++) {
|
|
3336
3336
|
_ops.push(this.op(fns[i]));
|
|
3337
3337
|
}
|
|
@@ -3342,18 +3342,18 @@ var Pt = class extends Float32Array {
|
|
|
3342
3342
|
* @param axis a string such as "xy" (use Const.xy) or an array to specify indices
|
|
3343
3343
|
*/
|
|
3344
3344
|
$take(axis) {
|
|
3345
|
-
|
|
3345
|
+
const p = [];
|
|
3346
3346
|
for (let i = 0, len = axis.length; i < len; i++) {
|
|
3347
3347
|
p.push(this[axis[i]] || 0);
|
|
3348
3348
|
}
|
|
3349
|
-
return new
|
|
3349
|
+
return new _Pt(p);
|
|
3350
3350
|
}
|
|
3351
3351
|
/**
|
|
3352
3352
|
* Concatenate this Pt with addition dimensional values and return as a new Pt.
|
|
3353
3353
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3354
3354
|
*/
|
|
3355
3355
|
$concat(...args) {
|
|
3356
|
-
return new
|
|
3356
|
+
return new _Pt(this.toArray().concat(Util.getArgs(args)));
|
|
3357
3357
|
}
|
|
3358
3358
|
/**
|
|
3359
3359
|
* Add scalar or vector values to this Pt.
|
|
@@ -3548,8 +3548,8 @@ var Pt = class extends Float32Array {
|
|
|
3548
3548
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3549
3549
|
*/
|
|
3550
3550
|
$min(...args) {
|
|
3551
|
-
|
|
3552
|
-
|
|
3551
|
+
const p = Util.getArgs(args);
|
|
3552
|
+
const m = this.clone();
|
|
3553
3553
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3554
3554
|
m[i] = Math.min(this[i], p[i]);
|
|
3555
3555
|
}
|
|
@@ -3560,8 +3560,8 @@ var Pt = class extends Float32Array {
|
|
|
3560
3560
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3561
3561
|
*/
|
|
3562
3562
|
$max(...args) {
|
|
3563
|
-
|
|
3564
|
-
|
|
3563
|
+
const p = Util.getArgs(args);
|
|
3564
|
+
const m = this.clone();
|
|
3565
3565
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3566
3566
|
m[i] = Math.max(this[i], p[i]);
|
|
3567
3567
|
}
|
|
@@ -3588,7 +3588,7 @@ var Pt = class extends Float32Array {
|
|
|
3588
3588
|
* @param anchor optional anchor point to scale from
|
|
3589
3589
|
*/
|
|
3590
3590
|
scale(scale, anchor) {
|
|
3591
|
-
Geom.scale(this, scale, anchor ||
|
|
3591
|
+
Geom.scale(this, scale, anchor || _Pt.make(this.length, 0));
|
|
3592
3592
|
return this;
|
|
3593
3593
|
}
|
|
3594
3594
|
/**
|
|
@@ -3598,7 +3598,7 @@ var Pt = class extends Float32Array {
|
|
|
3598
3598
|
* @param axis optional string such as "yz" to specify a 2D plane
|
|
3599
3599
|
*/
|
|
3600
3600
|
rotate2D(angle, anchor, axis) {
|
|
3601
|
-
Geom.rotate2D(this, angle, anchor ||
|
|
3601
|
+
Geom.rotate2D(this, angle, anchor || _Pt.make(this.length, 0), axis);
|
|
3602
3602
|
return this;
|
|
3603
3603
|
}
|
|
3604
3604
|
/**
|
|
@@ -3608,7 +3608,7 @@ var Pt = class extends Float32Array {
|
|
|
3608
3608
|
* @param axis optional string such as "yz" to specify a 2D plane
|
|
3609
3609
|
*/
|
|
3610
3610
|
shear2D(scale, anchor, axis) {
|
|
3611
|
-
Geom.shear2D(this, scale, anchor ||
|
|
3611
|
+
Geom.shear2D(this, scale, anchor || _Pt.make(this.length, 0), axis);
|
|
3612
3612
|
return this;
|
|
3613
3613
|
}
|
|
3614
3614
|
/**
|
|
@@ -3636,16 +3636,16 @@ var Pt = class extends Float32Array {
|
|
|
3636
3636
|
* Convert this Pt to a Group as new Group([0,...], pt)
|
|
3637
3637
|
*/
|
|
3638
3638
|
toGroup() {
|
|
3639
|
-
return new Group(
|
|
3639
|
+
return new Group(_Pt.make(this.length), this.clone());
|
|
3640
3640
|
}
|
|
3641
3641
|
/**
|
|
3642
3642
|
* Convert this Pt to a Bound as new Group([0,...], pt)
|
|
3643
3643
|
*/
|
|
3644
3644
|
toBound() {
|
|
3645
|
-
return new Bound(
|
|
3645
|
+
return new Bound(_Pt.make(this.length), this.clone());
|
|
3646
3646
|
}
|
|
3647
3647
|
};
|
|
3648
|
-
var Group = class extends Array {
|
|
3648
|
+
var Group = class _Group extends Array {
|
|
3649
3649
|
/**
|
|
3650
3650
|
* Create a Group by passing an array of [`Pt`](#link). You may also create a Group using [`Group.fromArray`](#link) or [`Group.fromPtArray`](#link).
|
|
3651
3651
|
* @param args an array of Pts
|
|
@@ -3714,7 +3714,7 @@ var Group = class extends Array {
|
|
|
3714
3714
|
* Depp clone this group and its Pts.
|
|
3715
3715
|
*/
|
|
3716
3716
|
clone() {
|
|
3717
|
-
|
|
3717
|
+
const group = new _Group();
|
|
3718
3718
|
for (let i = 0, len = this.length; i < len; i++) {
|
|
3719
3719
|
group.push(this[i].clone());
|
|
3720
3720
|
}
|
|
@@ -3726,9 +3726,9 @@ var Group = class extends Array {
|
|
|
3726
3726
|
* @example `Group.fromArray( [[1,2], [3,4], [5,6]] )`
|
|
3727
3727
|
*/
|
|
3728
3728
|
static fromArray(list) {
|
|
3729
|
-
|
|
3730
|
-
for (
|
|
3731
|
-
|
|
3729
|
+
const g = new _Group();
|
|
3730
|
+
for (const li of list) {
|
|
3731
|
+
const p = li instanceof Pt ? li : new Pt(li);
|
|
3732
3732
|
g.push(p);
|
|
3733
3733
|
}
|
|
3734
3734
|
return g;
|
|
@@ -3738,7 +3738,7 @@ var Group = class extends Array {
|
|
|
3738
3738
|
* @param list an Iterable<Pt>
|
|
3739
3739
|
*/
|
|
3740
3740
|
static fromPtArray(list) {
|
|
3741
|
-
return
|
|
3741
|
+
return _Group.from(list);
|
|
3742
3742
|
}
|
|
3743
3743
|
/**
|
|
3744
3744
|
* Split this Group into an array of sub-groups.
|
|
@@ -3747,7 +3747,7 @@ var Group = class extends Array {
|
|
|
3747
3747
|
* @param loopBack if `true`, always go through the array till the end and loop back to the beginning to complete the segments if needed
|
|
3748
3748
|
*/
|
|
3749
3749
|
split(chunkSize, stride, loopBack = false) {
|
|
3750
|
-
|
|
3750
|
+
const sp = Util.split(this, chunkSize, stride, loopBack);
|
|
3751
3751
|
return sp;
|
|
3752
3752
|
}
|
|
3753
3753
|
/**
|
|
@@ -3756,7 +3756,7 @@ var Group = class extends Array {
|
|
|
3756
3756
|
* @param index the index position to insert into
|
|
3757
3757
|
*/
|
|
3758
3758
|
insert(pts, index = 0) {
|
|
3759
|
-
|
|
3759
|
+
_Group.prototype.splice.apply(this, [index, 0, ...pts]);
|
|
3760
3760
|
return this;
|
|
3761
3761
|
}
|
|
3762
3762
|
/**
|
|
@@ -3766,8 +3766,8 @@ var Group = class extends Array {
|
|
|
3766
3766
|
* @returns The items that are removed.
|
|
3767
3767
|
*/
|
|
3768
3768
|
remove(index = 0, count = 1) {
|
|
3769
|
-
|
|
3770
|
-
return
|
|
3769
|
+
const param = index < 0 ? [index * -1 - 1, count] : [index, count];
|
|
3770
|
+
return _Group.prototype.splice.apply(this, param);
|
|
3771
3771
|
}
|
|
3772
3772
|
/**
|
|
3773
3773
|
* Split this group into an array of sub-group segments.
|
|
@@ -3818,7 +3818,7 @@ var Group = class extends Array {
|
|
|
3818
3818
|
* @returns a resulting function that takes other parameters required in `fn`
|
|
3819
3819
|
*/
|
|
3820
3820
|
op(fn) {
|
|
3821
|
-
|
|
3821
|
+
const self = this;
|
|
3822
3822
|
return (...params) => {
|
|
3823
3823
|
return fn(self, ...params);
|
|
3824
3824
|
};
|
|
@@ -3830,7 +3830,7 @@ var Group = class extends Array {
|
|
|
3830
3830
|
* @returns an array of resulting functions
|
|
3831
3831
|
*/
|
|
3832
3832
|
ops(fns) {
|
|
3833
|
-
|
|
3833
|
+
const _ops = [];
|
|
3834
3834
|
for (let i = 0, len = fns.length; i < len; i++) {
|
|
3835
3835
|
_ops.push(this.op(fns[i]));
|
|
3836
3836
|
}
|
|
@@ -3842,9 +3842,9 @@ var Group = class extends Array {
|
|
|
3842
3842
|
*/
|
|
3843
3843
|
interpolate(t) {
|
|
3844
3844
|
t = Num.clamp(t, 0, 1);
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3845
|
+
const chunk = this.length - 1;
|
|
3846
|
+
const tc = 1 / (this.length - 1);
|
|
3847
|
+
const idx = Math.floor(t / tc);
|
|
3848
3848
|
return Geom.interpolate(this[idx], this[Math.min(this.length - 1, idx + 1)], (t - idx * tc) * chunk);
|
|
3849
3849
|
}
|
|
3850
3850
|
/**
|
|
@@ -3859,7 +3859,7 @@ var Group = class extends Array {
|
|
|
3859
3859
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3860
3860
|
*/
|
|
3861
3861
|
moveTo(...args) {
|
|
3862
|
-
|
|
3862
|
+
const d = new Pt(Util.getArgs(args)).subtract(this[0]);
|
|
3863
3863
|
this.moveBy(d);
|
|
3864
3864
|
return this;
|
|
3865
3865
|
}
|
|
@@ -4007,7 +4007,7 @@ var Group = class extends Array {
|
|
|
4007
4007
|
return "Group[ " + this.reduce((p, c) => p + c.toString() + " ", "") + " ]";
|
|
4008
4008
|
}
|
|
4009
4009
|
};
|
|
4010
|
-
var Bound = class extends Group {
|
|
4010
|
+
var Bound = class _Bound extends Group {
|
|
4011
4011
|
/**
|
|
4012
4012
|
* 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.
|
|
4013
4013
|
* @param args a list of Pt as parameters
|
|
@@ -4028,7 +4028,7 @@ var Bound = class extends Group {
|
|
|
4028
4028
|
* @returns a Bound object
|
|
4029
4029
|
*/
|
|
4030
4030
|
static fromBoundingRect(rect) {
|
|
4031
|
-
|
|
4031
|
+
const b = new _Bound(new Pt(rect.left || 0, rect.top || 0), new Pt(rect.right || 0, rect.bottom || 0));
|
|
4032
4032
|
if (rect.width && rect.height)
|
|
4033
4033
|
b.size = new Pt(rect.width, rect.height);
|
|
4034
4034
|
return b;
|
|
@@ -4038,10 +4038,10 @@ var Bound = class extends Group {
|
|
|
4038
4038
|
* @param g a Group or an Iterable<PtLike>
|
|
4039
4039
|
*/
|
|
4040
4040
|
static fromGroup(g) {
|
|
4041
|
-
|
|
4041
|
+
const _g = Util.iterToArray(g);
|
|
4042
4042
|
if (_g.length < 2)
|
|
4043
4043
|
throw new Error("Cannot create a Bound from a group that has less than 2 Pt");
|
|
4044
|
-
return new
|
|
4044
|
+
return new _Bound(_g[0], _g[_g.length - 1]);
|
|
4045
4045
|
}
|
|
4046
4046
|
/**
|
|
4047
4047
|
* Initiate the bound's properties.
|
|
@@ -4052,8 +4052,8 @@ var Bound = class extends Group {
|
|
|
4052
4052
|
this._inited = true;
|
|
4053
4053
|
}
|
|
4054
4054
|
if (this.p1 && this.p2) {
|
|
4055
|
-
|
|
4056
|
-
|
|
4055
|
+
const a = this.p1;
|
|
4056
|
+
const b = this.p2;
|
|
4057
4057
|
this.topLeft = a.$min(b);
|
|
4058
4058
|
this._bottomRight = a.$max(b);
|
|
4059
4059
|
this._updateSize();
|
|
@@ -4064,7 +4064,7 @@ var Bound = class extends Group {
|
|
|
4064
4064
|
* Clone this bound and return a new one.
|
|
4065
4065
|
*/
|
|
4066
4066
|
clone() {
|
|
4067
|
-
return new
|
|
4067
|
+
return new _Bound(this._topLeft.clone(), this._bottomRight.clone());
|
|
4068
4068
|
}
|
|
4069
4069
|
/**
|
|
4070
4070
|
* Recalculte size and center.
|
|
@@ -4097,7 +4097,7 @@ var Bound = class extends Group {
|
|
|
4097
4097
|
* Recalculate based on center position and size.
|
|
4098
4098
|
*/
|
|
4099
4099
|
_updatePosFromCenter() {
|
|
4100
|
-
|
|
4100
|
+
const half = this._size.$multiply(0.5);
|
|
4101
4101
|
this._topLeft = this._center.$subtract(half);
|
|
4102
4102
|
this._bottomRight = this._center.$add(half);
|
|
4103
4103
|
}
|
|
@@ -4232,10 +4232,12 @@ var UIPointerActions = {
|
|
|
4232
4232
|
click: "click",
|
|
4233
4233
|
keydown: "keydown",
|
|
4234
4234
|
keyup: "keyup",
|
|
4235
|
+
pointerdown: "pointerdown",
|
|
4236
|
+
pointerup: "pointerup",
|
|
4235
4237
|
contextmenu: "contextmenu",
|
|
4236
4238
|
all: "all"
|
|
4237
4239
|
};
|
|
4238
|
-
var _UI = class {
|
|
4240
|
+
var _UI = class _UI {
|
|
4239
4241
|
/**
|
|
4240
4242
|
* 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).
|
|
4241
4243
|
* @param group a Group or an Iterable<PtLike> that defines the UI's appearance
|
|
@@ -4471,8 +4473,8 @@ var _UI = class {
|
|
|
4471
4473
|
}
|
|
4472
4474
|
}
|
|
4473
4475
|
};
|
|
4476
|
+
_UI._counter = 0;
|
|
4474
4477
|
var UI = _UI;
|
|
4475
|
-
UI._counter = 0;
|
|
4476
4478
|
var UIButton = class extends UI {
|
|
4477
4479
|
/**
|
|
4478
4480
|
* 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).
|
|
@@ -4497,7 +4499,7 @@ var UIButton = class extends UI {
|
|
|
4497
4499
|
if (hover && !this._states.hover) {
|
|
4498
4500
|
this.state("hover", true);
|
|
4499
4501
|
UI._trigger(this._actions[UA.enter], this, pt, UA.enter, evt);
|
|
4500
|
-
|
|
4502
|
+
let _capID = this.hold(UA.move);
|
|
4501
4503
|
this._hoverID = this.on(UA.move, (t, p) => {
|
|
4502
4504
|
if (!this._within(p) && !this.state("dragging")) {
|
|
4503
4505
|
this.state("hover", false);
|
|
@@ -4548,7 +4550,7 @@ var UIButton = class extends UI {
|
|
|
4548
4550
|
* @returns id numbers that refer to enter/leave handlers, for use in [`UIButton.offHover`](#link) or [`UI.off`](#link).
|
|
4549
4551
|
*/
|
|
4550
4552
|
onHover(enter, leave) {
|
|
4551
|
-
|
|
4553
|
+
let ids = [void 0, void 0];
|
|
4552
4554
|
if (enter)
|
|
4553
4555
|
ids[0] = this.on(UIPointerActions.enter, enter);
|
|
4554
4556
|
if (leave)
|
|
@@ -4562,7 +4564,7 @@ var UIButton = class extends UI {
|
|
|
4562
4564
|
* @returns an array of booleans indicating whether the handlers were removed successfully
|
|
4563
4565
|
*/
|
|
4564
4566
|
offHover(enterID, leaveID) {
|
|
4565
|
-
|
|
4567
|
+
let s = [false, false];
|
|
4566
4568
|
if (enterID === void 0 || enterID >= 0)
|
|
4567
4569
|
s[0] = this.off(UIPointerActions.enter, enterID);
|
|
4568
4570
|
if (leaveID === void 0 || leaveID >= 0)
|
|
@@ -4705,9 +4707,9 @@ var Space = class {
|
|
|
4705
4707
|
* @param player an [`IPlayer`](#link) object with animate function, or a callback function `fn(time, ftime)`.
|
|
4706
4708
|
*/
|
|
4707
4709
|
add(p) {
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4710
|
+
const player = typeof p == "function" ? { animate: p } : p;
|
|
4711
|
+
const k = this.playerCount++;
|
|
4712
|
+
const pid = player.animateID || this.id + k;
|
|
4711
4713
|
this.players[pid] = player;
|
|
4712
4714
|
player.animateID = pid;
|
|
4713
4715
|
if (player.resize && this.bound.inited)
|
|
@@ -4774,7 +4776,7 @@ var Space = class {
|
|
|
4774
4776
|
if (this._refresh)
|
|
4775
4777
|
this.clear();
|
|
4776
4778
|
if (this._isReady) {
|
|
4777
|
-
for (
|
|
4779
|
+
for (const k in this.players) {
|
|
4778
4780
|
if (this.players[k].animate)
|
|
4779
4781
|
this.players[k].animate(time, this._time.diff, this);
|
|
4780
4782
|
}
|
|
@@ -4892,7 +4894,7 @@ var MultiTouchSpace = class extends Space {
|
|
|
4892
4894
|
* Get the mouse or touch pointer that stores the last action.
|
|
4893
4895
|
*/
|
|
4894
4896
|
get pointer() {
|
|
4895
|
-
|
|
4897
|
+
const p = this._pointer.clone();
|
|
4896
4898
|
p.id = this._pointer.id;
|
|
4897
4899
|
return p;
|
|
4898
4900
|
}
|
|
@@ -4944,9 +4946,13 @@ var MultiTouchSpace = class extends Space {
|
|
|
4944
4946
|
this._mouseOut = this._mouseOut.bind(this);
|
|
4945
4947
|
this._mouseMove = this._mouseMove.bind(this);
|
|
4946
4948
|
this._mouseClick = this._mouseClick.bind(this);
|
|
4949
|
+
this._pointerDown = this._pointerDown.bind(this);
|
|
4950
|
+
this._pointerUp = this._pointerUp.bind(this);
|
|
4947
4951
|
this._contextMenu = this._contextMenu.bind(this);
|
|
4948
4952
|
this.bindCanvas("mousedown", this._mouseDown, {}, customTarget);
|
|
4953
|
+
this.bindCanvas("pointerdown", this._pointerDown, {}, customTarget);
|
|
4949
4954
|
this.bindCanvas("mouseup", this._mouseUp, {}, customTarget);
|
|
4955
|
+
this.bindCanvas("pointerup", this._pointerUp, {}, customTarget);
|
|
4950
4956
|
this.bindCanvas("mouseover", this._mouseOver, {}, customTarget);
|
|
4951
4957
|
this.bindCanvas("mouseout", this._mouseOut, {}, customTarget);
|
|
4952
4958
|
this.bindCanvas("mousemove", this._mouseMove, {}, customTarget);
|
|
@@ -4955,7 +4961,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
4955
4961
|
this._hasMouse = true;
|
|
4956
4962
|
} else {
|
|
4957
4963
|
this.unbindCanvas("mousedown", this._mouseDown, {}, customTarget);
|
|
4964
|
+
this.unbindCanvas("pointerdown", this._pointerDown, {}, customTarget);
|
|
4958
4965
|
this.unbindCanvas("mouseup", this._mouseUp, {}, customTarget);
|
|
4966
|
+
this.unbindCanvas("pointerup", this._pointerUp, {}, customTarget);
|
|
4959
4967
|
this.unbindCanvas("mouseover", this._mouseOver, {}, customTarget);
|
|
4960
4968
|
this.unbindCanvas("mouseout", this._mouseOut, {}, customTarget);
|
|
4961
4969
|
this.unbindCanvas("mousemove", this._mouseMove, {}, customTarget);
|
|
@@ -5013,9 +5021,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5013
5021
|
touchesToPoints(evt, which = "touches") {
|
|
5014
5022
|
if (!evt || !evt[which])
|
|
5015
5023
|
return [];
|
|
5016
|
-
|
|
5017
|
-
for (
|
|
5018
|
-
|
|
5024
|
+
const ts = [];
|
|
5025
|
+
for (let i = 0; i < evt[which].length; i++) {
|
|
5026
|
+
const t = evt[which].item(i);
|
|
5019
5027
|
ts.push(new Pt(t.pageX - this.bound.topLeft.x, t.pageY - this.bound.topLeft.y));
|
|
5020
5028
|
}
|
|
5021
5029
|
return ts;
|
|
@@ -5031,9 +5039,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5031
5039
|
return;
|
|
5032
5040
|
let px = 0, py = 0;
|
|
5033
5041
|
if (evt instanceof MouseEvent) {
|
|
5034
|
-
for (
|
|
5042
|
+
for (const k in this.players) {
|
|
5035
5043
|
if (this.players.hasOwnProperty(k)) {
|
|
5036
|
-
|
|
5044
|
+
const v = this.players[k];
|
|
5037
5045
|
px = evt.pageX - this.outerBound.x;
|
|
5038
5046
|
py = evt.pageY - this.outerBound.y;
|
|
5039
5047
|
if (v.action)
|
|
@@ -5041,11 +5049,11 @@ var MultiTouchSpace = class extends Space {
|
|
|
5041
5049
|
}
|
|
5042
5050
|
}
|
|
5043
5051
|
} else {
|
|
5044
|
-
for (
|
|
5052
|
+
for (const k in this.players) {
|
|
5045
5053
|
if (this.players.hasOwnProperty(k)) {
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5054
|
+
const v = this.players[k];
|
|
5055
|
+
const c = evt.changedTouches && evt.changedTouches.length > 0;
|
|
5056
|
+
const touch = evt.changedTouches.item(0);
|
|
5049
5057
|
px = c ? touch.pageX - this.outerBound.x : 0;
|
|
5050
5058
|
py = c ? touch.pageY - this.outerBound.y : 0;
|
|
5051
5059
|
if (v.action)
|
|
@@ -5067,6 +5075,13 @@ var MultiTouchSpace = class extends Space {
|
|
|
5067
5075
|
this._pressed = true;
|
|
5068
5076
|
return false;
|
|
5069
5077
|
}
|
|
5078
|
+
_pointerDown(evt) {
|
|
5079
|
+
this._mouseAction(UIPointerActions.pointerdown, evt);
|
|
5080
|
+
if (evt.target instanceof Element) {
|
|
5081
|
+
evt.target.setPointerCapture(evt.pointerId);
|
|
5082
|
+
}
|
|
5083
|
+
return false;
|
|
5084
|
+
}
|
|
5070
5085
|
/**
|
|
5071
5086
|
* MouseUp handler.
|
|
5072
5087
|
* @param evt
|
|
@@ -5081,6 +5096,16 @@ var MultiTouchSpace = class extends Space {
|
|
|
5081
5096
|
this._dragged = false;
|
|
5082
5097
|
return false;
|
|
5083
5098
|
}
|
|
5099
|
+
_pointerUp(evt) {
|
|
5100
|
+
this._mouseAction(UIPointerActions.pointerup, evt);
|
|
5101
|
+
if (evt.target instanceof Element) {
|
|
5102
|
+
evt.target.releasePointerCapture(evt.pointerId);
|
|
5103
|
+
if (this._dragged)
|
|
5104
|
+
this._mouseAction(UIPointerActions.drop, evt);
|
|
5105
|
+
this._dragged = false;
|
|
5106
|
+
}
|
|
5107
|
+
return false;
|
|
5108
|
+
}
|
|
5084
5109
|
/**
|
|
5085
5110
|
* MouseMove handler.
|
|
5086
5111
|
* @param evt
|
|
@@ -5159,9 +5184,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5159
5184
|
_keyboardAction(type, evt) {
|
|
5160
5185
|
if (!this.isPlaying)
|
|
5161
5186
|
return;
|
|
5162
|
-
for (
|
|
5187
|
+
for (const k in this.players) {
|
|
5163
5188
|
if (this.players.hasOwnProperty(k)) {
|
|
5164
|
-
|
|
5189
|
+
const v = this.players[k];
|
|
5165
5190
|
if (v.action)
|
|
5166
5191
|
v.action(type, evt.shiftKey ? 1 : 0, evt.altKey ? 1 : 0, evt);
|
|
5167
5192
|
}
|
|
@@ -5410,7 +5435,7 @@ var Typography = class {
|
|
|
5410
5435
|
};
|
|
5411
5436
|
|
|
5412
5437
|
// src/Image.ts
|
|
5413
|
-
var Img = class {
|
|
5438
|
+
var Img = class _Img {
|
|
5414
5439
|
/**
|
|
5415
5440
|
* Create an Img
|
|
5416
5441
|
* @param editable Specify if you want to manipulate pixels of this image. Default is `false`.
|
|
@@ -5435,7 +5460,7 @@ var Img = class {
|
|
|
5435
5460
|
* @param ready An optional ready callback function
|
|
5436
5461
|
*/
|
|
5437
5462
|
static load(src, editable = false, space, ready) {
|
|
5438
|
-
const img = new
|
|
5463
|
+
const img = new _Img(editable, space);
|
|
5439
5464
|
img.load(src).then((res) => {
|
|
5440
5465
|
if (ready)
|
|
5441
5466
|
ready(res);
|
|
@@ -5451,7 +5476,7 @@ var Img = class {
|
|
|
5451
5476
|
*/
|
|
5452
5477
|
static loadAsync(src, editable = false, space) {
|
|
5453
5478
|
return __async(this, null, function* () {
|
|
5454
|
-
const img = yield new
|
|
5479
|
+
const img = yield new _Img(editable, space).load(src);
|
|
5455
5480
|
return img;
|
|
5456
5481
|
});
|
|
5457
5482
|
}
|
|
@@ -5465,7 +5490,7 @@ var Img = class {
|
|
|
5465
5490
|
*/
|
|
5466
5491
|
static loadPattern(src, space, repeat = "repeat", editable = false) {
|
|
5467
5492
|
return __async(this, null, function* () {
|
|
5468
|
-
const img = yield
|
|
5493
|
+
const img = yield _Img.loadAsync(src, editable, space);
|
|
5469
5494
|
return img.pattern(repeat);
|
|
5470
5495
|
});
|
|
5471
5496
|
}
|
|
@@ -5476,7 +5501,7 @@ var Img = class {
|
|
|
5476
5501
|
* @param scale Optionally set a specific pixel scale (density) of the image canvas.
|
|
5477
5502
|
*/
|
|
5478
5503
|
static blank(size, space, scale) {
|
|
5479
|
-
let img = new
|
|
5504
|
+
let img = new _Img(true, space);
|
|
5480
5505
|
const s = scale ? scale : space.pixelScale;
|
|
5481
5506
|
img.initCanvas(size[0], size[1], s);
|
|
5482
5507
|
return img;
|
|
@@ -5582,7 +5607,7 @@ var Img = class {
|
|
|
5582
5607
|
*/
|
|
5583
5608
|
pixel(p, rescale = true) {
|
|
5584
5609
|
const s = typeof rescale == "number" ? rescale : rescale ? this._scale : 1;
|
|
5585
|
-
return
|
|
5610
|
+
return _Img.getPixel(this._data, [p[0] * s, p[1] * s]);
|
|
5586
5611
|
}
|
|
5587
5612
|
/**
|
|
5588
5613
|
* Given an ImaegData object and a position, return the RGBA pixel value at that position.
|
|
@@ -5647,7 +5672,7 @@ var Img = class {
|
|
|
5647
5672
|
*/
|
|
5648
5673
|
static fromBlob(blob, editable = false, space) {
|
|
5649
5674
|
let url = URL.createObjectURL(blob);
|
|
5650
|
-
return new
|
|
5675
|
+
return new _Img(editable, space).load(url);
|
|
5651
5676
|
}
|
|
5652
5677
|
/**
|
|
5653
5678
|
* 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.
|
|
@@ -5775,8 +5800,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5775
5800
|
this._bgcolor = "#e1e9f0";
|
|
5776
5801
|
this._offscreen = false;
|
|
5777
5802
|
this._initialResize = false;
|
|
5778
|
-
|
|
5779
|
-
|
|
5803
|
+
let _selector = null;
|
|
5804
|
+
let _existed = false;
|
|
5780
5805
|
this.id = "pt";
|
|
5781
5806
|
if (elem instanceof Element) {
|
|
5782
5807
|
_selector = elem;
|
|
@@ -5813,7 +5838,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5813
5838
|
* @param id element id attribute
|
|
5814
5839
|
*/
|
|
5815
5840
|
_createElement(elem = "div", id) {
|
|
5816
|
-
|
|
5841
|
+
const d = document.createElement(elem);
|
|
5817
5842
|
d.setAttribute("id", id);
|
|
5818
5843
|
return d;
|
|
5819
5844
|
}
|
|
@@ -5828,7 +5853,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5828
5853
|
this._resizeHandler(null);
|
|
5829
5854
|
this.clear(this._bgcolor);
|
|
5830
5855
|
this._canvas.dispatchEvent(new Event("ready"));
|
|
5831
|
-
for (
|
|
5856
|
+
for (const k in this.players) {
|
|
5832
5857
|
if (this.players.hasOwnProperty(k)) {
|
|
5833
5858
|
if (this.players[k].start)
|
|
5834
5859
|
this.players[k].start(this.bound.clone(), this);
|
|
@@ -5848,8 +5873,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5848
5873
|
this._bgcolor = opt.bgcolor ? opt.bgcolor : "transparent";
|
|
5849
5874
|
this.autoResize = opt.resize != void 0 ? opt.resize : false;
|
|
5850
5875
|
if (opt.retina !== false) {
|
|
5851
|
-
|
|
5852
|
-
|
|
5876
|
+
const r1 = window ? window.devicePixelRatio || 1 : 1;
|
|
5877
|
+
const r2 = this._ctx.webkitBackingStorePixelRatio || this._ctx.mozBackingStorePixelRatio || this._ctx.msBackingStorePixelRatio || this._ctx.oBackingStorePixelRatio || this._ctx.backingStorePixelRatio || 1;
|
|
5853
5878
|
this._pixelScale = Math.max(1, r1 / r2);
|
|
5854
5879
|
}
|
|
5855
5880
|
if (opt.offscreen) {
|
|
@@ -5903,9 +5928,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5903
5928
|
this._offCtx.scale(this._pixelScale, this._pixelScale);
|
|
5904
5929
|
}
|
|
5905
5930
|
}
|
|
5906
|
-
for (
|
|
5931
|
+
for (const k in this.players) {
|
|
5907
5932
|
if (this.players.hasOwnProperty(k)) {
|
|
5908
|
-
|
|
5933
|
+
const p = this.players[k];
|
|
5909
5934
|
if (p.resize)
|
|
5910
5935
|
p.resize(this.bound, evt);
|
|
5911
5936
|
}
|
|
@@ -5922,9 +5947,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5922
5947
|
_resizeHandler(evt) {
|
|
5923
5948
|
if (!window)
|
|
5924
5949
|
return;
|
|
5925
|
-
|
|
5950
|
+
const b = this._autoResize || this._initialResize ? this._container.getBoundingClientRect() : this._canvas.getBoundingClientRect();
|
|
5926
5951
|
if (b) {
|
|
5927
|
-
|
|
5952
|
+
const box = Bound.fromBoundingRect(b);
|
|
5928
5953
|
box.center = box.center.add(window.pageXOffset, window.pageYOffset);
|
|
5929
5954
|
this.resize(box, evt);
|
|
5930
5955
|
}
|
|
@@ -6067,14 +6092,14 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6067
6092
|
* @example `let rec = space.recorder(true); rec.start(); setTimeout( () => rec.stop(), 5000); // record 5s of video and download the file`
|
|
6068
6093
|
*/
|
|
6069
6094
|
recorder(downloadOrCallback, filetype = "webm", bitrate = 15e6) {
|
|
6070
|
-
|
|
6095
|
+
const stream = this._canvas.captureStream();
|
|
6071
6096
|
const recorder = new MediaRecorder(stream, { mimeType: `video/${filetype}`, bitsPerSecond: bitrate });
|
|
6072
6097
|
recorder.ondataavailable = function(d) {
|
|
6073
|
-
|
|
6098
|
+
const url = URL.createObjectURL(new Blob([d.data], { type: `video/${filetype}` }));
|
|
6074
6099
|
if (typeof downloadOrCallback === "function") {
|
|
6075
6100
|
downloadOrCallback(url);
|
|
6076
6101
|
} else if (downloadOrCallback) {
|
|
6077
|
-
|
|
6102
|
+
const a = document.createElement("a");
|
|
6078
6103
|
a.href = url;
|
|
6079
6104
|
a.download = `canvas_video.${filetype}`;
|
|
6080
6105
|
a.click();
|
|
@@ -6084,7 +6109,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6084
6109
|
return recorder;
|
|
6085
6110
|
}
|
|
6086
6111
|
};
|
|
6087
|
-
var CanvasForm = class extends VisualForm {
|
|
6112
|
+
var CanvasForm = class _CanvasForm extends VisualForm {
|
|
6088
6113
|
/**
|
|
6089
6114
|
* Create a new CanvasForm. You may also use [`CanvasSpace.getForm()`](#link) to get the default form.
|
|
6090
6115
|
* @param space an instance of CanvasSpace
|
|
@@ -6161,20 +6186,20 @@ var CanvasForm = class extends VisualForm {
|
|
|
6161
6186
|
}
|
|
6162
6187
|
}
|
|
6163
6188
|
/**
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6189
|
+
* Set current alpha value.
|
|
6190
|
+
* @example `form.alpha(0.6)`
|
|
6191
|
+
* @param a alpha value between 0 and 1
|
|
6192
|
+
*/
|
|
6168
6193
|
alpha(a) {
|
|
6169
6194
|
this._ctx.globalAlpha = a;
|
|
6170
6195
|
this._style.globalAlpha = a;
|
|
6171
6196
|
return this;
|
|
6172
6197
|
}
|
|
6173
6198
|
/**
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6199
|
+
* 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.
|
|
6200
|
+
* @example `form.fill("#F90")`, `form.fill("rgba(0,0,0,.5")`, `form.fill(false)`
|
|
6201
|
+
* @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))
|
|
6202
|
+
*/
|
|
6178
6203
|
fill(c) {
|
|
6179
6204
|
if (typeof c == "boolean") {
|
|
6180
6205
|
this.filled = c;
|
|
@@ -6186,21 +6211,21 @@ var CanvasForm = class extends VisualForm {
|
|
|
6186
6211
|
return this;
|
|
6187
6212
|
}
|
|
6188
6213
|
/**
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6214
|
+
* Set current fill style and remove stroke style.
|
|
6215
|
+
* @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))
|
|
6216
|
+
*/
|
|
6192
6217
|
fillOnly(c) {
|
|
6193
6218
|
this.stroke(false);
|
|
6194
6219
|
return this.fill(c);
|
|
6195
6220
|
}
|
|
6196
6221
|
/**
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6222
|
+
* Set current stroke style. Provide a valid color string or `false` to specify no stroke color.
|
|
6223
|
+
* @example `form.stroke("#F90")`, `form.stroke("rgba(0,0,0,.5")`, `form.stroke(false)`, `form.stroke("#000", 0.5, 'round', 'square')`
|
|
6224
|
+
* @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))
|
|
6225
|
+
* @param width Optional value (can be floating point) to set line width
|
|
6226
|
+
* @param linejoin Optional string to set line joint style. Can be "miter", "bevel", or "round".
|
|
6227
|
+
* @param linecap Optional string to set line cap style. Can be "butt", "round", or "square".
|
|
6228
|
+
*/
|
|
6204
6229
|
stroke(c, width, linejoin, linecap) {
|
|
6205
6230
|
if (typeof c == "boolean") {
|
|
6206
6231
|
this.stroked = c;
|
|
@@ -6224,24 +6249,24 @@ var CanvasForm = class extends VisualForm {
|
|
|
6224
6249
|
return this;
|
|
6225
6250
|
}
|
|
6226
6251
|
/**
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6252
|
+
* Set stroke style and remove fill style.
|
|
6253
|
+
* @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))
|
|
6254
|
+
* @param width Optional value (can be floating point) to set line width
|
|
6255
|
+
* @param linejoin Optional string to set line joint style. Can be "miter", "bevel", or "round".
|
|
6256
|
+
* @param linecap Optional string to set line cap style. Can be "butt", "round", or "square".
|
|
6257
|
+
*/
|
|
6233
6258
|
strokeOnly(c, width, linejoin, linecap) {
|
|
6234
6259
|
this.fill(false);
|
|
6235
6260
|
return this.stroke(c, width, linejoin, linecap);
|
|
6236
6261
|
}
|
|
6237
6262
|
/**
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6263
|
+
* A convenient function to apply fill and/or stroke after custom drawings using canvas context (eg, `form.ctx.ellipse(...)`).
|
|
6264
|
+
* You don't need to call this function if you're using Pts' drawing functions like `form.point` or `form.rect`
|
|
6265
|
+
* @param filled apply fill when set to `true`
|
|
6266
|
+
* @param stroked apply stroke when set to `true`
|
|
6267
|
+
* @param strokeWidth optionally set a stroke width
|
|
6268
|
+
* @example `form.ctx.beginPath(); form.ctx.ellipse(...); form.applyFillStroke();`
|
|
6269
|
+
*/
|
|
6245
6270
|
applyFillStroke(filled = true, stroked = true, strokeWidth = 1) {
|
|
6246
6271
|
if (filled) {
|
|
6247
6272
|
if (typeof filled === "string")
|
|
@@ -6256,22 +6281,22 @@ var CanvasForm = class extends VisualForm {
|
|
|
6256
6281
|
return this;
|
|
6257
6282
|
}
|
|
6258
6283
|
/**
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6284
|
+
* 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).
|
|
6285
|
+
* @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"]]`
|
|
6286
|
+
* @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.
|
|
6287
|
+
* @example `c1 = Circle.fromCenter(...); grad = form.gradient(["#f00", "#00f"]); form.fill( grad( c1, c2 ) ).circle( c1 )`
|
|
6288
|
+
*/
|
|
6264
6289
|
gradient(stops) {
|
|
6265
|
-
|
|
6290
|
+
const vals = [];
|
|
6266
6291
|
if (stops.length < 2)
|
|
6267
6292
|
stops.push([0.99, "#000"], [1, "#000"]);
|
|
6268
6293
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
6269
|
-
|
|
6270
|
-
|
|
6294
|
+
const t = typeof stops[i] === "string" ? i * (1 / (stops.length - 1)) : stops[i][0];
|
|
6295
|
+
const v = typeof stops[i] === "string" ? stops[i] : stops[i][1];
|
|
6271
6296
|
vals.push([t, v]);
|
|
6272
6297
|
}
|
|
6273
6298
|
return (area1, area2) => {
|
|
6274
|
-
|
|
6299
|
+
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]);
|
|
6275
6300
|
for (let i = 0, len = vals.length; i < len; i++) {
|
|
6276
6301
|
grad.addColorStop(vals[i][0], vals[i][1]);
|
|
6277
6302
|
}
|
|
@@ -6279,26 +6304,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6279
6304
|
};
|
|
6280
6305
|
}
|
|
6281
6306
|
/**
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6307
|
+
* 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.
|
|
6308
|
+
* @param mode a composite operation such as 'lighten', 'multiply', 'overlay', and 'color-burn'.
|
|
6309
|
+
*/
|
|
6285
6310
|
composite(mode = "source-over") {
|
|
6286
6311
|
this._ctx.globalCompositeOperation = mode;
|
|
6287
6312
|
return this;
|
|
6288
6313
|
}
|
|
6289
6314
|
/**
|
|
6290
|
-
|
|
6291
|
-
|
|
6315
|
+
* Create a clipping mask from the current path. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip) for details.
|
|
6316
|
+
*/
|
|
6292
6317
|
clip() {
|
|
6293
6318
|
this._ctx.clip();
|
|
6294
6319
|
return this;
|
|
6295
6320
|
}
|
|
6296
6321
|
/**
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6322
|
+
* Activate dashed stroke and set dash style. You can customize the segments and offset.
|
|
6323
|
+
* @example `form.dash()`, `form.dash([5, 10])`, `form.dash([5, 5], 5)`, `form.dash(false)`
|
|
6324
|
+
* @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))
|
|
6325
|
+
* @param offset Dash offset. Defaults to 0. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)
|
|
6326
|
+
*/
|
|
6302
6327
|
dash(segments = true, offset = 0) {
|
|
6303
6328
|
if (!segments) {
|
|
6304
6329
|
this._ctx.setLineDash([]);
|
|
@@ -6313,14 +6338,14 @@ var CanvasForm = class extends VisualForm {
|
|
|
6313
6338
|
return this;
|
|
6314
6339
|
}
|
|
6315
6340
|
/**
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6341
|
+
* Set the current font.
|
|
6342
|
+
* @param sizeOrFont either a number to specify font-size, or a `Font` object to specify all font properties
|
|
6343
|
+
* @param weight Optional font-weight string such as "bold"
|
|
6344
|
+
* @param style Optional font-style string such as "italic"
|
|
6345
|
+
* @param lineHeight Optional line-height number suchas 1.5
|
|
6346
|
+
* @param family Optional font-family such as "Helvetica, sans-serif"
|
|
6347
|
+
* @example `form.font( myFont )`, `form.font(14, "bold")`
|
|
6348
|
+
*/
|
|
6324
6349
|
font(sizeOrFont, weight, style, lineHeight, family) {
|
|
6325
6350
|
if (typeof sizeOrFont == "number") {
|
|
6326
6351
|
this._font.size = sizeOrFont;
|
|
@@ -6341,49 +6366,49 @@ var CanvasForm = class extends VisualForm {
|
|
|
6341
6366
|
return this;
|
|
6342
6367
|
}
|
|
6343
6368
|
/**
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6369
|
+
* Set whether to use html canvas' [`measureText`](#link) function, or a faster but less accurate heuristic function.
|
|
6370
|
+
* @param estimate `true` to use heuristic function, or `false` to use ctx.measureText
|
|
6371
|
+
*/
|
|
6347
6372
|
fontWidthEstimate(estimate = true) {
|
|
6348
6373
|
this._estimateTextWidth = estimate ? Typography.textWidthEstimator((c) => this._ctx.measureText(c).width) : void 0;
|
|
6349
6374
|
return this;
|
|
6350
6375
|
}
|
|
6351
6376
|
/**
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6377
|
+
* 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.
|
|
6378
|
+
* @param c a string of text contents
|
|
6379
|
+
*/
|
|
6355
6380
|
getTextWidth(c) {
|
|
6356
6381
|
return !this._estimateTextWidth ? this._ctx.measureText(c + " .").width : this._estimateTextWidth(c);
|
|
6357
6382
|
}
|
|
6358
6383
|
/**
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6384
|
+
* Truncate text to fit width.
|
|
6385
|
+
* @param str text to truncate
|
|
6386
|
+
* @param width width to fit
|
|
6387
|
+
* @param tail text to indicate overflow such as "...". Default is empty "".
|
|
6388
|
+
*/
|
|
6364
6389
|
_textTruncate(str, width, tail = "") {
|
|
6365
6390
|
return Typography.truncate(this.getTextWidth.bind(this), str, width, tail);
|
|
6366
6391
|
}
|
|
6367
6392
|
/**
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6393
|
+
* Align text within a rectangle box.
|
|
6394
|
+
* @param box a Group or an Iterable<PtLike> that defines a rectangular box
|
|
6395
|
+
* @param vertical a string that specifies the vertical alignment in the box: "top", "bottom", "middle", "start", "end"
|
|
6396
|
+
* @param offset Optional offset from the edge (like padding)
|
|
6397
|
+
* @param center Optional center position
|
|
6398
|
+
*/
|
|
6374
6399
|
_textAlign(box, vertical, offset, center) {
|
|
6375
|
-
|
|
6400
|
+
const _box = Util.iterToArray(box);
|
|
6376
6401
|
if (!Util.arrayCheck(_box))
|
|
6377
6402
|
return;
|
|
6378
6403
|
if (!center)
|
|
6379
6404
|
center = Rectangle.center(_box);
|
|
6380
|
-
|
|
6405
|
+
let px = _box[0][0];
|
|
6381
6406
|
if (this._ctx.textAlign == "end" || this._ctx.textAlign == "right") {
|
|
6382
6407
|
px = _box[1][0];
|
|
6383
6408
|
} else if (this._ctx.textAlign == "center" || this._ctx.textAlign == "middle") {
|
|
6384
6409
|
px = center[0];
|
|
6385
6410
|
}
|
|
6386
|
-
|
|
6411
|
+
let py = center[1];
|
|
6387
6412
|
if (vertical == "top" || vertical == "start") {
|
|
6388
6413
|
py = _box[0][1];
|
|
6389
6414
|
} else if (vertical == "end" || vertical == "bottom") {
|
|
@@ -6392,10 +6417,10 @@ var CanvasForm = class extends VisualForm {
|
|
|
6392
6417
|
return offset ? new Pt(px + offset[0], py + offset[1]) : new Pt(px, py);
|
|
6393
6418
|
}
|
|
6394
6419
|
/**
|
|
6395
|
-
|
|
6396
|
-
|
|
6420
|
+
* Reset the rendering context's common styles to this form's styles. This supports using multiple forms on the same canvas context.
|
|
6421
|
+
*/
|
|
6397
6422
|
reset() {
|
|
6398
|
-
for (
|
|
6423
|
+
for (const k in this._style) {
|
|
6399
6424
|
if (this._style.hasOwnProperty(k)) {
|
|
6400
6425
|
this._ctx[k] = this._style[k];
|
|
6401
6426
|
}
|
|
@@ -6411,38 +6436,38 @@ var CanvasForm = class extends VisualForm {
|
|
|
6411
6436
|
this._ctx.stroke();
|
|
6412
6437
|
}
|
|
6413
6438
|
/**
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6439
|
+
* A static function to draw a point.
|
|
6440
|
+
* @param ctx canvas rendering context
|
|
6441
|
+
* @param p a Pt object
|
|
6442
|
+
* @param radius radius of the point. Default is 5.
|
|
6443
|
+
* @param shape The shape of the point. Defaults to "square", but it can be "circle" or a custom shape function in your own implementation.
|
|
6444
|
+
* @example `form.point( p )`, `form.point( p, 10, "circle" )`
|
|
6445
|
+
*/
|
|
6421
6446
|
static point(ctx, p, radius = 5, shape = "square") {
|
|
6422
6447
|
if (!p)
|
|
6423
6448
|
return;
|
|
6424
|
-
if (!
|
|
6449
|
+
if (!_CanvasForm[shape])
|
|
6425
6450
|
throw new Error(`${shape} is not a static function of CanvasForm`);
|
|
6426
|
-
|
|
6451
|
+
_CanvasForm[shape](ctx, p, radius);
|
|
6427
6452
|
}
|
|
6428
6453
|
/**
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6454
|
+
* Draws a point.
|
|
6455
|
+
* @param p a Pt object
|
|
6456
|
+
* @param radius radius of the point. Default is 5.
|
|
6457
|
+
* @param shape The shape of the point. Defaults to "square", but it can be "circle" or a custom shape function in your own implementation.
|
|
6458
|
+
* @example `form.point( p )`, `form.point( p, 10, "circle" )`
|
|
6459
|
+
*/
|
|
6435
6460
|
point(p, radius = 5, shape = "square") {
|
|
6436
|
-
|
|
6461
|
+
_CanvasForm.point(this._ctx, p, radius, shape);
|
|
6437
6462
|
this._paint();
|
|
6438
6463
|
return this;
|
|
6439
6464
|
}
|
|
6440
6465
|
/**
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6466
|
+
* A static function to draw a circle.
|
|
6467
|
+
* @param ctx canvas rendering context
|
|
6468
|
+
* @param pt center position of the circle
|
|
6469
|
+
* @param radius radius of the circle
|
|
6470
|
+
*/
|
|
6446
6471
|
static circle(ctx, pt, radius = 10) {
|
|
6447
6472
|
if (!pt)
|
|
6448
6473
|
return;
|
|
@@ -6451,25 +6476,25 @@ var CanvasForm = class extends VisualForm {
|
|
|
6451
6476
|
ctx.closePath();
|
|
6452
6477
|
}
|
|
6453
6478
|
/**
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6479
|
+
* Draw a circle. See also [`Circle.fromCenter`](#link)
|
|
6480
|
+
* @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] ]
|
|
6481
|
+
*/
|
|
6457
6482
|
circle(pts) {
|
|
6458
|
-
|
|
6459
|
-
|
|
6483
|
+
const p = Util.iterToArray(pts);
|
|
6484
|
+
_CanvasForm.circle(this._ctx, p[0], p[1][0]);
|
|
6460
6485
|
this._paint();
|
|
6461
6486
|
return this;
|
|
6462
6487
|
}
|
|
6463
6488
|
/**
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6489
|
+
* A static function to draw an ellipse.
|
|
6490
|
+
* @param ctx canvas rendering context
|
|
6491
|
+
* @param pt center position
|
|
6492
|
+
* @param radius radius [x, y] of the ellipse
|
|
6493
|
+
* @param rotation rotation of the ellipse in radian. Default is 0.
|
|
6494
|
+
* @param startAngle start angle of the ellipse. Default is 0.
|
|
6495
|
+
* @param endAngle end angle of the ellipse. Default is 2 PI.
|
|
6496
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6497
|
+
*/
|
|
6473
6498
|
static ellipse(ctx, pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6474
6499
|
if (!pt || !radius)
|
|
6475
6500
|
return;
|
|
@@ -6477,28 +6502,28 @@ var CanvasForm = class extends VisualForm {
|
|
|
6477
6502
|
ctx.ellipse(pt[0], pt[1], radius[0], radius[1], rotation, startAngle, endAngle, cc);
|
|
6478
6503
|
}
|
|
6479
6504
|
/**
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6505
|
+
* Draw an ellipse.
|
|
6506
|
+
* @param pt center position
|
|
6507
|
+
* @param radius radius [x, y] of the ellipse
|
|
6508
|
+
* @param rotation rotation of the ellipse in radian. Default is 0.
|
|
6509
|
+
* @param startAngle start angle of the ellipse. Default is 0.
|
|
6510
|
+
* @param endAngle end angle of the ellipse. Default is 2 PI.
|
|
6511
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6512
|
+
*/
|
|
6488
6513
|
ellipse(pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6489
|
-
|
|
6514
|
+
_CanvasForm.ellipse(this._ctx, pt, radius, rotation, startAngle, endAngle, cc);
|
|
6490
6515
|
this._paint();
|
|
6491
6516
|
return this;
|
|
6492
6517
|
}
|
|
6493
6518
|
/**
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6519
|
+
* A static function to draw an arc.
|
|
6520
|
+
* @param ctx canvas rendering context
|
|
6521
|
+
* @param pt center position
|
|
6522
|
+
* @param radius radius of the arc circle
|
|
6523
|
+
* @param startAngle start angle of the arc
|
|
6524
|
+
* @param endAngle end angle of the arc
|
|
6525
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6526
|
+
*/
|
|
6502
6527
|
static arc(ctx, pt, radius, startAngle, endAngle, cc) {
|
|
6503
6528
|
if (!pt)
|
|
6504
6529
|
return;
|
|
@@ -6506,31 +6531,31 @@ var CanvasForm = class extends VisualForm {
|
|
|
6506
6531
|
ctx.arc(pt[0], pt[1], radius, startAngle, endAngle, cc);
|
|
6507
6532
|
}
|
|
6508
6533
|
/**
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6534
|
+
* Draw an arc.
|
|
6535
|
+
* @param pt center position
|
|
6536
|
+
* @param radius radius of the arc circle
|
|
6537
|
+
* @param startAngle start angle of the arc
|
|
6538
|
+
* @param endAngle end angle of the arc
|
|
6539
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6540
|
+
*/
|
|
6516
6541
|
arc(pt, radius, startAngle, endAngle, cc) {
|
|
6517
|
-
|
|
6542
|
+
_CanvasForm.arc(this._ctx, pt, radius, startAngle, endAngle, cc);
|
|
6518
6543
|
this._paint();
|
|
6519
6544
|
return this;
|
|
6520
6545
|
}
|
|
6521
6546
|
/**
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6547
|
+
* A static function to draw a square.
|
|
6548
|
+
* @param ctx canvas rendering context
|
|
6549
|
+
* @param pt center position of the square
|
|
6550
|
+
* @param halfsize half size of the square
|
|
6551
|
+
*/
|
|
6527
6552
|
static square(ctx, pt, halfsize) {
|
|
6528
6553
|
if (!pt)
|
|
6529
6554
|
return;
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6555
|
+
const x1 = pt[0] - halfsize;
|
|
6556
|
+
const y1 = pt[1] - halfsize;
|
|
6557
|
+
const x2 = pt[0] + halfsize;
|
|
6558
|
+
const y2 = pt[1] + halfsize;
|
|
6534
6559
|
ctx.beginPath();
|
|
6535
6560
|
ctx.moveTo(x1, y1);
|
|
6536
6561
|
ctx.lineTo(x1, y2);
|
|
@@ -6539,26 +6564,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6539
6564
|
ctx.closePath();
|
|
6540
6565
|
}
|
|
6541
6566
|
/**
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6567
|
+
* Draw a square, given a center and its half-size.
|
|
6568
|
+
* @param pt center Pt
|
|
6569
|
+
* @param halfsize half-size
|
|
6570
|
+
*/
|
|
6546
6571
|
square(pt, halfsize) {
|
|
6547
|
-
|
|
6572
|
+
_CanvasForm.square(this._ctx, pt, halfsize);
|
|
6548
6573
|
this._paint();
|
|
6549
6574
|
return this;
|
|
6550
6575
|
}
|
|
6551
6576
|
/**
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6577
|
+
* A static function to draw a line or polyline.
|
|
6578
|
+
* @param ctx canvas rendering context
|
|
6579
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6580
|
+
*/
|
|
6556
6581
|
static line(ctx, pts) {
|
|
6557
6582
|
if (!Util.arrayCheck(pts))
|
|
6558
6583
|
return;
|
|
6559
6584
|
let i = 0;
|
|
6560
6585
|
ctx.beginPath();
|
|
6561
|
-
for (
|
|
6586
|
+
for (const it of pts) {
|
|
6562
6587
|
if (it) {
|
|
6563
6588
|
if (i++ > 0) {
|
|
6564
6589
|
ctx.lineTo(it[0], it[1]);
|
|
@@ -6569,41 +6594,41 @@ var CanvasForm = class extends VisualForm {
|
|
|
6569
6594
|
}
|
|
6570
6595
|
}
|
|
6571
6596
|
/**
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6597
|
+
* Draw a line or polyline.
|
|
6598
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6599
|
+
*/
|
|
6575
6600
|
line(pts) {
|
|
6576
|
-
|
|
6601
|
+
_CanvasForm.line(this._ctx, pts);
|
|
6577
6602
|
this._paint();
|
|
6578
6603
|
return this;
|
|
6579
6604
|
}
|
|
6580
6605
|
/**
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6606
|
+
* A static function to draw a polygon.
|
|
6607
|
+
* @param ctx canvas rendering context
|
|
6608
|
+
* @param pts a Group or an Iterable<PtLike> representing a polygon
|
|
6609
|
+
*/
|
|
6585
6610
|
static polygon(ctx, pts) {
|
|
6586
6611
|
if (!Util.arrayCheck(pts))
|
|
6587
6612
|
return;
|
|
6588
|
-
|
|
6613
|
+
_CanvasForm.line(ctx, pts);
|
|
6589
6614
|
ctx.closePath();
|
|
6590
6615
|
}
|
|
6591
6616
|
/**
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6617
|
+
* Draw a polygon.
|
|
6618
|
+
* @param pts a Group or an Iterable<PtLike> representingg a polygon
|
|
6619
|
+
*/
|
|
6595
6620
|
polygon(pts) {
|
|
6596
|
-
|
|
6621
|
+
_CanvasForm.polygon(this._ctx, pts);
|
|
6597
6622
|
this._paint();
|
|
6598
6623
|
return this;
|
|
6599
6624
|
}
|
|
6600
6625
|
/**
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6626
|
+
* A static function to draw a rectangle.
|
|
6627
|
+
* @param ctx canvas rendering context
|
|
6628
|
+
* @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.
|
|
6629
|
+
*/
|
|
6605
6630
|
static rect(ctx, pts) {
|
|
6606
|
-
|
|
6631
|
+
const p = Util.iterToArray(pts);
|
|
6607
6632
|
if (!Util.arrayCheck(p))
|
|
6608
6633
|
return;
|
|
6609
6634
|
ctx.beginPath();
|
|
@@ -6614,29 +6639,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6614
6639
|
ctx.closePath();
|
|
6615
6640
|
}
|
|
6616
6641
|
/**
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6642
|
+
* Draw a rectangle.
|
|
6643
|
+
* @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.
|
|
6644
|
+
*/
|
|
6620
6645
|
rect(pts) {
|
|
6621
|
-
|
|
6646
|
+
_CanvasForm.rect(this._ctx, pts);
|
|
6622
6647
|
this._paint();
|
|
6623
6648
|
return this;
|
|
6624
6649
|
}
|
|
6625
6650
|
/**
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6651
|
+
* A static function to draw an image.
|
|
6652
|
+
* @param ctx canvas rendering context
|
|
6653
|
+
* @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>`)
|
|
6654
|
+
* @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.
|
|
6655
|
+
* @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.
|
|
6656
|
+
*/
|
|
6632
6657
|
static image(ctx, ptOrRect, img, orig) {
|
|
6633
|
-
|
|
6658
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6634
6659
|
let pos;
|
|
6635
6660
|
if (typeof t[0] === "number") {
|
|
6636
6661
|
pos = t;
|
|
6637
6662
|
} else {
|
|
6638
6663
|
if (orig) {
|
|
6639
|
-
|
|
6664
|
+
const o = Util.iterToArray(orig);
|
|
6640
6665
|
pos = [
|
|
6641
6666
|
o[0][0],
|
|
6642
6667
|
o[0][1],
|
|
@@ -6660,29 +6685,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6660
6685
|
}
|
|
6661
6686
|
}
|
|
6662
6687
|
/**
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6688
|
+
* Draw an image.
|
|
6689
|
+
* @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>`)
|
|
6690
|
+
* @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.
|
|
6691
|
+
* @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.
|
|
6692
|
+
*/
|
|
6668
6693
|
image(ptOrRect, img, orig) {
|
|
6669
6694
|
if (img instanceof Img) {
|
|
6670
6695
|
if (img.loaded) {
|
|
6671
|
-
|
|
6696
|
+
_CanvasForm.image(this._ctx, ptOrRect, img.image, orig);
|
|
6672
6697
|
}
|
|
6673
6698
|
} else {
|
|
6674
|
-
|
|
6699
|
+
_CanvasForm.image(this._ctx, ptOrRect, img, orig);
|
|
6675
6700
|
}
|
|
6676
6701
|
return this;
|
|
6677
6702
|
}
|
|
6678
6703
|
/**
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6704
|
+
* A static function to draw ImageData on canvas
|
|
6705
|
+
* @param ctx canvas rendering context
|
|
6706
|
+
* @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.
|
|
6707
|
+
* @param img an ImageData object
|
|
6708
|
+
*/
|
|
6684
6709
|
static imageData(ctx, ptOrRect, img) {
|
|
6685
|
-
|
|
6710
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6686
6711
|
if (typeof t[0] === "number") {
|
|
6687
6712
|
ctx.putImageData(img, t[0], t[1]);
|
|
6688
6713
|
} else {
|
|
@@ -6690,74 +6715,74 @@ var CanvasForm = class extends VisualForm {
|
|
|
6690
6715
|
}
|
|
6691
6716
|
}
|
|
6692
6717
|
/**
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6718
|
+
* Draw ImageData on canvas using ImageData
|
|
6719
|
+
* @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.
|
|
6720
|
+
* @param img an ImageData object
|
|
6721
|
+
*/
|
|
6697
6722
|
imageData(ptOrRect, img) {
|
|
6698
|
-
|
|
6723
|
+
_CanvasForm.imageData(this._ctx, ptOrRect, img);
|
|
6699
6724
|
return this;
|
|
6700
6725
|
}
|
|
6701
6726
|
/**
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6727
|
+
* A static function to draw text.
|
|
6728
|
+
* @param ctx canvas rendering context
|
|
6729
|
+
* @param `pt` a Point object to specify the anchor point
|
|
6730
|
+
* @param `txt` a string of text to draw
|
|
6731
|
+
* @param `maxWidth` specify a maximum width per line
|
|
6732
|
+
*/
|
|
6708
6733
|
static text(ctx, pt, txt, maxWidth) {
|
|
6709
6734
|
if (!pt)
|
|
6710
6735
|
return;
|
|
6711
6736
|
ctx.fillText(txt, pt[0], pt[1], maxWidth);
|
|
6712
6737
|
}
|
|
6713
6738
|
/**
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6739
|
+
* Draw text on canvas.
|
|
6740
|
+
* @param `pt` a Pt or numeric array to specify the anchor point
|
|
6741
|
+
* @param `txt` text
|
|
6742
|
+
* @param `maxWidth` specify a maximum width per line
|
|
6743
|
+
*/
|
|
6719
6744
|
text(pt, txt, maxWidth) {
|
|
6720
|
-
|
|
6745
|
+
_CanvasForm.text(this._ctx, pt, txt, maxWidth);
|
|
6721
6746
|
return this;
|
|
6722
6747
|
}
|
|
6723
6748
|
/**
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6749
|
+
* Fit a single-line text in a rectangular box.
|
|
6750
|
+
* @param box a rectangle box defined by a Group or an Iterable<Pt>
|
|
6751
|
+
* @param txt string of text
|
|
6752
|
+
* @param tail text to indicate overflow such as "...". Default is empty "".
|
|
6753
|
+
* @param verticalAlign "top", "middle", or "bottom" to specify vertical alignment inside the box
|
|
6754
|
+
* @param overrideBaseline If `true`, use the corresponding baseline as verticalAlign. If `false`, use the current canvas context's textBaseline setting. Default is `true`.
|
|
6755
|
+
*/
|
|
6731
6756
|
textBox(box, txt, verticalAlign = "middle", tail = "", overrideBaseline = true) {
|
|
6732
6757
|
if (overrideBaseline)
|
|
6733
6758
|
this._ctx.textBaseline = verticalAlign;
|
|
6734
|
-
|
|
6735
|
-
|
|
6759
|
+
const size = Rectangle.size(box);
|
|
6760
|
+
const t = this._textTruncate(txt, size[0], tail);
|
|
6736
6761
|
this.text(this._textAlign(box, verticalAlign), t[0]);
|
|
6737
6762
|
return this;
|
|
6738
6763
|
}
|
|
6739
6764
|
/**
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6765
|
+
* Fit multi-line text in a rectangular box. Note that this will also set canvas context's textBaseline to "top".
|
|
6766
|
+
* @param box a Group or an Iterable<PtLike> with 2 Pt that represents a bounding box
|
|
6767
|
+
* @param txt string of text
|
|
6768
|
+
* @param lineHeight line height as a ratio of font size. Default is 1.2.
|
|
6769
|
+
* @param verticalAlign "top", "middle", or "bottom" to specify vertical alignment inside the box
|
|
6770
|
+
* @param crop a boolean to specify whether to crop text when overflowing
|
|
6771
|
+
*/
|
|
6747
6772
|
paragraphBox(box, txt, lineHeight = 1.2, verticalAlign = "top", crop = true) {
|
|
6748
|
-
|
|
6749
|
-
|
|
6773
|
+
const b = Util.iterToArray(box);
|
|
6774
|
+
const size = Rectangle.size(b);
|
|
6750
6775
|
this._ctx.textBaseline = "top";
|
|
6751
|
-
|
|
6752
|
-
|
|
6776
|
+
const lstep = this._font.size * lineHeight;
|
|
6777
|
+
const nextLine = (sub, buffer = [], cc = 0) => {
|
|
6753
6778
|
if (!sub)
|
|
6754
6779
|
return buffer;
|
|
6755
6780
|
if (crop && cc * lstep > size[1] - lstep * 2)
|
|
6756
6781
|
return buffer;
|
|
6757
6782
|
if (cc > 1e4)
|
|
6758
6783
|
throw new Error("max recursion reached (10000)");
|
|
6759
|
-
|
|
6760
|
-
|
|
6784
|
+
const t = this._textTruncate(sub, size[0], "");
|
|
6785
|
+
const newln = t[0].indexOf("\n");
|
|
6761
6786
|
if (newln >= 0) {
|
|
6762
6787
|
buffer.push(t[0].substr(0, newln));
|
|
6763
6788
|
return nextLine(sub.substr(newln + 1), buffer, cc + 1);
|
|
@@ -6765,12 +6790,12 @@ var CanvasForm = class extends VisualForm {
|
|
|
6765
6790
|
let dt = t[0].lastIndexOf(" ") + 1;
|
|
6766
6791
|
if (dt <= 0 || t[1] === sub.length)
|
|
6767
6792
|
dt = void 0;
|
|
6768
|
-
|
|
6793
|
+
const line = t[0].substr(0, dt);
|
|
6769
6794
|
buffer.push(line);
|
|
6770
6795
|
return t[1] <= 0 || t[1] === sub.length ? buffer : nextLine(sub.substr(dt || t[1]), buffer, cc + 1);
|
|
6771
6796
|
};
|
|
6772
|
-
|
|
6773
|
-
|
|
6797
|
+
const lines = nextLine(txt);
|
|
6798
|
+
const lsize = lines.length * lstep;
|
|
6774
6799
|
let lbox = b;
|
|
6775
6800
|
if (verticalAlign == "middle" || verticalAlign == "center") {
|
|
6776
6801
|
let lpad = (size[1] - lsize) / 2;
|
|
@@ -6782,17 +6807,17 @@ var CanvasForm = class extends VisualForm {
|
|
|
6782
6807
|
} else {
|
|
6783
6808
|
lbox = new Group(b[0], b[0].$add(size[0], lsize));
|
|
6784
6809
|
}
|
|
6785
|
-
|
|
6810
|
+
const center = Rectangle.center(lbox);
|
|
6786
6811
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
6787
6812
|
this.text(this._textAlign(lbox, "top", [0, i * lstep], center), lines[i]);
|
|
6788
6813
|
}
|
|
6789
6814
|
return this;
|
|
6790
6815
|
}
|
|
6791
6816
|
/**
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6817
|
+
* Set text alignment and baseline (eg, vertical-align).
|
|
6818
|
+
* @param alignment HTML canvas' textAlign option: "left", "right", "center", "start", or "end"
|
|
6819
|
+
* @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")
|
|
6820
|
+
*/
|
|
6796
6821
|
alignText(alignment = "left", baseline = "alphabetic") {
|
|
6797
6822
|
if (baseline == "center")
|
|
6798
6823
|
baseline = "middle";
|
|
@@ -6803,11 +6828,11 @@ var CanvasForm = class extends VisualForm {
|
|
|
6803
6828
|
return this;
|
|
6804
6829
|
}
|
|
6805
6830
|
/**
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6831
|
+
* 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.
|
|
6832
|
+
* @param txt text
|
|
6833
|
+
*/
|
|
6809
6834
|
log(txt) {
|
|
6810
|
-
|
|
6835
|
+
const w = this._ctx.measureText(txt).width + 20;
|
|
6811
6836
|
this.stroke(false).fill("rgba(0,0,0,.4)").rect([[0, 0], [w, 20]]);
|
|
6812
6837
|
this.fill("#fff").text([10, 14], txt);
|
|
6813
6838
|
return this;
|
|
@@ -7270,7 +7295,7 @@ var Noise = class extends Pt {
|
|
|
7270
7295
|
return Num.lerp(Num.lerp(n00, n10, tx), Num.lerp(n01, n11, tx), _fade(y));
|
|
7271
7296
|
}
|
|
7272
7297
|
};
|
|
7273
|
-
var Delaunay = class extends Group {
|
|
7298
|
+
var Delaunay = class _Delaunay extends Group {
|
|
7274
7299
|
constructor() {
|
|
7275
7300
|
super(...arguments);
|
|
7276
7301
|
this._mesh = [];
|
|
@@ -7317,7 +7342,7 @@ var Delaunay = class extends Group {
|
|
|
7317
7342
|
edges.push(circum.i, circum.j, circum.j, circum.k, circum.k, circum.i);
|
|
7318
7343
|
opened.splice(j, 1);
|
|
7319
7344
|
}
|
|
7320
|
-
|
|
7345
|
+
_Delaunay._dedupe(edges);
|
|
7321
7346
|
j = edges.length;
|
|
7322
7347
|
while (j > 1) {
|
|
7323
7348
|
opened.push(this._circum(edges[--j], edges[--j], c, false, pts));
|
|
@@ -7459,7 +7484,7 @@ var Delaunay = class extends Group {
|
|
|
7459
7484
|
};
|
|
7460
7485
|
|
|
7461
7486
|
// src/Color.ts
|
|
7462
|
-
var _Color = class extends Pt {
|
|
7487
|
+
var _Color = class _Color extends Pt {
|
|
7463
7488
|
/**
|
|
7464
7489
|
* Create a Color. Same as creating a Pt. Optionally you may use [`Color.from`](#link) to create a color.
|
|
7465
7490
|
* @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
|
|
@@ -7474,8 +7499,8 @@ var _Color = class extends Pt {
|
|
|
7474
7499
|
* @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
|
|
7475
7500
|
*/
|
|
7476
7501
|
static from(...args) {
|
|
7477
|
-
|
|
7478
|
-
|
|
7502
|
+
const p = [1, 1, 1, 1];
|
|
7503
|
+
const c = Util.getArgs(args);
|
|
7479
7504
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
7480
7505
|
if (i < c.length)
|
|
7481
7506
|
p[i] = c[i];
|
|
@@ -7490,7 +7515,7 @@ var _Color = class extends Pt {
|
|
|
7490
7515
|
if (hex[0] == "#")
|
|
7491
7516
|
hex = hex.substr(1);
|
|
7492
7517
|
if (hex.length <= 3) {
|
|
7493
|
-
|
|
7518
|
+
const fn = (i) => hex[i] || "F";
|
|
7494
7519
|
hex = `${fn(0)}${fn(0)}${fn(1)}${fn(1)}${fn(2)}${fn(2)}`;
|
|
7495
7520
|
}
|
|
7496
7521
|
let alpha = 1;
|
|
@@ -7498,7 +7523,7 @@ var _Color = class extends Pt {
|
|
|
7498
7523
|
alpha = hex.substr(6) && 255 / 255;
|
|
7499
7524
|
hex = hex.substring(0, 6);
|
|
7500
7525
|
}
|
|
7501
|
-
|
|
7526
|
+
const hexVal = parseInt(hex, 16);
|
|
7502
7527
|
return new _Color(hexVal >> 16, hexVal >> 8 & 255, hexVal & 255, alpha);
|
|
7503
7528
|
}
|
|
7504
7529
|
/**
|
|
@@ -7580,7 +7605,7 @@ var _Color = class extends Pt {
|
|
|
7580
7605
|
* Clone this Color.
|
|
7581
7606
|
*/
|
|
7582
7607
|
clone() {
|
|
7583
|
-
|
|
7608
|
+
const c = new _Color(this);
|
|
7584
7609
|
c.toMode(this._mode);
|
|
7585
7610
|
return c;
|
|
7586
7611
|
}
|
|
@@ -7591,7 +7616,7 @@ var _Color = class extends Pt {
|
|
|
7591
7616
|
*/
|
|
7592
7617
|
toMode(mode, convert = false) {
|
|
7593
7618
|
if (convert) {
|
|
7594
|
-
|
|
7619
|
+
const fname = this._mode.toUpperCase() + "to" + mode.toUpperCase();
|
|
7595
7620
|
if (_Color[fname]) {
|
|
7596
7621
|
this.to(_Color[fname](this, this._isNorm, this._isNorm));
|
|
7597
7622
|
} else {
|
|
@@ -7643,7 +7668,7 @@ var _Color = class extends Pt {
|
|
|
7643
7668
|
return this._mode == "lch" ? this[2] : this[0];
|
|
7644
7669
|
}
|
|
7645
7670
|
set h(n) {
|
|
7646
|
-
|
|
7671
|
+
const i = this._mode == "lch" ? 2 : 0;
|
|
7647
7672
|
this[i] = n;
|
|
7648
7673
|
}
|
|
7649
7674
|
/**
|
|
@@ -7662,7 +7687,7 @@ var _Color = class extends Pt {
|
|
|
7662
7687
|
return this._mode == "hsl" ? this[2] : this[0];
|
|
7663
7688
|
}
|
|
7664
7689
|
set l(n) {
|
|
7665
|
-
|
|
7690
|
+
const i = this._mode == "hsl" ? 2 : 0;
|
|
7666
7691
|
this[i] = n;
|
|
7667
7692
|
}
|
|
7668
7693
|
// lab, lch, luv
|
|
@@ -7728,7 +7753,7 @@ var _Color = class extends Pt {
|
|
|
7728
7753
|
normalize(toNorm = true) {
|
|
7729
7754
|
if (this._isNorm == toNorm)
|
|
7730
7755
|
return this;
|
|
7731
|
-
|
|
7756
|
+
const ranges = _Color.ranges[this._mode];
|
|
7732
7757
|
for (let i = 0; i < 3; i++) {
|
|
7733
7758
|
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);
|
|
7734
7759
|
}
|
|
@@ -7749,8 +7774,8 @@ var _Color = class extends Pt {
|
|
|
7749
7774
|
*/
|
|
7750
7775
|
toString(format = "mode") {
|
|
7751
7776
|
if (format == "hex") {
|
|
7752
|
-
|
|
7753
|
-
|
|
7777
|
+
const _hex = (n) => {
|
|
7778
|
+
const s = Math.floor(n).toString(16);
|
|
7754
7779
|
return s.length < 2 ? "0" + s : s;
|
|
7755
7780
|
};
|
|
7756
7781
|
return `#${_hex(this[0])}${_hex(this[1])}${_hex(this[2])}`;
|
|
@@ -7770,17 +7795,17 @@ var _Color = class extends Pt {
|
|
|
7770
7795
|
* @returns a new HSL Color
|
|
7771
7796
|
*/
|
|
7772
7797
|
static RGBtoHSL(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7798
|
+
const [r, g, b] = !normalizedInput ? rgb.$normalize() : rgb;
|
|
7799
|
+
const max = Math.max(r, g, b);
|
|
7800
|
+
const min = Math.min(r, g, b);
|
|
7776
7801
|
let h = (max + min) / 2;
|
|
7777
7802
|
let s = h;
|
|
7778
|
-
|
|
7803
|
+
const l = h;
|
|
7779
7804
|
if (max == min) {
|
|
7780
7805
|
h = 0;
|
|
7781
7806
|
s = 0;
|
|
7782
7807
|
} else {
|
|
7783
|
-
|
|
7808
|
+
const d = max - min;
|
|
7784
7809
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
7785
7810
|
h = 0;
|
|
7786
7811
|
if (max === r) {
|
|
@@ -7806,9 +7831,9 @@ var _Color = class extends Pt {
|
|
|
7806
7831
|
h = h / 360;
|
|
7807
7832
|
if (s == 0)
|
|
7808
7833
|
return _Color.rgb(l * 255, l * 255, l * 255, hsl.alpha);
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7834
|
+
const q = l <= 0.5 ? l * (1 + s) : l + s - l * s;
|
|
7835
|
+
const p = 2 * l - q;
|
|
7836
|
+
const convert = (t) => {
|
|
7812
7837
|
t = t < 0 ? t + 1 : t > 1 ? t - 1 : t;
|
|
7813
7838
|
if (t * 6 < 1) {
|
|
7814
7839
|
return p + (q - p) * t * 6;
|
|
@@ -7820,7 +7845,7 @@ var _Color = class extends Pt {
|
|
|
7820
7845
|
return p;
|
|
7821
7846
|
}
|
|
7822
7847
|
};
|
|
7823
|
-
|
|
7848
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7824
7849
|
return _Color.rgb(
|
|
7825
7850
|
sc * convert(h + 1 / 3),
|
|
7826
7851
|
sc * convert(h),
|
|
@@ -7836,13 +7861,13 @@ var _Color = class extends Pt {
|
|
|
7836
7861
|
* @returns a new HSB Color
|
|
7837
7862
|
*/
|
|
7838
7863
|
static RGBtoHSB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7864
|
+
const [r, g, b] = !normalizedInput ? rgb.$normalize() : rgb;
|
|
7865
|
+
const max = Math.max(r, g, b);
|
|
7866
|
+
const min = Math.min(r, g, b);
|
|
7867
|
+
const d = max - min;
|
|
7843
7868
|
let h = 0;
|
|
7844
|
-
|
|
7845
|
-
|
|
7869
|
+
const s = max === 0 ? 0 : d / max;
|
|
7870
|
+
const v = max;
|
|
7846
7871
|
if (max != min) {
|
|
7847
7872
|
if (max === r) {
|
|
7848
7873
|
h = (g - b) / d + (g < b ? 6 : 0);
|
|
@@ -7865,12 +7890,12 @@ var _Color = class extends Pt {
|
|
|
7865
7890
|
let [h, s, v] = hsb;
|
|
7866
7891
|
if (!normalizedInput)
|
|
7867
7892
|
h = h / 360;
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7893
|
+
const i = Math.floor(h * 6);
|
|
7894
|
+
const f = h * 6 - i;
|
|
7895
|
+
const p = v * (1 - s);
|
|
7896
|
+
const q = v * (1 - f * s);
|
|
7897
|
+
const t = v * (1 - (1 - f) * s);
|
|
7898
|
+
const pick = [
|
|
7874
7899
|
[v, t, p],
|
|
7875
7900
|
[q, v, p],
|
|
7876
7901
|
[p, v, t],
|
|
@@ -7878,8 +7903,8 @@ var _Color = class extends Pt {
|
|
|
7878
7903
|
[t, p, v],
|
|
7879
7904
|
[v, p, q]
|
|
7880
7905
|
];
|
|
7881
|
-
|
|
7882
|
-
|
|
7906
|
+
const c = pick[i % 6];
|
|
7907
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7883
7908
|
return _Color.rgb(
|
|
7884
7909
|
sc * c[0],
|
|
7885
7910
|
sc * c[1],
|
|
@@ -7895,7 +7920,7 @@ var _Color = class extends Pt {
|
|
|
7895
7920
|
* @returns a new LAB Color
|
|
7896
7921
|
*/
|
|
7897
7922
|
static RGBtoLAB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7898
|
-
|
|
7923
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7899
7924
|
return _Color.XYZtoLAB(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
7900
7925
|
}
|
|
7901
7926
|
/**
|
|
@@ -7906,7 +7931,7 @@ var _Color = class extends Pt {
|
|
|
7906
7931
|
* @returns a new RGB Color
|
|
7907
7932
|
*/
|
|
7908
7933
|
static LABtoRGB(lab, normalizedInput = false, normalizedOutput = false) {
|
|
7909
|
-
|
|
7934
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
7910
7935
|
return _Color.XYZtoRGB(_Color.LABtoXYZ(c), false, normalizedOutput);
|
|
7911
7936
|
}
|
|
7912
7937
|
/**
|
|
@@ -7917,7 +7942,7 @@ var _Color = class extends Pt {
|
|
|
7917
7942
|
* @returns a new LCH Color
|
|
7918
7943
|
*/
|
|
7919
7944
|
static RGBtoLCH(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7920
|
-
|
|
7945
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7921
7946
|
return _Color.LABtoLCH(_Color.RGBtoLAB(c), false, normalizedOutput);
|
|
7922
7947
|
}
|
|
7923
7948
|
/**
|
|
@@ -7928,7 +7953,7 @@ var _Color = class extends Pt {
|
|
|
7928
7953
|
* @returns a new RGB Color
|
|
7929
7954
|
*/
|
|
7930
7955
|
static LCHtoRGB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
7931
|
-
|
|
7956
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
7932
7957
|
return _Color.LABtoRGB(_Color.LCHtoLAB(c), false, normalizedOutput);
|
|
7933
7958
|
}
|
|
7934
7959
|
/**
|
|
@@ -7939,7 +7964,7 @@ var _Color = class extends Pt {
|
|
|
7939
7964
|
* @returns a new LUV Color
|
|
7940
7965
|
*/
|
|
7941
7966
|
static RGBtoLUV(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7942
|
-
|
|
7967
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7943
7968
|
return _Color.XYZtoLUV(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
7944
7969
|
}
|
|
7945
7970
|
/**
|
|
@@ -7950,7 +7975,7 @@ var _Color = class extends Pt {
|
|
|
7950
7975
|
* @returns a new RGB Color
|
|
7951
7976
|
*/
|
|
7952
7977
|
static LUVtoRGB(luv, normalizedInput = false, normalizedOutput = false) {
|
|
7953
|
-
|
|
7978
|
+
const c = normalizedInput ? luv.$normalize(false) : luv;
|
|
7954
7979
|
return _Color.XYZtoRGB(_Color.LUVtoXYZ(c), false, normalizedOutput);
|
|
7955
7980
|
}
|
|
7956
7981
|
/**
|
|
@@ -7961,13 +7986,13 @@ var _Color = class extends Pt {
|
|
|
7961
7986
|
* @returns a new XYZ Color
|
|
7962
7987
|
*/
|
|
7963
7988
|
static RGBtoXYZ(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7964
|
-
|
|
7989
|
+
const c = !normalizedInput ? rgb.$normalize() : rgb.clone();
|
|
7965
7990
|
for (let i = 0; i < 3; i++) {
|
|
7966
7991
|
c[i] = c[i] > 0.04045 ? Math.pow((c[i] + 0.055) / 1.055, 2.4) : c[i] / 12.92;
|
|
7967
7992
|
if (!normalizedOutput)
|
|
7968
7993
|
c[i] = c[i] * 100;
|
|
7969
7994
|
}
|
|
7970
|
-
|
|
7995
|
+
const cc = _Color.xyz(
|
|
7971
7996
|
c[0] * 0.4124564 + c[1] * 0.3575761 + c[2] * 0.1804375,
|
|
7972
7997
|
c[0] * 0.2126729 + c[1] * 0.7151522 + c[2] * 0.072175,
|
|
7973
7998
|
c[0] * 0.0193339 + c[1] * 0.119192 + c[2] * 0.9503041,
|
|
@@ -7983,8 +8008,8 @@ var _Color = class extends Pt {
|
|
|
7983
8008
|
* @returns a new RGB Color
|
|
7984
8009
|
*/
|
|
7985
8010
|
static XYZtoRGB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
7986
|
-
|
|
7987
|
-
|
|
8011
|
+
const [x, y, z] = !normalizedInput ? xyz.$normalize() : xyz;
|
|
8012
|
+
const rgb = [
|
|
7988
8013
|
x * 3.2406254773200533 + y * -1.5372079722103187 + z * -0.4986285986982479,
|
|
7989
8014
|
x * -0.9689307147293197 + y * 1.8757560608852415 + z * 0.041517523842953964,
|
|
7990
8015
|
x * 0.055710120445510616 + y * -0.2040210505984867 + z * 1.0569959422543882
|
|
@@ -7995,7 +8020,7 @@ var _Color = class extends Pt {
|
|
|
7995
8020
|
if (!normalizedOutput)
|
|
7996
8021
|
rgb[i] = Math.round(rgb[i] * 255);
|
|
7997
8022
|
}
|
|
7998
|
-
|
|
8023
|
+
const cc = _Color.rgb(rgb[0], rgb[1], rgb[2], xyz.alpha);
|
|
7999
8024
|
return normalizedOutput ? cc.normalize() : cc;
|
|
8000
8025
|
}
|
|
8001
8026
|
/**
|
|
@@ -8006,13 +8031,13 @@ var _Color = class extends Pt {
|
|
|
8006
8031
|
* @returns a new LAB Color
|
|
8007
8032
|
*/
|
|
8008
8033
|
static XYZtoLAB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8009
|
-
|
|
8034
|
+
const c = normalizedInput ? xyz.$normalize(false) : xyz.clone();
|
|
8010
8035
|
const eps = 0.00885645167;
|
|
8011
8036
|
const kap = 903.296296296;
|
|
8012
8037
|
c.divide(_Color.D65);
|
|
8013
|
-
|
|
8014
|
-
|
|
8015
|
-
|
|
8038
|
+
const fn = (n) => n > eps ? Math.pow(n, 1 / 3) : (kap * n + 16) / 116;
|
|
8039
|
+
const cy = fn(c[1]);
|
|
8040
|
+
const cc = _Color.lab(
|
|
8016
8041
|
116 * cy - 16,
|
|
8017
8042
|
500 * (fn(c[0]) - cy),
|
|
8018
8043
|
200 * (cy - fn(c[2])),
|
|
@@ -8028,16 +8053,16 @@ var _Color = class extends Pt {
|
|
|
8028
8053
|
* @returns a new XYZ Color
|
|
8029
8054
|
*/
|
|
8030
8055
|
static LABtoXYZ(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8056
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8057
|
+
const y = (c[0] + 16) / 116;
|
|
8058
|
+
const x = c[1] / 500 + y;
|
|
8059
|
+
const z = y - c[2] / 200;
|
|
8035
8060
|
const eps = 0.00885645167;
|
|
8036
8061
|
const kap = 903.296296296;
|
|
8037
|
-
|
|
8062
|
+
const d = _Color.D65;
|
|
8038
8063
|
const xxx = Math.pow(x, 3);
|
|
8039
8064
|
const zzz = Math.pow(z, 3);
|
|
8040
|
-
|
|
8065
|
+
const cc = _Color.xyz(
|
|
8041
8066
|
d[0] * (xxx > eps ? xxx : (116 * x - 16) / kap),
|
|
8042
8067
|
d[1] * (c[0] > kap * eps ? Math.pow((c[0] + 16) / 116, 3) : c[0] / kap),
|
|
8043
8068
|
d[2] * (zzz > eps ? zzz : (116 * z - 16) / kap),
|
|
@@ -8054,13 +8079,13 @@ var _Color = class extends Pt {
|
|
|
8054
8079
|
*/
|
|
8055
8080
|
static XYZtoLUV(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8056
8081
|
let [x, y, z] = normalizedInput ? xyz.$normalize(false) : xyz;
|
|
8057
|
-
|
|
8058
|
-
|
|
8082
|
+
const u = 4 * x / (x + 15 * y + 3 * z);
|
|
8083
|
+
const v = 9 * y / (x + 15 * y + 3 * z);
|
|
8059
8084
|
y = y / 100;
|
|
8060
8085
|
y = y > 8856e-6 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8086
|
+
const refU = 4 * _Color.D65[0] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8087
|
+
const refV = 9 * _Color.D65[1] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8088
|
+
const L = 116 * y - 16;
|
|
8064
8089
|
return _Color.luv(
|
|
8065
8090
|
L,
|
|
8066
8091
|
13 * L * (u - refU),
|
|
@@ -8078,15 +8103,15 @@ var _Color = class extends Pt {
|
|
|
8078
8103
|
static LUVtoXYZ(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8079
8104
|
let [l, u, v] = normalizedInput ? luv.$normalize(false) : luv;
|
|
8080
8105
|
let y = (l + 16) / 116;
|
|
8081
|
-
|
|
8106
|
+
const cubeY = y * y * y;
|
|
8082
8107
|
y = cubeY > 8856e-6 ? cubeY : (y - 16 / 116) / 7.787;
|
|
8083
|
-
|
|
8084
|
-
|
|
8108
|
+
const refU = 4 * _Color.D65[0] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8109
|
+
const refV = 9 * _Color.D65[1] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8085
8110
|
u = u / (13 * l) + refU;
|
|
8086
8111
|
v = v / (13 * l) + refV;
|
|
8087
8112
|
y = y * 100;
|
|
8088
|
-
|
|
8089
|
-
|
|
8113
|
+
const x = -1 * (9 * y * u) / ((u - 4) * v - u * v);
|
|
8114
|
+
const z = (9 * y - 15 * v * y - v * x) / (3 * v);
|
|
8090
8115
|
return _Color.xyz(x, y, z, luv.alpha);
|
|
8091
8116
|
}
|
|
8092
8117
|
/**
|
|
@@ -8097,8 +8122,8 @@ var _Color = class extends Pt {
|
|
|
8097
8122
|
* @returns a new LCH Color
|
|
8098
8123
|
*/
|
|
8099
8124
|
static LABtoLCH(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8100
|
-
|
|
8101
|
-
|
|
8125
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8126
|
+
const h = Geom.toDegree(Geom.boundRadian(Math.atan2(c[2], c[1])));
|
|
8102
8127
|
return _Color.lch(
|
|
8103
8128
|
c[0],
|
|
8104
8129
|
Math.sqrt(c[1] * c[1] + c[2] * c[2]),
|
|
@@ -8114,8 +8139,8 @@ var _Color = class extends Pt {
|
|
|
8114
8139
|
* @returns a new LAB Color
|
|
8115
8140
|
*/
|
|
8116
8141
|
static LCHtoLAB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
8117
|
-
|
|
8118
|
-
|
|
8142
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8143
|
+
const rad = Geom.toRadian(c[2]);
|
|
8119
8144
|
return _Color.lab(
|
|
8120
8145
|
c[0],
|
|
8121
8146
|
Math.cos(rad) * c[1],
|
|
@@ -8124,13 +8149,12 @@ var _Color = class extends Pt {
|
|
|
8124
8149
|
);
|
|
8125
8150
|
}
|
|
8126
8151
|
};
|
|
8127
|
-
var Color = _Color;
|
|
8128
8152
|
// XYZ property for Standard Observer 2deg, Daylight/sRGB illuminant D65
|
|
8129
|
-
|
|
8153
|
+
_Color.D65 = new Pt(95.047, 100, 108.883, 1);
|
|
8130
8154
|
/**
|
|
8131
8155
|
* Value range for each color space
|
|
8132
8156
|
*/
|
|
8133
|
-
|
|
8157
|
+
_Color.ranges = {
|
|
8134
8158
|
rgb: new Group(new Pt(0, 255), new Pt(0, 255), new Pt(0, 255)),
|
|
8135
8159
|
hsl: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
8136
8160
|
hsb: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
@@ -8139,9 +8163,10 @@ Color.ranges = {
|
|
|
8139
8163
|
luv: new Group(new Pt(0, 100), new Pt(-134, 220), new Pt(-140, 122)),
|
|
8140
8164
|
xyz: new Group(new Pt(0, 100), new Pt(0, 100), new Pt(0, 100))
|
|
8141
8165
|
};
|
|
8166
|
+
var Color = _Color;
|
|
8142
8167
|
|
|
8143
8168
|
// src/Dom.ts
|
|
8144
|
-
var DOMSpace = class extends MultiTouchSpace {
|
|
8169
|
+
var DOMSpace = class _DOMSpace extends MultiTouchSpace {
|
|
8145
8170
|
/**
|
|
8146
8171
|
* Create a DOMSpace for HTML DOM elements
|
|
8147
8172
|
* @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.
|
|
@@ -8154,8 +8179,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8154
8179
|
this._autoResize = true;
|
|
8155
8180
|
this._bgcolor = "#e1e9f0";
|
|
8156
8181
|
this._css = {};
|
|
8157
|
-
|
|
8158
|
-
|
|
8182
|
+
let _selector = null;
|
|
8183
|
+
let _existed = false;
|
|
8159
8184
|
this.id = "pts";
|
|
8160
8185
|
if (elem instanceof Element) {
|
|
8161
8186
|
_selector = elem;
|
|
@@ -8166,8 +8191,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8166
8191
|
this.id = elem.substr(1);
|
|
8167
8192
|
}
|
|
8168
8193
|
if (!_selector) {
|
|
8169
|
-
this._container =
|
|
8170
|
-
this._canvas =
|
|
8194
|
+
this._container = _DOMSpace.createElement("div", "pts_container");
|
|
8195
|
+
this._canvas = _DOMSpace.createElement("div", "pts_element");
|
|
8171
8196
|
this._container.appendChild(this._canvas);
|
|
8172
8197
|
document.body.appendChild(this._container);
|
|
8173
8198
|
_existed = false;
|
|
@@ -8429,7 +8454,7 @@ var HTMLSpace = class extends DOMSpace {
|
|
|
8429
8454
|
return super.removeAll();
|
|
8430
8455
|
}
|
|
8431
8456
|
};
|
|
8432
|
-
var _HTMLForm = class extends VisualForm {
|
|
8457
|
+
var _HTMLForm = class _HTMLForm extends VisualForm {
|
|
8433
8458
|
/**
|
|
8434
8459
|
* Create a new `HTMLForm`. Alternatively, you can use [`HTMLSpace.getForm`](#link) function to get an instance of HTMLForm.
|
|
8435
8460
|
* @param space the space to use
|
|
@@ -8848,12 +8873,12 @@ var _HTMLForm = class extends VisualForm {
|
|
|
8848
8873
|
return this;
|
|
8849
8874
|
}
|
|
8850
8875
|
};
|
|
8876
|
+
_HTMLForm.groupID = 0;
|
|
8877
|
+
_HTMLForm.domID = 0;
|
|
8851
8878
|
var HTMLForm = _HTMLForm;
|
|
8852
|
-
HTMLForm.groupID = 0;
|
|
8853
|
-
HTMLForm.domID = 0;
|
|
8854
8879
|
|
|
8855
8880
|
// src/Svg.ts
|
|
8856
|
-
var SVGSpace = class extends DOMSpace {
|
|
8881
|
+
var SVGSpace = class _SVGSpace extends DOMSpace {
|
|
8857
8882
|
/**
|
|
8858
8883
|
* Create a SVGSpace which represents a Space for SVG elements.
|
|
8859
8884
|
* @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.
|
|
@@ -8864,7 +8889,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8864
8889
|
super(elem, callback);
|
|
8865
8890
|
this._bgcolor = "#999";
|
|
8866
8891
|
if (this._canvas.nodeName.toLowerCase() != "svg") {
|
|
8867
|
-
let s =
|
|
8892
|
+
let s = _SVGSpace.svgElement(this._canvas, "svg", `${this.id}_svg`);
|
|
8868
8893
|
this._container = this._canvas;
|
|
8869
8894
|
this._canvas = s;
|
|
8870
8895
|
}
|
|
@@ -8890,7 +8915,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8890
8915
|
*/
|
|
8891
8916
|
resize(b, evt) {
|
|
8892
8917
|
super.resize(b, evt);
|
|
8893
|
-
|
|
8918
|
+
_SVGSpace.setAttr(this.element, {
|
|
8894
8919
|
"viewBox": `0 0 ${this.bound.width} ${this.bound.height}`,
|
|
8895
8920
|
"width": `${this.bound.width}`,
|
|
8896
8921
|
"height": `${this.bound.height}`,
|
|
@@ -8935,7 +8960,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8935
8960
|
return super.removeAll();
|
|
8936
8961
|
}
|
|
8937
8962
|
};
|
|
8938
|
-
var _SVGForm = class extends VisualForm {
|
|
8963
|
+
var _SVGForm = class _SVGForm extends VisualForm {
|
|
8939
8964
|
/**
|
|
8940
8965
|
* Create a new SVGForm. You may also use [`SVGSpace.getForm`](#link) to get a default form directly.
|
|
8941
8966
|
* @param space an instance of SVGSpace
|
|
@@ -9429,12 +9454,12 @@ var _SVGForm = class extends VisualForm {
|
|
|
9429
9454
|
return this;
|
|
9430
9455
|
}
|
|
9431
9456
|
};
|
|
9457
|
+
_SVGForm.groupID = 0;
|
|
9458
|
+
_SVGForm.domID = 0;
|
|
9432
9459
|
var SVGForm = _SVGForm;
|
|
9433
|
-
SVGForm.groupID = 0;
|
|
9434
|
-
SVGForm.domID = 0;
|
|
9435
9460
|
|
|
9436
9461
|
// src/Physics.ts
|
|
9437
|
-
var World = class {
|
|
9462
|
+
var World = class _World {
|
|
9438
9463
|
/**
|
|
9439
9464
|
* Create a `World` for 2D physics simulation.
|
|
9440
9465
|
* @param bound a Group or an Iterable<Pt> representing a rectangular bounding box
|
|
@@ -9522,13 +9547,10 @@ var World = class {
|
|
|
9522
9547
|
* @returns a Body, or undefined if not found
|
|
9523
9548
|
*/
|
|
9524
9549
|
body(id) {
|
|
9525
|
-
let idx = id;
|
|
9526
9550
|
if (typeof id === "string" && id.length > 0) {
|
|
9527
|
-
|
|
9551
|
+
return this._bodies[this._bnames.indexOf(id)];
|
|
9528
9552
|
}
|
|
9529
|
-
|
|
9530
|
-
return void 0;
|
|
9531
|
-
return this._bodies[idx];
|
|
9553
|
+
return typeof id === "number" && id >= 0 ? this._bodies[id] : void 0;
|
|
9532
9554
|
}
|
|
9533
9555
|
/**
|
|
9534
9556
|
* Get a particle in this world by index or string id.
|
|
@@ -9536,13 +9558,10 @@ var World = class {
|
|
|
9536
9558
|
* @returns a Particle, or undefined if not found
|
|
9537
9559
|
*/
|
|
9538
9560
|
particle(id) {
|
|
9539
|
-
let idx = id;
|
|
9540
9561
|
if (typeof id === "string" && id.length > 0) {
|
|
9541
|
-
|
|
9562
|
+
return this._particles[this._pnames.indexOf(id)];
|
|
9542
9563
|
}
|
|
9543
|
-
|
|
9544
|
-
return void 0;
|
|
9545
|
-
return this._particles[idx];
|
|
9564
|
+
return typeof id === "number" && id >= 0 ? this._particles[id] : void 0;
|
|
9546
9565
|
}
|
|
9547
9566
|
/**
|
|
9548
9567
|
* Given a body's name, return its index in the bodies array, or -1 if not found.
|
|
@@ -9689,7 +9708,7 @@ var World = class {
|
|
|
9689
9708
|
for (let i = 0, len = this._particles.length; i < len; i++) {
|
|
9690
9709
|
let p = this._particles[i];
|
|
9691
9710
|
this.integrate(p, dt, this._lastTime);
|
|
9692
|
-
|
|
9711
|
+
_World.boundConstraint(p, this._bound, this._damping);
|
|
9693
9712
|
for (let k = i + 1; k < len; k++) {
|
|
9694
9713
|
if (i !== k) {
|
|
9695
9714
|
let p2 = this._particles[k];
|
|
@@ -9710,7 +9729,7 @@ var World = class {
|
|
|
9710
9729
|
if (bds) {
|
|
9711
9730
|
for (let k = 0, klen = bds.length; k < klen; k++) {
|
|
9712
9731
|
let bk = bds[k];
|
|
9713
|
-
|
|
9732
|
+
_World.boundConstraint(bk, this._bound, this._damping);
|
|
9714
9733
|
this.integrate(bk, dt, this._lastTime);
|
|
9715
9734
|
}
|
|
9716
9735
|
for (let k = i + 1; k < len; k++) {
|
|
@@ -9893,7 +9912,7 @@ var Particle = class extends Pt {
|
|
|
9893
9912
|
return `Particle: ${this[0]} ${this[1]} | previous ${this._prev[0]} ${this._prev[1]} | mass ${this._mass}`;
|
|
9894
9913
|
}
|
|
9895
9914
|
};
|
|
9896
|
-
var Body = class extends Group {
|
|
9915
|
+
var Body = class _Body extends Group {
|
|
9897
9916
|
/**
|
|
9898
9917
|
* 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.
|
|
9899
9918
|
*/
|
|
@@ -9912,7 +9931,7 @@ var Body = class extends Group {
|
|
|
9912
9931
|
* @param autoMass Automatically calculate the mass based on the area of the polygon. Default is true.
|
|
9913
9932
|
*/
|
|
9914
9933
|
static fromGroup(body, stiff = 1, autoLink = true, autoMass = true) {
|
|
9915
|
-
let b = new
|
|
9934
|
+
let b = new _Body().init(body);
|
|
9916
9935
|
if (autoLink)
|
|
9917
9936
|
b.linkAll(stiff);
|
|
9918
9937
|
if (autoMass)
|
|
@@ -10067,7 +10086,7 @@ var Body = class extends Group {
|
|
|
10067
10086
|
};
|
|
10068
10087
|
|
|
10069
10088
|
// src/Play.ts
|
|
10070
|
-
var Tempo = class {
|
|
10089
|
+
var Tempo = class _Tempo {
|
|
10071
10090
|
/**
|
|
10072
10091
|
* Construct a new Tempo instance by beats-per-minute. Alternatively, you can use [`Tempo.fromBeat`](#link) to create from milliseconds.
|
|
10073
10092
|
* @param bpm beats per minute
|
|
@@ -10083,7 +10102,7 @@ var Tempo = class {
|
|
|
10083
10102
|
* @param ms milliseconds per beat
|
|
10084
10103
|
*/
|
|
10085
10104
|
static fromBeat(ms) {
|
|
10086
|
-
return new
|
|
10105
|
+
return new _Tempo(6e4 / ms);
|
|
10087
10106
|
}
|
|
10088
10107
|
/**
|
|
10089
10108
|
* Beats-per-minute value
|
|
@@ -10125,16 +10144,16 @@ var Tempo = class {
|
|
|
10125
10144
|
* @returns an object with chainable functions
|
|
10126
10145
|
*/
|
|
10127
10146
|
every(beats) {
|
|
10128
|
-
|
|
10129
|
-
|
|
10147
|
+
const self = this;
|
|
10148
|
+
const p = Array.isArray(beats) ? beats[0] : beats;
|
|
10130
10149
|
return {
|
|
10131
10150
|
start: function(fn, offset = 0, name) {
|
|
10132
|
-
|
|
10151
|
+
const id = name || self._createID(fn);
|
|
10133
10152
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: false, fn };
|
|
10134
10153
|
return this;
|
|
10135
10154
|
},
|
|
10136
10155
|
progress: function(fn, offset = 0, name) {
|
|
10137
|
-
|
|
10156
|
+
const id = name || self._createID(fn);
|
|
10138
10157
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: true, fn };
|
|
10139
10158
|
return this;
|
|
10140
10159
|
}
|
|
@@ -10146,11 +10165,11 @@ var Tempo = class {
|
|
|
10146
10165
|
* @param time current time in milliseconds
|
|
10147
10166
|
*/
|
|
10148
10167
|
track(time) {
|
|
10149
|
-
for (
|
|
10168
|
+
for (const k in this._listeners) {
|
|
10150
10169
|
if (this._listeners.hasOwnProperty(k)) {
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10170
|
+
const li = this._listeners[k];
|
|
10171
|
+
const _t = li.offset ? time + li.offset : time;
|
|
10172
|
+
const ms = li.period * this._ms;
|
|
10154
10173
|
let isStart = false;
|
|
10155
10174
|
if (_t > li.duration + ms) {
|
|
10156
10175
|
li.duration = _t - _t % this._ms;
|
|
@@ -10160,10 +10179,10 @@ var Tempo = class {
|
|
|
10160
10179
|
}
|
|
10161
10180
|
isStart = true;
|
|
10162
10181
|
}
|
|
10163
|
-
|
|
10164
|
-
|
|
10182
|
+
const count = Math.max(0, Math.ceil(Math.floor(li.duration / this._ms) / li.period));
|
|
10183
|
+
const params = li.continuous ? [count, Num.clamp((_t - li.duration) / ms, 0, 1), _t, isStart] : [count];
|
|
10165
10184
|
if (li.continuous || isStart) {
|
|
10166
|
-
|
|
10185
|
+
const done = li.fn.apply(li, params);
|
|
10167
10186
|
if (done)
|
|
10168
10187
|
delete this._listeners[li.name];
|
|
10169
10188
|
}
|
|
@@ -10197,7 +10216,7 @@ var Tempo = class {
|
|
|
10197
10216
|
return;
|
|
10198
10217
|
}
|
|
10199
10218
|
};
|
|
10200
|
-
var Sound = class {
|
|
10219
|
+
var Sound = class _Sound {
|
|
10201
10220
|
// Tracking play time against ctx.currentTime
|
|
10202
10221
|
/**
|
|
10203
10222
|
* 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).
|
|
@@ -10212,7 +10231,7 @@ var Sound = class {
|
|
|
10212
10231
|
* Create an AudioContext instance. This is called internally only.
|
|
10213
10232
|
*/
|
|
10214
10233
|
_createAudioContext() {
|
|
10215
|
-
|
|
10234
|
+
const _ctx = window.AudioContext;
|
|
10216
10235
|
if (!_ctx)
|
|
10217
10236
|
throw new Error("Your browser doesn't support Web Audio. (No AudioContext)");
|
|
10218
10237
|
this._ctx = _ctx ? new _ctx() : void 0;
|
|
@@ -10226,7 +10245,7 @@ var Sound = class {
|
|
|
10226
10245
|
* @returns a `Sound` instance
|
|
10227
10246
|
*/
|
|
10228
10247
|
static from(node, ctx, type = "gen", stream) {
|
|
10229
|
-
|
|
10248
|
+
const s = new _Sound(type);
|
|
10230
10249
|
s._node = node;
|
|
10231
10250
|
s._ctx = ctx;
|
|
10232
10251
|
if (stream)
|
|
@@ -10242,7 +10261,7 @@ var Sound = class {
|
|
|
10242
10261
|
*/
|
|
10243
10262
|
static load(source, crossOrigin = "anonymous") {
|
|
10244
10263
|
return new Promise((resolve, reject) => {
|
|
10245
|
-
|
|
10264
|
+
const s = new _Sound("file");
|
|
10246
10265
|
s._source = typeof source === "string" ? new Audio(source) : source;
|
|
10247
10266
|
s._source.autoplay = false;
|
|
10248
10267
|
s._source.crossOrigin = crossOrigin;
|
|
@@ -10267,10 +10286,10 @@ var Sound = class {
|
|
|
10267
10286
|
*/
|
|
10268
10287
|
static loadAsBuffer(url) {
|
|
10269
10288
|
return new Promise((resolve, reject) => {
|
|
10270
|
-
|
|
10289
|
+
const request = new XMLHttpRequest();
|
|
10271
10290
|
request.open("GET", url, true);
|
|
10272
10291
|
request.responseType = "arraybuffer";
|
|
10273
|
-
|
|
10292
|
+
const s = new _Sound("file");
|
|
10274
10293
|
request.onload = function() {
|
|
10275
10294
|
s._ctx.decodeAudioData(request.response, function(buffer) {
|
|
10276
10295
|
s.createBuffer(buffer);
|
|
@@ -10302,13 +10321,13 @@ var Sound = class {
|
|
|
10302
10321
|
* @example `Sound.generate( 'sine', 120 )`
|
|
10303
10322
|
*/
|
|
10304
10323
|
static generate(type, val) {
|
|
10305
|
-
|
|
10324
|
+
const s = new _Sound("gen");
|
|
10306
10325
|
return s._gen(type, val);
|
|
10307
10326
|
}
|
|
10308
10327
|
// Create the oscillator
|
|
10309
10328
|
_gen(type, val) {
|
|
10310
10329
|
this._node = this._ctx.createOscillator();
|
|
10311
|
-
|
|
10330
|
+
const osc = this._node;
|
|
10312
10331
|
osc.type = type;
|
|
10313
10332
|
if (type === "custom") {
|
|
10314
10333
|
osc.setPeriodicWave(val);
|
|
@@ -10326,7 +10345,7 @@ var Sound = class {
|
|
|
10326
10345
|
static input(constraint) {
|
|
10327
10346
|
return __async(this, null, function* () {
|
|
10328
10347
|
try {
|
|
10329
|
-
|
|
10348
|
+
const s = new _Sound("input");
|
|
10330
10349
|
if (!s)
|
|
10331
10350
|
return void 0;
|
|
10332
10351
|
const c = constraint ? constraint : { audio: true, video: false };
|
|
@@ -10396,7 +10415,7 @@ var Sound = class {
|
|
|
10396
10415
|
get progress() {
|
|
10397
10416
|
let dur = 0;
|
|
10398
10417
|
let curr = 0;
|
|
10399
|
-
if (
|
|
10418
|
+
if (this._buffer) {
|
|
10400
10419
|
dur = this._buffer.duration;
|
|
10401
10420
|
curr = this._timestamp ? this._ctx.currentTime - this._timestamp : 0;
|
|
10402
10421
|
} else {
|
|
@@ -10468,7 +10487,7 @@ var Sound = class {
|
|
|
10468
10487
|
* @param smooth Optional smoothing value (corresponds to `AnalyserNode.smoothingTimeConstant`)
|
|
10469
10488
|
*/
|
|
10470
10489
|
analyze(size = 256, minDb = -100, maxDb = -30, smooth = 0.8) {
|
|
10471
|
-
|
|
10490
|
+
const a = this._ctx.createAnalyser();
|
|
10472
10491
|
a.fftSize = size * 2;
|
|
10473
10492
|
a.minDecibels = minDb;
|
|
10474
10493
|
a.maxDecibels = maxDb;
|
|
@@ -10495,8 +10514,8 @@ var Sound = class {
|
|
|
10495
10514
|
}
|
|
10496
10515
|
// Map domain data to another range
|
|
10497
10516
|
_domainTo(time, size, position = [0, 0], trim = [0, 0]) {
|
|
10498
|
-
|
|
10499
|
-
|
|
10517
|
+
const data = time ? this.timeDomain() : this.freqDomain();
|
|
10518
|
+
const g = new Group();
|
|
10500
10519
|
for (let i = trim[0], len = data.length - trim[1]; i < len; i++) {
|
|
10501
10520
|
g.push(new Pt(position[0] + size[0] * i / len, position[1] + size[1] * data[i] / 255));
|
|
10502
10521
|
}
|
|
@@ -10555,7 +10574,7 @@ var Sound = class {
|
|
|
10555
10574
|
this._ctx.resume();
|
|
10556
10575
|
}
|
|
10557
10576
|
if (this._type === "file") {
|
|
10558
|
-
if (
|
|
10577
|
+
if (this._buffer) {
|
|
10559
10578
|
this._node.start(timeAt);
|
|
10560
10579
|
this._timestamp = this._ctx.currentTime + timeAt;
|
|
10561
10580
|
} else {
|
|
@@ -10580,7 +10599,7 @@ var Sound = class {
|
|
|
10580
10599
|
if (this._playing)
|
|
10581
10600
|
(this._outputNode || this._node).disconnect(this._ctx.destination);
|
|
10582
10601
|
if (this._type === "file") {
|
|
10583
|
-
if (
|
|
10602
|
+
if (this._buffer) {
|
|
10584
10603
|
if (this.progress < 1)
|
|
10585
10604
|
this._node.stop();
|
|
10586
10605
|
} else {
|