pts 0.11.6 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +5 -0
- package/.eslintrc.js +52 -0
- package/dist/index.d.mts +1380 -0
- package/dist/index.d.ts +26 -26
- package/dist/index.js +701 -707
- package/dist/index.mjs +701 -707
- package/dist/pts.js +701 -707
- package/dist/pts.min.js +3 -3
- package/dist/pts.min.js.map +1 -1
- package/package.json +10 -5
package/dist/index.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
|
}
|
|
@@ -4237,7 +4237,7 @@ var UIPointerActions = {
|
|
|
4237
4237
|
contextmenu: "contextmenu",
|
|
4238
4238
|
all: "all"
|
|
4239
4239
|
};
|
|
4240
|
-
var _UI = class {
|
|
4240
|
+
var _UI = class _UI {
|
|
4241
4241
|
/**
|
|
4242
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).
|
|
4243
4243
|
* @param group a Group or an Iterable<PtLike> that defines the UI's appearance
|
|
@@ -4473,8 +4473,8 @@ var _UI = class {
|
|
|
4473
4473
|
}
|
|
4474
4474
|
}
|
|
4475
4475
|
};
|
|
4476
|
+
_UI._counter = 0;
|
|
4476
4477
|
var UI = _UI;
|
|
4477
|
-
UI._counter = 0;
|
|
4478
4478
|
var UIButton = class extends UI {
|
|
4479
4479
|
/**
|
|
4480
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).
|
|
@@ -4499,7 +4499,7 @@ var UIButton = class extends UI {
|
|
|
4499
4499
|
if (hover && !this._states.hover) {
|
|
4500
4500
|
this.state("hover", true);
|
|
4501
4501
|
UI._trigger(this._actions[UA.enter], this, pt, UA.enter, evt);
|
|
4502
|
-
|
|
4502
|
+
let _capID = this.hold(UA.move);
|
|
4503
4503
|
this._hoverID = this.on(UA.move, (t, p) => {
|
|
4504
4504
|
if (!this._within(p) && !this.state("dragging")) {
|
|
4505
4505
|
this.state("hover", false);
|
|
@@ -4550,7 +4550,7 @@ var UIButton = class extends UI {
|
|
|
4550
4550
|
* @returns id numbers that refer to enter/leave handlers, for use in [`UIButton.offHover`](#link) or [`UI.off`](#link).
|
|
4551
4551
|
*/
|
|
4552
4552
|
onHover(enter, leave) {
|
|
4553
|
-
|
|
4553
|
+
let ids = [void 0, void 0];
|
|
4554
4554
|
if (enter)
|
|
4555
4555
|
ids[0] = this.on(UIPointerActions.enter, enter);
|
|
4556
4556
|
if (leave)
|
|
@@ -4564,7 +4564,7 @@ var UIButton = class extends UI {
|
|
|
4564
4564
|
* @returns an array of booleans indicating whether the handlers were removed successfully
|
|
4565
4565
|
*/
|
|
4566
4566
|
offHover(enterID, leaveID) {
|
|
4567
|
-
|
|
4567
|
+
let s = [false, false];
|
|
4568
4568
|
if (enterID === void 0 || enterID >= 0)
|
|
4569
4569
|
s[0] = this.off(UIPointerActions.enter, enterID);
|
|
4570
4570
|
if (leaveID === void 0 || leaveID >= 0)
|
|
@@ -4707,9 +4707,9 @@ var Space = class {
|
|
|
4707
4707
|
* @param player an [`IPlayer`](#link) object with animate function, or a callback function `fn(time, ftime)`.
|
|
4708
4708
|
*/
|
|
4709
4709
|
add(p) {
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4710
|
+
const player = typeof p == "function" ? { animate: p } : p;
|
|
4711
|
+
const k = this.playerCount++;
|
|
4712
|
+
const pid = player.animateID || this.id + k;
|
|
4713
4713
|
this.players[pid] = player;
|
|
4714
4714
|
player.animateID = pid;
|
|
4715
4715
|
if (player.resize && this.bound.inited)
|
|
@@ -4776,7 +4776,7 @@ var Space = class {
|
|
|
4776
4776
|
if (this._refresh)
|
|
4777
4777
|
this.clear();
|
|
4778
4778
|
if (this._isReady) {
|
|
4779
|
-
for (
|
|
4779
|
+
for (const k in this.players) {
|
|
4780
4780
|
if (this.players[k].animate)
|
|
4781
4781
|
this.players[k].animate(time, this._time.diff, this);
|
|
4782
4782
|
}
|
|
@@ -4894,7 +4894,7 @@ var MultiTouchSpace = class extends Space {
|
|
|
4894
4894
|
* Get the mouse or touch pointer that stores the last action.
|
|
4895
4895
|
*/
|
|
4896
4896
|
get pointer() {
|
|
4897
|
-
|
|
4897
|
+
const p = this._pointer.clone();
|
|
4898
4898
|
p.id = this._pointer.id;
|
|
4899
4899
|
return p;
|
|
4900
4900
|
}
|
|
@@ -5021,9 +5021,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5021
5021
|
touchesToPoints(evt, which = "touches") {
|
|
5022
5022
|
if (!evt || !evt[which])
|
|
5023
5023
|
return [];
|
|
5024
|
-
|
|
5025
|
-
for (
|
|
5026
|
-
|
|
5024
|
+
const ts = [];
|
|
5025
|
+
for (let i = 0; i < evt[which].length; i++) {
|
|
5026
|
+
const t = evt[which].item(i);
|
|
5027
5027
|
ts.push(new Pt(t.pageX - this.bound.topLeft.x, t.pageY - this.bound.topLeft.y));
|
|
5028
5028
|
}
|
|
5029
5029
|
return ts;
|
|
@@ -5039,9 +5039,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5039
5039
|
return;
|
|
5040
5040
|
let px = 0, py = 0;
|
|
5041
5041
|
if (evt instanceof MouseEvent) {
|
|
5042
|
-
for (
|
|
5042
|
+
for (const k in this.players) {
|
|
5043
5043
|
if (this.players.hasOwnProperty(k)) {
|
|
5044
|
-
|
|
5044
|
+
const v = this.players[k];
|
|
5045
5045
|
px = evt.pageX - this.outerBound.x;
|
|
5046
5046
|
py = evt.pageY - this.outerBound.y;
|
|
5047
5047
|
if (v.action)
|
|
@@ -5049,11 +5049,11 @@ var MultiTouchSpace = class extends Space {
|
|
|
5049
5049
|
}
|
|
5050
5050
|
}
|
|
5051
5051
|
} else {
|
|
5052
|
-
for (
|
|
5052
|
+
for (const k in this.players) {
|
|
5053
5053
|
if (this.players.hasOwnProperty(k)) {
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5054
|
+
const v = this.players[k];
|
|
5055
|
+
const c = evt.changedTouches && evt.changedTouches.length > 0;
|
|
5056
|
+
const touch = evt.changedTouches.item(0);
|
|
5057
5057
|
px = c ? touch.pageX - this.outerBound.x : 0;
|
|
5058
5058
|
py = c ? touch.pageY - this.outerBound.y : 0;
|
|
5059
5059
|
if (v.action)
|
|
@@ -5184,9 +5184,9 @@ var MultiTouchSpace = class extends Space {
|
|
|
5184
5184
|
_keyboardAction(type, evt) {
|
|
5185
5185
|
if (!this.isPlaying)
|
|
5186
5186
|
return;
|
|
5187
|
-
for (
|
|
5187
|
+
for (const k in this.players) {
|
|
5188
5188
|
if (this.players.hasOwnProperty(k)) {
|
|
5189
|
-
|
|
5189
|
+
const v = this.players[k];
|
|
5190
5190
|
if (v.action)
|
|
5191
5191
|
v.action(type, evt.shiftKey ? 1 : 0, evt.altKey ? 1 : 0, evt);
|
|
5192
5192
|
}
|
|
@@ -5435,7 +5435,7 @@ var Typography = class {
|
|
|
5435
5435
|
};
|
|
5436
5436
|
|
|
5437
5437
|
// src/Image.ts
|
|
5438
|
-
var Img = class {
|
|
5438
|
+
var Img = class _Img {
|
|
5439
5439
|
/**
|
|
5440
5440
|
* Create an Img
|
|
5441
5441
|
* @param editable Specify if you want to manipulate pixels of this image. Default is `false`.
|
|
@@ -5460,7 +5460,7 @@ var Img = class {
|
|
|
5460
5460
|
* @param ready An optional ready callback function
|
|
5461
5461
|
*/
|
|
5462
5462
|
static load(src, editable = false, space, ready) {
|
|
5463
|
-
const img = new
|
|
5463
|
+
const img = new _Img(editable, space);
|
|
5464
5464
|
img.load(src).then((res) => {
|
|
5465
5465
|
if (ready)
|
|
5466
5466
|
ready(res);
|
|
@@ -5476,7 +5476,7 @@ var Img = class {
|
|
|
5476
5476
|
*/
|
|
5477
5477
|
static loadAsync(src, editable = false, space) {
|
|
5478
5478
|
return __async(this, null, function* () {
|
|
5479
|
-
const img = yield new
|
|
5479
|
+
const img = yield new _Img(editable, space).load(src);
|
|
5480
5480
|
return img;
|
|
5481
5481
|
});
|
|
5482
5482
|
}
|
|
@@ -5490,7 +5490,7 @@ var Img = class {
|
|
|
5490
5490
|
*/
|
|
5491
5491
|
static loadPattern(src, space, repeat = "repeat", editable = false) {
|
|
5492
5492
|
return __async(this, null, function* () {
|
|
5493
|
-
const img = yield
|
|
5493
|
+
const img = yield _Img.loadAsync(src, editable, space);
|
|
5494
5494
|
return img.pattern(repeat);
|
|
5495
5495
|
});
|
|
5496
5496
|
}
|
|
@@ -5501,7 +5501,7 @@ var Img = class {
|
|
|
5501
5501
|
* @param scale Optionally set a specific pixel scale (density) of the image canvas.
|
|
5502
5502
|
*/
|
|
5503
5503
|
static blank(size, space, scale) {
|
|
5504
|
-
let img = new
|
|
5504
|
+
let img = new _Img(true, space);
|
|
5505
5505
|
const s = scale ? scale : space.pixelScale;
|
|
5506
5506
|
img.initCanvas(size[0], size[1], s);
|
|
5507
5507
|
return img;
|
|
@@ -5607,7 +5607,7 @@ var Img = class {
|
|
|
5607
5607
|
*/
|
|
5608
5608
|
pixel(p, rescale = true) {
|
|
5609
5609
|
const s = typeof rescale == "number" ? rescale : rescale ? this._scale : 1;
|
|
5610
|
-
return
|
|
5610
|
+
return _Img.getPixel(this._data, [p[0] * s, p[1] * s]);
|
|
5611
5611
|
}
|
|
5612
5612
|
/**
|
|
5613
5613
|
* Given an ImaegData object and a position, return the RGBA pixel value at that position.
|
|
@@ -5672,7 +5672,7 @@ var Img = class {
|
|
|
5672
5672
|
*/
|
|
5673
5673
|
static fromBlob(blob, editable = false, space) {
|
|
5674
5674
|
let url = URL.createObjectURL(blob);
|
|
5675
|
-
return new
|
|
5675
|
+
return new _Img(editable, space).load(url);
|
|
5676
5676
|
}
|
|
5677
5677
|
/**
|
|
5678
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.
|
|
@@ -5800,8 +5800,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5800
5800
|
this._bgcolor = "#e1e9f0";
|
|
5801
5801
|
this._offscreen = false;
|
|
5802
5802
|
this._initialResize = false;
|
|
5803
|
-
|
|
5804
|
-
|
|
5803
|
+
let _selector = null;
|
|
5804
|
+
let _existed = false;
|
|
5805
5805
|
this.id = "pt";
|
|
5806
5806
|
if (elem instanceof Element) {
|
|
5807
5807
|
_selector = elem;
|
|
@@ -5838,7 +5838,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5838
5838
|
* @param id element id attribute
|
|
5839
5839
|
*/
|
|
5840
5840
|
_createElement(elem = "div", id) {
|
|
5841
|
-
|
|
5841
|
+
const d = document.createElement(elem);
|
|
5842
5842
|
d.setAttribute("id", id);
|
|
5843
5843
|
return d;
|
|
5844
5844
|
}
|
|
@@ -5853,7 +5853,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5853
5853
|
this._resizeHandler(null);
|
|
5854
5854
|
this.clear(this._bgcolor);
|
|
5855
5855
|
this._canvas.dispatchEvent(new Event("ready"));
|
|
5856
|
-
for (
|
|
5856
|
+
for (const k in this.players) {
|
|
5857
5857
|
if (this.players.hasOwnProperty(k)) {
|
|
5858
5858
|
if (this.players[k].start)
|
|
5859
5859
|
this.players[k].start(this.bound.clone(), this);
|
|
@@ -5873,8 +5873,8 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5873
5873
|
this._bgcolor = opt.bgcolor ? opt.bgcolor : "transparent";
|
|
5874
5874
|
this.autoResize = opt.resize != void 0 ? opt.resize : false;
|
|
5875
5875
|
if (opt.retina !== false) {
|
|
5876
|
-
|
|
5877
|
-
|
|
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;
|
|
5878
5878
|
this._pixelScale = Math.max(1, r1 / r2);
|
|
5879
5879
|
}
|
|
5880
5880
|
if (opt.offscreen) {
|
|
@@ -5928,9 +5928,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5928
5928
|
this._offCtx.scale(this._pixelScale, this._pixelScale);
|
|
5929
5929
|
}
|
|
5930
5930
|
}
|
|
5931
|
-
for (
|
|
5931
|
+
for (const k in this.players) {
|
|
5932
5932
|
if (this.players.hasOwnProperty(k)) {
|
|
5933
|
-
|
|
5933
|
+
const p = this.players[k];
|
|
5934
5934
|
if (p.resize)
|
|
5935
5935
|
p.resize(this.bound, evt);
|
|
5936
5936
|
}
|
|
@@ -5947,9 +5947,9 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
5947
5947
|
_resizeHandler(evt) {
|
|
5948
5948
|
if (!window)
|
|
5949
5949
|
return;
|
|
5950
|
-
|
|
5950
|
+
const b = this._autoResize || this._initialResize ? this._container.getBoundingClientRect() : this._canvas.getBoundingClientRect();
|
|
5951
5951
|
if (b) {
|
|
5952
|
-
|
|
5952
|
+
const box = Bound.fromBoundingRect(b);
|
|
5953
5953
|
box.center = box.center.add(window.pageXOffset, window.pageYOffset);
|
|
5954
5954
|
this.resize(box, evt);
|
|
5955
5955
|
}
|
|
@@ -6092,14 +6092,14 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6092
6092
|
* @example `let rec = space.recorder(true); rec.start(); setTimeout( () => rec.stop(), 5000); // record 5s of video and download the file`
|
|
6093
6093
|
*/
|
|
6094
6094
|
recorder(downloadOrCallback, filetype = "webm", bitrate = 15e6) {
|
|
6095
|
-
|
|
6095
|
+
const stream = this._canvas.captureStream();
|
|
6096
6096
|
const recorder = new MediaRecorder(stream, { mimeType: `video/${filetype}`, bitsPerSecond: bitrate });
|
|
6097
6097
|
recorder.ondataavailable = function(d) {
|
|
6098
|
-
|
|
6098
|
+
const url = URL.createObjectURL(new Blob([d.data], { type: `video/${filetype}` }));
|
|
6099
6099
|
if (typeof downloadOrCallback === "function") {
|
|
6100
6100
|
downloadOrCallback(url);
|
|
6101
6101
|
} else if (downloadOrCallback) {
|
|
6102
|
-
|
|
6102
|
+
const a = document.createElement("a");
|
|
6103
6103
|
a.href = url;
|
|
6104
6104
|
a.download = `canvas_video.${filetype}`;
|
|
6105
6105
|
a.click();
|
|
@@ -6109,7 +6109,7 @@ var CanvasSpace2 = class extends MultiTouchSpace {
|
|
|
6109
6109
|
return recorder;
|
|
6110
6110
|
}
|
|
6111
6111
|
};
|
|
6112
|
-
var CanvasForm = class extends VisualForm {
|
|
6112
|
+
var CanvasForm = class _CanvasForm extends VisualForm {
|
|
6113
6113
|
/**
|
|
6114
6114
|
* Create a new CanvasForm. You may also use [`CanvasSpace.getForm()`](#link) to get the default form.
|
|
6115
6115
|
* @param space an instance of CanvasSpace
|
|
@@ -6186,20 +6186,20 @@ var CanvasForm = class extends VisualForm {
|
|
|
6186
6186
|
}
|
|
6187
6187
|
}
|
|
6188
6188
|
/**
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6189
|
+
* Set current alpha value.
|
|
6190
|
+
* @example `form.alpha(0.6)`
|
|
6191
|
+
* @param a alpha value between 0 and 1
|
|
6192
|
+
*/
|
|
6193
6193
|
alpha(a) {
|
|
6194
6194
|
this._ctx.globalAlpha = a;
|
|
6195
6195
|
this._style.globalAlpha = a;
|
|
6196
6196
|
return this;
|
|
6197
6197
|
}
|
|
6198
6198
|
/**
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
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
|
+
*/
|
|
6203
6203
|
fill(c) {
|
|
6204
6204
|
if (typeof c == "boolean") {
|
|
6205
6205
|
this.filled = c;
|
|
@@ -6211,21 +6211,21 @@ var CanvasForm = class extends VisualForm {
|
|
|
6211
6211
|
return this;
|
|
6212
6212
|
}
|
|
6213
6213
|
/**
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
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
|
+
*/
|
|
6217
6217
|
fillOnly(c) {
|
|
6218
6218
|
this.stroke(false);
|
|
6219
6219
|
return this.fill(c);
|
|
6220
6220
|
}
|
|
6221
6221
|
/**
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
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
|
+
*/
|
|
6229
6229
|
stroke(c, width, linejoin, linecap) {
|
|
6230
6230
|
if (typeof c == "boolean") {
|
|
6231
6231
|
this.stroked = c;
|
|
@@ -6249,24 +6249,24 @@ var CanvasForm = class extends VisualForm {
|
|
|
6249
6249
|
return this;
|
|
6250
6250
|
}
|
|
6251
6251
|
/**
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
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
|
+
*/
|
|
6258
6258
|
strokeOnly(c, width, linejoin, linecap) {
|
|
6259
6259
|
this.fill(false);
|
|
6260
6260
|
return this.stroke(c, width, linejoin, linecap);
|
|
6261
6261
|
}
|
|
6262
6262
|
/**
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
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
|
+
*/
|
|
6270
6270
|
applyFillStroke(filled = true, stroked = true, strokeWidth = 1) {
|
|
6271
6271
|
if (filled) {
|
|
6272
6272
|
if (typeof filled === "string")
|
|
@@ -6281,22 +6281,22 @@ var CanvasForm = class extends VisualForm {
|
|
|
6281
6281
|
return this;
|
|
6282
6282
|
}
|
|
6283
6283
|
/**
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
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
|
+
*/
|
|
6289
6289
|
gradient(stops) {
|
|
6290
|
-
|
|
6290
|
+
const vals = [];
|
|
6291
6291
|
if (stops.length < 2)
|
|
6292
6292
|
stops.push([0.99, "#000"], [1, "#000"]);
|
|
6293
6293
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
6294
|
-
|
|
6295
|
-
|
|
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];
|
|
6296
6296
|
vals.push([t, v]);
|
|
6297
6297
|
}
|
|
6298
6298
|
return (area1, area2) => {
|
|
6299
|
-
|
|
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]);
|
|
6300
6300
|
for (let i = 0, len = vals.length; i < len; i++) {
|
|
6301
6301
|
grad.addColorStop(vals[i][0], vals[i][1]);
|
|
6302
6302
|
}
|
|
@@ -6304,26 +6304,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6304
6304
|
};
|
|
6305
6305
|
}
|
|
6306
6306
|
/**
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
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
|
+
*/
|
|
6310
6310
|
composite(mode = "source-over") {
|
|
6311
6311
|
this._ctx.globalCompositeOperation = mode;
|
|
6312
6312
|
return this;
|
|
6313
6313
|
}
|
|
6314
6314
|
/**
|
|
6315
|
-
|
|
6316
|
-
|
|
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
|
+
*/
|
|
6317
6317
|
clip() {
|
|
6318
6318
|
this._ctx.clip();
|
|
6319
6319
|
return this;
|
|
6320
6320
|
}
|
|
6321
6321
|
/**
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
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
|
+
*/
|
|
6327
6327
|
dash(segments = true, offset = 0) {
|
|
6328
6328
|
if (!segments) {
|
|
6329
6329
|
this._ctx.setLineDash([]);
|
|
@@ -6338,14 +6338,14 @@ var CanvasForm = class extends VisualForm {
|
|
|
6338
6338
|
return this;
|
|
6339
6339
|
}
|
|
6340
6340
|
/**
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
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
|
+
*/
|
|
6349
6349
|
font(sizeOrFont, weight, style, lineHeight, family) {
|
|
6350
6350
|
if (typeof sizeOrFont == "number") {
|
|
6351
6351
|
this._font.size = sizeOrFont;
|
|
@@ -6366,49 +6366,49 @@ var CanvasForm = class extends VisualForm {
|
|
|
6366
6366
|
return this;
|
|
6367
6367
|
}
|
|
6368
6368
|
/**
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
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
|
+
*/
|
|
6372
6372
|
fontWidthEstimate(estimate = true) {
|
|
6373
6373
|
this._estimateTextWidth = estimate ? Typography.textWidthEstimator((c) => this._ctx.measureText(c).width) : void 0;
|
|
6374
6374
|
return this;
|
|
6375
6375
|
}
|
|
6376
6376
|
/**
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
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
|
+
*/
|
|
6380
6380
|
getTextWidth(c) {
|
|
6381
6381
|
return !this._estimateTextWidth ? this._ctx.measureText(c + " .").width : this._estimateTextWidth(c);
|
|
6382
6382
|
}
|
|
6383
6383
|
/**
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
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
|
+
*/
|
|
6389
6389
|
_textTruncate(str, width, tail = "") {
|
|
6390
6390
|
return Typography.truncate(this.getTextWidth.bind(this), str, width, tail);
|
|
6391
6391
|
}
|
|
6392
6392
|
/**
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
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
|
+
*/
|
|
6399
6399
|
_textAlign(box, vertical, offset, center) {
|
|
6400
|
-
|
|
6400
|
+
const _box = Util.iterToArray(box);
|
|
6401
6401
|
if (!Util.arrayCheck(_box))
|
|
6402
6402
|
return;
|
|
6403
6403
|
if (!center)
|
|
6404
6404
|
center = Rectangle.center(_box);
|
|
6405
|
-
|
|
6405
|
+
let px = _box[0][0];
|
|
6406
6406
|
if (this._ctx.textAlign == "end" || this._ctx.textAlign == "right") {
|
|
6407
6407
|
px = _box[1][0];
|
|
6408
6408
|
} else if (this._ctx.textAlign == "center" || this._ctx.textAlign == "middle") {
|
|
6409
6409
|
px = center[0];
|
|
6410
6410
|
}
|
|
6411
|
-
|
|
6411
|
+
let py = center[1];
|
|
6412
6412
|
if (vertical == "top" || vertical == "start") {
|
|
6413
6413
|
py = _box[0][1];
|
|
6414
6414
|
} else if (vertical == "end" || vertical == "bottom") {
|
|
@@ -6417,10 +6417,10 @@ var CanvasForm = class extends VisualForm {
|
|
|
6417
6417
|
return offset ? new Pt(px + offset[0], py + offset[1]) : new Pt(px, py);
|
|
6418
6418
|
}
|
|
6419
6419
|
/**
|
|
6420
|
-
|
|
6421
|
-
|
|
6420
|
+
* Reset the rendering context's common styles to this form's styles. This supports using multiple forms on the same canvas context.
|
|
6421
|
+
*/
|
|
6422
6422
|
reset() {
|
|
6423
|
-
for (
|
|
6423
|
+
for (const k in this._style) {
|
|
6424
6424
|
if (this._style.hasOwnProperty(k)) {
|
|
6425
6425
|
this._ctx[k] = this._style[k];
|
|
6426
6426
|
}
|
|
@@ -6436,38 +6436,38 @@ var CanvasForm = class extends VisualForm {
|
|
|
6436
6436
|
this._ctx.stroke();
|
|
6437
6437
|
}
|
|
6438
6438
|
/**
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
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
|
+
*/
|
|
6446
6446
|
static point(ctx, p, radius = 5, shape = "square") {
|
|
6447
6447
|
if (!p)
|
|
6448
6448
|
return;
|
|
6449
|
-
if (!
|
|
6449
|
+
if (!_CanvasForm[shape])
|
|
6450
6450
|
throw new Error(`${shape} is not a static function of CanvasForm`);
|
|
6451
|
-
|
|
6451
|
+
_CanvasForm[shape](ctx, p, radius);
|
|
6452
6452
|
}
|
|
6453
6453
|
/**
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
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
|
+
*/
|
|
6460
6460
|
point(p, radius = 5, shape = "square") {
|
|
6461
|
-
|
|
6461
|
+
_CanvasForm.point(this._ctx, p, radius, shape);
|
|
6462
6462
|
this._paint();
|
|
6463
6463
|
return this;
|
|
6464
6464
|
}
|
|
6465
6465
|
/**
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
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
|
+
*/
|
|
6471
6471
|
static circle(ctx, pt, radius = 10) {
|
|
6472
6472
|
if (!pt)
|
|
6473
6473
|
return;
|
|
@@ -6476,25 +6476,25 @@ var CanvasForm = class extends VisualForm {
|
|
|
6476
6476
|
ctx.closePath();
|
|
6477
6477
|
}
|
|
6478
6478
|
/**
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
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
|
+
*/
|
|
6482
6482
|
circle(pts) {
|
|
6483
|
-
|
|
6484
|
-
|
|
6483
|
+
const p = Util.iterToArray(pts);
|
|
6484
|
+
_CanvasForm.circle(this._ctx, p[0], p[1][0]);
|
|
6485
6485
|
this._paint();
|
|
6486
6486
|
return this;
|
|
6487
6487
|
}
|
|
6488
6488
|
/**
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
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
|
+
*/
|
|
6498
6498
|
static ellipse(ctx, pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6499
6499
|
if (!pt || !radius)
|
|
6500
6500
|
return;
|
|
@@ -6502,28 +6502,28 @@ var CanvasForm = class extends VisualForm {
|
|
|
6502
6502
|
ctx.ellipse(pt[0], pt[1], radius[0], radius[1], rotation, startAngle, endAngle, cc);
|
|
6503
6503
|
}
|
|
6504
6504
|
/**
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
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
|
+
*/
|
|
6513
6513
|
ellipse(pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6514
|
-
|
|
6514
|
+
_CanvasForm.ellipse(this._ctx, pt, radius, rotation, startAngle, endAngle, cc);
|
|
6515
6515
|
this._paint();
|
|
6516
6516
|
return this;
|
|
6517
6517
|
}
|
|
6518
6518
|
/**
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
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
|
+
*/
|
|
6527
6527
|
static arc(ctx, pt, radius, startAngle, endAngle, cc) {
|
|
6528
6528
|
if (!pt)
|
|
6529
6529
|
return;
|
|
@@ -6531,31 +6531,31 @@ var CanvasForm = class extends VisualForm {
|
|
|
6531
6531
|
ctx.arc(pt[0], pt[1], radius, startAngle, endAngle, cc);
|
|
6532
6532
|
}
|
|
6533
6533
|
/**
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
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
|
+
*/
|
|
6541
6541
|
arc(pt, radius, startAngle, endAngle, cc) {
|
|
6542
|
-
|
|
6542
|
+
_CanvasForm.arc(this._ctx, pt, radius, startAngle, endAngle, cc);
|
|
6543
6543
|
this._paint();
|
|
6544
6544
|
return this;
|
|
6545
6545
|
}
|
|
6546
6546
|
/**
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
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
|
+
*/
|
|
6552
6552
|
static square(ctx, pt, halfsize) {
|
|
6553
6553
|
if (!pt)
|
|
6554
6554
|
return;
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6555
|
+
const x1 = pt[0] - halfsize;
|
|
6556
|
+
const y1 = pt[1] - halfsize;
|
|
6557
|
+
const x2 = pt[0] + halfsize;
|
|
6558
|
+
const y2 = pt[1] + halfsize;
|
|
6559
6559
|
ctx.beginPath();
|
|
6560
6560
|
ctx.moveTo(x1, y1);
|
|
6561
6561
|
ctx.lineTo(x1, y2);
|
|
@@ -6564,26 +6564,26 @@ var CanvasForm = class extends VisualForm {
|
|
|
6564
6564
|
ctx.closePath();
|
|
6565
6565
|
}
|
|
6566
6566
|
/**
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6567
|
+
* Draw a square, given a center and its half-size.
|
|
6568
|
+
* @param pt center Pt
|
|
6569
|
+
* @param halfsize half-size
|
|
6570
|
+
*/
|
|
6571
6571
|
square(pt, halfsize) {
|
|
6572
|
-
|
|
6572
|
+
_CanvasForm.square(this._ctx, pt, halfsize);
|
|
6573
6573
|
this._paint();
|
|
6574
6574
|
return this;
|
|
6575
6575
|
}
|
|
6576
6576
|
/**
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
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
|
+
*/
|
|
6581
6581
|
static line(ctx, pts) {
|
|
6582
6582
|
if (!Util.arrayCheck(pts))
|
|
6583
6583
|
return;
|
|
6584
6584
|
let i = 0;
|
|
6585
6585
|
ctx.beginPath();
|
|
6586
|
-
for (
|
|
6586
|
+
for (const it of pts) {
|
|
6587
6587
|
if (it) {
|
|
6588
6588
|
if (i++ > 0) {
|
|
6589
6589
|
ctx.lineTo(it[0], it[1]);
|
|
@@ -6594,41 +6594,41 @@ var CanvasForm = class extends VisualForm {
|
|
|
6594
6594
|
}
|
|
6595
6595
|
}
|
|
6596
6596
|
/**
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6597
|
+
* Draw a line or polyline.
|
|
6598
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6599
|
+
*/
|
|
6600
6600
|
line(pts) {
|
|
6601
|
-
|
|
6601
|
+
_CanvasForm.line(this._ctx, pts);
|
|
6602
6602
|
this._paint();
|
|
6603
6603
|
return this;
|
|
6604
6604
|
}
|
|
6605
6605
|
/**
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
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
|
+
*/
|
|
6610
6610
|
static polygon(ctx, pts) {
|
|
6611
6611
|
if (!Util.arrayCheck(pts))
|
|
6612
6612
|
return;
|
|
6613
|
-
|
|
6613
|
+
_CanvasForm.line(ctx, pts);
|
|
6614
6614
|
ctx.closePath();
|
|
6615
6615
|
}
|
|
6616
6616
|
/**
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6617
|
+
* Draw a polygon.
|
|
6618
|
+
* @param pts a Group or an Iterable<PtLike> representingg a polygon
|
|
6619
|
+
*/
|
|
6620
6620
|
polygon(pts) {
|
|
6621
|
-
|
|
6621
|
+
_CanvasForm.polygon(this._ctx, pts);
|
|
6622
6622
|
this._paint();
|
|
6623
6623
|
return this;
|
|
6624
6624
|
}
|
|
6625
6625
|
/**
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
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
|
+
*/
|
|
6630
6630
|
static rect(ctx, pts) {
|
|
6631
|
-
|
|
6631
|
+
const p = Util.iterToArray(pts);
|
|
6632
6632
|
if (!Util.arrayCheck(p))
|
|
6633
6633
|
return;
|
|
6634
6634
|
ctx.beginPath();
|
|
@@ -6639,29 +6639,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6639
6639
|
ctx.closePath();
|
|
6640
6640
|
}
|
|
6641
6641
|
/**
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
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
|
+
*/
|
|
6645
6645
|
rect(pts) {
|
|
6646
|
-
|
|
6646
|
+
_CanvasForm.rect(this._ctx, pts);
|
|
6647
6647
|
this._paint();
|
|
6648
6648
|
return this;
|
|
6649
6649
|
}
|
|
6650
6650
|
/**
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
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
|
+
*/
|
|
6657
6657
|
static image(ctx, ptOrRect, img, orig) {
|
|
6658
|
-
|
|
6658
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6659
6659
|
let pos;
|
|
6660
6660
|
if (typeof t[0] === "number") {
|
|
6661
6661
|
pos = t;
|
|
6662
6662
|
} else {
|
|
6663
6663
|
if (orig) {
|
|
6664
|
-
|
|
6664
|
+
const o = Util.iterToArray(orig);
|
|
6665
6665
|
pos = [
|
|
6666
6666
|
o[0][0],
|
|
6667
6667
|
o[0][1],
|
|
@@ -6685,29 +6685,29 @@ var CanvasForm = class extends VisualForm {
|
|
|
6685
6685
|
}
|
|
6686
6686
|
}
|
|
6687
6687
|
/**
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
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
|
+
*/
|
|
6693
6693
|
image(ptOrRect, img, orig) {
|
|
6694
6694
|
if (img instanceof Img) {
|
|
6695
6695
|
if (img.loaded) {
|
|
6696
|
-
|
|
6696
|
+
_CanvasForm.image(this._ctx, ptOrRect, img.image, orig);
|
|
6697
6697
|
}
|
|
6698
6698
|
} else {
|
|
6699
|
-
|
|
6699
|
+
_CanvasForm.image(this._ctx, ptOrRect, img, orig);
|
|
6700
6700
|
}
|
|
6701
6701
|
return this;
|
|
6702
6702
|
}
|
|
6703
6703
|
/**
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
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
|
+
*/
|
|
6709
6709
|
static imageData(ctx, ptOrRect, img) {
|
|
6710
|
-
|
|
6710
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6711
6711
|
if (typeof t[0] === "number") {
|
|
6712
6712
|
ctx.putImageData(img, t[0], t[1]);
|
|
6713
6713
|
} else {
|
|
@@ -6715,74 +6715,74 @@ var CanvasForm = class extends VisualForm {
|
|
|
6715
6715
|
}
|
|
6716
6716
|
}
|
|
6717
6717
|
/**
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
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
|
+
*/
|
|
6722
6722
|
imageData(ptOrRect, img) {
|
|
6723
|
-
|
|
6723
|
+
_CanvasForm.imageData(this._ctx, ptOrRect, img);
|
|
6724
6724
|
return this;
|
|
6725
6725
|
}
|
|
6726
6726
|
/**
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
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
|
+
*/
|
|
6733
6733
|
static text(ctx, pt, txt, maxWidth) {
|
|
6734
6734
|
if (!pt)
|
|
6735
6735
|
return;
|
|
6736
6736
|
ctx.fillText(txt, pt[0], pt[1], maxWidth);
|
|
6737
6737
|
}
|
|
6738
6738
|
/**
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
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
|
+
*/
|
|
6744
6744
|
text(pt, txt, maxWidth) {
|
|
6745
|
-
|
|
6745
|
+
_CanvasForm.text(this._ctx, pt, txt, maxWidth);
|
|
6746
6746
|
return this;
|
|
6747
6747
|
}
|
|
6748
6748
|
/**
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
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
|
+
*/
|
|
6756
6756
|
textBox(box, txt, verticalAlign = "middle", tail = "", overrideBaseline = true) {
|
|
6757
6757
|
if (overrideBaseline)
|
|
6758
6758
|
this._ctx.textBaseline = verticalAlign;
|
|
6759
|
-
|
|
6760
|
-
|
|
6759
|
+
const size = Rectangle.size(box);
|
|
6760
|
+
const t = this._textTruncate(txt, size[0], tail);
|
|
6761
6761
|
this.text(this._textAlign(box, verticalAlign), t[0]);
|
|
6762
6762
|
return this;
|
|
6763
6763
|
}
|
|
6764
6764
|
/**
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
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
|
+
*/
|
|
6772
6772
|
paragraphBox(box, txt, lineHeight = 1.2, verticalAlign = "top", crop = true) {
|
|
6773
|
-
|
|
6774
|
-
|
|
6773
|
+
const b = Util.iterToArray(box);
|
|
6774
|
+
const size = Rectangle.size(b);
|
|
6775
6775
|
this._ctx.textBaseline = "top";
|
|
6776
|
-
|
|
6777
|
-
|
|
6776
|
+
const lstep = this._font.size * lineHeight;
|
|
6777
|
+
const nextLine = (sub, buffer = [], cc = 0) => {
|
|
6778
6778
|
if (!sub)
|
|
6779
6779
|
return buffer;
|
|
6780
6780
|
if (crop && cc * lstep > size[1] - lstep * 2)
|
|
6781
6781
|
return buffer;
|
|
6782
6782
|
if (cc > 1e4)
|
|
6783
6783
|
throw new Error("max recursion reached (10000)");
|
|
6784
|
-
|
|
6785
|
-
|
|
6784
|
+
const t = this._textTruncate(sub, size[0], "");
|
|
6785
|
+
const newln = t[0].indexOf("\n");
|
|
6786
6786
|
if (newln >= 0) {
|
|
6787
6787
|
buffer.push(t[0].substr(0, newln));
|
|
6788
6788
|
return nextLine(sub.substr(newln + 1), buffer, cc + 1);
|
|
@@ -6790,12 +6790,12 @@ var CanvasForm = class extends VisualForm {
|
|
|
6790
6790
|
let dt = t[0].lastIndexOf(" ") + 1;
|
|
6791
6791
|
if (dt <= 0 || t[1] === sub.length)
|
|
6792
6792
|
dt = void 0;
|
|
6793
|
-
|
|
6793
|
+
const line = t[0].substr(0, dt);
|
|
6794
6794
|
buffer.push(line);
|
|
6795
6795
|
return t[1] <= 0 || t[1] === sub.length ? buffer : nextLine(sub.substr(dt || t[1]), buffer, cc + 1);
|
|
6796
6796
|
};
|
|
6797
|
-
|
|
6798
|
-
|
|
6797
|
+
const lines = nextLine(txt);
|
|
6798
|
+
const lsize = lines.length * lstep;
|
|
6799
6799
|
let lbox = b;
|
|
6800
6800
|
if (verticalAlign == "middle" || verticalAlign == "center") {
|
|
6801
6801
|
let lpad = (size[1] - lsize) / 2;
|
|
@@ -6807,17 +6807,17 @@ var CanvasForm = class extends VisualForm {
|
|
|
6807
6807
|
} else {
|
|
6808
6808
|
lbox = new Group(b[0], b[0].$add(size[0], lsize));
|
|
6809
6809
|
}
|
|
6810
|
-
|
|
6810
|
+
const center = Rectangle.center(lbox);
|
|
6811
6811
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
6812
6812
|
this.text(this._textAlign(lbox, "top", [0, i * lstep], center), lines[i]);
|
|
6813
6813
|
}
|
|
6814
6814
|
return this;
|
|
6815
6815
|
}
|
|
6816
6816
|
/**
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
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
|
+
*/
|
|
6821
6821
|
alignText(alignment = "left", baseline = "alphabetic") {
|
|
6822
6822
|
if (baseline == "center")
|
|
6823
6823
|
baseline = "middle";
|
|
@@ -6828,11 +6828,11 @@ var CanvasForm = class extends VisualForm {
|
|
|
6828
6828
|
return this;
|
|
6829
6829
|
}
|
|
6830
6830
|
/**
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
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
|
+
*/
|
|
6834
6834
|
log(txt) {
|
|
6835
|
-
|
|
6835
|
+
const w = this._ctx.measureText(txt).width + 20;
|
|
6836
6836
|
this.stroke(false).fill("rgba(0,0,0,.4)").rect([[0, 0], [w, 20]]);
|
|
6837
6837
|
this.fill("#fff").text([10, 14], txt);
|
|
6838
6838
|
return this;
|
|
@@ -7295,7 +7295,7 @@ var Noise = class extends Pt {
|
|
|
7295
7295
|
return Num.lerp(Num.lerp(n00, n10, tx), Num.lerp(n01, n11, tx), _fade(y));
|
|
7296
7296
|
}
|
|
7297
7297
|
};
|
|
7298
|
-
var Delaunay = class extends Group {
|
|
7298
|
+
var Delaunay = class _Delaunay extends Group {
|
|
7299
7299
|
constructor() {
|
|
7300
7300
|
super(...arguments);
|
|
7301
7301
|
this._mesh = [];
|
|
@@ -7342,7 +7342,7 @@ var Delaunay = class extends Group {
|
|
|
7342
7342
|
edges.push(circum.i, circum.j, circum.j, circum.k, circum.k, circum.i);
|
|
7343
7343
|
opened.splice(j, 1);
|
|
7344
7344
|
}
|
|
7345
|
-
|
|
7345
|
+
_Delaunay._dedupe(edges);
|
|
7346
7346
|
j = edges.length;
|
|
7347
7347
|
while (j > 1) {
|
|
7348
7348
|
opened.push(this._circum(edges[--j], edges[--j], c, false, pts));
|
|
@@ -7484,7 +7484,7 @@ var Delaunay = class extends Group {
|
|
|
7484
7484
|
};
|
|
7485
7485
|
|
|
7486
7486
|
// src/Color.ts
|
|
7487
|
-
var _Color = class extends Pt {
|
|
7487
|
+
var _Color = class _Color extends Pt {
|
|
7488
7488
|
/**
|
|
7489
7489
|
* Create a Color. Same as creating a Pt. Optionally you may use [`Color.from`](#link) to create a color.
|
|
7490
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
|
|
@@ -7499,8 +7499,8 @@ var _Color = class extends Pt {
|
|
|
7499
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
|
|
7500
7500
|
*/
|
|
7501
7501
|
static from(...args) {
|
|
7502
|
-
|
|
7503
|
-
|
|
7502
|
+
const p = [1, 1, 1, 1];
|
|
7503
|
+
const c = Util.getArgs(args);
|
|
7504
7504
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
7505
7505
|
if (i < c.length)
|
|
7506
7506
|
p[i] = c[i];
|
|
@@ -7515,7 +7515,7 @@ var _Color = class extends Pt {
|
|
|
7515
7515
|
if (hex[0] == "#")
|
|
7516
7516
|
hex = hex.substr(1);
|
|
7517
7517
|
if (hex.length <= 3) {
|
|
7518
|
-
|
|
7518
|
+
const fn = (i) => hex[i] || "F";
|
|
7519
7519
|
hex = `${fn(0)}${fn(0)}${fn(1)}${fn(1)}${fn(2)}${fn(2)}`;
|
|
7520
7520
|
}
|
|
7521
7521
|
let alpha = 1;
|
|
@@ -7523,7 +7523,7 @@ var _Color = class extends Pt {
|
|
|
7523
7523
|
alpha = hex.substr(6) && 255 / 255;
|
|
7524
7524
|
hex = hex.substring(0, 6);
|
|
7525
7525
|
}
|
|
7526
|
-
|
|
7526
|
+
const hexVal = parseInt(hex, 16);
|
|
7527
7527
|
return new _Color(hexVal >> 16, hexVal >> 8 & 255, hexVal & 255, alpha);
|
|
7528
7528
|
}
|
|
7529
7529
|
/**
|
|
@@ -7605,7 +7605,7 @@ var _Color = class extends Pt {
|
|
|
7605
7605
|
* Clone this Color.
|
|
7606
7606
|
*/
|
|
7607
7607
|
clone() {
|
|
7608
|
-
|
|
7608
|
+
const c = new _Color(this);
|
|
7609
7609
|
c.toMode(this._mode);
|
|
7610
7610
|
return c;
|
|
7611
7611
|
}
|
|
@@ -7616,7 +7616,7 @@ var _Color = class extends Pt {
|
|
|
7616
7616
|
*/
|
|
7617
7617
|
toMode(mode, convert = false) {
|
|
7618
7618
|
if (convert) {
|
|
7619
|
-
|
|
7619
|
+
const fname = this._mode.toUpperCase() + "to" + mode.toUpperCase();
|
|
7620
7620
|
if (_Color[fname]) {
|
|
7621
7621
|
this.to(_Color[fname](this, this._isNorm, this._isNorm));
|
|
7622
7622
|
} else {
|
|
@@ -7668,7 +7668,7 @@ var _Color = class extends Pt {
|
|
|
7668
7668
|
return this._mode == "lch" ? this[2] : this[0];
|
|
7669
7669
|
}
|
|
7670
7670
|
set h(n) {
|
|
7671
|
-
|
|
7671
|
+
const i = this._mode == "lch" ? 2 : 0;
|
|
7672
7672
|
this[i] = n;
|
|
7673
7673
|
}
|
|
7674
7674
|
/**
|
|
@@ -7687,7 +7687,7 @@ var _Color = class extends Pt {
|
|
|
7687
7687
|
return this._mode == "hsl" ? this[2] : this[0];
|
|
7688
7688
|
}
|
|
7689
7689
|
set l(n) {
|
|
7690
|
-
|
|
7690
|
+
const i = this._mode == "hsl" ? 2 : 0;
|
|
7691
7691
|
this[i] = n;
|
|
7692
7692
|
}
|
|
7693
7693
|
// lab, lch, luv
|
|
@@ -7753,7 +7753,7 @@ var _Color = class extends Pt {
|
|
|
7753
7753
|
normalize(toNorm = true) {
|
|
7754
7754
|
if (this._isNorm == toNorm)
|
|
7755
7755
|
return this;
|
|
7756
|
-
|
|
7756
|
+
const ranges = _Color.ranges[this._mode];
|
|
7757
7757
|
for (let i = 0; i < 3; i++) {
|
|
7758
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);
|
|
7759
7759
|
}
|
|
@@ -7774,8 +7774,8 @@ var _Color = class extends Pt {
|
|
|
7774
7774
|
*/
|
|
7775
7775
|
toString(format = "mode") {
|
|
7776
7776
|
if (format == "hex") {
|
|
7777
|
-
|
|
7778
|
-
|
|
7777
|
+
const _hex = (n) => {
|
|
7778
|
+
const s = Math.floor(n).toString(16);
|
|
7779
7779
|
return s.length < 2 ? "0" + s : s;
|
|
7780
7780
|
};
|
|
7781
7781
|
return `#${_hex(this[0])}${_hex(this[1])}${_hex(this[2])}`;
|
|
@@ -7795,17 +7795,17 @@ var _Color = class extends Pt {
|
|
|
7795
7795
|
* @returns a new HSL Color
|
|
7796
7796
|
*/
|
|
7797
7797
|
static RGBtoHSL(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
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);
|
|
7801
7801
|
let h = (max + min) / 2;
|
|
7802
7802
|
let s = h;
|
|
7803
|
-
|
|
7803
|
+
const l = h;
|
|
7804
7804
|
if (max == min) {
|
|
7805
7805
|
h = 0;
|
|
7806
7806
|
s = 0;
|
|
7807
7807
|
} else {
|
|
7808
|
-
|
|
7808
|
+
const d = max - min;
|
|
7809
7809
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
7810
7810
|
h = 0;
|
|
7811
7811
|
if (max === r) {
|
|
@@ -7831,9 +7831,9 @@ var _Color = class extends Pt {
|
|
|
7831
7831
|
h = h / 360;
|
|
7832
7832
|
if (s == 0)
|
|
7833
7833
|
return _Color.rgb(l * 255, l * 255, l * 255, hsl.alpha);
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7834
|
+
const q = l <= 0.5 ? l * (1 + s) : l + s - l * s;
|
|
7835
|
+
const p = 2 * l - q;
|
|
7836
|
+
const convert = (t) => {
|
|
7837
7837
|
t = t < 0 ? t + 1 : t > 1 ? t - 1 : t;
|
|
7838
7838
|
if (t * 6 < 1) {
|
|
7839
7839
|
return p + (q - p) * t * 6;
|
|
@@ -7845,7 +7845,7 @@ var _Color = class extends Pt {
|
|
|
7845
7845
|
return p;
|
|
7846
7846
|
}
|
|
7847
7847
|
};
|
|
7848
|
-
|
|
7848
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7849
7849
|
return _Color.rgb(
|
|
7850
7850
|
sc * convert(h + 1 / 3),
|
|
7851
7851
|
sc * convert(h),
|
|
@@ -7861,13 +7861,13 @@ var _Color = class extends Pt {
|
|
|
7861
7861
|
* @returns a new HSB Color
|
|
7862
7862
|
*/
|
|
7863
7863
|
static RGBtoHSB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
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;
|
|
7868
7868
|
let h = 0;
|
|
7869
|
-
|
|
7870
|
-
|
|
7869
|
+
const s = max === 0 ? 0 : d / max;
|
|
7870
|
+
const v = max;
|
|
7871
7871
|
if (max != min) {
|
|
7872
7872
|
if (max === r) {
|
|
7873
7873
|
h = (g - b) / d + (g < b ? 6 : 0);
|
|
@@ -7890,12 +7890,12 @@ var _Color = class extends Pt {
|
|
|
7890
7890
|
let [h, s, v] = hsb;
|
|
7891
7891
|
if (!normalizedInput)
|
|
7892
7892
|
h = h / 360;
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
|
|
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 = [
|
|
7899
7899
|
[v, t, p],
|
|
7900
7900
|
[q, v, p],
|
|
7901
7901
|
[p, v, t],
|
|
@@ -7903,8 +7903,8 @@ var _Color = class extends Pt {
|
|
|
7903
7903
|
[t, p, v],
|
|
7904
7904
|
[v, p, q]
|
|
7905
7905
|
];
|
|
7906
|
-
|
|
7907
|
-
|
|
7906
|
+
const c = pick[i % 6];
|
|
7907
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7908
7908
|
return _Color.rgb(
|
|
7909
7909
|
sc * c[0],
|
|
7910
7910
|
sc * c[1],
|
|
@@ -7920,7 +7920,7 @@ var _Color = class extends Pt {
|
|
|
7920
7920
|
* @returns a new LAB Color
|
|
7921
7921
|
*/
|
|
7922
7922
|
static RGBtoLAB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7923
|
-
|
|
7923
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7924
7924
|
return _Color.XYZtoLAB(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
7925
7925
|
}
|
|
7926
7926
|
/**
|
|
@@ -7931,7 +7931,7 @@ var _Color = class extends Pt {
|
|
|
7931
7931
|
* @returns a new RGB Color
|
|
7932
7932
|
*/
|
|
7933
7933
|
static LABtoRGB(lab, normalizedInput = false, normalizedOutput = false) {
|
|
7934
|
-
|
|
7934
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
7935
7935
|
return _Color.XYZtoRGB(_Color.LABtoXYZ(c), false, normalizedOutput);
|
|
7936
7936
|
}
|
|
7937
7937
|
/**
|
|
@@ -7942,7 +7942,7 @@ var _Color = class extends Pt {
|
|
|
7942
7942
|
* @returns a new LCH Color
|
|
7943
7943
|
*/
|
|
7944
7944
|
static RGBtoLCH(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7945
|
-
|
|
7945
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7946
7946
|
return _Color.LABtoLCH(_Color.RGBtoLAB(c), false, normalizedOutput);
|
|
7947
7947
|
}
|
|
7948
7948
|
/**
|
|
@@ -7953,7 +7953,7 @@ var _Color = class extends Pt {
|
|
|
7953
7953
|
* @returns a new RGB Color
|
|
7954
7954
|
*/
|
|
7955
7955
|
static LCHtoRGB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
7956
|
-
|
|
7956
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
7957
7957
|
return _Color.LABtoRGB(_Color.LCHtoLAB(c), false, normalizedOutput);
|
|
7958
7958
|
}
|
|
7959
7959
|
/**
|
|
@@ -7964,7 +7964,7 @@ var _Color = class extends Pt {
|
|
|
7964
7964
|
* @returns a new LUV Color
|
|
7965
7965
|
*/
|
|
7966
7966
|
static RGBtoLUV(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7967
|
-
|
|
7967
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
7968
7968
|
return _Color.XYZtoLUV(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
7969
7969
|
}
|
|
7970
7970
|
/**
|
|
@@ -7975,7 +7975,7 @@ var _Color = class extends Pt {
|
|
|
7975
7975
|
* @returns a new RGB Color
|
|
7976
7976
|
*/
|
|
7977
7977
|
static LUVtoRGB(luv, normalizedInput = false, normalizedOutput = false) {
|
|
7978
|
-
|
|
7978
|
+
const c = normalizedInput ? luv.$normalize(false) : luv;
|
|
7979
7979
|
return _Color.XYZtoRGB(_Color.LUVtoXYZ(c), false, normalizedOutput);
|
|
7980
7980
|
}
|
|
7981
7981
|
/**
|
|
@@ -7986,13 +7986,13 @@ var _Color = class extends Pt {
|
|
|
7986
7986
|
* @returns a new XYZ Color
|
|
7987
7987
|
*/
|
|
7988
7988
|
static RGBtoXYZ(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7989
|
-
|
|
7989
|
+
const c = !normalizedInput ? rgb.$normalize() : rgb.clone();
|
|
7990
7990
|
for (let i = 0; i < 3; i++) {
|
|
7991
7991
|
c[i] = c[i] > 0.04045 ? Math.pow((c[i] + 0.055) / 1.055, 2.4) : c[i] / 12.92;
|
|
7992
7992
|
if (!normalizedOutput)
|
|
7993
7993
|
c[i] = c[i] * 100;
|
|
7994
7994
|
}
|
|
7995
|
-
|
|
7995
|
+
const cc = _Color.xyz(
|
|
7996
7996
|
c[0] * 0.4124564 + c[1] * 0.3575761 + c[2] * 0.1804375,
|
|
7997
7997
|
c[0] * 0.2126729 + c[1] * 0.7151522 + c[2] * 0.072175,
|
|
7998
7998
|
c[0] * 0.0193339 + c[1] * 0.119192 + c[2] * 0.9503041,
|
|
@@ -8008,8 +8008,8 @@ var _Color = class extends Pt {
|
|
|
8008
8008
|
* @returns a new RGB Color
|
|
8009
8009
|
*/
|
|
8010
8010
|
static XYZtoRGB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8011
|
-
|
|
8012
|
-
|
|
8011
|
+
const [x, y, z] = !normalizedInput ? xyz.$normalize() : xyz;
|
|
8012
|
+
const rgb = [
|
|
8013
8013
|
x * 3.2406254773200533 + y * -1.5372079722103187 + z * -0.4986285986982479,
|
|
8014
8014
|
x * -0.9689307147293197 + y * 1.8757560608852415 + z * 0.041517523842953964,
|
|
8015
8015
|
x * 0.055710120445510616 + y * -0.2040210505984867 + z * 1.0569959422543882
|
|
@@ -8020,7 +8020,7 @@ var _Color = class extends Pt {
|
|
|
8020
8020
|
if (!normalizedOutput)
|
|
8021
8021
|
rgb[i] = Math.round(rgb[i] * 255);
|
|
8022
8022
|
}
|
|
8023
|
-
|
|
8023
|
+
const cc = _Color.rgb(rgb[0], rgb[1], rgb[2], xyz.alpha);
|
|
8024
8024
|
return normalizedOutput ? cc.normalize() : cc;
|
|
8025
8025
|
}
|
|
8026
8026
|
/**
|
|
@@ -8031,13 +8031,13 @@ var _Color = class extends Pt {
|
|
|
8031
8031
|
* @returns a new LAB Color
|
|
8032
8032
|
*/
|
|
8033
8033
|
static XYZtoLAB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8034
|
-
|
|
8034
|
+
const c = normalizedInput ? xyz.$normalize(false) : xyz.clone();
|
|
8035
8035
|
const eps = 0.00885645167;
|
|
8036
8036
|
const kap = 903.296296296;
|
|
8037
8037
|
c.divide(_Color.D65);
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
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(
|
|
8041
8041
|
116 * cy - 16,
|
|
8042
8042
|
500 * (fn(c[0]) - cy),
|
|
8043
8043
|
200 * (cy - fn(c[2])),
|
|
@@ -8053,16 +8053,16 @@ var _Color = class extends Pt {
|
|
|
8053
8053
|
* @returns a new XYZ Color
|
|
8054
8054
|
*/
|
|
8055
8055
|
static LABtoXYZ(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
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;
|
|
8060
8060
|
const eps = 0.00885645167;
|
|
8061
8061
|
const kap = 903.296296296;
|
|
8062
|
-
|
|
8062
|
+
const d = _Color.D65;
|
|
8063
8063
|
const xxx = Math.pow(x, 3);
|
|
8064
8064
|
const zzz = Math.pow(z, 3);
|
|
8065
|
-
|
|
8065
|
+
const cc = _Color.xyz(
|
|
8066
8066
|
d[0] * (xxx > eps ? xxx : (116 * x - 16) / kap),
|
|
8067
8067
|
d[1] * (c[0] > kap * eps ? Math.pow((c[0] + 16) / 116, 3) : c[0] / kap),
|
|
8068
8068
|
d[2] * (zzz > eps ? zzz : (116 * z - 16) / kap),
|
|
@@ -8079,13 +8079,13 @@ var _Color = class extends Pt {
|
|
|
8079
8079
|
*/
|
|
8080
8080
|
static XYZtoLUV(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8081
8081
|
let [x, y, z] = normalizedInput ? xyz.$normalize(false) : xyz;
|
|
8082
|
-
|
|
8083
|
-
|
|
8082
|
+
const u = 4 * x / (x + 15 * y + 3 * z);
|
|
8083
|
+
const v = 9 * y / (x + 15 * y + 3 * z);
|
|
8084
8084
|
y = y / 100;
|
|
8085
8085
|
y = y > 8856e-6 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
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;
|
|
8089
8089
|
return _Color.luv(
|
|
8090
8090
|
L,
|
|
8091
8091
|
13 * L * (u - refU),
|
|
@@ -8103,15 +8103,15 @@ var _Color = class extends Pt {
|
|
|
8103
8103
|
static LUVtoXYZ(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8104
8104
|
let [l, u, v] = normalizedInput ? luv.$normalize(false) : luv;
|
|
8105
8105
|
let y = (l + 16) / 116;
|
|
8106
|
-
|
|
8106
|
+
const cubeY = y * y * y;
|
|
8107
8107
|
y = cubeY > 8856e-6 ? cubeY : (y - 16 / 116) / 7.787;
|
|
8108
|
-
|
|
8109
|
-
|
|
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]);
|
|
8110
8110
|
u = u / (13 * l) + refU;
|
|
8111
8111
|
v = v / (13 * l) + refV;
|
|
8112
8112
|
y = y * 100;
|
|
8113
|
-
|
|
8114
|
-
|
|
8113
|
+
const x = -1 * (9 * y * u) / ((u - 4) * v - u * v);
|
|
8114
|
+
const z = (9 * y - 15 * v * y - v * x) / (3 * v);
|
|
8115
8115
|
return _Color.xyz(x, y, z, luv.alpha);
|
|
8116
8116
|
}
|
|
8117
8117
|
/**
|
|
@@ -8122,8 +8122,8 @@ var _Color = class extends Pt {
|
|
|
8122
8122
|
* @returns a new LCH Color
|
|
8123
8123
|
*/
|
|
8124
8124
|
static LABtoLCH(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8125
|
-
|
|
8126
|
-
|
|
8125
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8126
|
+
const h = Geom.toDegree(Geom.boundRadian(Math.atan2(c[2], c[1])));
|
|
8127
8127
|
return _Color.lch(
|
|
8128
8128
|
c[0],
|
|
8129
8129
|
Math.sqrt(c[1] * c[1] + c[2] * c[2]),
|
|
@@ -8139,8 +8139,8 @@ var _Color = class extends Pt {
|
|
|
8139
8139
|
* @returns a new LAB Color
|
|
8140
8140
|
*/
|
|
8141
8141
|
static LCHtoLAB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
8142
|
-
|
|
8143
|
-
|
|
8142
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8143
|
+
const rad = Geom.toRadian(c[2]);
|
|
8144
8144
|
return _Color.lab(
|
|
8145
8145
|
c[0],
|
|
8146
8146
|
Math.cos(rad) * c[1],
|
|
@@ -8149,13 +8149,12 @@ var _Color = class extends Pt {
|
|
|
8149
8149
|
);
|
|
8150
8150
|
}
|
|
8151
8151
|
};
|
|
8152
|
-
var Color = _Color;
|
|
8153
8152
|
// XYZ property for Standard Observer 2deg, Daylight/sRGB illuminant D65
|
|
8154
|
-
|
|
8153
|
+
_Color.D65 = new Pt(95.047, 100, 108.883, 1);
|
|
8155
8154
|
/**
|
|
8156
8155
|
* Value range for each color space
|
|
8157
8156
|
*/
|
|
8158
|
-
|
|
8157
|
+
_Color.ranges = {
|
|
8159
8158
|
rgb: new Group(new Pt(0, 255), new Pt(0, 255), new Pt(0, 255)),
|
|
8160
8159
|
hsl: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
8161
8160
|
hsb: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
@@ -8164,9 +8163,10 @@ Color.ranges = {
|
|
|
8164
8163
|
luv: new Group(new Pt(0, 100), new Pt(-134, 220), new Pt(-140, 122)),
|
|
8165
8164
|
xyz: new Group(new Pt(0, 100), new Pt(0, 100), new Pt(0, 100))
|
|
8166
8165
|
};
|
|
8166
|
+
var Color = _Color;
|
|
8167
8167
|
|
|
8168
8168
|
// src/Dom.ts
|
|
8169
|
-
var DOMSpace = class extends MultiTouchSpace {
|
|
8169
|
+
var DOMSpace = class _DOMSpace extends MultiTouchSpace {
|
|
8170
8170
|
/**
|
|
8171
8171
|
* Create a DOMSpace for HTML DOM elements
|
|
8172
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.
|
|
@@ -8179,8 +8179,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8179
8179
|
this._autoResize = true;
|
|
8180
8180
|
this._bgcolor = "#e1e9f0";
|
|
8181
8181
|
this._css = {};
|
|
8182
|
-
|
|
8183
|
-
|
|
8182
|
+
let _selector = null;
|
|
8183
|
+
let _existed = false;
|
|
8184
8184
|
this.id = "pts";
|
|
8185
8185
|
if (elem instanceof Element) {
|
|
8186
8186
|
_selector = elem;
|
|
@@ -8191,8 +8191,8 @@ var DOMSpace = class extends MultiTouchSpace {
|
|
|
8191
8191
|
this.id = elem.substr(1);
|
|
8192
8192
|
}
|
|
8193
8193
|
if (!_selector) {
|
|
8194
|
-
this._container =
|
|
8195
|
-
this._canvas =
|
|
8194
|
+
this._container = _DOMSpace.createElement("div", "pts_container");
|
|
8195
|
+
this._canvas = _DOMSpace.createElement("div", "pts_element");
|
|
8196
8196
|
this._container.appendChild(this._canvas);
|
|
8197
8197
|
document.body.appendChild(this._container);
|
|
8198
8198
|
_existed = false;
|
|
@@ -8454,7 +8454,7 @@ var HTMLSpace = class extends DOMSpace {
|
|
|
8454
8454
|
return super.removeAll();
|
|
8455
8455
|
}
|
|
8456
8456
|
};
|
|
8457
|
-
var _HTMLForm = class extends VisualForm {
|
|
8457
|
+
var _HTMLForm = class _HTMLForm extends VisualForm {
|
|
8458
8458
|
/**
|
|
8459
8459
|
* Create a new `HTMLForm`. Alternatively, you can use [`HTMLSpace.getForm`](#link) function to get an instance of HTMLForm.
|
|
8460
8460
|
* @param space the space to use
|
|
@@ -8873,12 +8873,12 @@ var _HTMLForm = class extends VisualForm {
|
|
|
8873
8873
|
return this;
|
|
8874
8874
|
}
|
|
8875
8875
|
};
|
|
8876
|
+
_HTMLForm.groupID = 0;
|
|
8877
|
+
_HTMLForm.domID = 0;
|
|
8876
8878
|
var HTMLForm = _HTMLForm;
|
|
8877
|
-
HTMLForm.groupID = 0;
|
|
8878
|
-
HTMLForm.domID = 0;
|
|
8879
8879
|
|
|
8880
8880
|
// src/Svg.ts
|
|
8881
|
-
var SVGSpace = class extends DOMSpace {
|
|
8881
|
+
var SVGSpace = class _SVGSpace extends DOMSpace {
|
|
8882
8882
|
/**
|
|
8883
8883
|
* Create a SVGSpace which represents a Space for SVG elements.
|
|
8884
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.
|
|
@@ -8889,7 +8889,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8889
8889
|
super(elem, callback);
|
|
8890
8890
|
this._bgcolor = "#999";
|
|
8891
8891
|
if (this._canvas.nodeName.toLowerCase() != "svg") {
|
|
8892
|
-
let s =
|
|
8892
|
+
let s = _SVGSpace.svgElement(this._canvas, "svg", `${this.id}_svg`);
|
|
8893
8893
|
this._container = this._canvas;
|
|
8894
8894
|
this._canvas = s;
|
|
8895
8895
|
}
|
|
@@ -8915,7 +8915,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8915
8915
|
*/
|
|
8916
8916
|
resize(b, evt) {
|
|
8917
8917
|
super.resize(b, evt);
|
|
8918
|
-
|
|
8918
|
+
_SVGSpace.setAttr(this.element, {
|
|
8919
8919
|
"viewBox": `0 0 ${this.bound.width} ${this.bound.height}`,
|
|
8920
8920
|
"width": `${this.bound.width}`,
|
|
8921
8921
|
"height": `${this.bound.height}`,
|
|
@@ -8960,7 +8960,7 @@ var SVGSpace = class extends DOMSpace {
|
|
|
8960
8960
|
return super.removeAll();
|
|
8961
8961
|
}
|
|
8962
8962
|
};
|
|
8963
|
-
var _SVGForm = class extends VisualForm {
|
|
8963
|
+
var _SVGForm = class _SVGForm extends VisualForm {
|
|
8964
8964
|
/**
|
|
8965
8965
|
* Create a new SVGForm. You may also use [`SVGSpace.getForm`](#link) to get a default form directly.
|
|
8966
8966
|
* @param space an instance of SVGSpace
|
|
@@ -9454,12 +9454,12 @@ var _SVGForm = class extends VisualForm {
|
|
|
9454
9454
|
return this;
|
|
9455
9455
|
}
|
|
9456
9456
|
};
|
|
9457
|
+
_SVGForm.groupID = 0;
|
|
9458
|
+
_SVGForm.domID = 0;
|
|
9457
9459
|
var SVGForm = _SVGForm;
|
|
9458
|
-
SVGForm.groupID = 0;
|
|
9459
|
-
SVGForm.domID = 0;
|
|
9460
9460
|
|
|
9461
9461
|
// src/Physics.ts
|
|
9462
|
-
var World = class {
|
|
9462
|
+
var World = class _World {
|
|
9463
9463
|
/**
|
|
9464
9464
|
* Create a `World` for 2D physics simulation.
|
|
9465
9465
|
* @param bound a Group or an Iterable<Pt> representing a rectangular bounding box
|
|
@@ -9547,13 +9547,10 @@ var World = class {
|
|
|
9547
9547
|
* @returns a Body, or undefined if not found
|
|
9548
9548
|
*/
|
|
9549
9549
|
body(id) {
|
|
9550
|
-
let idx = id;
|
|
9551
9550
|
if (typeof id === "string" && id.length > 0) {
|
|
9552
|
-
|
|
9551
|
+
return this._bodies[this._bnames.indexOf(id)];
|
|
9553
9552
|
}
|
|
9554
|
-
|
|
9555
|
-
return void 0;
|
|
9556
|
-
return this._bodies[idx];
|
|
9553
|
+
return typeof id === "number" && id >= 0 ? this._bodies[id] : void 0;
|
|
9557
9554
|
}
|
|
9558
9555
|
/**
|
|
9559
9556
|
* Get a particle in this world by index or string id.
|
|
@@ -9561,13 +9558,10 @@ var World = class {
|
|
|
9561
9558
|
* @returns a Particle, or undefined if not found
|
|
9562
9559
|
*/
|
|
9563
9560
|
particle(id) {
|
|
9564
|
-
let idx = id;
|
|
9565
9561
|
if (typeof id === "string" && id.length > 0) {
|
|
9566
|
-
|
|
9562
|
+
return this._particles[this._pnames.indexOf(id)];
|
|
9567
9563
|
}
|
|
9568
|
-
|
|
9569
|
-
return void 0;
|
|
9570
|
-
return this._particles[idx];
|
|
9564
|
+
return typeof id === "number" && id >= 0 ? this._particles[id] : void 0;
|
|
9571
9565
|
}
|
|
9572
9566
|
/**
|
|
9573
9567
|
* Given a body's name, return its index in the bodies array, or -1 if not found.
|
|
@@ -9714,7 +9708,7 @@ var World = class {
|
|
|
9714
9708
|
for (let i = 0, len = this._particles.length; i < len; i++) {
|
|
9715
9709
|
let p = this._particles[i];
|
|
9716
9710
|
this.integrate(p, dt, this._lastTime);
|
|
9717
|
-
|
|
9711
|
+
_World.boundConstraint(p, this._bound, this._damping);
|
|
9718
9712
|
for (let k = i + 1; k < len; k++) {
|
|
9719
9713
|
if (i !== k) {
|
|
9720
9714
|
let p2 = this._particles[k];
|
|
@@ -9735,7 +9729,7 @@ var World = class {
|
|
|
9735
9729
|
if (bds) {
|
|
9736
9730
|
for (let k = 0, klen = bds.length; k < klen; k++) {
|
|
9737
9731
|
let bk = bds[k];
|
|
9738
|
-
|
|
9732
|
+
_World.boundConstraint(bk, this._bound, this._damping);
|
|
9739
9733
|
this.integrate(bk, dt, this._lastTime);
|
|
9740
9734
|
}
|
|
9741
9735
|
for (let k = i + 1; k < len; k++) {
|
|
@@ -9918,7 +9912,7 @@ var Particle = class extends Pt {
|
|
|
9918
9912
|
return `Particle: ${this[0]} ${this[1]} | previous ${this._prev[0]} ${this._prev[1]} | mass ${this._mass}`;
|
|
9919
9913
|
}
|
|
9920
9914
|
};
|
|
9921
|
-
var Body = class extends Group {
|
|
9915
|
+
var Body = class _Body extends Group {
|
|
9922
9916
|
/**
|
|
9923
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.
|
|
9924
9918
|
*/
|
|
@@ -9937,7 +9931,7 @@ var Body = class extends Group {
|
|
|
9937
9931
|
* @param autoMass Automatically calculate the mass based on the area of the polygon. Default is true.
|
|
9938
9932
|
*/
|
|
9939
9933
|
static fromGroup(body, stiff = 1, autoLink = true, autoMass = true) {
|
|
9940
|
-
let b = new
|
|
9934
|
+
let b = new _Body().init(body);
|
|
9941
9935
|
if (autoLink)
|
|
9942
9936
|
b.linkAll(stiff);
|
|
9943
9937
|
if (autoMass)
|
|
@@ -10092,7 +10086,7 @@ var Body = class extends Group {
|
|
|
10092
10086
|
};
|
|
10093
10087
|
|
|
10094
10088
|
// src/Play.ts
|
|
10095
|
-
var Tempo = class {
|
|
10089
|
+
var Tempo = class _Tempo {
|
|
10096
10090
|
/**
|
|
10097
10091
|
* Construct a new Tempo instance by beats-per-minute. Alternatively, you can use [`Tempo.fromBeat`](#link) to create from milliseconds.
|
|
10098
10092
|
* @param bpm beats per minute
|
|
@@ -10108,7 +10102,7 @@ var Tempo = class {
|
|
|
10108
10102
|
* @param ms milliseconds per beat
|
|
10109
10103
|
*/
|
|
10110
10104
|
static fromBeat(ms) {
|
|
10111
|
-
return new
|
|
10105
|
+
return new _Tempo(6e4 / ms);
|
|
10112
10106
|
}
|
|
10113
10107
|
/**
|
|
10114
10108
|
* Beats-per-minute value
|
|
@@ -10150,16 +10144,16 @@ var Tempo = class {
|
|
|
10150
10144
|
* @returns an object with chainable functions
|
|
10151
10145
|
*/
|
|
10152
10146
|
every(beats) {
|
|
10153
|
-
|
|
10154
|
-
|
|
10147
|
+
const self = this;
|
|
10148
|
+
const p = Array.isArray(beats) ? beats[0] : beats;
|
|
10155
10149
|
return {
|
|
10156
10150
|
start: function(fn, offset = 0, name) {
|
|
10157
|
-
|
|
10151
|
+
const id = name || self._createID(fn);
|
|
10158
10152
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: false, fn };
|
|
10159
10153
|
return this;
|
|
10160
10154
|
},
|
|
10161
10155
|
progress: function(fn, offset = 0, name) {
|
|
10162
|
-
|
|
10156
|
+
const id = name || self._createID(fn);
|
|
10163
10157
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: true, fn };
|
|
10164
10158
|
return this;
|
|
10165
10159
|
}
|
|
@@ -10171,11 +10165,11 @@ var Tempo = class {
|
|
|
10171
10165
|
* @param time current time in milliseconds
|
|
10172
10166
|
*/
|
|
10173
10167
|
track(time) {
|
|
10174
|
-
for (
|
|
10168
|
+
for (const k in this._listeners) {
|
|
10175
10169
|
if (this._listeners.hasOwnProperty(k)) {
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10170
|
+
const li = this._listeners[k];
|
|
10171
|
+
const _t = li.offset ? time + li.offset : time;
|
|
10172
|
+
const ms = li.period * this._ms;
|
|
10179
10173
|
let isStart = false;
|
|
10180
10174
|
if (_t > li.duration + ms) {
|
|
10181
10175
|
li.duration = _t - _t % this._ms;
|
|
@@ -10185,10 +10179,10 @@ var Tempo = class {
|
|
|
10185
10179
|
}
|
|
10186
10180
|
isStart = true;
|
|
10187
10181
|
}
|
|
10188
|
-
|
|
10189
|
-
|
|
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];
|
|
10190
10184
|
if (li.continuous || isStart) {
|
|
10191
|
-
|
|
10185
|
+
const done = li.fn.apply(li, params);
|
|
10192
10186
|
if (done)
|
|
10193
10187
|
delete this._listeners[li.name];
|
|
10194
10188
|
}
|
|
@@ -10222,7 +10216,7 @@ var Tempo = class {
|
|
|
10222
10216
|
return;
|
|
10223
10217
|
}
|
|
10224
10218
|
};
|
|
10225
|
-
var Sound = class {
|
|
10219
|
+
var Sound = class _Sound {
|
|
10226
10220
|
// Tracking play time against ctx.currentTime
|
|
10227
10221
|
/**
|
|
10228
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).
|
|
@@ -10237,7 +10231,7 @@ var Sound = class {
|
|
|
10237
10231
|
* Create an AudioContext instance. This is called internally only.
|
|
10238
10232
|
*/
|
|
10239
10233
|
_createAudioContext() {
|
|
10240
|
-
|
|
10234
|
+
const _ctx = window.AudioContext;
|
|
10241
10235
|
if (!_ctx)
|
|
10242
10236
|
throw new Error("Your browser doesn't support Web Audio. (No AudioContext)");
|
|
10243
10237
|
this._ctx = _ctx ? new _ctx() : void 0;
|
|
@@ -10251,7 +10245,7 @@ var Sound = class {
|
|
|
10251
10245
|
* @returns a `Sound` instance
|
|
10252
10246
|
*/
|
|
10253
10247
|
static from(node, ctx, type = "gen", stream) {
|
|
10254
|
-
|
|
10248
|
+
const s = new _Sound(type);
|
|
10255
10249
|
s._node = node;
|
|
10256
10250
|
s._ctx = ctx;
|
|
10257
10251
|
if (stream)
|
|
@@ -10267,7 +10261,7 @@ var Sound = class {
|
|
|
10267
10261
|
*/
|
|
10268
10262
|
static load(source, crossOrigin = "anonymous") {
|
|
10269
10263
|
return new Promise((resolve, reject) => {
|
|
10270
|
-
|
|
10264
|
+
const s = new _Sound("file");
|
|
10271
10265
|
s._source = typeof source === "string" ? new Audio(source) : source;
|
|
10272
10266
|
s._source.autoplay = false;
|
|
10273
10267
|
s._source.crossOrigin = crossOrigin;
|
|
@@ -10292,10 +10286,10 @@ var Sound = class {
|
|
|
10292
10286
|
*/
|
|
10293
10287
|
static loadAsBuffer(url) {
|
|
10294
10288
|
return new Promise((resolve, reject) => {
|
|
10295
|
-
|
|
10289
|
+
const request = new XMLHttpRequest();
|
|
10296
10290
|
request.open("GET", url, true);
|
|
10297
10291
|
request.responseType = "arraybuffer";
|
|
10298
|
-
|
|
10292
|
+
const s = new _Sound("file");
|
|
10299
10293
|
request.onload = function() {
|
|
10300
10294
|
s._ctx.decodeAudioData(request.response, function(buffer) {
|
|
10301
10295
|
s.createBuffer(buffer);
|
|
@@ -10327,13 +10321,13 @@ var Sound = class {
|
|
|
10327
10321
|
* @example `Sound.generate( 'sine', 120 )`
|
|
10328
10322
|
*/
|
|
10329
10323
|
static generate(type, val) {
|
|
10330
|
-
|
|
10324
|
+
const s = new _Sound("gen");
|
|
10331
10325
|
return s._gen(type, val);
|
|
10332
10326
|
}
|
|
10333
10327
|
// Create the oscillator
|
|
10334
10328
|
_gen(type, val) {
|
|
10335
10329
|
this._node = this._ctx.createOscillator();
|
|
10336
|
-
|
|
10330
|
+
const osc = this._node;
|
|
10337
10331
|
osc.type = type;
|
|
10338
10332
|
if (type === "custom") {
|
|
10339
10333
|
osc.setPeriodicWave(val);
|
|
@@ -10351,7 +10345,7 @@ var Sound = class {
|
|
|
10351
10345
|
static input(constraint) {
|
|
10352
10346
|
return __async(this, null, function* () {
|
|
10353
10347
|
try {
|
|
10354
|
-
|
|
10348
|
+
const s = new _Sound("input");
|
|
10355
10349
|
if (!s)
|
|
10356
10350
|
return void 0;
|
|
10357
10351
|
const c = constraint ? constraint : { audio: true, video: false };
|
|
@@ -10421,7 +10415,7 @@ var Sound = class {
|
|
|
10421
10415
|
get progress() {
|
|
10422
10416
|
let dur = 0;
|
|
10423
10417
|
let curr = 0;
|
|
10424
|
-
if (
|
|
10418
|
+
if (this._buffer) {
|
|
10425
10419
|
dur = this._buffer.duration;
|
|
10426
10420
|
curr = this._timestamp ? this._ctx.currentTime - this._timestamp : 0;
|
|
10427
10421
|
} else {
|
|
@@ -10493,7 +10487,7 @@ var Sound = class {
|
|
|
10493
10487
|
* @param smooth Optional smoothing value (corresponds to `AnalyserNode.smoothingTimeConstant`)
|
|
10494
10488
|
*/
|
|
10495
10489
|
analyze(size = 256, minDb = -100, maxDb = -30, smooth = 0.8) {
|
|
10496
|
-
|
|
10490
|
+
const a = this._ctx.createAnalyser();
|
|
10497
10491
|
a.fftSize = size * 2;
|
|
10498
10492
|
a.minDecibels = minDb;
|
|
10499
10493
|
a.maxDecibels = maxDb;
|
|
@@ -10520,8 +10514,8 @@ var Sound = class {
|
|
|
10520
10514
|
}
|
|
10521
10515
|
// Map domain data to another range
|
|
10522
10516
|
_domainTo(time, size, position = [0, 0], trim = [0, 0]) {
|
|
10523
|
-
|
|
10524
|
-
|
|
10517
|
+
const data = time ? this.timeDomain() : this.freqDomain();
|
|
10518
|
+
const g = new Group();
|
|
10525
10519
|
for (let i = trim[0], len = data.length - trim[1]; i < len; i++) {
|
|
10526
10520
|
g.push(new Pt(position[0] + size[0] * i / len, position[1] + size[1] * data[i] / 255));
|
|
10527
10521
|
}
|
|
@@ -10580,7 +10574,7 @@ var Sound = class {
|
|
|
10580
10574
|
this._ctx.resume();
|
|
10581
10575
|
}
|
|
10582
10576
|
if (this._type === "file") {
|
|
10583
|
-
if (
|
|
10577
|
+
if (this._buffer) {
|
|
10584
10578
|
this._node.start(timeAt);
|
|
10585
10579
|
this._timestamp = this._ctx.currentTime + timeAt;
|
|
10586
10580
|
} else {
|
|
@@ -10605,7 +10599,7 @@ var Sound = class {
|
|
|
10605
10599
|
if (this._playing)
|
|
10606
10600
|
(this._outputNode || this._node).disconnect(this._ctx.destination);
|
|
10607
10601
|
if (this._type === "file") {
|
|
10608
|
-
if (
|
|
10602
|
+
if (this._buffer) {
|
|
10609
10603
|
if (this.progress < 1)
|
|
10610
10604
|
this._node.stop();
|
|
10611
10605
|
} else {
|