我想绘制一条线宽可变的曲线。如果我想使用点而不是线,我通常会执行以下操作:
gnuplot> plot 'curve.dat' u ($1):($2):($1) ps var
其中 curve.dat 填充有:
0 0
1 1
2 4
3 9
4 16
5 25
等等。现在,如果我尝试类似的线宽:
gnuplot> plot 'curve.dat' u ($1):($2):($1) lw var
我收到错误消息:
undefined variable: var
或者这是 gnuplot 无法完成的事情?
你是对的,
linewidth
不像var
那样接受pointsize
。但是你可以通过使用 filledcurves
: 来达到类似的效果
WIDTH_FACTOR=20
plot 'curve.dat' u ($1):($2+$1/WIDTH_FACTOR):($2-$1/WIDTH_FACTOR) w filledcurves
到目前为止,gnuplot 中还没有可变线宽。 此外,如果您的数据有
N
点,您将有 N-1
线,尽管您在数据中给出了 N
线宽。应跳过哪个数据点的哪个线宽?第一个还是最后一个?
如果你画锥形线,你就不会遇到这个问题。您可以为此使用 fillcurves,但正如 @Ilya Zakharevich 提到的,@Gavin Portwood 的解决方案实际上是绘制 line height,而不是 line width。
下面的解决方案也使用填充曲线,但绘制真实的线宽。为此,您必须转到像素坐标,进行一些计算并返回到轴坐标(尚不适用于对数刻度)。 gnuplot 可以轻松地用相同的 x 值填充两个 y 值之间的曲线,但这在这里没有帮助。但 gnuplot 也可以填充闭合曲线。因此,脚本通过创建路径的“右”轮廓和锥形“线”的反向“左”轮廓来创建闭合曲线。
编辑:完成修订
x + j*y
,而不是 x 和 y 值的单独函数和变量,其中 j = sqrt(-1)
是虚数单位。这稍微缩短了脚本。脚本:(适用于 gnuplot>=5.2.0,2017 年 9 月)
### variable linewidth / tapered lines plot
reset session
$Data <<EOD
1 10 1.0
9 20 25.0
2 30 15.0
4 20 5.0
7 40 5.0
3 70 1.0
2 50 25.0
4 40 3.0
7 70 30.0
9 40 80.0
EOD
# plot data to get GPVAL_... values and number of rows
plot $Data u (r=$0+1,$1):2
j = {0, 1} # imaginary unit
array P[r]
array LW[r]
stats $Data u (P[$0+1]=$1+j*$2, LW[$0+1]=$3) nooutput # put data into arrays
# axes to pixel conversion and vice versa
Factor = GPVAL_VERSION==5.2 && int(GPVAL_PATCHLEVEL)<=7 ? \
GPVAL_TERM eq "wxt" ? 20 : GPVAL_TERM eq "qt" ? 10 : 1 : 1
aMin = GPVAL_X_MIN + j*GPVAL_Y_MIN
pMin = GPVAL_TERM_XMIN + j*GPVAL_TERM_YMIN
R = Factor*((GPVAL_X_MAX-real(aMin))/(GPVAL_TERM_XMAX-real(pMin)) + \
j*(GPVAL_Y_MAX-imag(aMin))/(GPVAL_TERM_YMAX-imag(pMin)))
a2p(a) = (real(a)-real(aMin))/real(R) + real(pMin) + j*((imag(a)-imag(aMin))/imag(R) + imag(pMin))
p2a(p) = (real(p)-real(pMin))*real(R) + real(aMin) + j*((imag(p)-imag(pMin))*imag(R) + imag(aMin))
# various functions in pixel coordinates
dp(i) = a2p(P[i+1])-a2p(P[i]) # distance between two points
ap(i) = atan2(imag(dp(i)),real(dp(i))) + acos(0) # perpendicular angle (independent of setting degrees or radians)
wp(i,k) = LW[k]*0.5*(cos(ap(i)) + j*sin(ap(i))) # offset for outline
array OUTL[4*|P|-4]
do for [i=1:2*|P|-2] {
m0 = (i-1)/2 + 1 # integer division!
n0 = i/2 + 1 #
m1 = |P| - m0
n1 = |P| - n0 + 1
OUTL[i] = p2a(a2p(P[n0]) - wp(m0,n0))
OUTL[i+2*|P|-2] = p2a(a2p(P[n1]) + wp(m1,n1))
}
set style fill noborder
set key noautotitle
set grid x,y
plot OUTL u (real(OUTL[$0+1])):(imag(OUTL[$0+1])) w filledcurves lc "web-green"
### end of script
评论:
qt
终端中,结果看起来不同,这不是预期的方式,但我猜原因是图形库填充区域的方式。该脚本需要一些调整。pngcairo
终端:由于您必须绘制两次(第一次获取 GPVAL_...
变量),您还必须设置文件名两次,即类似这样:reset session
...
set term pngcairo
set output "SO52250137.png"
plot $Data u (r=$0+1,$1):2
set output "SO52250137.png"
...
plot OUTL u (real(OUTL[$0+1])):(imag(OUTL[$0+1])) w filledcurves lc "web-green"
set output
### end of script
结果:(来自
wxt
和 pngcairo
终端)
(从
qt
终端输出)