小白最近闲来无事,自学了一点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