Given Graphics
object, how do I determine the range of coordinates needed to include all of graphics? Basically I need something like what Show
does by default, but I want to specify PlotRange
,PlotRangePadding
and ImagePadding
explicitly.
Example, two Show
s below should render the same
g = Graphics[{Thickness[1], CapForm["Round"], Line[{{0, 0}, {1, 1}}]}];
Show[g]
Show[g, PlotRange -> getPlotRange[g], PlotRangePadding->getPlotRangePadding[g], ImagePadding->getImagePadding[g]]
Motivation: fixing diagrams in this question
Update:
AbsoluteOptions
gives me PlotRange
but not the other two options. Explicitly specifying ImagePadding->Automatic
changes appearance though it's supposedly Automatic
by default.
Two images below show differently and I don't understand why
g = Graphics[{Thickness[1], CapForm["Round"], Line[{{0, 0}, {1, 1}}]}];
Show[g]
Show[g, Sequence @@ AbsoluteOptions[Show[g]]]
Update 2: A similar problem was brought up a year ago, with no solutions proposed, and not fixed as of Mathematica 8.0. To summarize
- There's no way to reproduce
Show[g]
above with explicit setting ofPlotRange
- There's no way to get absolute
ImagePadding
used byShow[g]
Show[g,PlotRange->Automatic]
looks different fromShow[g]
AbsoluteOptions
can give the wrong result forPlotRange
I, too, sometimes find it confusing how to get Mathematica to display
Graphics
in a consistent way, particularly when insetting graphics.For the specified graphic
g
, it doesn't matter what you provide for thePlotRange
, becauseThickness[1]
always draws a line whose thickness is equal to the horizontal plot range. In your example,Show[g, ___]
gives the correct result:.
Show[g]
, or simplyg
, is anomalous.Why?
I don't know where/if this is documented, but here are a few things that might be relevant to the question.
Obviously
DisplayForm[Graphics[___]]
is a raster.We can get a raster for g using Rasterize[g]. What is the RasterSize? From trial and error, I found that RasterSize is 10 * screen resolution (reported as 72 pixels per inch on my system). How do I know this? If I rasterize g with resolutions less than 718, I get an image with dimensions {360,361}, whereas the default image size for g is 360 pixels on my system, so I figure to Show[] a graphic, Mathematica
Rasterize
's it at 10x the screen resolution. Anybody know if this is true? You can get your screen resolution (at least as Mathematica sees it) from the Options Inspector. Edit That the following expression evaluates asTrue
seems to show that the displayed graphic is rasterized at the ImageSize:ImportString[ExportString[Show[g,ImageSize->100],"PNG"]] === ImportString[ExportString[Rasterize[g,RasterSize->100,ImageSize->100],"PNG"]
To reproduce
Show[g]
when usingPlotRange
I need to useShow[g,PlotRange->{{0,1},{0,1}},ImagePadding->90.3]
to get it to crop to the perimeter of the line. So it seems that Mathematica is telling the truth that the
PlotRange
is{{0,1},{0,1}}
when usingAbsoluteOptions[]
. It is not reporting the actual value ofImagePadding
. Perhaps becauseImagePadding->Automatic
is based on a rule that uses the currentImageSize
,PlotRangeClipping
,... settings? TheImagePadding
of 90.3 only works forImageSize->360
; settingImageSize->200
makes theImagePadding
value wrong. For your graphic,ImagePadding->90.3*OptionValue[ImageSize]/360
reproducesShow[g,ImageSize->_]
on my system.That's all I've found out so far.
You can try adding a recognizable object at a known location and then see where it shows up in the exported version to provide a scale reference. I thought a vector export (SVG or EPS) would be easier to parse, but I think raster is easier after playing around a bit.
For example, add a green rectangle covering the theoretical plot range:
The code is basically identifying where all the green pixels are. The padding in this case is {{92, 92}, {92, 92}}, but it need not be symmetrical.
I can suggest the following
Ticks
hack:The trick is that real
PlotRange
is determined by the FrontEnd, not by the Kernel. So we must force the FrontEnd to render the graphics in order to get tick functions evaluated. This hack gives the completePlotRange
with explicit value ofPlotRangePadding
added.More general solution taking into account a possibility that
pl
has non-standard value ofDisplayFinction
option and that it may haveAxes
option set toFalse
:One can get the exact
PlotRange
(without thePlotRangePadding
added) with the following function:P.S. On the Documentation page for
PlotRange
under the "More information" one can read: "AbsoluteOptions
gives the actual settings for options used internally by Mathematica when the setting given isAutomatic
orAll
. " (emphasis mine). So it seems that the Documentation does not even guarantee thatAbsoluteOptions
will give correct values forPlotRange
when it is notAutomatic
orAll
.