这个问题是 "Ma Yue" <[email protected]> 提出来的。
他想把一个 数据文件 绘制出来, 但是只显示其中从 (-0.15, 0) 到 (0.1, 1.1) 之间的部分。他写的 MetaPost 代码如下:
input graph; fs = 1.5; beginfig(1) draw begingraph(10cm,10cm); setrange(-0.15,0, 0.1,1.1); glabel.lft(btex $I_{\mathrm{ref}}$ etex,OUT) scaled fs rotated 90; glabel.bot(btex $\kappa$ etex,OUT) scaled fs; gdraw("pd1_tc1d6_V8_E10_c"); endgraph; endfig; end
结果得到的图形是这个:
可以看到,数据文件里本来有点落在他要求的 range 之外。 但是 graph.mp 本来提供的函数是没有办法不画某些点的。所以我们 必须采取其它办法。
我们可以把 endgraph 拆开来达到这个目的。
首先我们要明确一下两个变量的地位:
def Gxyscale = xscaled X_.gdim yscaled Y_.gdim enddef;
所以我们只要用
unitsquare Gxyscale
就可以得到一个当前 Gfin_ 的 bounding rectangle.
我们来分析一下,graph.mp 的 endgraph。它的代码如下:
def endgraph = if Gneedgr_: autogrid(otick.bot, otick.lft); fi if Gneedfr_: frame; fi setcoords(linear,linear); interim truecorners:=1; for b=bbox Gfin_: setbounds Gfin_ to b; for i=0 step .5 until 3.5: if known Ggl_[i]: addto Gfin_ also Ggl_[i] shifted point i of b; fi endfor endfor Gfin_ endgroup enddef;
通常在 endgraph 被调用之前,所有的数据点都已经由 gdraw 记录 Gfin_ 中。所有的 glable 做的标记,记录到了Ggl_[] 数组里。
当 endgraph 被调用时,它首先用 autogrid 和 frame 两条语句把 grid 和 frame 信息记录到下来. 但是 grid 和 frame 必须在 setcoords 被调用时才会真正被加到 Gfin_ 中,而且是以当前的 setrange 设定的范围为界限的。
所以 endgraph 调用了 setcoords, 这样 grid 和 frame 被加入到 了 Gfin_ 中。
然后 endgraph 一一把 label 加到 Gfin_。最后返回 Gfin_ 给 draw。于是一个数据图就被画出来了。
这里总结一下就是:
这样我的解决方案就是这样:
input graph; fs = 1.5; beginfig(1) draw begingraph(10cm,10cm); % 首先调用 setrange 设定绘图范围 setrange(-0.15, 0, 0.1, 1.1); % 用 gdraw 把数据点路径记录下来 gdraw("pd1_tc1d6_V8_E10_c"); % 把数据点绘制到 Gfin_ 中成为一个曲线,然后把 Gfin_ 超出范 % 围的部分用 clip 切掉 setcoords(linear,linear); clip Gfin_ to unitsquare Gxyscale; % setcoords 会忘记当前的 range, 必须重新设定 setrange(-0.15, 0, 0.1, 1.1); % 然后把 grid 信息记录下来 autogrid(otick.bot, otick.lft); % 把 frame 信息记录下来 frame; % 再次调用 setcoords. grid 和 frame 都被加到 Gfin_ setcoords(linear,linear); % 记录两个外围 label glabel.lft(btex $I_{\mathrm{ref}}$ etex,OUT) scaled fs rotated 90; glabel.bot(btex $\kappa$ etex,OUT) scaled fs; % 把 label 都加到 Gfin_ interim truecorners:=1; for b=bbox Gfin_: setbounds Gfin_ to b; for i=0 step .5 until 3.5: if known Ggl_[i]: addto Gfin_ also Ggl_[i] shifted point i of b; fi endfor endfor % 返回 Gfin_ 给 draw Gfin_ endgroup endfig; end
最后的 endgroup 是由于 begingraph 里实际上有一个 begingroup 跟它配对。
于是我们绘制的图形如下: