-
-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add decompose function #2
Comments
Hi Chrvadala, are you still working on this? I saw that https://www.npmjs.com/package/transformation-matrix-js is deprecated, and I'm looking into an alternative, but we do need the decompose function. |
This is great feature that I'd like to have, but actually I don't have enough time to work on it. |
Hi @peebeebee, do you have some progress on this? |
No, I’d normally do it during my work hours, since it’s work related, but we’ve found a way around the problem sadly.
Still on my to-do list though!
… On 13 Jan 2019, at 23:33, Christian ***@***.***> wrote:
Hi @peebeebee <https://github.com/peebeebee>, do you have some progress on this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub <#2 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAIRVJ9EAHeMngwQ2zmE3kiPbLxurwjJks5vC7Q4gaJpZM4MI5If>.
|
you’re right, are you open to submit a PR? |
We've been using the export interface Transform {
readonly translate: Point;
readonly rotation: number;
readonly scale: Vector;
}
export class Transform {
static toMatrix(transform: Transform): Matrix {
return matrix.compose(
matrix.translate(transform.translate.x, transform.translate.y),
matrix.rotate(transform.rotation),
matrix.scale(transform.scale.x, transform.scale.y));
}
}
/**
* Decompose a matrix into rigid transform components (i.e. translate, rotation and scale).
* Note unlike SlideTransform, scale contains flip, so its components can be negative.
* @param m
*/
export function decompose(m: Matrix, horizontalFlip = false, verticalFlip = false): Transform {
// Remove flip from the matrix first - flip could be incorrectly interpreted as
// rotations (e.g. h-flip + v-flip = rotate by 180 degrees).
if (horizontalFlip) {
if (verticalFlip) {
m = matrix.compose(m, matrix.scale(-1, -1));
} else {
m = matrix.compose(m, matrix.scale(-1, 1));
}
} else if (verticalFlip) {
m = matrix.compose(m, matrix.scale(1, -1));
}
const a = m.a, b = m.b;
const c = m.c, d = m.d;
let scaleX: number, scaleY: number, rotation: number;
if (a !== 0 || c !== 0) {
const hypotAc = Math.hypot(a, c);
scaleX = hypotAc;
scaleY = (a * d - b * c) / hypotAc;
const acos = Math.acos(a / hypotAc);
rotation = c > 0 ? -acos : acos;
} else if (b !== 0 || d !== 0) {
const hypotBd = Math.hypot(b, d);
scaleX = (a * d - b * c) / hypotBd;
scaleY = hypotBd;
const acos = Math.acos(b / hypotBd);
rotation = Math.PI / 2 + (d > 0 ? -acos : acos);
} else {
scaleX = 0;
scaleY = 0;
rotation = 0;
}
// put the flip factors back
if (horizontalFlip) {
scaleX = -scaleX;
}
if (verticalFlip) {
scaleY = -scaleY;
}
return {
translate: { x: m.e, y: m.f },
rotation: rotation,
scale: { x: scaleX, y: scaleY }
}
} Feel free to use it in your code. |
That is fantastic! It should close this old issue 🙂 |
I think we've referenced several posts on Stack Overflow and Mathematics Stack Exchange, and a few other implementations in other libraries (it's ridiculous that it takes so much effort to make such a primitive algorithm work!); and with something homebrew (mostly the flip removing part). I'd be happy to submit a PR, but what's the code of conduct of tests here? We didn't write any test for this function, it just worked well in our production environment. |
I know, this algorithm is really tricky and it is important that it covers all the cases. This is why I asked you about some algorithm references. Unfortunately there are some algorithm that covers just a subset of transformation matrices. Regarding the tests I think that it will be really useful to create some matrices (leveraging on the other functions available in this library) and verify that they are "decomposable". We have to test both primitive matrices (e.g. translate) and composed matrices (e.g. translate+scale+rotate) examples const matrix = translate(42, 42)
expect(decompose(matrix)).toEqual({
translate: { tx: 20, y: 20 },
rotation: 0,
scale: { x: 1, y: 1 }
}) Just one note about the returned object. In order to keep consistency with https://github.com/chrvadala/transformation-matrix#fromdefinitiondefinitionorarrayofdefinition--arraymatrix signature, can I suggest the following alternative signature? What do you think? {
translate: { tx: 0, ty: 0 },
rotation: { angle: 0 },
scale: { sx: 1, sy: 1 }
} |
I‘m totally OK with the alternative signature, in our case we are just reusing some existing structs. I'll see what I can do with then PR when I can catch some time. |
I've created PR #88. |
Released with v2.10.0 |
No description provided.
The text was updated successfully, but these errors were encountered: