7.7 -K-O 选项

-K 选项和 -O 选项是GMT绘图中常用的两个选项,也是经常产生错误的两个选项。

7.7.1 图层

要理解 -K 选项和 -O 选项,首先要理解图层的概念。对于使用过PhotoShop或者是在PowerPoint中画过图的人,应该很容易理解这一概念。所谓图层,可以理解成一张画有线条与文字的透明胶片,将这些透明胶片按照顺序一张张重叠起来,即构成了最终的图片。以PhotoShop中的图层为例,使用图层的好处在于,可以将某一图层单独拿出来修改,而不影响到其他图层。

图层的概念也适用于GMT。通常来说,用GMT绘图时是不可能用一个命令就画出想要的效果的。比如要画一个震中和台站的分布图,通常需要将如下几个命令组合起来:

# 本示例中命令不完整,仅供演示用途

# 绘制海岸线
gmt pscoast ... > map.ps
# 用五角星表示地震位置
gmt psxy event.dat -Sa0.5c ... >> map.ps
# 用三角形表示台站位置
gmt psxy station.in -St0.5c ... >> map.ps

每一个绘图命令本质上都是在向PS文件中新增了一个图层,所以上面生成的PS文件中共有三个图层,第一个图层仅包含了海岸线,第二个图层仅包含一些五角星,第三个图层仅包含一些三角形。这些图层按照顺序叠加起来,就组成了我们最终看到的图片。在图层叠加过程中,后面的图层中的非透明区域会覆盖前面的图层,比如第二个图层中填充了颜色的五角星就有可能把前一图层中的某一小段海岸线给覆盖掉。

7.7.2 PS文件结构

在理解了图层的概念之后在来说说PS文件的结构。

任何一个PS文件都由header、body和trailer组成,可以理解成头、身体和尾巴。其中头部的作用是初始化PS文件,比如设置纸张大小、纸张方向、载入字体等;身体部分则是真正的绘图部分,包含了每个绘图命令绘制的图层;尾巴部分则用于控制PS文件的显示。

../../_images/GMT_-OK.png

图 7.17 -K-O 选项的原理

因而,一个PS文件中,只有一个头和尾巴,可以有零个、一个或多个身体。

7.7.3 -K-O 的作用

在不使用 -K-O 选项的情况下,GMT的每个绘图命令都会产生完整的PS代码,即包含了头部、身体和尾部。而在使用多个命令绘制一张图片的多个图层时,则要保证第一个绘图命令必须省略尾部,中间的绘图命令必须省略头部和尾部,最后一个绘图命令必须省略头部。

-K 选项的作用是省略尾部,即意味着后面还有追加新的图层。 -O 选项的作用是省略头部,即这个图层要覆盖在前一图层上。

因而,在一张图中绘制多个图层时,绘制第一个图层的命令需要使用 -K 选项省略尾部,绘制中间图层的命令需要使用 -K -O 选项,绘制最后一个图层的命令则需要使用 -O 选项。

因而,对于含多个图层的图片来说,绘图命令如下所示:

gmt pscmd1 ... -K > out.ps
gmt pscmd2 ... -K -O >> out.ps
...
gmt pscmd3 ... -K -O >> out.ps
gmt pscmd4 ... -O >> out.ps

7.7.4 -K-O 的使用

总结一下 -K-O 选项的用法。对于有n个图层的PS文件:

  • 第1个绘图命令需要使用 -K 和重定向符号 >
  • 第2到n-1个绘图命令需要使用 -K -O 和重定向符号 >>
  • 第n个绘图命令需要使用 -O 和重定向符号 >>

上面总结的 -K-O 选项的用法看上去很简单,但实际绘图中却非常容易出错。

想象一下这样一个场景,你需要画一张稍复杂的图,所以需要在脚本中写一堆命令来完成绘图。当你写脚本的时候正确地使用了 -K-O 选项以及重定向符号,然后也初步完成了绘图。且不说绘图的过程有多艰辛,在完成初步绘图后你可能需要对这张图做一些微调,比如下面这些情形:

  • 由于后面的图层会覆盖前面的图层,而有些覆盖是你不想要的,所以你可能会希望调换两个绘图命令的顺序。比如需要调整最开始的两个命令的顺序,或者要调整最后两个命令的顺序,你是否记得在调整顺序的时候要修改 -K-O 选项以及重定向符号?
  • 比如需要在第一个绘图命令前再加一个绘图命令,你是否记得要把原来的第一个绘图命令加上 -O 选项以及 >>
  • 比如需要在最后一个绘图后面再加一个绘图命令,你是否记得要把原来的最后一个绘图命令加上 -K 选项?

上面列举的一些情形,即便是对于GMT比较熟悉的人,也偶尔会因为一时粗心而弄错。画图已经很不容易啦,还要时时注意 -K-O 和重定向有没有用错,还能不能安心的画图了?

在被 -K-O 的用法坑了几次之后,就得想一想,有没有办法可以避免这个问题呢?下面展示了一些小技巧:

#!/bin/bash

PS=map.ps
J=JX5c/5c
R=0/10/0/10

# 写入文件头
gmt psxy -J$J -R$R -T -K > $PS

# 真正的绘图命令
gmt xxxx -J$J -R$R ... -K -O >> $PS
gmt xxxx -J$J -R$R ... -K -O >> $PS

# 写入文件尾
gmt psxy -J$J -R$R -T -O >> $PS

解释一下:

  • 对于需要用多个命令绘图的图片,最好将命令写到脚本文件中,这样方便记录和调试命令
  • 上面的脚本是bash脚本,并将常出现的值定义成变量,以方便使用和修改
  • psxy 模块的 -T 选项表示空输入,即该命令不会绘制任何实际的图形
  • gmt psxy ... -T -K 只向PS文件中写入头部
  • gmt psxy ... -T -O 只向PS文件中写入尾部
  • 中间的全部绘图命令统一用 -K -O >> 。这样的统一使得,任意调整命令顺序或删减命令,都不需要修改 -K-O 和重定向符号!
  • 实际使用中, 第一个 gmt psxy -T -K 命令也可以考虑改成只绘制底图边框的 gmt psbasemap -B ... -K