Thursday, November 19, 2009

无比强大的绘图脚本Asymptote

未完
写paper就免不了要绘制一些示意图,而且又需要是矢量图.其中的一些简单的也就用ppt之类的对付了.还有一些对于位置或者每个部分的尺寸精度要求比较高,更适合用脚本来生成.曾经用过一段时间metapost.但是它古怪的语法最后还是让我放弃了.之后便一直忍受着Visio或者用tgif这样的古董.直到我发现了Asymptote.这是一个用于绘制矢量图的脚本语言.其语法一方面继承了很多metapost的优秀的部分,另一方面又加入了一些类似于Python等现代脚本语言的特性.所以上手起来很快.最让我惊奇的是asymptote这样一个用于制图的语言还支持面向对象,high order function以及匿名函数这样的功能.不得不赞叹:asymptote 麻雀虽小五脏俱全.

这里有一个Gallery(link),大家可以看看这个语言的强大.

基本用法是
$asy inputfilename
inputfilename是你的asy输入源文件名称.如果它是helloworld.asy,那么asy就把这个源文件编译,输出为helloworld.eps.可以用-o选项指定输出文件名.

这里是我总结的Asymptote中最常用的命令和语法
在指定位置绘制一个点:
  • 在(0,0)这个坐标处绘制一个点

    dot((0,0));
  • 在(0,0)这个坐标处绘制一个蓝色的点

    dot((0,0), blue);

给定两个点,绘制直线:
  • 直线

    draw((0,0)--(2,1));
  • 带Arrow的直线

    draw((0,0)--(50,0),BeginArrow);
    draw((0,-10)--(50,-10),MidArrow);
    draw((0,-20)--(50,-20),EndArrow);
    draw((0,-30)--(50,-30),Arrows);
    这里设置arrow的参数可以为None(没有箭头,默认), Blank (不但不画箭头,线都不画), BeginArrow(箭头在起始端), MidArrow(箭头在正中间), EndArrow(箭头在末端,也简写成Arrow), 以及Arrows(两端都有)
  • 带Bar的直线

    draw((0,0)--(2,1),Bar);
    这里的参数还可以是None, BeginBar, EndBar (或者等价的简写为Bar), Bars(两端都是Bar)

在制定位置写文本:
  • 可以与LaTeX配合,写数学公式:

    unitsize(1cm);
    draw(unitsquare);
    label("$P_{0,0}$", (0,0), SW);
    label("$P_{1,1}$", (1,1), NE);

调整图的大小:
asymptote中用直角坐标绘图,默认时候一个点的大小是1/72 inch. 所以从(0,0)到(0,72)的线段长度是1 inch.有两种方法可以调整图的尺寸:
  • 设置单位长度

    unitsize(1cm);
    这样(0,0)到(0,72)的距离就是72 inch而不是1 inch
  • 设置最大尺寸

    size(100,200);
    这样所画的图会被自动scale到100*200这样的大小. 如果使用

    size(0,200);
    x轴方向上不scale而在y方向上scale到200个pt

调试:
write(a)
输出a的值,

例子:
我作业中要画的马尔科夫链
size(400,200);
import flowchart;
block state0 = circle(" $0$ ", (0,0));
block state1 = circle(" $1$ ", (10,0));
block state2 = circle(" $2$ ", (20,0));
block state3 = circle(" $3$ ", (30,0));
block state4 = circle(" ... ", (40,0), fillpen=invisible, drawpen = invisible);

draw(state0);
draw(state1);
draw(state2);
draw(state3);
draw(state4);

add(new void(picture pic, transform t) {
    real r = 0.4;
    //state0
    draw(pic,"$\lambda$", state0.position(2-r, t){NE}..{SE}state1.position(r,t),0.5*N, Arrow);
    //state1
    draw(pic,"$\lambda$", state1.position(2-r, t){NE}..{SE}state2.position(r,t),0.5*N, Arrow);
    draw(pic,"$\mu$",state1.position(-r, t){SW}..{NW}state0.position(2+r,t),0.5*N, Arrow);
    //state2
    draw(pic,"$\lambda$", state2.position(2-r, t){NE}..{SE}state3.position(r,t),0.5*N, Arrow);
    draw(pic,"$\mu$",state2.position(-r, t){SW}..{NW}state1.position(2+r,t),0.5*N, Arrow);
    //state3
    draw(pic,"$\lambda$", state3.position(2-r, t){NE}..{SE}state4.position(r,t),0.5*N, Arrow);
    draw(pic,"$\mu$",state3.position(-r, t){SW}..{NW}state2.position(2+r,t),0.5*N, Arrow);
    //state4
    draw(pic,"$\mu$",state4.position(-r, t){SW}..{NW}state3.position(2+r,t),0.5*N, Arrow);
});


参考

No comments: