@js-draw/math 1.3.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/cjs/Mat33.d.ts +1 -14
- package/dist/cjs/Mat33.js +1 -119
- package/dist/cjs/Mat33.test.d.ts +1 -0
- package/dist/mjs/Mat33.d.ts +1 -14
- package/dist/mjs/Mat33.mjs +1 -119
- package/dist/mjs/Mat33.test.d.ts +1 -0
- package/package.json +3 -3
- package/src/Mat33.ts +1 -1
package/dist/cjs/Mat33.d.ts
CHANGED
@@ -130,22 +130,9 @@ export declare class Mat33 {
|
|
130
130
|
/**
|
131
131
|
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
132
132
|
*
|
133
|
-
* @see {@link fromCSSMatrix}
|
133
|
+
* @see {@link fromCSSMatrix}
|
134
134
|
*/
|
135
135
|
toCSSMatrix(): string;
|
136
|
-
/**
|
137
|
-
* @beta May change or even be removed between minor releases.
|
138
|
-
*
|
139
|
-
* Converts this matrix into a list of CSS transforms that attempt to preserve
|
140
|
-
* this matrix's translation.
|
141
|
-
*
|
142
|
-
* In Chrome/Firefox, translation attributes only support 6 digits (likely an artifact
|
143
|
-
* of using lower-precision floating point numbers). This works around
|
144
|
-
* that by expanding this matrix into the product of several CSS transforms.
|
145
|
-
*
|
146
|
-
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
147
|
-
*/
|
148
|
-
toSafeCSSTransformList(): string;
|
149
136
|
/**
|
150
137
|
* Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33.
|
151
138
|
*
|
package/dist/cjs/Mat33.js
CHANGED
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.Mat33 = void 0;
|
7
7
|
const Vec2_1 = require("./Vec2");
|
8
8
|
const Vec3_1 = __importDefault(require("./Vec3"));
|
9
|
-
const rounding_1 = require("./rounding");
|
10
9
|
/**
|
11
10
|
* Represents a three dimensional linear transformation or
|
12
11
|
* a two-dimensional affine transformation. (An affine transformation scales/rotates/shears
|
@@ -321,128 +320,11 @@ class Mat33 {
|
|
321
320
|
/**
|
322
321
|
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
323
322
|
*
|
324
|
-
* @see {@link fromCSSMatrix}
|
323
|
+
* @see {@link fromCSSMatrix}
|
325
324
|
*/
|
326
325
|
toCSSMatrix() {
|
327
326
|
return `matrix(${this.a1},${this.b1},${this.a2},${this.b2},${this.a3},${this.b3})`;
|
328
327
|
}
|
329
|
-
/**
|
330
|
-
* @beta May change or even be removed between minor releases.
|
331
|
-
*
|
332
|
-
* Converts this matrix into a list of CSS transforms that attempt to preserve
|
333
|
-
* this matrix's translation.
|
334
|
-
*
|
335
|
-
* In Chrome/Firefox, translation attributes only support 6 digits (likely an artifact
|
336
|
-
* of using lower-precision floating point numbers). This works around
|
337
|
-
* that by expanding this matrix into the product of several CSS transforms.
|
338
|
-
*
|
339
|
-
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
340
|
-
*/
|
341
|
-
toSafeCSSTransformList() {
|
342
|
-
// Check whether it's safe to return just the CSS matrix
|
343
|
-
const translation = Vec2_1.Vec2.of(this.a3, this.b3);
|
344
|
-
const translationRoundedX = (0, rounding_1.toRoundedString)(translation.x);
|
345
|
-
const translationRoundedY = (0, rounding_1.toRoundedString)(translation.y);
|
346
|
-
const nonDigitsRegex = /[^0-9]+/g;
|
347
|
-
const translationXDigits = translationRoundedX.replace(nonDigitsRegex, '').length;
|
348
|
-
const translationYDigits = translationRoundedY.replace(nonDigitsRegex, '').length;
|
349
|
-
// Is it safe to just return the default CSS matrix?
|
350
|
-
if (translationXDigits <= 5 && translationYDigits <= 5) {
|
351
|
-
return this.toCSSMatrix();
|
352
|
-
}
|
353
|
-
// Remove the last column (the translation column)
|
354
|
-
let transform = new Mat33(this.a1, this.a2, 0, this.b1, this.b2, 0, 0, 0, 1);
|
355
|
-
const transforms = [];
|
356
|
-
let lastScale = null;
|
357
|
-
// Appends a translate() command to the list of `transforms`.
|
358
|
-
const addTranslate = (translation) => {
|
359
|
-
lastScale = null;
|
360
|
-
if (!translation.eq(Vec2_1.Vec2.zero)) {
|
361
|
-
transforms.push(`translate(${(0, rounding_1.toRoundedString)(translation.x)}px, ${(0, rounding_1.toRoundedString)(translation.y)}px)`);
|
362
|
-
}
|
363
|
-
};
|
364
|
-
// Appends a scale() command to the list of transforms, possibly merging with
|
365
|
-
// the last command, if a scale().
|
366
|
-
const addScale = (scale) => {
|
367
|
-
// Merge with the last scale
|
368
|
-
if (lastScale) {
|
369
|
-
const newScale = lastScale.scale(scale);
|
370
|
-
// Don't merge if the new scale has very large values
|
371
|
-
if (newScale.maximumEntryMagnitude() < 1e7) {
|
372
|
-
const previousCommand = transforms.pop();
|
373
|
-
console.assert(previousCommand.startsWith('scale'), 'Invalid state: Merging scale commands');
|
374
|
-
scale = newScale;
|
375
|
-
}
|
376
|
-
}
|
377
|
-
if (scale.x === scale.y) {
|
378
|
-
transforms.push(`scale(${(0, rounding_1.toRoundedString)(scale.x)})`);
|
379
|
-
}
|
380
|
-
else {
|
381
|
-
transforms.push(`scale(${(0, rounding_1.toRoundedString)(scale.x)}, ${(0, rounding_1.toRoundedString)(scale.y)})`);
|
382
|
-
}
|
383
|
-
lastScale = scale;
|
384
|
-
};
|
385
|
-
// Returns the number of digits before the `.` in the given number string.
|
386
|
-
const digitsPreDecimalCount = (numberString) => {
|
387
|
-
let decimalIndex = numberString.indexOf('.');
|
388
|
-
if (decimalIndex === -1) {
|
389
|
-
decimalIndex = numberString.length;
|
390
|
-
}
|
391
|
-
return numberString.substring(0, decimalIndex).replace(nonDigitsRegex, '').length;
|
392
|
-
};
|
393
|
-
// Returns the number of digits (positive for left shift, negative for right shift)
|
394
|
-
// required to shift the decimal to the middle of the number.
|
395
|
-
const getShift = (numberString) => {
|
396
|
-
const preDecimal = digitsPreDecimalCount(numberString);
|
397
|
-
const postDecimal = (numberString.match(/[.](\d*)/) ?? ['', ''])[1].length;
|
398
|
-
// The shift required to center the decimal point.
|
399
|
-
const toCenter = postDecimal - preDecimal;
|
400
|
-
// toCenter is positive for a left shift (adding more pre-decimals),
|
401
|
-
// so, after applying it,
|
402
|
-
const postShiftPreDecimal = preDecimal + toCenter;
|
403
|
-
// We want the digits before the decimal to have a length at most 4, however.
|
404
|
-
// Thus, right shift until this is the case.
|
405
|
-
const shiftForAtMost5DigitsPreDecimal = 4 - Math.max(postShiftPreDecimal, 4);
|
406
|
-
return toCenter + shiftForAtMost5DigitsPreDecimal;
|
407
|
-
};
|
408
|
-
const addShiftedTranslate = (translate, depth = 0) => {
|
409
|
-
const xString = (0, rounding_1.toRoundedString)(translate.x);
|
410
|
-
const yString = (0, rounding_1.toRoundedString)(translate.y);
|
411
|
-
const xShiftDigits = getShift(xString);
|
412
|
-
const yShiftDigits = getShift(yString);
|
413
|
-
const shift = Vec2_1.Vec2.of(Math.pow(10, xShiftDigits), Math.pow(10, yShiftDigits));
|
414
|
-
const invShift = Vec2_1.Vec2.of(Math.pow(10, -xShiftDigits), Math.pow(10, -yShiftDigits));
|
415
|
-
addScale(invShift);
|
416
|
-
const shiftedTranslate = translate.scale(shift);
|
417
|
-
const roundedShiftedTranslate = Vec2_1.Vec2.of(Math.floor(shiftedTranslate.x), Math.floor(shiftedTranslate.y));
|
418
|
-
addTranslate(roundedShiftedTranslate);
|
419
|
-
// Don't recurse more than 3 times -- the more times we recurse, the more
|
420
|
-
// the scaling is influenced by error.
|
421
|
-
if (!roundedShiftedTranslate.eq(shiftedTranslate) && depth < 3) {
|
422
|
-
addShiftedTranslate(shiftedTranslate.minus(roundedShiftedTranslate), depth + 1);
|
423
|
-
}
|
424
|
-
addScale(shift);
|
425
|
-
return translate;
|
426
|
-
};
|
427
|
-
const adjustTransformFromScale = () => {
|
428
|
-
if (lastScale) {
|
429
|
-
const scaledTransform = transform.rightMul(Mat33.scaling2D(lastScale));
|
430
|
-
// If adding the scale to the transform leads to large values, avoid
|
431
|
-
// doing this.
|
432
|
-
if (scaledTransform.maximumEntryMagnitude() < 1e12) {
|
433
|
-
transforms.pop();
|
434
|
-
transform = transform.rightMul(Mat33.scaling2D(lastScale));
|
435
|
-
lastScale = null;
|
436
|
-
}
|
437
|
-
}
|
438
|
-
};
|
439
|
-
addShiftedTranslate(translation);
|
440
|
-
adjustTransformFromScale();
|
441
|
-
if (!transform.eq(Mat33.identity)) {
|
442
|
-
transforms.push(transform.toCSSMatrix());
|
443
|
-
}
|
444
|
-
return transforms.join(' ');
|
445
|
-
}
|
446
328
|
/**
|
447
329
|
* Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33.
|
448
330
|
*
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/dist/mjs/Mat33.d.ts
CHANGED
@@ -130,22 +130,9 @@ export declare class Mat33 {
|
|
130
130
|
/**
|
131
131
|
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
132
132
|
*
|
133
|
-
* @see {@link fromCSSMatrix}
|
133
|
+
* @see {@link fromCSSMatrix}
|
134
134
|
*/
|
135
135
|
toCSSMatrix(): string;
|
136
|
-
/**
|
137
|
-
* @beta May change or even be removed between minor releases.
|
138
|
-
*
|
139
|
-
* Converts this matrix into a list of CSS transforms that attempt to preserve
|
140
|
-
* this matrix's translation.
|
141
|
-
*
|
142
|
-
* In Chrome/Firefox, translation attributes only support 6 digits (likely an artifact
|
143
|
-
* of using lower-precision floating point numbers). This works around
|
144
|
-
* that by expanding this matrix into the product of several CSS transforms.
|
145
|
-
*
|
146
|
-
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
147
|
-
*/
|
148
|
-
toSafeCSSTransformList(): string;
|
149
136
|
/**
|
150
137
|
* Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33.
|
151
138
|
*
|
package/dist/mjs/Mat33.mjs
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Vec2 } from './Vec2.mjs';
|
2
2
|
import Vec3 from './Vec3.mjs';
|
3
|
-
import { toRoundedString } from './rounding.mjs';
|
4
3
|
/**
|
5
4
|
* Represents a three dimensional linear transformation or
|
6
5
|
* a two-dimensional affine transformation. (An affine transformation scales/rotates/shears
|
@@ -315,128 +314,11 @@ export class Mat33 {
|
|
315
314
|
/**
|
316
315
|
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
317
316
|
*
|
318
|
-
* @see {@link fromCSSMatrix}
|
317
|
+
* @see {@link fromCSSMatrix}
|
319
318
|
*/
|
320
319
|
toCSSMatrix() {
|
321
320
|
return `matrix(${this.a1},${this.b1},${this.a2},${this.b2},${this.a3},${this.b3})`;
|
322
321
|
}
|
323
|
-
/**
|
324
|
-
* @beta May change or even be removed between minor releases.
|
325
|
-
*
|
326
|
-
* Converts this matrix into a list of CSS transforms that attempt to preserve
|
327
|
-
* this matrix's translation.
|
328
|
-
*
|
329
|
-
* In Chrome/Firefox, translation attributes only support 6 digits (likely an artifact
|
330
|
-
* of using lower-precision floating point numbers). This works around
|
331
|
-
* that by expanding this matrix into the product of several CSS transforms.
|
332
|
-
*
|
333
|
-
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
334
|
-
*/
|
335
|
-
toSafeCSSTransformList() {
|
336
|
-
// Check whether it's safe to return just the CSS matrix
|
337
|
-
const translation = Vec2.of(this.a3, this.b3);
|
338
|
-
const translationRoundedX = toRoundedString(translation.x);
|
339
|
-
const translationRoundedY = toRoundedString(translation.y);
|
340
|
-
const nonDigitsRegex = /[^0-9]+/g;
|
341
|
-
const translationXDigits = translationRoundedX.replace(nonDigitsRegex, '').length;
|
342
|
-
const translationYDigits = translationRoundedY.replace(nonDigitsRegex, '').length;
|
343
|
-
// Is it safe to just return the default CSS matrix?
|
344
|
-
if (translationXDigits <= 5 && translationYDigits <= 5) {
|
345
|
-
return this.toCSSMatrix();
|
346
|
-
}
|
347
|
-
// Remove the last column (the translation column)
|
348
|
-
let transform = new Mat33(this.a1, this.a2, 0, this.b1, this.b2, 0, 0, 0, 1);
|
349
|
-
const transforms = [];
|
350
|
-
let lastScale = null;
|
351
|
-
// Appends a translate() command to the list of `transforms`.
|
352
|
-
const addTranslate = (translation) => {
|
353
|
-
lastScale = null;
|
354
|
-
if (!translation.eq(Vec2.zero)) {
|
355
|
-
transforms.push(`translate(${toRoundedString(translation.x)}px, ${toRoundedString(translation.y)}px)`);
|
356
|
-
}
|
357
|
-
};
|
358
|
-
// Appends a scale() command to the list of transforms, possibly merging with
|
359
|
-
// the last command, if a scale().
|
360
|
-
const addScale = (scale) => {
|
361
|
-
// Merge with the last scale
|
362
|
-
if (lastScale) {
|
363
|
-
const newScale = lastScale.scale(scale);
|
364
|
-
// Don't merge if the new scale has very large values
|
365
|
-
if (newScale.maximumEntryMagnitude() < 1e7) {
|
366
|
-
const previousCommand = transforms.pop();
|
367
|
-
console.assert(previousCommand.startsWith('scale'), 'Invalid state: Merging scale commands');
|
368
|
-
scale = newScale;
|
369
|
-
}
|
370
|
-
}
|
371
|
-
if (scale.x === scale.y) {
|
372
|
-
transforms.push(`scale(${toRoundedString(scale.x)})`);
|
373
|
-
}
|
374
|
-
else {
|
375
|
-
transforms.push(`scale(${toRoundedString(scale.x)}, ${toRoundedString(scale.y)})`);
|
376
|
-
}
|
377
|
-
lastScale = scale;
|
378
|
-
};
|
379
|
-
// Returns the number of digits before the `.` in the given number string.
|
380
|
-
const digitsPreDecimalCount = (numberString) => {
|
381
|
-
let decimalIndex = numberString.indexOf('.');
|
382
|
-
if (decimalIndex === -1) {
|
383
|
-
decimalIndex = numberString.length;
|
384
|
-
}
|
385
|
-
return numberString.substring(0, decimalIndex).replace(nonDigitsRegex, '').length;
|
386
|
-
};
|
387
|
-
// Returns the number of digits (positive for left shift, negative for right shift)
|
388
|
-
// required to shift the decimal to the middle of the number.
|
389
|
-
const getShift = (numberString) => {
|
390
|
-
const preDecimal = digitsPreDecimalCount(numberString);
|
391
|
-
const postDecimal = (numberString.match(/[.](\d*)/) ?? ['', ''])[1].length;
|
392
|
-
// The shift required to center the decimal point.
|
393
|
-
const toCenter = postDecimal - preDecimal;
|
394
|
-
// toCenter is positive for a left shift (adding more pre-decimals),
|
395
|
-
// so, after applying it,
|
396
|
-
const postShiftPreDecimal = preDecimal + toCenter;
|
397
|
-
// We want the digits before the decimal to have a length at most 4, however.
|
398
|
-
// Thus, right shift until this is the case.
|
399
|
-
const shiftForAtMost5DigitsPreDecimal = 4 - Math.max(postShiftPreDecimal, 4);
|
400
|
-
return toCenter + shiftForAtMost5DigitsPreDecimal;
|
401
|
-
};
|
402
|
-
const addShiftedTranslate = (translate, depth = 0) => {
|
403
|
-
const xString = toRoundedString(translate.x);
|
404
|
-
const yString = toRoundedString(translate.y);
|
405
|
-
const xShiftDigits = getShift(xString);
|
406
|
-
const yShiftDigits = getShift(yString);
|
407
|
-
const shift = Vec2.of(Math.pow(10, xShiftDigits), Math.pow(10, yShiftDigits));
|
408
|
-
const invShift = Vec2.of(Math.pow(10, -xShiftDigits), Math.pow(10, -yShiftDigits));
|
409
|
-
addScale(invShift);
|
410
|
-
const shiftedTranslate = translate.scale(shift);
|
411
|
-
const roundedShiftedTranslate = Vec2.of(Math.floor(shiftedTranslate.x), Math.floor(shiftedTranslate.y));
|
412
|
-
addTranslate(roundedShiftedTranslate);
|
413
|
-
// Don't recurse more than 3 times -- the more times we recurse, the more
|
414
|
-
// the scaling is influenced by error.
|
415
|
-
if (!roundedShiftedTranslate.eq(shiftedTranslate) && depth < 3) {
|
416
|
-
addShiftedTranslate(shiftedTranslate.minus(roundedShiftedTranslate), depth + 1);
|
417
|
-
}
|
418
|
-
addScale(shift);
|
419
|
-
return translate;
|
420
|
-
};
|
421
|
-
const adjustTransformFromScale = () => {
|
422
|
-
if (lastScale) {
|
423
|
-
const scaledTransform = transform.rightMul(Mat33.scaling2D(lastScale));
|
424
|
-
// If adding the scale to the transform leads to large values, avoid
|
425
|
-
// doing this.
|
426
|
-
if (scaledTransform.maximumEntryMagnitude() < 1e12) {
|
427
|
-
transforms.pop();
|
428
|
-
transform = transform.rightMul(Mat33.scaling2D(lastScale));
|
429
|
-
lastScale = null;
|
430
|
-
}
|
431
|
-
}
|
432
|
-
};
|
433
|
-
addShiftedTranslate(translation);
|
434
|
-
adjustTransformFromScale();
|
435
|
-
if (!transform.eq(Mat33.identity)) {
|
436
|
-
transforms.push(transform.toCSSMatrix());
|
437
|
-
}
|
438
|
-
return transforms.join(' ');
|
439
|
-
}
|
440
322
|
/**
|
441
323
|
* Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33.
|
442
324
|
*
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@js-draw/math",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.6.0",
|
4
4
|
"description": "A math library for js-draw. ",
|
5
5
|
"types": "./dist/mjs/lib.d.ts",
|
6
6
|
"main": "./dist/cjs/lib.js",
|
@@ -28,7 +28,7 @@
|
|
28
28
|
"bezier-js": "6.1.3"
|
29
29
|
},
|
30
30
|
"devDependencies": {
|
31
|
-
"@js-draw/build-tool": "^1.0
|
31
|
+
"@js-draw/build-tool": "^1.4.0",
|
32
32
|
"@types/bezier-js": "4.1.0",
|
33
33
|
"@types/jest": "29.5.3",
|
34
34
|
"@types/jsdom": "21.1.1"
|
@@ -45,5 +45,5 @@
|
|
45
45
|
"svg",
|
46
46
|
"math"
|
47
47
|
],
|
48
|
-
"gitHead": "
|
48
|
+
"gitHead": "c2278b6819ca0e464e4e7d2c3c2045e3394b1fe8"
|
49
49
|
}
|
package/src/Mat33.ts
CHANGED
@@ -423,7 +423,7 @@ export class Mat33 {
|
|
423
423
|
/**
|
424
424
|
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`.
|
425
425
|
*
|
426
|
-
* @see {@link fromCSSMatrix}
|
426
|
+
* @see {@link fromCSSMatrix}
|
427
427
|
*/
|
428
428
|
public toCSSMatrix(): string {
|
429
429
|
return `matrix(${this.a1},${this.b1},${this.a2},${this.b2},${this.a3},${this.b3})`;
|