如何确定PlotRange以包括所有图形?

34

给定Graphics对象,如何确定需要包括所有图形的坐标范围?基本上我需要像Show默认情况下所做的那样的东西,但我想明确指定PlotRangePlotRangePaddingImagePadding

例如,下面的两个Show应该呈现相同的效果

g = Graphics[{Thickness[1], CapForm["Round"], Line[{{0, 0}, {1, 1}}]}];
Show[g]
Show[g, PlotRange -> getPlotRange[g], PlotRangePadding->getPlotRangePadding[g], ImagePadding->getImagePadding[g]]

动机: 修复这个问题中的图表

更新: AbsoluteOptions 给了我 PlotRange 但没有其他两个选项。明确指定 ImagePadding->Automatic 改变了外观,尽管据说默认情况下是 Automatic

下面的两幅图显示不同,我不明白为什么

g = Graphics[{Thickness[1], CapForm["Round"], Line[{{0, 0}, {1, 1}}]}];
Show[g]
Show[g, Sequence @@ AbsoluteOptions[Show[g]]]

更新2:一年前曾经提出类似的问题,但没有提出解决方案,并且在Mathematica 8.0中仍未修复。总结如下:

  1. 没有办法使用显式设置的PlotRange来重现上面的Show[g]
  2. 没有办法获取Show[g]所使用的绝对ImagePadding
  3. Show[g,PlotRange->Automatic]Show[g]看起来不同
  4. AbsoluteOptions对于PlotRange可能会给出错误的结果

1
我也在尝试使用AbsoluteOptions,但有时它会返回错误的值。 - Dr. belisarius
是的...也许我最好自己实现粗线... - Yaroslav Bulatov
1
似乎这个问题并不新鲜:http://thedailyreviewer.com/compsys/view/problems-absolute-plotrange-108108947 - Dr. belisarius
是的,这似乎来自MathGroup档案,我在Mathematica 8中得到了与那里报告的相同行为。 - Yaroslav Bulatov
3个回答

7
我可以建议以下的“刻度”hack:

我可以建议以下Ticks hack:

pl = Plot[Sin[x], {x, 0, 10}];
Reap[Rasterize[Show[pl, Ticks -> {Sow[{##}] &, Sow[{##}] &}, ImageSize -> 0], 
   ImageResolution -> 1]][[2, 1]]

=> {{-0.208333, 10.2083}, {-1.04167, 1.04167}} 

关键在于真正的PlotRange是由前端而不是内核确定的。因此,我们必须强制前端呈现图形以评估刻度函数。这个技巧提供了完整的PlotRange,并添加了PlotRangePadding的显式值。

更一般的解决方案考虑到pl可能具有非标准的DisplayFinction选项值,以及它可能设置为FalseAxes选项:

completePlotRange[plot:(_Graphics|_Graphics3D|_Graph)] := 
 Quiet@Last@
   Last@Reap[
     Rasterize[
      Show[plot, Axes -> True, Frame -> False, Ticks -> (Sow[{##}] &), 
       DisplayFunction -> Identity, ImageSize -> 0], ImageResolution -> 1]]

使用以下函数可以获得准确的PlotRange(不包括添加的PlotRangePadding):

plotRange[plot : (_Graphics | _Graphics3D | _Graph)] := 
 Quiet@Last@
   Last@Reap[
     Rasterize[
      Show[plot, PlotRangePadding -> None, Axes -> True, Frame -> False, 
       Ticks -> (Sow[{##}] &), DisplayFunction -> Identity, ImageSize -> 0], 
      ImageResolution -> 1]]

附注:在PlotRange文档页面的“更多信息”下,可以阅读到:“AbsoluteOptions会提供Mathematica内部使用的选项的实际设置当给定的设置为AutomaticAll。”(强调是我的)。因此,文档甚至不能保证AbsoluteOptions在不是AutomaticAll时会给出正确的PlotRange值。


先生,您真是赢家!那个最后的函数非常有用。 - El Developer

3
我也有时会感到困惑,如何让Mathematica以一致的方式显示Graphics,特别是在插入图形时。
对于指定的图形g,提供PlotRange的值并不重要,因为Thickness[1]总是绘制一条线,其厚度等于水平绘图范围。在您的示例中,Show[g, ___]给出了正确的结果: automatic image padding. Show[g]或简单地g是异常的。
为什么?
我不知道这是否有记录,但以下是一些可能与问题相关的事项。
1. 显然,DisplayForm [Graphics [___]]是光栅图像。 2. 我们可以使用Rasterize [g]获取g的光栅图像。 RasterSize是多少?通过试错,我发现RasterSize是10 *屏幕分辨率(在我的系统上报告为每英寸72个像素)。我怎么知道这个?如果我使用小于718的分辨率光栅化g,则会得到一个尺寸为{360,361}的图像,而g的默认图像大小在我的系统上为360像素,因此我认为要显示一个图形,Mathematica会将其光栅化为屏幕分辨率的10倍。有人知道这是否正确吗?您可以从选项检查器中获取屏幕分辨率(至少在Mathematica看来)。
编辑:以下表达式的评估似乎显示出显示的图形在ImageSize处被光栅化: ImportString[ExportString [Show [g,ImageSize->100],“PNG”]] === ImportString [ExportString [Rasterize [g,RasterSize->100,ImageSize->100],“PNG”]] 3. 要在使用PlotRange时重现Show [g],我需要使用Show [g,PlotRange-> {{0,1},{0,1}},ImagePadding-> 90.3]specific image padding

为了使其裁剪到线的周长,需要进行以下操作。因此,当使用AbsoluteOptions[]时,Mathematica告诉我们PlotRange{{0,1},{0,1}}。它没有报告ImagePadding的实际值。也许是因为ImagePadding->Automatic基于一个规则,该规则使用当前的ImageSizePlotRangeClipping等设置?对于ImageSize->360ImagePadding为90.3才能正常工作;而将ImageSize->200会使ImagePadding的值错误。对于您的图形,在我的系统上,ImagePadding->90.3*OptionValue[ImageSize]/360可以复制Show[g,ImageSize->_]

这就是我目前发现的全部内容。


请在评论中发布您的图像的imgurl地址,我会将它们上传。 - Dr. belisarius
@belisarius 一个赞已经给了我足够的声望来添加这些图片。非常感谢您的提议。 - JxB
可能是列表第二部分的分析不正确:显示的光栅可能会在图像大小处光栅化... - JxB

3
您可以尝试在已知位置添加一个可识别的对象,然后查看它在导出版本中的显示位置,以提供比例参考。我原以为向量导出(SVG或EPS)会更容易解析,但经过一番尝试后发现光栅图像更容易处理。
例如,添加一个覆盖理论绘图范围的绿色矩形:
g = Graphics[{Blue, Thickness[1], CapForm["Round"], 
   Line[{{0, 0}, {1, 1}}], Green, Rectangle[{0, 0}, {1, 1}]}];

enter image description here

im = Rasterize[g, ImageSize -> 360];
xy = Transpose[Position[ImageData[im], {0., 1., 0.}]];
pad = Map[{Min[#1], 360 - Max[#1] } &, xy];
Show[g, ImagePadding -> pad]

这段代码基本上是识别所有绿色像素的位置。 在这种情况下,填充(padding)是{{92, 92}, {92, 92}},但不一定要对称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接