Skip to content

Instantly share code, notes, and snippets.

@duhaime
Created July 6, 2016 19:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save duhaime/6195b082ac5fd34a0112c7e7b391baf7 to your computer and use it in GitHub Desktop.
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
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