- 2023-07-22 23:51:45
如果将gnuplot视为一个绘图系统, 以便进行比较自由的绘制, 那么首先需要明确的是如何指定一个像素点的位置.
对于gnuplot, 指定一个像素点的位置时可以使用几种不同的坐标系统:
axis
: 默认的轴坐标, 与绘制数据所用坐标系相同graph
: 图形分数坐标, 范围[0, 1], 以绘图边框(XY轴边框)为基准screen
: 屏幕分数坐标, 或称画布坐标, 页面坐标, 范围[0, 1], 以整个绘制区域(页面, 画布, canvas)为基准
这几种坐标的选择, 以方便为主.
下面是一个具体的绘图示例, 使用了这几种坐标系. 其中浅灰为整个画布, 浅红为图形坐标系统范围.
如果需要在这几种坐标系统之间进行转换, 需要知道:
- 画布大小: 由终端设置决定, 也可借助gnuplot内置变量推算
- 图形坐标轴的数值范围: 自动确定或手动指定
- 图形坐标在画布中的范围: 借助gnuplot内置变量获知
在绘图之后, 可以使用show variables all
或 show variables GPVAL_
来显示gnuplot的内置变量. 对于上面绘制的图片, 终端为pngcario
, 画布大小为 2000×1500 像素, 显示结果如下:
GPVAL_X_MIN = 0.0
GPVAL_X_MAX = 15.0
GPVAL_X_LOG = 10.0
GPVAL_DATA_X_MIN = 8.98846567431158e+307
GPVAL_DATA_X_MAX = -8.98846567431158e+307
GPVAL_Y_MIN = -0.5
GPVAL_Y_MAX = 1.0
GPVAL_Y_LOG = 10.0
GPVAL_DATA_Y_MIN = -0.402759374714085
GPVAL_DATA_Y_MAX = 1.0
GPVAL_X2_MIN = 0.0
GPVAL_X2_MAX = 15.0
GPVAL_X2_LOG = 10.0
GPVAL_DATA_X2_MIN = 8.98846567431158e+307
GPVAL_DATA_X2_MAX = -8.98846567431158e+307
GPVAL_Y2_MIN = 8.98846567431158e+307
GPVAL_Y2_MAX = -8.98846567431158e+307
GPVAL_Y2_LOG = 10.0
GPVAL_DATA_Y2_MIN = 8.98846567431158e+307
GPVAL_DATA_Y2_MAX = -8.98846567431158e+307
GPVAL_Z_MIN = -10.0
GPVAL_Z_MAX = 10.0
GPVAL_Z_LOG = 10.0
GPVAL_DATA_Z_MIN = 0.0
GPVAL_DATA_Z_MAX = 0.0
GPVAL_CB_MIN = 8.98846567431158e+307
GPVAL_CB_MAX = -8.98846567431158e+307
GPVAL_CB_LOG = 10.0
GPVAL_DATA_CB_MIN = 8.98846567431158e+307
GPVAL_DATA_CB_MAX = -8.98846567431158e+307
GPVAL_T_MIN = -5.0
GPVAL_T_MAX = 5.0
GPVAL_T_LOG = 10.0
GPVAL_U_MIN = -5.0
GPVAL_U_MAX = 5.0
GPVAL_U_LOG = 10.0
GPVAL_V_MIN = -5.0
GPVAL_V_MAX = 5.0
GPVAL_V_LOG = 10.0
GPVAL_R_MIN = 8.98846567431158e+307
GPVAL_R_MAX = -8.98846567431158e+307
GPVAL_R_LOG = 10.0
GPVAL_TERM_XMIN = 252
GPVAL_TERM_XMAX = 1908
GPVAL_TERM_YMIN = 182
GPVAL_TERM_YMAX = 1157
GPVAL_TERM_XSIZE = 39980
GPVAL_TERM_YSIZE = 29980
GPVAL_TERM_SCALE = 20
GPVAL_TERM_HCHAR = 603
GPVAL_TERM_VCHAR = 1139
GPVAL_VIEW_MAP = 0
GPVAL_VIEW_ROT_X = 60.0
GPVAL_VIEW_ROT_Z = 30.0
GPVAL_VIEW_SCALE = 1.0
GPVAL_VIEW_ZSCALE = 1.0
GPVAL_VIEW_AZIMUTH = 0.0
GPVAL_VIEW_XCENT = 1.0
GPVAL_VIEW_YCENT = 0.0
GPVAL_VIEW_RADIUS = 0.0
这些内置变量中与绘制数据有关的变量有:
GPVAL_DATA_X_MIN = 8.98846567431158e+307
: 数据点X方向最小值GPVAL_DATA_X_MAX = -8.98846567431158e+307
: 数据点X方向最大值GPVAL_DATA_Y_MIN = -0.402759374714085
: 数据点Y方向最小值GPVAL_DATA_Y_MAX = 1.0
: 数据点Y方向最大值
与坐标轴显示范围有关的变量有:
GPVAL_X_MIN = 0.0
: X方向坐标起点GPVAL_X_MAX = 15.0
: X方向坐标终点GPVAL_Y_MIN = -0.5
: Y方向坐标起点GPVAL_Y_MAX = 1.0
: Y方向坐标终点
与画布坐标系统(像素)有关的变量如下:
GPVAL_TERM_SCALE = 20
: gnuplot在绘图时会先将整个绘图区域放大, 绘制完成后再缩小回指定大小, 以此进行反走样, 减少锯齿, 提高图形的清晰度. 对png终端, 所用缩放系数为20
, 其他一些终端所用缩放系数可能不同.GPVAL_TERM_XMIN = 252
: X轴起始位置的像素序号, 从0开始计数GPVAL_TERM_XMAX = 1908
: X轴终止位置的像素序号, 从0开始计数GPVAL_TERM_XSIZE = 39980
: 绘图区域X方向的总像素数, 此值为放大后的大小GPVAL_TERM_HCHAR = 603
: X方向可容纳的总字符数, 取决于字体设置GPVAL_TERM_YMIN = 182
: 同上, Y方向的GPVAL_TERM_YMAX = 1157
:GPVAL_TERM_YSIZE = 29980
:GPVAL_TERM_VCHAR = 1139
:
有了这些数据, 我们就可以进行一些简单的计算, 获得一些设置的具体值, 或在不同坐标系统之间进行转换.
图形坐标的页边距
也就是图形坐标系左右上下的屏幕坐标
LMARGIN = GPVAL_TERM_XMIN / (1.0*GPVAL_TERM_XSIZE/GPVAL_TERM_SCALE)
RMARGIN = GPVAL_TERM_XMAX / (1.0*GPVAL_TERM_XSIZE/GPVAL_TERM_SCALE)
TMARGIN = GPVAL_TERM_YMAX / (1.0*GPVAL_TERM_YSIZE/GPVAL_TERM_SCALE)
BMARGIN = GPVAL_TERM_YMIN / (1.0*GPVAL_TERM_YSIZE/GPVAL_TERM_SCALE)
将轴坐标(X, Y)转换为图形坐标(Xg, Yg), 屏幕坐标(Xs, Ys)
图形坐标实际相当于归一化后的分数坐标, 可以根据轴坐标的范围与起始点计算
Xg = (X - GPVAL_X_MIN) / (1.*(GPVAL_X_MAX - GPVAL_X_MIN))
要转换到屏幕坐标, 我们需要知道在整个画布上, 以像素为单位时轴坐标的范围与起始点, 所以先要将轴坐标转换到画布上的像素坐标Xp,
Xp = GPVAL_TERM_XMIN + Xg * (GPVAL_TERM_XMAX - GPVAL_TERM_XMIN)
再归一化, 得到屏幕坐标
Xs = Xp / (GPVAL_TERM_XSIZE / GPVAL_TERM_SCALE)
综合起来
Xs = ( GPVAL_TERM_XMIN + (X-GPVAL_X_MIN)/(1.*(GPVAL_X_MAX-GPVAL_X_MIN)) * (GPVAL_TERM_XMAX-GPVAL_TERM_XMIN) ) / (1.*GPVAL_TERM_XSIZE/GPVAL_TERM_SCALE)
Ys = ( GPVAL_TERM_YMIN + (Y-GPVAL_Y_MIN)/(1.*(GPVAL_Y_MAX-GPVAL_Y_MIN)) * (GPVAL_TERM_YMAX-GPVAL_TERM_YMIN) ) / (1.*GPVAL_TERM_YSIZE/GPVAL_TERM_SCALE)
circle半径的换算
gnuplot在使用 circle
进行绘图时所指定的半径是以X坐标为标准的, 如果XY坐标的像素比例不为1, 那么一个圆在Y方向的半径数值就与X方向的不同, 这可能导致绘图时自动设定的Y轴范围不合适, 图形显示不完整.
如上面的图所示, 绘制时自动指定的坐标范围是根据数据点确定的, 没有考虑圆的半径. 绘制时所指定的圆半径为0.5, 是X方向的, Y方向半径对应的具体值则与Y方向的坐标范围有关. 对于具体的数据, 我们可以手动调整Y轴显示范围使得所有圆形显示完整, 但我们也需要能够自动计算所需范围的方法.
基本的想法是, 先绘制一遍图形, 获知绘图的Y轴默认范围, 在此基础上将其两端都扩展Y方向半径的值, 作为新的Y轴范围, 并以其重新绘制图形.
先根据X方向的半径值来计算对应的像素数
Rx = 0.5
Rp = Rx * (GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)/(1.*(GPVAL_X_MAX-GPVAL_X_MIN))
同理, 调整Y方向坐标范围后, 以Y方向半径值计算应该得到相同的像素数
Rp = Ry * (GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)/(1.*(GPVAL_Y_MAX-GPVAL_Y_MIN+2*Ry))
由此, 可以解出
Ry = (GPVAL_Y_MAX-GPVAL_Y_MIN) / (1.*(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)/Rp - 2.)
所以重新绘图时Y轴范围为[GPVAL_Y_MIN-Ry : GPVAL_Y_MAX+Ry]
. 这样绘制出的图形就可以完整显示所有圆了.
`