上次使用Mathematica的图形命令绘制三角形图象做Low Poly图象的时候,发现绘制出来的图像周边总是有白边,使用裁切命令的话又无法精准的控制图像的大小,最后只能使用图像高亮并配合二值化的方式进行处理。而这个白边的问题一直没有得到处理。今天在用Mathematica绘制函数图象的时候,发现图像绘制的时候如果要设置网格,那么网格的边缘总是会越界,这样看上去就像是一张覆盖在函数图象上的网格一样,十分难看。于是自习研究了一下处理方式,然后记录一下。
1.默认网格线
打开MMA的笔记本,直接输入下面的命令绘制一个彩色的正弦函数曲线:
1 |
Plot[Sin[x], {x, 0, 2 Pi}, GridLines -> Automatic, GridLinesStyle -> Directive[RGBColor[0.5, 0.8, 0.2]], ColorFunction -> "BlueGreenYellow", ImageSize -> 600] |
可以得到下面的图像:

MMA绘图网格线越界
观察图片的纵坐标可以发现,网格的左边是越界的。这主要是由于使用GridLines命令的时候,虽然控制范围是PlotRange的范围,凡事MMA实际上是在图片的周边会产生一定的赋予空间,这样的话就会导致网格填充超过坐标线。
2.解决方案一
最简单的方式就是直接使用PlotRangePadding命令来限制MMA的自动扩大填充范围。按照MMA帮助文件的说法,在绘图的时候MMA会在每个方向上增加2%的填充。那么使用下面的命令就可以了:
1 |
Plot[Sin[x], {x, 0, 2 Pi}, GridLines -> Automatic, GridLinesStyle -> Directive[RGBColor[0.5, 0.8, 0.2]], ColorFunction -> "BlueGreenYellow", ImageSize -> 600, PlotRangePadding -> 0] |
这样限制了填充之后,MMA只会绘制PlotRange范围内的图像了。

MMA绘图网格线越界
使用这种方式还可以绘制Graphics图象,在没有使用PlotRangePadding情况下,绘制出来的图片是存在白边的:

MMA绘图网格线越界
但是这样图片如果要生成遮罩是没办法用的,还是需要添加上PlotRangePadding->0。这样可以得到下面的图片:

MMA绘图网格线越界
使用上面的图片进行遮罩处理就会方便很多。当然如果并不是强迫症,就可以将坐标范围调整一下,这样即便是MMA自动进行2%的填充也没关系:

MMA绘图网格线越界
3.解决方案二
除了使用上面的方式进行调整之外,还可以使用Frame进行控制,如果使用了Frame,那么这个Frame就是边界,图像的所有填充都不会超出Frame,使用下面的命令绘制:
1 |
Plot[Sin[x], {x, 0, 2 Pi}, GridLines -> Automatic, GridLinesStyle -> Directive[RGBColor[0.5, 0.8, 0.2]], ColorFunction -> "BlueGreenYellow", Frame -> True, ImageSize -> 600] |
得到下面的图片:

MMA绘图网格线越界
仔细观察上图会发现,其实自动填充的问题还是存在的,只是不会发生在Frame外面,而是在Frame内部。这样的自动填充可以让图像更加完整一点,也可以用PlotRangePadding->0使得图像充分显示:

MMA绘图网格线越界
当然,也可以通过调整Frame的显示与隐藏来伪装一个类似标准坐标轴的图形:
1 |
Plot[Sin[x], {x, 0, 2 Pi}, GridLines -> Automatic, GridLinesStyle -> Directive[RGBColor[0.5, 0.8, 0.2]], ColorFunction -> "BlueGreenYellow", Frame -> {{True, False}, {True, False}}, FrameTicks -> {{Automatic, None}, {Automatic, None}}, PlotRangePadding -> 0, ImageSize -> 600] |
这样就可以得到下面的图形:

MMA绘图网格线越界
如果增加AxesStyle -> Opacity[0]可以彻底隐藏图片中间的线条:
1 |
Plot[Sin[x], {x, 0, 2 Pi}, GridLines -> Automatic, GridLinesStyle -> Directive[RGBColor[0.5, 0.8, 0.2]], ColorFunction -> "BlueGreenYellow", Frame -> {{True, False}, {True, False}}, FrameTicks -> {{Automatic, None}, {Automatic, None}}, PlotRangePadding -> 0, AxesStyle -> Opacity[0], ImageSize -> 600] |
这样得到的图片也是很好看的:

MMA绘图网格线越界
4.End小结
这个问题弄了好久,最主要是在Graphics的帮助里面是没有介绍怎么消除白边的,因此想要通过图形绘制遮罩的想法就一直没有实现,但是正好今天发现在用Plot绘图的时候,网格线竟然会超出范围,结合之前的现象,就考虑了一下是不是可以通过这个PlotRangePadding来处理,发现果然是可以的。
给出一个文中代码的下载链接:KX40R7.zip