用Metapost绘制坐标纸

如果你需要一个100×100的正方形网格,每一格的大小为1.5毫米见方,并且内部不划线,而是用“点阵”来替代,可以采用什么方法?

问题起源于此:我的外公退休后无事可做,开始研究各种“百字图”。大概的意思就是对字形进行设计,比如一个“龙”字可以有100种写法。老人家最初是在一张A4打印纸上手工绘制的,每张对应1个字的100种写法。在写完十二生肖之后,他希望将这些作品存储在电脑中,进行“数字化”处理。问题在于,原来手工绘制在纸张上的文字通过扫描仪输入在计算机看来还是“图形”,并且是标量图形,在放大之后会有不可避免的失真。那么用怎样的方法才能将其“矢量化”?

因为这不是在做一款可用的字体,所以将每个字做成矢量图形就可以了。而且由于汉字是由各种笔画组成的,并且变形后的字形包含的笔画主要是直线与光滑的曲线,所以,将字形离散化,最好是能用每一个关键节点的坐标来描述最好不过了。

那么第一步,需要一个合适大小的网格。这个网格的要求如文章开始时描述。为了保证使用者不被网格本身干扰,需要用点阵替代网格线;同时为了后处理方便,还需要有一定数量的浅色的内部网格和坐标。我一开始先考虑用Photoshop,方法大致如下:

  1. 创建1.5mm×1.5mm大小的图形,用70%灰度对其左边和上边描边处理,并另存为“图案”。
  2. 创建15cm×15cm大小的图形,用上一步制作好的图案进行填充。

问题在于,这样做出来的图形在每一边上都不是正好100个正方形,不知道问题出在哪里。而且如果要加上坐标的话也很麻烦。

然后我就突然想起Metapost,这样有着精确要求,重复性操作的活用它最合适。不过我承认在一个假期没有用Metapost自己都有点生疏了。参考做毕业论文时候写的代码,总算是完成任务。做出来的效果图如下:

Metapost生成的是EPS格式的矢量图,上边这个是转化后的jpeg格式。如果您也需要,推荐您下载PDF格式(矢量)。

至于代码就很简单了:

%*******************************  
 prologues := 3;  
 filenametemplate “%j-%c.eps”;  
%*******************************  
 beginfig(1)

u:=1.5mm;

% 网格点  
 for h:=0 upto 100:  
 for l:=0 upto 100:  
 drawdot (h*u,l*u);  
 endfor;  
 endfor;  

% 外框线  
 draw (0,0)–(0,100u)–(100u,100u)–(100u,0)–cycle;  

% 内框线  
 for h:=1 upto 9:  
 draw (h*10u,0)–(h*10u,100u) withcolor .7white;  
 draw (0,h*10u)–(100u,h*10u) withcolor .7white;  
 endfor;  

% 坐标  
 for h:=0 upto 10:  
 dotlabel.bot(decimal (h*10), (h*10u,0));  
 dotlabel.top(decimal (h*10), (h*10u,100u));  
 dotlabel.lft(decimal (h*10), (0,h*10u));  
 dotlabel.rt(decimal (h*10), (100u,h*10u));  
 endfor;

 endfig;  
 end;

当然,这段代码还有很大的改进余地!^_^