8
$\begingroup$

I have a number of rotations computed by rot = RotationTransform[theta, point], and I would like to compose them to produce one function that is the composition of all the rotations. I need this function in a form that I can then use in, say, FindMinimum[].

I solved my problem by using TransformationMatrix[rot], multiplying all the matrices, and defining a function based on that. But it would be cleaner to create one function that is the composition of the others, rather than take the detour through matrices. Ideally I would input a list of `theta, point' values, and get back a function that is the composition of all those rotations.

I'd appreciate learning how to do this. Thanks!

$\endgroup$
8
  • 2
    $\begingroup$ Why don't you post the code for the functions your have. Then someone can suggest how to compose them. $\endgroup$
    – DavidC
    Mar 12, 2012 at 15:49
  • 2
    $\begingroup$ Why would you not want to work with the matrices directly? Seems like a straightforward way to compose the combined rotation. $\endgroup$
    – Yves Klett
    Mar 12, 2012 at 15:54
  • 1
    $\begingroup$ @David: I didn't want to bias the answers to my specific situation. The various rotations are computed in separate parts of the code, and only lashed together at the end. I would have to contrive an example to make it independent of my details. $\endgroup$ Mar 12, 2012 at 17:15
  • $\begingroup$ @Yves: It works perfectly by multiplying matrices. I just thought that was an inelegant solution. $\endgroup$ Mar 12, 2012 at 17:16
  • $\begingroup$ Ultimately, the matrices will get multiplied together, anyway. The question is whether or not you do it yourself. $\endgroup$
    – rcollyer
    Mar 12, 2012 at 17:21

3 Answers 3

9
$\begingroup$

The function your looking for is Composition which does exactly what you would like it to do. For instance,

{rot1, rot2} = MapThread[RotationTransform, {{theta1,theta1},{point1,point2}}]
composed = Composition @@ %
Composition[
     RotationTransform[theta1, point1], 
     RotationTransform[theta1, point2]
  ]

which can then be used like rot1 and rot2 would, e.g. composed[ {x, y, z} ]. From some experiments, it seems that Composition will combine multiple TransformationFunction into a single TransformationFunction, e.g.

Composition[ RotationTransform[ Pi/2 ], RotationTransform[ Pi/2] ] ]

simplifies to

RotationTransform[ Pi ]

Here is a specific example using the following rotations

RotationTransform[Pi/2, {1, 0}]
RotationTransform[Pi/2, {1, 1}]
composed = Composition @@ {%, %%}

which gives the output (it's in picture form as the output is displayed using boxes):

enter image description here

Now, applying them one at a time to a triangle, using the following code

FoldList[
  {EdgeForm[Black], White, #2[#1]} &, 
   Polygon[{{1, 0}, {0, Sqrt[3]}, {-1, 0}}], 
  {# &, 
   GeometricTransformation[#, RotationTransform[Pi/2, {1, 0}]] &, 
   GeometricTransformation[#, RotationTransform[Pi/2, {1, 1}]] &}
][[2 ;;]] //
GraphicsRow[
 Graphics[#, Frame -> True, PlotRange -> {{-3, 3}, {-3, 3}}] & /@ # 
]&

gives

enter image description here

Using the composition directly via

Graphics[{
   EdgeForm[Black], White, 
   GeometricTransformation[
       Polygon[{{1, 0}, {0, Sqrt[3]}, {-1, 0}}], 
       composed]
  }, Frame -> True, PlotRange -> {{-3, 3}, {-3, 3}}]

gives the identical end result

enter image description here

Two things to note here. First, the functions are entered into Composition in reverse order of application, i.e. the first function to be applied is last, and the last function is first. Second, I made use of GeometricTransformation to apply the rotations to a Graphics primitive.

$\endgroup$
7
  • $\begingroup$ If you supply explicit values for the points like point1={u1, u2} the result is properly evaluated as well. $\endgroup$
    – Yves Klett
    Mar 12, 2012 at 16:12
  • $\begingroup$ @YvesKlett actually, yes it does. You can combine any of the specializations of TransformFunction and they will be made into a single unit. $\endgroup$
    – rcollyer
    Mar 12, 2012 at 16:14
  • $\begingroup$ Would you mind editing in an example with explicit rotation points? Should be quite instructive for future browsing. $\endgroup$
    – Yves Klett
    Mar 12, 2012 at 16:41
  • 1
    $\begingroup$ @YvesKlett added an example with graphics for visual oriented people. $\endgroup$
    – rcollyer
    Mar 12, 2012 at 17:16
  • $\begingroup$ Wonderful! This is exactly what I sought. Thanks! $\endgroup$ Mar 12, 2012 at 17:16
6
$\begingroup$

It seems you want a built-in function Composition. Having two functions f and g, where g depends on two arguments it works like this :

Composition[f, g] @@ {x, y}
f[g[x, y]]

E.g.

g[x_, y_] := ArcTan[x^2 y]
f[z_]     := 1/2 Tan[z]
Composition[f, g] @@ {x, y}
(x^2 y)/2

Composition works with many functions as well, e.g. :

Composition[f1, f2, f3, f4] @@ {x, y, z}
f1[f2[f3[f4[x, y, z]]]]           
$\endgroup$
10
  • 2
    $\begingroup$ I wasn't aware that Composition will evaluate when transformation functions are passed to it. I think you should give an example using transformation functions to make this explicit. This is a special behaviour of Composition, specific to TransformationFunctions. $\endgroup$
    – Szabolcs
    Mar 12, 2012 at 16:06
  • 1
    $\begingroup$ Composition is also mentioned in the help under guide/GeometricTransforms. In this case it is a neat thing, but the GeometricTransformation framework can be a bit opaque IMHO. $\endgroup$
    – Yves Klett
    Mar 12, 2012 at 16:22
  • $\begingroup$ Thank you so much, two equivalent answers! $\endgroup$ Mar 12, 2012 at 17:17
  • $\begingroup$ @JosephO'Rourke You are welcome. $\endgroup$
    – Artes
    Mar 12, 2012 at 17:37
  • 2
    $\begingroup$ @Artes My meaning was that I was surprised and delighted to find that Compose[f,g] does indeed auto-simplify if f and g are TransformationFunctions, like rcollyer showed in his answer. I read your answer first and thought that it's less efficient than hand-multiplying the matrices and construction a new TranformationFunction from them. But I checked if Composition would actually evaluate, and surprise---it did! This only happens for TranformationFunction objects, and it is not obvious, so I asked you to include it (but it seems rcollyer did first). $\endgroup$
    – Szabolcs
    Mar 13, 2012 at 5:37
5
$\begingroup$

One more thing that may be useful when working with Composition: to include a transformation that does nothing, use Identity.

You may ask why you'd ever need that. An example is given in this post for a shadow projection function: How to make a drop-shadow for a Graphics3D objects?

There is a transformation in the Composition that is supposed to be left out under certain conditions. The link also illustrates how much simpler Composition is than the alternative of adding vectors and multiplying matrices.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.