小白最近闲来无事,自学了一点metapost,主要用它来绘制拓扑图或流程图。小白最近在写自己从工作以来的所学,写成了一份PDF的电子文档(小白不太会使用MS Word)。小白又不想使用JPEG或PNG格式的图片作为插图,因为它们不是矢量的图形,放大后图形就显得不够美观。


好了,废话不多说了,直接来个例子吧,这个插图来自是小白上学时的一本书《操作系统教程》。附代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# cat GnuLinux.mp
verbatimtex
\documentclass[10pt]{article}
\usepackage{CJK}
\AtBeginDocument{\begin{CJK}{UTF8}{gbsn}}
\AtEndDocument{\end{CJK}}
\begin{document}
etex
   
input boxes;
 
% system variables
ahangle := 40;
 
% fig0 is linux virtual  file  system topo
outputtemplate :=  "vfs.mps" ;
beginfig(0);
   boxit.a(btex 用户进程 etex);
   boxit.b(btex 系统调用界面 etex);
   boxit.c(btex VFS etex);
   boxit.d(btex Ext3 etex);
   boxit.e(btex Buffer Cache etex);
   boxit.f(btex 设备驱动程序 etex);
   boxit.g(btex 硬盘控制器 etex);
   boxit.minix(btex Minix etex);
   boxit.nfs(btex NFS etex);
   boxit.sysv(btex Sysv etex);
   boxit.direc(btex 目录cache etex);
   boxit.inode(btex Inode cache etex);
   boxit.hard(btex etex);
   
   % Len is the box's length
   % Hig is the box's hight
   numeric Len;
   numeric Hig;
   Len := 65;
   Hig := 14pt;
   a.e - a.w = (Len,0); a.n - a.s = (0,Hig);
   b.e - b.w = (Len,0); b.n - b.s = (0,Hig);
   c.e - c.w = (Len,0); c.n - c.s = (0,Hig);
   d.e - d.w = (35,0); d.n - d.s = (0,Hig);
   minix.e - minix.w = (35,0); minix.n - minix.s = (0,Hig);
   nfs.e - nfs.w = (35,0); nfs.n - nfs.s = (0,Hig);
   sysv.e - sysv.w = (35,0); sysv.n - sysv.s = (0,Hig);
   e.e - e.w = (Len,0); e.n - e.s = (0,Hig);
   f.e - f.w = (Len,0); f.n - f.s = (0,Hig);
   g.e - g.w = (Len,0); g.n - g.s = (0,Hig);
   direc.e - direc.w = (Len,0); direc.n - direc.s = (0,Hig);
   inode.e - inode.w = (Len,0); inode.n - inode.s = (0,Hig);
   
   % Dis is the hight between the boxes
   numeric Dis;
   Dis := 20;
   a.s - b.n = (0,30);
   b.s - c.n = (0,Dis);
   c.s - d. ne  = (5,Dis);
   d.se - e.n = (-5,Dis);
   c.s - nfs.nw = (-5,Dis);
   d.w - minix.e = (10,0);
   sysv.w - nfs.e = (10,0);
   e.s - f.n = (0,Dis);
   f.s - g.n = (0,30);
   c.w - direc.e = (Dis,0);
   c.e - inode.w = (-Dis,0);
   hard.c = g.c;
   hard.e - hard.w = (100,0);
   hard.n - hard.s = (0,34);
   
   drawboxed(a,b,c,d,e,f,g,minix,nfs,sysv,direc,inode,hard);
   
   % draw the connectors
   drawarrow a.s -- b.n;
   drawarrow b.s -- c.n;
   
   drawarrow c.s -- minix.n;
   drawarrow c.s -- d.n;
   drawarrow c.s -- nfs.n;
   drawarrow c.s -- sysv.n;
   pair A[];
   A[1] = 1 /5 [e.nw,e. ne ];
   A[2] = 2 /5 [e.nw,e. ne ];
   A[3] = 3 /5 [e.nw,e. ne ];
   A[4] = 4 /5 [e.nw,e. ne ];
   drawarrow minix.s -- A[1];
   drawarrow d.s -- A[2];
   drawarrow nfs.s -- A[3];
   drawarrow sysv.s -- A[4];
   drawarrow e.s -- f.n;
   drawarrow f.s -- g.n;
   drawarrow c.w -- direc.e;
   drawarrow c.e -- inode.w;
   
   % draw the outline
   pair B[];
   B[1] = direc.w - (5,-56);
   B[2] = inode.e - (-5,-56);
   B[3] = inode.e - (-5,119);
   B[4] = direc.w - (5,119);
   draw B[1] -- B[2] -- B[3] -- B[4] -- cycle dashed evenly;
   
   label.rt(btex 硬件层 etex,hard.e);
   label.rt(btex Linux内核层 etex,b.e+(15,0));
   label.rt(btex 系统调用 etex,a.se+(15,-5));
endfig;
end


小白觉得这些代码有些臃肿,因为是刚学,所以小白也只能做到这样了。后续还需多加练习,才能写出比较紧凑、高效的代码。


如何编译呢,在windows或gnu/linux系统上(需要安装相关TeX),

1
2
3
4
# mpost -tex=latex GnuLinux
# mpost -tex=latex GnuLinux.mp
# mptopdf vfs.mps


效果图为:

wKioL1WZ-XihD8ORAAHeWyvwb8Y279.jpg