Home > Back-end >  3D-Coordinate Transformation in C#
3D-Coordinate Transformation in C#

Time:12-01

What is the Goal?: I want to know the new Coordinates of a point after rotating the 3D-Object (Cuboid), around the anchorpoint (x,y & z) on the opposite side.

What i did: I tried to calculate the position with the following function. I had to convert doubles to floats , because of the Autodesk Inventor API. Note: Vector is the difference from the origin /anchorpoint to the designated point.

Vector3 coordinateTransformation(Vector3 vector, float r_x, float r_y, float r_z, Vector3 origin)
        {
            vector.X = vector.X;  //Just for demonstration
            vector.Y = vector.Y * Convert.ToSingle(Math.Cos(DegreesToRadians(r_x))) - vector.Z * Convert.ToSingle(Math.Sin(DegreesToRadians(r_x)));
            vector.Z = vector.Y * Convert.ToSingle(Math.Sin(DegreesToRadians(r_x)))   vector.Z * Convert.ToSingle(Math.Cos(DegreesToRadians(r_x)));
            
            vector.X = vector.X * Convert.ToSingle(Math.Cos(DegreesToRadians(r_y)))   vector.Z * Convert.ToSingle(Math.Sin(DegreesToRadians(r_y)));
            vector.Y = vector.Y;  //Just for demonstration
            vector.Z = vector.Z * Convert.ToSingle(Math.Cos(DegreesToRadians(r_y))) - vector.X * Convert.ToSingle(Math.Sin(DegreesToRadians(r_y)));
            
            vector.X = vector.X * Convert.ToSingle(Math.Cos(DegreesToRadians(r_z))) - vector.Y * Convert.ToSingle(Math.Sin(DegreesToRadians(r_z)));
            vector.Y = vector.X * Convert.ToSingle(Math.Sin(DegreesToRadians(r_z)))   vector.Y * Convert.ToSingle(Math.Cos(DegreesToRadians(r_z)));
            vector.Z = vector.Z;  //Just for demonstration

            vector.X = Math.Abs(vector.X)   origin.X;
            vector.Y = Math.Abs(vector.Y)   origin.Y;
            vector.Z = Math.Abs(vector.Z)   origin.Z;
            
            return vector;
        }

Somehow the object does not get placed on the correct place.

Next step: On the internet i found a website which does the correct transformation.Casio Website If i manually set vector to the calculated point on the website, everything else works fine. So i somehow have to get the exact same calculation into my code.

If you need further information, feel free to comment!

CodePudding user response:

Do not mess around with vectors and angled by hand. Use some library for your vector functions and use matrices to do your transformations. For example System.Numerics or Math.Net.Numerics.

Assuming you have an euler angle to start with you can use CreateFromYawPitchRoll to create your rotation matrix. If you want to rotate around a specific point you just subtract your rotation center from all your points, apply the rotation and move the points back. This can all be done by just multiplying the transformation matrices:

var totalTransform = Matrix4x4.CreateTranslation(-rotationCenter) *
                    Matrix4x4.CreateFromYawPitchRoll(yawInRadians, pitchInRadians, rollInRadians) *
                    Matrix4x4.CreateTranslation(rotationCenter);

to apply the resulting transform you just call Vector3.Transform to produce a new, transformed vector.

This will all be a bit easier if you have some introduction to linear algebra. It is also common to do things like applying the transforms in the wrong order or something, and sometimes it is easiest to just try some different things until you get it right. I would also note that rotations are just hard to understand. I tend to prefer quaternions over eutler angles, not because the math is easier to understand, but since there are methods like CreateFromAxisAngle, that I can understand.

CodePudding user response:

When you apply rotation to a vector manually, you'd need to update all the components (X, Y and Z) at once as follows.

Vector3 coordinateTransformation(Vector3 vector, float r_x, float r_y, float r_z, Vector3 origin)
{

    // In the rotation around X axis below, `Y relies on Z` and `Z relies on Y`. So both must be updated simultaneously. 
    vector = new Vector3(
        vector.X,
        vector.Y * Convert.ToSingle(Math.Cos(DegreesToRadians(r_x))) - vector.Z * Convert.ToSingle(Math.Sin(DegreesToRadians(r_x))),
        vector.Y * Convert.ToSingle(Math.Sin(DegreesToRadians(r_x)))   vector.Z * Convert.ToSingle(Math.Cos(DegreesToRadians(r_x)))
    );

    vector = new Vector3(
        vector.X * Convert.ToSingle(Math.Cos(DegreesToRadians(r_y)))   vector.Z * Convert.ToSingle(Math.Sin(DegreesToRadians(r_y))),
        vector.Y,
        vector.Z * Convert.ToSingle(Math.Cos(DegreesToRadians(r_y))) - vector.X * Convert.ToSingle(Math.Sin(DegreesToRadians(r_y)))
    );

    vector = new Vector3(
        vector.X * Convert.ToSingle(Math.Cos(DegreesToRadians(r_z))) - vector.Y * Convert.ToSingle(Math.Sin(DegreesToRadians(r_z))),
        vector.X * Convert.ToSingle(Math.Sin(DegreesToRadians(r_z)))   vector.Y * Convert.ToSingle(Math.Cos(DegreesToRadians(r_z))),
        vector.Z
    );

    vector.X = Math.Abs(vector.X)   origin.X;
    vector.Y = Math.Abs(vector.Y)   origin.Y;
    vector.Z = Math.Abs(vector.Z)   origin.Z;

    return vector;
}

Appendix A: Use of Matrix4x4

As @JonasH suggests, it's a good idea to use reliable libraries, if there are.

Since, row-vectors are used in the .NET world (while your implementation is based on column-vectors), X->Y->Z rotations can be written by straightforward matrices multiplications as follows.

Vector3 coordinateTransformation(Vector3 vector, float r_x, float r_y, float r_z, Vector3 origin)
{

    var mat = Matrix4x4.CreateRotationX(DegreesToRadians(r_x))
        * Matrix4x4.CreateRotationY(DegreesToRadians(r_y))
        * Matrix4x4.CreateRotationZ(DegreesToRadians(r_z));

    vector = Vector3.Transform(vector, mat);
    
    vector.X = Math.Abs(vector.X)   origin.X;
    vector.Y = Math.Abs(vector.Y)   origin.Y;
    vector.Z = Math.Abs(vector.Z)   origin.Z;

    return vector;
}

Appendix B: Use of Matrix4x4.CreateFromYawPitchRoll

CreateFromYawPitchRoll yields a matrix to apply rotations in Z->Y->X order, which is different from the order X->Y->Z. Therefore, if you'd like to manage to use CreateFromYawPitchRoll, you would need to re-map axes.

Vector3 coordinateTransformation(Vector3 vector, float r_x, float r_y, float r_z, Vector3 origin)
{
    var mat = Matrix4x4.CreateFromYawPitchRoll(
        (float)DegreesToRadians(r_z), 
        (float)DegreesToRadians(r_y),
        (float)DegreesToRadians(r_x)
    );
    var matRemap = Matrix4x4.CreateFromAxisAngle(Vector3.Normalize(new Vector3(1, 1, 1)), (float)DegreesToRadians(-120));

    mat = matRemap * mat * Matrix4x4.Transpose(matRemap);

    vector = Vector3.Transform(vector, mat);
    
    vector.X = Math.Abs(vector.X)   origin.X;
    vector.Y = Math.Abs(vector.Y)   origin.Y;
    vector.Z = Math.Abs(vector.Z)   origin.Z;

    return vector;
}
  • Related