Transform.ChangeOfBasis() Is missing an overload?

It seems that Transform.ChangeOfBasis(Pane fromPlane, Plane toPlane) ignores the origin of the planes. The other overload takes basis vector parameters, but no origin params. It would be great if this was added, as I have reached for this function many times:


        private Transform ChangeOfBasis(
            Point3f fromOrigin,
            Vector3f fromX,
            Vector3f fromY,
            Vector3f fromZ,
            Point3f toOrigin,
            Vector3f toX,
            Vector3f toY,
            Vector3f toZ
            ) {
            Transform translateFromOldOrigin = Transform.Translation(Point3d.Origin - fromOrigin);
            Transform changeOfBasis = Transform.ChangeBasis(fromX, fromY, fromZ, toX, toY, toZ);
            Transform translateToNewOrigin = Transform.Translation(toOrigin - Point3d.Origin);
            return translateToNewOrigin * changeOfBasis * translateFromOldOrigin;
        }

Please let me know if Iā€™m missing something.

Also please let me know if I should avoid commentary like this and save this forum for questions.

Best,
Nick

@Nick_Drian - are you sure youā€™re using the right transform?

ā€“ Dale

1 Like

Got it, I guess Iā€™m confused because the constructor of Plane dictates that its x and y vectors dont have to be orthogonal, or unit. This makes if feel like PlaneToPlane should be an affine transformation. Instead it seems to be some sort of orient function.

Anyway, It still seems that the functionality that I provided above is missing from the rhino sdk. I just want to be able to create an affine transformation from one Frame to another (like a change of basis but moving the origin too).

@Nick_Drian - Transform.PlaneToPlane (aka Rotation) is an affine transformation.

ā€“ Dale

I guess I miss spoke. Of course its affine as because all reasonable Rhino.Geometry.Transformā€™s are affine. What I meant is non-linear.

Anyway, It feels like were getting away from my original goal which was to point out a common function that seems to be missing. Its commonly known as a change of frame. It is like a change of basis but with a change of origin too.

Use Transform.PlaneToPlane.

ā€“ Dale

PlaneToPlane is not what Iā€™m looking for. I want to be able to remap all 3 basis vectors and the origin. There is no plane constructor with a third basis vector.

Signing off.

@Nick_Drian - when you sign back on, if you want more help then please some details as to what you are trying to do and why. Often, picture or .3dm files can be helpful.

Thanks,

ā€“ Dale

1 Like

This sounds like you are interested to use shear transformation.

Otherwise to define a plane, a coordinate system, an origin point and 2 vectors are plenty and the 3rd vector is useless, or better, would possibly over-define the plane, creating an impossible situation.

1 Like

Hi @Nick_Drian,

Are you looking for something like this?

/// <summary>
/// Creates a rotational transformation
/// </summary>
/// <param name="P0">Initial frame center</param>
/// <param name="X0">Initial frame X</param>
/// <param name="Y0">Initial frame Y</param>
/// <param name="Z0">Initial frame Z</param>
/// <param name="P1">Final frame center</param>
/// <param name="X1">Final frame X</param>
/// <param name="Y1">Final frame Y</param>
/// <param name="Z1">Final frame Z</param>
/// <returns></returns>
public static Transform TransformRotation(
  Point3d P0,
  Vector3d X0,
  Vector3d Y0,
  Vector3d Z0,
  Point3d P1,
  Vector3d X1,
  Vector3d Y1,
  Vector3d Z1
  )
{
  Transform T0 = Transform.Translation(Point3d.Origin - P0);
  Transform R = Transform.Rotation(X0, Y0, Z0, X1, Y1, Z1);
  Transform T1 = Transform.Translation(P1 - Point3d.Origin);
  return T1 * R * T0;
}

ā€“ Dale

Hi Dale, That Transform.Rotation function states that ā€œThe frames should be right hand orthogonalā€. Which is not what Iā€™m looking for, I want to be able to remap the basis vectors however. Here is a working implementation of the function that I was looking for:

        private static Transform ChangeOfFrame(
            Point3d fromOrigin,
            Vector3d fromX,
            Vector3d fromY,
            Vector3d fromZ,
            Point3d toOrigin,
            Vector3d toX,
            Vector3d toY,
            Vector3d toZ
        ) {

            Transform from = new Transform();
            from.M00 = fromX.X; from.M01 = fromY.X; from.M02 = fromZ.X; from.M03 = fromOrigin.X;
            from.M10 = fromX.Y; from.M11 = fromY.Y; from.M12 = fromZ.Y; from.M13 = fromOrigin.Y;
            from.M20 = fromX.Z; from.M21 = fromY.Z; from.M22 = fromZ.Z; from.M23 = fromOrigin.Z;
            from.M30 = 0; from.M31 = 0; from.M32 = 0; from.M33 = 1;

            Transform to = new Transform();
            to.M00 = toX.X; to.M01 = toY.X; to.M02 = toZ.X; to.M03 = toOrigin.X;
            to.M10 = toX.Y; to.M11 = toY.Y; to.M12 = toZ.Y; to.M13 = toOrigin.Y;
            to.M20 = toX.Z; to.M21 = toY.Z; to.M22 = toZ.Z; to.M23 = toOrigin.Z;
            to.M30 = 0; to.M31 = 0; to.M32 = 0; to.M33 = 1;

            Transform fromInverted;
            from.TryGetInverse(out fromInverted);

            return to * fromInverted;

        }

This function returns a transform that: first uses the inverted ā€˜fromā€™ matrix to get the model into the world coordinate system. then uses the ā€˜toā€™ matrix to get the model into the desired coordinate system.

It would be a lot more legible if Transform had a constructor that takes a System.Numerics.Matrix4x4

Thanks for you continued efforts!

Best,
Nick

Hi @Nick_Drian,

Iā€™ve exposed this to RhinoCommon, wonā€™t be available until SR17.

ā€“ Dale

1 Like

Amazing, Thanks Dale.

This is exactly what I was looking for :slight_smile:

Hi Dale,

Will this also be available in rhinoscriptsyntax

Roger

Sorry, no. If you need, you will need to to straight to RhinoCommon.

ā€“ Dale