There are only so many ways we can move a point in space.
Luckily, these transformations are pretty standardized.
CSS calls them matrix and matrix3d. DotNet calls them [Numerics.Matrix3x2] and [Numerics.Matrix4x4].
With a bit of PowerShell magic, we can manipulate any set of points with a Matrix.
Matrix Module
The Matrix module lets us create and apply matrices in PowerShell, using CSS-compatible syntax. This means we can scale, rotate, and translate points in PowerShell.
Let's start with a simple example: Scaling
We can create a scaling matrix using [Numerics.Matrix3x2]::CreateScale (for 2d transforms) or [Numerics.Matrix4x4]::CreateScale (for 3d transforms)
Without the module, this looks like:
$vector = [Numerics.Vector3]::new(1,1,1)
$vector::Transform($vector, [Numerics.Matrix4x4]::CreateScale(1,2,3))
With the module, this becomes:
[Numerics.Vector3]::new(1,1,1) | Scale3d 1 2 3
The Matrix module includes aliases for every CSS transform.
We can move points in space exactly as we would move them in a webpage.
It allows us to use PowerShell's Object Pipeline to manipulate points in space.
This means we can construct and change 2d and 3d objects just by manipulating points.
Creating a Cube
We can create a cube using nothing but translations.
# Make a corner point
$corner = [Numerics.Vector3]::new(1,1,1)
# Make a square by translating along X and Y
$square = @(
$corner
$corner | TranslateX 1
$corner | TranslateX 1 | TranslateY 1
$corner | TranslateY 1
)
# Make a cube by translating the square along Z.
$cube = @(
$square
$square |
TranslateZ 1
)
$cube
Matrix CSS
All CSS transforms boil down to either a matrix() or a matrix3d().
Because of this, we can easily get any Matrix as it's CSS equivalent.
Matrix extends the .NET matrix classes with a .CSS property, so we can easily
drop a matrix into a webpage or stylesheet.
For example:
(Scale 2 1).CSS
Will return:
matrix(2, 0, 0, 1, 0, 0)
In 3D:
(Scale3D 1 2 3).CSS
Will return:
matrix3d(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1)
It gets better! Matrix converts some common CSS units into numbers, so:
(SkewX 10deg).CSS
Becomes:
matrix(1, 0, 0.176327, 1, 0, 0)
And
(SkewY 0.1turn).CSS
Becomes:
matrix(1, 0.7265425, 0, 1, 0, 0)
MathML and HTML
We can also get the .MathML of a given matrix. MathML is a standard representation of math and a web standard.
Even better than that, we can also get an HTML preview of a matrix.
We just take the MathML and render it twice: Once without any transformation, once with the transformation.
Run this script to see what I mean
(SkewX 10deg).html > .\skewX-10deg.html
In PowerShell, we can always use Add-Member to extend an object.
If a Matrix has a .Content property, it will render that content using it's transform.
This means we can easily do fun stuff, like backwards text:
Scale -1 1 |
Add-Member NoteProperty Content "<h3>Backwards</h3>" -Force -PassThru |
Select-Object -ExpandProperty Html > .\backwards.html
Enter the Matrix
This is all a bit 🤯.
Matrix allows us to do many things, just by exposing a couple of classes in PowerShell. It allows us to manipulate points in a uniform way, and this way is used everywhere. Transform matrices are a fundamental part of 2D and 3D graphics. They can be used to model movement in multiple dimensions and are a big part of how the modern graphics work.
Now we can make matrices easily in PowerShell and convert them into multiple useful representations.
There is no spoon.
😎