Transform Multiply - Documentation / Order of transformation

Dear Steve and Menno @stevebaer @menno

I am a bit confused about how Matrix Multiplication is implemented here:
thanks for the nice explanation of Menno in this post

My question is about the Order the transformation will be combined.
The Documentation claims for xform = A*B

The resulting Transform gives the same result as though you’d first apply A then B.

I think it is the other way round:
->The resulting Transform gives the same result as though you’d first apply B then A.

the following example uses a Translation M (Move) X+100, and a rotation R around the Y-Axis:

    protected override Result RunCommand(RhinoDoc doc, RunMode mode)

        ObjRef[] obj_refs;
        var rc = RhinoGet.GetMultipleObjects("Select points to move", false, ObjectType.Point, out obj_refs);
        if (rc != Result.Success || obj_refs == null)
            return rc;
        // Translate x+ 100
        Transform xFormMove = Transform.Translation(100, 0, 0);
        // rotate 30degree arround y-Axis
        Transform xFromRotY = Transform.Rotation(Math.PI / 6.0, new Vector3d(0, 1, 0), new Point3d(0, 0, 0));

        // combine
        Transform xForm_MxR = xFormMove * xFromRotY;
        Transform xForm_RxM = xFromRotY * xFormMove;
        // check * and Transform.Multiply
        Transform xForm_RxM_2 = Transform.Multiply(xFromRotY, xFormMove);

        foreach (var obj_ref in obj_refs)
            Guid newID_MxR;
            Guid newID_RxM;

            // move * Rotate -> color Red
            newID_MxR = doc.Objects.Transform(obj_ref, xForm_MxR,false);
            RhinoObject ptMxR = (new ObjRef(newID_MxR)).Object();
            ptMxR.Attributes.ColorSource = ObjectColorSource.ColorFromObject;
            ptMxR.Attributes.Name = "MxR";
            ptMxR.Attributes.ObjectColor = System.Drawing.Color.FromArgb(231, 0, 0);

            // Rotate * Move -> color green
            newID_RxM = doc.Objects.Transform(obj_ref, xForm_RxM, false);
            RhinoObject ptRxM = (new ObjRef(newID_RxM)).Object();
            ptRxM.Attributes.ColorSource = ObjectColorSource.ColorFromObject;
            ptRxM.Attributes.Name = "RxM";
            ptRxM.Attributes.ObjectColor = System.Drawing.Color.FromArgb(0, 231, 0);

            // compare operator vs Method
            newID_RxM = doc.Objects.Transform(obj_ref, xForm_RxM_2, false);
            RhinoObject ptRxM2 = (new ObjRef(newID_RxM)).Object();
            ptRxM2.Attributes.ColorSource = ObjectColorSource.ColorFromObject;
            ptRxM2.Attributes.Name = "RxM_2";
            ptRxM2.Attributes.ObjectColor = System.Drawing.Color.FromArgb(0, 0, 231);

        return Result.Success;

You are correct (I think I made a mistake in the post you refer to)

TS = TS => Scale then Translate
ST = S
T => Translate then Scale

The order of multiplication is reversed in the order of application of transforms.

Thanks Menno
And please Steve, update the documentation. - Thanks

I think something is incorrect here as well.

Ah, OK, sorry … did not see Tom’s link

I added an issue to our bugtracker to fix this


Dear Steve - this is still not adjusted/ fixed…
thanks for any update…
kind regards -tom

@stevebaer If you ever get around to fixing this area of documentation you might want to take a look at the Transform Methods->Rotation Method.

In the first overload (Double, Point3d) parameter description “rotation center” says “Rotation axis is vertical.”. I don’t think this is very helpful: vertical with respect to what?

In the second (Double, Vector3d,Point3d) “rotation center” says the same thing as the first ie: “Rotation axis is vertical”. Shouldn’t this be removed, as the rotation axis is as specified by the vector3d?

In the fifth (Vector3d,Vector3d,Vector3d,Vector3d,Vector3d,Vector3d) shouldn’t the vectors be described as " “From” vector component along (x,y,z) axis" and " “To” vector component along (x,y,z) axis" to be a bit more descriptive? Or am I incorrectly interpreting what this version does?
Also: What about rotation center? Shouldn’t this overload have a caution about moving the object to the origin before rotation and then moving it back? Or at least some info about how that’s handled?

Hi @AlW,

This should read:

Constructs a new rotation transformation with specified angle and rotation center. 
The 3D unit axis of rotation is Vector3d.ZAxis.


This override should read:

Constructs a transformation that maps X0 to X1, Y0 to Y1, Z0 to Z1.
The frames should be right hand orthonormal frames (unit vectors with Z = X x Y).
The resulting rotation fixes the origin (0,0,0), maps initial X to final X, 
initial Y to final Y, and initial Z to final Z.

I’ll see that the comments for these methods are updated.

– Dale

Thanks @Tom_P - I’ll see that this is fixed.

– Dale

Hi all,
the documentation still says:

The resulting Transform gives the same result as though you’d first apply B and then A.

As the first post suggests, transformations are not commutative.

From what I have found out if:
Transform A; // is some rotation, we want to keep it the first transform
Transform B; //is some Translation, we want to do it after the rotation

Expected is:
Transform doAthenB = B * A;

As opposed, that would execute first B and then A transformation:
Transform doBthenA = A * B;

It would be great to have the documentation that suggests the first transformation will be applied after the second one.


combinedTransform = SecondTransform * FirstTransform

same as

combinedTransform = Transform.Multiply (SecondTransform,FirstTransform)


… no … it got updated and looks correct to me now - also compared to the old version, screenshot above in post of emilio, nov’16

Ahhh okay, I misunderstood that it says it is commutative and no matter B or A order.

Cheers and thanks