@js-draw/math 1.3.1 → 1.6.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.
@@ -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} and {@link toSafeCSSTransformList}
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} and {@link toSafeCSSTransformList}
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 {};
@@ -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} and {@link toSafeCSSTransformList}
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
  *
@@ -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} and {@link toSafeCSSTransformList}
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.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.2",
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": "65af7ec944f70b69b2a4b07d98e5bb92eeeca029"
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} and {@link toSafeCSSTransformList}
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})`;