The Problem
I need to put together different graphics objects in a precise way inside a Graphics
. Some objects are drawn directly by graphics primitives, some others are the result of calls to built-in and custom functions.
I've use Inset
to place these objects, but the result is unsatisfactory, as the objects appears in wrong sizes.
For analizing better the problem, I've wrote a simple general example, where there are five objects that are placed in the Graphics
sharing the very same shape, size and parameters. They differ only by the way how they are generated (please see the full code below).
There are five bars: redBar, greenBar, blueBar, yellowBar, orangeBar, they should be draw as the following picture (manually adjusted):
but instead, putting the elements together with this code (fragment):
Graphics[{
redBar[barW, barH]
, Inset[greenBar[barW, barH, options], {0, yPos}, {0, 0}] /. {yPos -> 100}
, Inset[blueBar[barW, barH, options], {0, yPos}, {Left, Bottom}] /. {yPos -> 200}
, Inset[yellowBar[barW, barH, options], {0, yPos}, {Left, Bottom}] /. {yPos -> 300}
, Inset[orangeBar[barW, barH, options], {0, yPos}, {Left, Bottom}] /. {yPos -> 400}
}
, Axes -> True
, PlotRange -> {{0, slideW}, {0, slideH}}
, ImageSize -> {slideW, slideH}
, AspectRatio -> Automatic
]
will give this kind of output:
Sample Code
Here it is the full code for this example:
(* --- Functions definitions --- *)
(* a simple bar as a base for the red, green and blue bars*)
bar[w_, h_] := {Opacity[0.6], Rectangle[{0, 0}, {w, h}]};
(* Red Bar: this return a simple graphics Primitive *)
redBar[w_, h_] := {Red, bar[w, h]};
(* Green Bar: this returns a Graphics object, based on the shared bar primitive *)
greenBar[w_, h_, options_] := Graphics[{Green, bar[w, h]}, Sequence@options];
(* Blue Bar: this returns a composed Graphics object *)
blueBarToInset[w_, h_, options_] := Graphics[{Blue, bar[w, h]}, Sequence@options];
blueBar[w_, h_, options_] := Graphics[Inset[blueBarToInset[w, h, options], {0, 0}, {Left, Bottom}], Sequence@options];
(* Yellow Bar, this is just the usual Plot function output *)
yellowBar[w_, h_, options_] := Plot[Sin[x], {x, 0, 4 Pi}, Axes -> True, Background -> Directive[Opacity[0.6], Yellow], Evaluate@Sequence@options];
(* Orange Bar, this is just the same as above, but without Axes *)
orangeBar[w_, h_, options_] := Plot[Sin[x], {x, 0, 4 Pi}, Axes -> False, Background -> Directive[Opacity[0.6], Orange], Evaluate@Sequence@options];
(* --- Main code --- *)
slideW = 500;
slideH = 500;
barW = 300;
barH = 100;
Manipulate[
(*shared Graphics options*)
options = {ImageSize -> {barW, barH}, AspectRatio -> aspectRatio, PlotRangePadding -> plotRangePadding};
(*put elements together*)
Graphics[{
redBar[barW, barH]
, Inset[greenBar[barW, barH, options], {0, yPos}, {0, 0}] /. {yPos -> 100}
, Inset[blueBar[barW, barH, options], {0, yPos}, {Left, Bottom}] /. {yPos -> 200}
, Inset[yellowBar[barW, barH, options], {0, yPos}, {Left, Bottom}] /. {yPos -> 300}
, Inset[orangeBar[barW, barH, options], {0, yPos}, {Left, Bottom}] /. {yPos -> 400}
}
, Axes -> True
, PlotRange -> {{0, slideW}, {0, slideH}}
, ImageSize -> {slideW, slideH}
, AspectRatio -> Automatic
]
, {plotRangePadding, {Automatic, None}}
, {aspectRatio, {Automatic, Full, (barH/barW) -> "barH/barW"}}
]
Another Test
To be sure that the graphics elements are actually similar in size, I've put them in a Column
, obtaining almost the proper size, so this may prove than the problem is within Inset
, not with the graphics elements themselfs:
Framed@Column[{
orangeBar[barW, barH, options],
yellowBar[barW, barH, options],
blueBar[barW, barH, options],
greenBar[barW, barH, options],
Graphics[redBar[barW, barH], options]
}
, Alignment -> Left
, Spacings -> 0]
IMHO
Maybe is my fault in understanding which option is to be given, but I think that this kind of (apparently simple) operations hasn't to be so difficult and frustrating..
Inset
is a little mysterious, and it took me a little while to figure out how it works. In addition,GraphicsColumn
is non-ideal for various reasons. In any case, see these posts: (1), (2), (3) for some ideas. I recommend usingGraphicsColumn
(which usesInset
internally) with equal padding, and scaling all the figures to be the same size. $\endgroup$Inset
is a little bit obscure, it is really difficult to understand when the problem is coming from a hypothetical bug or from the user's incompetence $\endgroup$