Transforming points

Hi guys, please help me! I have a Transform2D structure with position and rotation. I can multiply one Transform2D by another Transform2D (this one is like from local coordinates to world coordinates). How do I do the opposite? I know how it works with matrices, it is necessary to multiply the inverted matrix A by B. I tried to do this, but I don’t know how to return the invert angle in radiants


        public float PositionX;
        public float PositionY;
        public float ScaleX;
        public float ScaleY;
        public float Rotation;

        public static Transform2D operator *(Transform2D a, Transform2D b)
        {
            float sin = (float)Math.Sin(b.Rotation);
            float cos = (float)Math.Cos(b.Rotation);
            var positionX = (cos * a.PositionX - sin * a.PositionY) * b.ScaleX;
            var positionY = (sin * a.PositionX - cos * a.PositionY) * b.ScaleY;

            return new Transform2D(positionX + b.PositionX, positionY + b.PositionY, 
                       a.ScaleX * b.ScaleX, a.ScaleY * b.ScaleY, a.Rotation + b.Rotation);
        }

        public static Transform2D operator /(Transform2D a, Transform2D b)
        {
               // what do?
        }

Hey are you just wanting to convert an angle to radians? Is so, here is an example:

Example, convert 145 degrees to radians

145 degrees → to convert it to radians:
Solution → Multiply by (Pi/180 degrees)

We have:
(145) Pi
----- * –
180 1

Which is the same as :
(145) * Pi
----------
180

Which gives :
(145) * 3.1415

  180

And the result is approximately 2.53 Radians

public class Transform2D
{
    public float PositionX;
    public float PositionY;
    public float ScaleX;
    public float ScaleY;
    public float Rotation;

    public Transform2D(float positionX, float positionY, float scaleX, float scaleY, float rotation)
    {
        PositionX = positionX;
        PositionY = positionY;
        ScaleX = scaleX;
        ScaleY = scaleY;
        Rotation = rotation;
    }

    public static Transform2D operator *(Transform2D a, Transform2D b)
    {
        var preRotatedX = a.PositionX * b.ScaleX; // usually scale before rotating otherwise scaleX affects X & Y 
        var preRotatedY = a.PositionY * b.ScaleY;
        float sin = (float)Math.Sin(b.Rotation);
        float cos = (float)Math.Cos(b.Rotation);
        var positionX = (cos * preRotatedX - sin * preRotatedY);
        var positionY = (sin * preRotatedX + cos * preRotatedY); // this should be add not subtract

        return new Transform2D(positionX + b.PositionX, positionY + b.PositionY,
            a.ScaleX * b.ScaleX, a.ScaleY * b.ScaleY, a.Rotation + b.Rotation);
    }

    public static Transform2D operator /(Transform2D a, Transform2D b)
    {
        // what do?
        //         do what
        //         is above in reverse order
        var preRotatedX = (a.PositionX - b.PositionX); // reverse translation
        var preRotatedY = (a.PositionY - b.PositionY);
        float sin = (float)Math.Sin(-b.Rotation);
        float cos = (float)Math.Cos(-b.Rotation);
        var positionX = (cos * preRotatedX - sin * preRotatedY) / b.ScaleX; // reverse rotation then scale
        var positionY = (sin * preRotatedX + cos * preRotatedY) / b.ScaleY;

        return new Transform2D(positionX, positionY,
            a.ScaleX / b.ScaleX, a.ScaleY / b.ScaleY, a.Rotation - b.Rotation);
    }

    public static void OtherOptionsWithTests()
    {
        // Change These Values To Test
        float PositionX1 = -50.0f;
        float PositionY1 = 10.0f;
        float ScaleX1 = 5.0f;
        float ScaleY1 = 25.0f;
        float Rotation1 = MathHelper.ToRadians(-15f);

        float PositionX2 = -500.0f;
        float PositionY2 = 600.0f;
        float ScaleX2 = 75.0f;
        float ScaleY2 = 10.0f;
        float Rotation2 = MathHelper.ToRadians(135f);

        // Option 1) Transform2D
        Transform2D transformA = new Transform2D(PositionX1, PositionY1, ScaleX1, ScaleY1, Rotation1);
        Transform2D transformB = new Transform2D(PositionX2, PositionY2, ScaleX2, ScaleY2, Rotation2);
        Transform2D transformC = transformA * transformB;
        Transform2D transformBackToA = transformC / transformB;

        // Option 2) Standard Matrix But Use Z-Axis For Rotation As Shown In Image
        // (Tried to make a cross-eyed 3d stereogram for fun but something doesn't look quite right with it)
        Matrix matrixA = Matrix.CreateScale(new Vector3(ScaleX1, ScaleY1, 1)) *
            Matrix.CreateRotationZ(Rotation1) *
            Matrix.CreateTranslation(new Vector3(PositionX1, PositionY1, 0));
        Matrix matrixB = Matrix.CreateScale(new Vector3(ScaleX2, ScaleY2, 1)) *
            Matrix.CreateRotationZ(Rotation2) *
            Matrix.CreateTranslation(new Vector3(PositionX2, PositionY2, 0));
        Matrix matrixC = matrixA * matrixB;
        Matrix.Invert(ref matrixB, out Matrix matrixBInverted);
        Matrix matrixBackToA = matrixC * matrixBInverted;

        // Option 3) System.Numerics.Matrix3x2 For 2D Transforms
        System.Numerics.Matrix3x2 matrix3X2A = System.Numerics.Matrix3x2.CreateScale(ScaleX1, ScaleY1) *
            System.Numerics.Matrix3x2.CreateRotation(Rotation1) *
            System.Numerics.Matrix3x2.CreateTranslation(PositionX1, PositionY1);
        System.Numerics.Matrix3x2 matrix3X2B = System.Numerics.Matrix3x2.CreateScale(ScaleX2, ScaleY2) *
            System.Numerics.Matrix3x2.CreateRotation(Rotation2) *
            System.Numerics.Matrix3x2.CreateTranslation(PositionX2, PositionY2);
        System.Numerics.Matrix3x2 matrix3X2C = matrix3X2A * matrix3X2B;
        System.Numerics.Matrix3x2.Invert(matrix3X2B, out System.Numerics.Matrix3x2 matrix3X2BInverted);
        System.Numerics.Matrix3x2 matrix3X2BackToA = matrix3X2C * matrix3X2BInverted;

        // Check Values Are Correct By Adding A Breakpoint
        Vector2 transform2DTranslationC = new Vector2(transformC.PositionX, transformC.PositionY);
        Vector2 matrixTranslationC = new Vector2(matrixC.Translation.X, matrixC.Translation.Y);
        Vector2 matrix3X2TranslationC = new Vector2(matrix3X2C.Translation.X, matrix3X2C.Translation.Y);

        Vector2 transform2DTranslationBackToA = new Vector2(transformBackToA.PositionX, transformBackToA.PositionY);
        Vector2 matrixTranslationBackToA = new Vector2(matrixBackToA.Translation.X, matrixBackToA.Translation.Y);
        Vector2 matrix3X2TranslationBackToA = new Vector2(matrix3X2BackToA.Translation.X, matrix3X2BackToA.Translation.Y);
    } // Add Breakpoint here
}

1 Like

Thank you so much for such a detailed answer! This is an invaluable help. Thanks to your answer, I realized that it was necessary to rotate back with a negative rotation

1 Like