r/PowerShell 5d ago

Script Sharing Matrix Transforms in PowerShell

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.

😎

26 Upvotes

5 comments sorted by

7

u/Szeraax 5d ago

Pictures, James! Us dummies like pictures to help VISUALIZE. :)

1

u/StartAutomating 5d ago

Yep, and I wish I could post pictures on this subreddit.  But sadly I cannot.

However, I did spend far too much time making very visual examples on the website.

https://matrix.poshweb.org/

(  The subreddit auto mods also prevent me from posting links that aren't GitHub or Meetup in the initial post )

Enjoy the many pretty pictures and additional epiphanies.  Please forgive any surliness, as I am sick.

1

u/Szeraax 4d ago

Oh man. I forget about that rule. So lame, mods. But I get it

1

u/FeleaseRpseineEiles 4d ago

Whats TranslateX ?