Created
July 6, 2016 19:51
-
-
Save duhaime/6195b082ac5fd34a0112c7e7b391baf7 to your computer and use it in GitHub Desktop.
Matrix Transform Gist: calculates the X matrix for AX = B linear algebra equation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
""" | |
This script identifies a transform matrix X such that | |
one can determine how to perform a css matrix translation | |
to map one div's coordinates to those of another. | |
A fiddle demonstrating the input div, output div, | |
and a transformation that maps the input to the output | |
may be found here: https://jsfiddle.net/dduhaime/9444Lnjp/ | |
The script below provides the values to populate the transform property | |
of that fiddle. | |
In this script the x and y values denote the pixel coordinates | |
of the div to be transformed. Specifically: | |
x0, y0 denote the x,y coordinates of the top-left hand corner position | |
x1, y1 denote the x,y coordinates of the bottom-left hand corner position | |
x2, y2 denote the x,y coordinates of the top-right hand corner position | |
x3, y3 denote the x,y coordinates of the bottom-right hand corner position | |
Likewise, the u and v values denote the pixel coordinates | |
of the div into which the original div should be transposed. | |
Just as above: | |
u0, v0 denote the x,y coordinates of the top-left hand corner position | |
u1, v1 denote the x,y coordinates of the bottom-left hand corner position | |
u2, v2 denote the x,y coordinates of the top-right hand corner position | |
u3, v3 denote the x,y coordinates of the bottom-right hand corner position | |
Output from the script has the following form: | |
[2.000000 0.000000 -0.000000 0.000000 2.000000 -0.000000 0.000000 0.000000] | |
Treating these values as h0, h1, ... h7, we can construct the following 3 x 3 matrix: | |
[[h0, h1, h2], | |
[h3, h4, h5], | |
[h6, h7, h8]] | |
where h8 = 1. | |
To interpolate these values into a 3d matrix, we can make | |
the z index values map back to themselves: | |
[[h0, h1, 0, h2], | |
[h3, h4, 0, h5], | |
[0, 0, 1, 0 ], | |
[h6, h7, 0, h8]] | |
Finally, we can use these values in a css | |
transform to make an input div's dimensions map | |
perfectly to an output div's dimensions. To do so, | |
one must arrange the values in column-major order: | |
[h0, h3, 0, h6, h1, h4, 0, h7, 0, 0, 1, 0, h2, h5, 0, h8] | |
These values can be specified in the css transorm as follows: | |
transform: matrix3d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); | |
One must also remember to set the transform-origin to specify | |
the position of the 0, 0 position within the coordinate space. | |
Because the div to be transformed in this simple example sits | |
at 50px, 50px, the fiddle uses: | |
transform-origin: -50px -50px; | |
""" | |
x0 = 50 | |
x1 = 50 | |
x2 = 100 | |
x3 = 100 | |
y0 = 50 | |
y1 = 100 | |
y2 = 50 | |
y3 = 100 | |
u0 = 100 | |
u1 = 100 | |
u2 = 200 | |
u3 = 200 | |
v0 = 100 | |
v1 = 200 | |
v2 = 100 | |
v3 = 200 | |
matrixa = np.array([ [x0, y0, 1, 0, 0, 0, -1 * u0 * x0, -1 * u0 * y0], | |
[0, 0, 0, x0, y0, 1, -1 * v0 * x0, -1 * v0 * y0], | |
[x1, y1, 1, 0, 0, 0, -1 * u1 * x1, -1 * u1 * y1], | |
[0, 0, 0, x1, y1, 1, -1 * v1 * x1, -1 * v1 * y1], | |
[x2, y2, 1, 0, 0, 0, -1 * u2 * x2, -1 * u2 * y2], | |
[0, 0, 0, x2, y2, 1, -1 * v2 * x2, -1 * v2 * y2], | |
[x3, y3, 1, 0, 0, 0, -1 * u3 * x3, -1 * u3 * y3], | |
[0, 0, 0, x3, y3, 1, -1 * v3 * x3, -1 * v3 * y3] ]) | |
matrixb = np.array([ u0, v0, u1, v1, u2, v2, u3, v3]) | |
x = np.linalg.solve(matrixa, matrixb) | |
# use decimal notation for output | |
np.set_printoptions(formatter={'float_kind':'{:f}'.format}) | |
print x | |
# validate that the dot product of ax = b | |
print np.allclose(np.dot(matrixa, x), matrixb) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment