# Transform Multiply - Documentation / Order of transformation

Dear Steve and Menno @stevebaer @menno

I am a bit confused about how Matrix Multiplication is implemented here:
http://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Transform_Multiply.htm
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);
ptMxR.CommitChanges();

// 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);
ptRxM.CommitChanges();

// 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);
ptRxM2.CommitChanges();
}

doc.Views.Redraw();
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.

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

I think something is incorrect here as well.

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

I added an issue to our bugtracker to fix this
https://mcneel.myjetbrains.com/youtrack/issue/RH-36264

Thanks

@stevebaer
Dear Steve - this is still not adjusted/ fixed…
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Transform_op_Multiply_1.htm
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,

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

Sure.

``````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.

Paweł

``````combinedTransform = SecondTransform * FirstTransform
``````

same as

``````combinedTransform = Transform.Multiply (SecondTransform,FirstTransform)
``````

@pawel.unger1

… 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