这个问题是 "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 跟它配对。
于是我们绘制的图形如下: