@js-draw/math
Advanced tools
Comparing version 1.3.1 to 1.4.0
@@ -137,15 +137,2 @@ import { Point2, Vec2 } from './Vec2'; | ||
/** | ||
* @beta May change or even be removed between minor releases. | ||
* | ||
* Converts this matrix into a list of CSS transforms that attempt to preserve | ||
* this matrix's translation. | ||
* | ||
* In Chrome/Firefox, translation attributes only support 6 digits (likely an artifact | ||
* of using lower-precision floating point numbers). This works around | ||
* that by expanding this matrix into the product of several CSS transforms. | ||
* | ||
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`. | ||
*/ | ||
toSafeCSSTransformList(): string; | ||
/** | ||
* Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33. | ||
@@ -152,0 +139,0 @@ * |
@@ -9,3 +9,2 @@ "use strict"; | ||
const Vec3_1 = __importDefault(require("./Vec3")); | ||
const rounding_1 = require("./rounding"); | ||
/** | ||
@@ -331,119 +330,2 @@ * Represents a three dimensional linear transformation or | ||
/** | ||
* @beta May change or even be removed between minor releases. | ||
* | ||
* Converts this matrix into a list of CSS transforms that attempt to preserve | ||
* this matrix's translation. | ||
* | ||
* In Chrome/Firefox, translation attributes only support 6 digits (likely an artifact | ||
* of using lower-precision floating point numbers). This works around | ||
* that by expanding this matrix into the product of several CSS transforms. | ||
* | ||
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`. | ||
*/ | ||
toSafeCSSTransformList() { | ||
// Check whether it's safe to return just the CSS matrix | ||
const translation = Vec2_1.Vec2.of(this.a3, this.b3); | ||
const translationRoundedX = (0, rounding_1.toRoundedString)(translation.x); | ||
const translationRoundedY = (0, rounding_1.toRoundedString)(translation.y); | ||
const nonDigitsRegex = /[^0-9]+/g; | ||
const translationXDigits = translationRoundedX.replace(nonDigitsRegex, '').length; | ||
const translationYDigits = translationRoundedY.replace(nonDigitsRegex, '').length; | ||
// Is it safe to just return the default CSS matrix? | ||
if (translationXDigits <= 5 && translationYDigits <= 5) { | ||
return this.toCSSMatrix(); | ||
} | ||
// Remove the last column (the translation column) | ||
let transform = new Mat33(this.a1, this.a2, 0, this.b1, this.b2, 0, 0, 0, 1); | ||
const transforms = []; | ||
let lastScale = null; | ||
// Appends a translate() command to the list of `transforms`. | ||
const addTranslate = (translation) => { | ||
lastScale = null; | ||
if (!translation.eq(Vec2_1.Vec2.zero)) { | ||
transforms.push(`translate(${(0, rounding_1.toRoundedString)(translation.x)}px, ${(0, rounding_1.toRoundedString)(translation.y)}px)`); | ||
} | ||
}; | ||
// Appends a scale() command to the list of transforms, possibly merging with | ||
// the last command, if a scale(). | ||
const addScale = (scale) => { | ||
// Merge with the last scale | ||
if (lastScale) { | ||
const newScale = lastScale.scale(scale); | ||
// Don't merge if the new scale has very large values | ||
if (newScale.maximumEntryMagnitude() < 1e7) { | ||
const previousCommand = transforms.pop(); | ||
console.assert(previousCommand.startsWith('scale'), 'Invalid state: Merging scale commands'); | ||
scale = newScale; | ||
} | ||
} | ||
if (scale.x === scale.y) { | ||
transforms.push(`scale(${(0, rounding_1.toRoundedString)(scale.x)})`); | ||
} | ||
else { | ||
transforms.push(`scale(${(0, rounding_1.toRoundedString)(scale.x)}, ${(0, rounding_1.toRoundedString)(scale.y)})`); | ||
} | ||
lastScale = scale; | ||
}; | ||
// Returns the number of digits before the `.` in the given number string. | ||
const digitsPreDecimalCount = (numberString) => { | ||
let decimalIndex = numberString.indexOf('.'); | ||
if (decimalIndex === -1) { | ||
decimalIndex = numberString.length; | ||
} | ||
return numberString.substring(0, decimalIndex).replace(nonDigitsRegex, '').length; | ||
}; | ||
// Returns the number of digits (positive for left shift, negative for right shift) | ||
// required to shift the decimal to the middle of the number. | ||
const getShift = (numberString) => { | ||
const preDecimal = digitsPreDecimalCount(numberString); | ||
const postDecimal = (numberString.match(/[.](\d*)/) ?? ['', ''])[1].length; | ||
// The shift required to center the decimal point. | ||
const toCenter = postDecimal - preDecimal; | ||
// toCenter is positive for a left shift (adding more pre-decimals), | ||
// so, after applying it, | ||
const postShiftPreDecimal = preDecimal + toCenter; | ||
// We want the digits before the decimal to have a length at most 4, however. | ||
// Thus, right shift until this is the case. | ||
const shiftForAtMost5DigitsPreDecimal = 4 - Math.max(postShiftPreDecimal, 4); | ||
return toCenter + shiftForAtMost5DigitsPreDecimal; | ||
}; | ||
const addShiftedTranslate = (translate, depth = 0) => { | ||
const xString = (0, rounding_1.toRoundedString)(translate.x); | ||
const yString = (0, rounding_1.toRoundedString)(translate.y); | ||
const xShiftDigits = getShift(xString); | ||
const yShiftDigits = getShift(yString); | ||
const shift = Vec2_1.Vec2.of(Math.pow(10, xShiftDigits), Math.pow(10, yShiftDigits)); | ||
const invShift = Vec2_1.Vec2.of(Math.pow(10, -xShiftDigits), Math.pow(10, -yShiftDigits)); | ||
addScale(invShift); | ||
const shiftedTranslate = translate.scale(shift); | ||
const roundedShiftedTranslate = Vec2_1.Vec2.of(Math.floor(shiftedTranslate.x), Math.floor(shiftedTranslate.y)); | ||
addTranslate(roundedShiftedTranslate); | ||
// Don't recurse more than 3 times -- the more times we recurse, the more | ||
// the scaling is influenced by error. | ||
if (!roundedShiftedTranslate.eq(shiftedTranslate) && depth < 3) { | ||
addShiftedTranslate(shiftedTranslate.minus(roundedShiftedTranslate), depth + 1); | ||
} | ||
addScale(shift); | ||
return translate; | ||
}; | ||
const adjustTransformFromScale = () => { | ||
if (lastScale) { | ||
const scaledTransform = transform.rightMul(Mat33.scaling2D(lastScale)); | ||
// If adding the scale to the transform leads to large values, avoid | ||
// doing this. | ||
if (scaledTransform.maximumEntryMagnitude() < 1e12) { | ||
transforms.pop(); | ||
transform = transform.rightMul(Mat33.scaling2D(lastScale)); | ||
lastScale = null; | ||
} | ||
} | ||
}; | ||
addShiftedTranslate(translation); | ||
adjustTransformFromScale(); | ||
if (!transform.eq(Mat33.identity)) { | ||
transforms.push(transform.toCSSMatrix()); | ||
} | ||
return transforms.join(' '); | ||
} | ||
/** | ||
* Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33. | ||
@@ -450,0 +332,0 @@ * |
@@ -137,15 +137,2 @@ import { Point2, Vec2 } from './Vec2'; | ||
/** | ||
* @beta May change or even be removed between minor releases. | ||
* | ||
* Converts this matrix into a list of CSS transforms that attempt to preserve | ||
* this matrix's translation. | ||
* | ||
* In Chrome/Firefox, translation attributes only support 6 digits (likely an artifact | ||
* of using lower-precision floating point numbers). This works around | ||
* that by expanding this matrix into the product of several CSS transforms. | ||
* | ||
* **Note**: Assumes `this.c1 = this.c2 = 0` and `this.c3 = 1`. | ||
*/ | ||
toSafeCSSTransformList(): string; | ||
/** | ||
* Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33. | ||
@@ -152,0 +139,0 @@ * |
{ | ||
"name": "@js-draw/math", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "A math library for js-draw. ", | ||
@@ -31,3 +31,3 @@ "types": "./dist/mjs/lib.d.ts", | ||
"devDependencies": { | ||
"@js-draw/build-tool": "^1.0.2", | ||
"@js-draw/build-tool": "^1.4.0", | ||
"@types/bezier-js": "4.1.0", | ||
@@ -49,3 +49,3 @@ "@types/jest": "29.5.3", | ||
], | ||
"gitHead": "65af7ec944f70b69b2a4b07d98e5bb92eeeca029" | ||
"gitHead": "b520078c16a4d23d9bed4531eafda87bfce3f6b1" | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
132
451249
12331