8
$\begingroup$

This question already has an answer here:

This may be a trivial question, but I seem to be missing something. Let's say I create a graphics object like so:

tp = Plot[{Sin[x], -Sin[x]}, {x, 0, 1 Pi}, AspectRatio -> Automatic, 
          Axes -> None, PlotStyle -> {Black, Black}, Filling -> Axis]

Now perhaps I want a rotated and scaled version of the same:

tprs = Magnify[Rotate[tp, 45*Degree], 0.5]

And now I want to have a graphic containing both of these:

Show[tp, tprs]

That last one fails, since tprs is not a graphics, according to Mathematica. What is it I am missing?

More generally I would like to be able to move around, rotate, and scale objects like my tp above arbitrarily, and combine them with other graphics objects within a single graphic. I guess what I really want is a new graphics primitive that I can later call as "objectname[{x,y}, s, \theta]" to make it appear at point {x, y} (relative to some reference point of the object), magnified by a factor s, and rotated by an angle \theta.

$\endgroup$

marked as duplicate by Kuba, m_goldberg, Artes, MarcoB, István Zachar Jul 28 '16 at 15:09

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ Overlay[{tp, tprs}] works, but I hate to use such a method... $\endgroup$ – Jason B. Jul 27 '16 at 20:43
  • 1
    $\begingroup$ Not a duplicate, because of the Magnify, but relevant: mathematica.stackexchange.com/q/57803/9490 $\endgroup$ – Jason B. Jul 27 '16 at 20:43
  • $\begingroup$ Yep, I know about Overlay, but like you say, that's not really the right approach. I have seen the other thread you linked to, but in the end this doesn't quite do what I ultimately want, either. I think the real question is the one of how I can define a function as described in the last remark in my original post. A method to do something of that sort would be enormously helpful for many, many applications. It would allow us to create arbitrary graphical objects that act somewhat like the objects in libraries for bolts and nuts and valves and fittings, etc., etc. that CAD packages have. $\endgroup$ – Pirx Jul 27 '16 at 20:57
  • $\begingroup$ You also need to use Scale instead of Magnify with the solution in the duplicate. $\endgroup$ – Michael E2 Jul 28 '16 at 12:20
7
$\begingroup$

Something quick and dirty like this,

rotateAndRescaleGraphics[g_Graphics, scale_, angle_] := 
  Module[{xr, yr},
   {xr, yr} = Charting`get2DPlotRange@g;
   g /. {x_?NumericQ, 
      y_?NumericQ} :> ({Rescale[#1, xr, scale xr], 
         Rescale[#2, yr, scale yr]} & @@ (RotationMatrix[angle].{x, 
          y}))
   ];

Show[tp,
 rotateAndRescaleGraphics[tp, 0.5, 45 Degree]
 ]

Mathematica graphics

Another, probably more powerful, way to go is to use Inset:

Show[tp,
 Epilog -> 
  Inset[tp, {0, 0}, {0, 0}, Scaled[{.5, .5}], 
   RotationMatrix[45 Degree].{1, 0}]
 ]

which gives the exact same result as above.

$\endgroup$
  • $\begingroup$ This is awesome, since Inset does everything I want to do: I can scale, rotate, and shift. The only fly in the ointment is that, with stuff stuck in an Epilog, apparently Show doesn't know the size of graphics that are being added, so something like PlotRange->All does nothing. Is there any way to fix that? $\endgroup$ – Pirx Jul 27 '16 at 21:40
  • $\begingroup$ Everything I'm reading says you need to manually add an ImagePadding specification, and then use PlotRangeClipping -> False. See here $\endgroup$ – Jason B. Jul 27 '16 at 21:44
  • $\begingroup$ Hah, figured it out: The Epilog isn't needed, as long as we wrap Graphics around the Inset, like so: Show[tp, Graphics[Inset[tp, {0, 0}, {0, 0}, Scaled[{.5, .5}], RotationMatrix[45 Degree].{1, 0}]]] $\endgroup$ – Pirx Jul 27 '16 at 21:49
  • $\begingroup$ Yeah, but there your Inset is already in the plot range. Look at Show[tp, Graphics[ Inset[tp, {0, 0}, Center, Scaled[{.5, .5}], RotationMatrix[45 Degree].{1, 0}]], PlotRange -> All] - can't figure out how to show that without ImagePadding $\endgroup$ – Jason B. Jul 27 '16 at 21:51
  • $\begingroup$ Yes, this only allows me to get rid of the Epilog (I hate asymmetries that don't belong ;-), it doesn't solve the minor issue with PlotRange. $\endgroup$ – Pirx Jul 27 '16 at 21:53
6
$\begingroup$

As your own title says, you should use Scale instead of Magnify as follows:

tp = Plot[{Sin[x], -Sin[x]}, {x, 0, 1 Pi}, AspectRatio -> Automatic, 
   Axes -> None, PlotStyle -> {Black, Black}, Filling -> Axis];

tprs = Graphics[Scale[Rotate[tp[[1]], 45*Degree], 0.5]];

Show[tp, tprs]

enter image description here

To be able to apply Scale, I first extract the Graphics primitives returned by Plot. Afterwards, I wrap the result back into a Graphics.

$\endgroup$
  • $\begingroup$ Ahah! So the trick is to first do tp[[1]], and later wrap everything back in Graphics. It should be easy to turn this into a function that scales and rotates whatever graphics I want treated in this way. Now the only element that's missing is to move my graphics around... ;-) $\endgroup$ – Pirx Jul 27 '16 at 21:21
  • $\begingroup$ @Pirx - Just add Translate at the appropriate point in the chain: ....Translate[tp[[1]], {-1, 1}]..... $\endgroup$ – Jason B. Jul 27 '16 at 22:00
  • $\begingroup$ @JasonB Thanks, that's what I was looking for! $\endgroup$ – Pirx Jul 27 '16 at 22:45
  • $\begingroup$ Thanks @JasonB for the moving comment... Anyway, the nice thing is that these commands also work in 3D. $\endgroup$ – Jens Jul 27 '16 at 23:09
  • $\begingroup$ @Pirx. To get the placement you want for the transformed graphics, just use tprs = Graphics[Rotate[Scale[tp[[1]], 0.5, {0, 0}], 45*Degree, {0, 0}]] $\endgroup$ – m_goldberg Jul 28 '16 at 1:24
4
$\begingroup$

An alternative method using pure graphics.

form = 
  Module[{top, btm},
    top = N @ Table[{t, Sin[t]}, {t, Subdivide[π, 20]}];
    btm = Reverse[{1, -1} # & /@ top];
    {EdgeForm[Black], FaceForm[LightGray], FilledCurve[Line[top~Join~btm]]}];

Graphics[{Opacity[.7], form, Rotate[Scale[form, 0.5, {0, 0}], 45*Degree, {0, 0}]}]

figure

$\endgroup$

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