Gnuplot:渐变彩色箭头

3
我想画一支箭头,不只是单色,而是沿其长度呈现渐变颜色。 有人知道如何实现吗?以下是创建箭头的伪代码,起始为红色,结束为蓝色:
set palette defined (0 "red", 1 "blue")
set cbr [0:1]
set arrow from 0,0 to 1,1 linecolor palette cb [0:1] # this doesn't work
2个回答

2

使用 line palette 可以对一条线进行颜色编码。通过第二个命令,可以使用 set arrow 或者 plot vector 命令来设置箭头。

set palette defined (0 "red", 1 "blue")
set cbr [0:1]

set arrow 1 from 0.9,0.9 to 1,1 lc "blue"
plot sample [t=0:1] "+" us (t):(t):(t) w l palette

因此需要两个命令。箭头的头部是单色的,需要您指定颜色。

2
除了@Friedrich的解决方案,我想建议一个更一般的解决方案(尽管更复杂)。
我假设你想绘制箭头以外的东西。 如果您的图形需要使用调色板,我猜您会遇到麻烦,因为我不确定gnuplot是否支持在一个plot命令中使用多个调色板 (参见Gnuplot 5.2 splot: Multiple pm3d palette in one plot call)。因此,您必须自己实现箭头的调色板(例如,请参见Gnuplot: transparency of data points when using palette)。如果您想使用Cubic Bézier绘制弯曲箭头,请参考(https://stackoverflow.com/a/60389081/7295599)。 代码:
### arrow with color gradient (besides other palette in plot)
reset session

array A[4] = [-4,-2,4,2]   # arrow coordinates x0,y0,x1,y1
Ax(t) = A[1] + t*(A[3]-A[1])
Ay(t) = A[2] + t*(A[4]-A[2])
AColorStart = 0xff0000   # red
AColorEnd =   0x0000ff   # blue
r(c) = (c & 0xff0000)>>16
g(c) = (c & 0x00ff00)>>8
b(c) = (c & 0x0000ff)
AColor(t) = ((int(r(AColorStart)*(1-t)+r(AColorEnd)*t))<<16) + \
            ((int(g(AColorStart)*(1-t)+g(AColorEnd)*t))<<8)  + \
              int(b(AColorStart)*(1-t)+b(AColorEnd)*t)

array AHead[1]   # dummy array for plotting a single point, here: arrow head
set angle degrees
set style arrow 1 lw 3 lc rgb var size 0.5,15 fixed

set palette grey

plot '++' u 1:2:($1*$2) w image notitle, \
     [0:0.99] '+' u (Ax($1)):(Ay($1)):(AColor($1)) w l lw 3 lc rgb var notitle,\
     AHead u (Ax(0.99)):(Ay(0.99)):(Ax(1)-Ax(0.99)):(Ay(1)-Ay(0.99)):(AColor($1)) w vec as 1 notitle
### end of code

Result:

enter image description here

补充:

以下是一种变化形式,允许绘制多个箭头,每个箭头带有不同的调色板。我猜这需要 gnuplot 5.2,因为它需要索引数据块 $PALETTE[i]

代码:

### multiple arrows each with different color gradients (besides other palette in plot)
reset session

# define palettes
set print $myPalettes
    test palette                # get default palette into datablock $PALETTE
    print $PALETTE              # add palette to $myPalettes
    set palette rgb 33,13,10    # define next palette
    test palette                # get palette into datablock $PALETTE
    print $PALETTE              # add palette to $myPalettes
    set palette defined (0 "blue", 1 "black", 2 "red")   # define next palette
    test palette                                         # get palette into datablock $PALETTE
    print $PALETTE                                       # add palette to $myPalettes
set print
    
ColorComp(p,t,c) = int(word($myPalettes[p*257+int(255*t)+1],c+1)*0xff)
AColor(p,t) = (ColorComp(p,t,1)<<16) + (ColorComp(p,t,2)<<8) + ColorComp(p,t,3)
           
set size ratio -1
set angle degrees
unset key
set style arrow 1 lw 3 lc rgb var size 0.5,15 fixed
array AHead[1]      # dummy array for plotting a single point, here: arrow head
set palette grey    # yet another palette for the background

# x0 y0 x1  y1  paletteNo
$Arrows <<EOD
-4  -4   4   0   0
-4  -2   4   2   1
-4   0   4   4   2
EOD

Ax(i,t) = word($Arrows[i],1) + t*(word($Arrows[i],3)-word($Arrows[i],1))
Ay(i,t) = word($Arrows[i],2) + t*(word($Arrows[i],4)-word($Arrows[i],2))
Palette(i) = int(word($Arrows[i],5))

plot '++' u 1:2:($1*$2) w image, \
     for [i=1:|$Arrows|] [0:0.99:0.01] '+' u (Ax(i,$1)):(Ay(i,$1)):(AColor(Palette(i),$1)) w l lw 4 lc rgb var, \
     for [i=1:|$Arrows|] AHead u (Ax(i,0.99)):(Ay(i,0.99)): \
         (Ax(i,1)-Ax(i,0.99)):(Ay(i,1)-Ay(i,0.99)):(AColor(Palette(i),$1)) w vec as 1
### end of code

Result:

enter image description here


哇,有很多我迄今为止没有想过的有趣结构。在我的情况下,只有一个调色板,但是手头有你的解决方案仍然很不错。关于向量图,我有一个问题:绘制了多少箭头?我猜这取决于采样密度?对于非常高的值,像@Friedrich建议的那样添加一个短箭头可能更有效。 - Eldrad
1
很高兴听到这对您有所帮助。默认采样率为100。因此,最好只绘制一个向量。最小采样率为2。可能可以单独设置采样,但我不确定如何操作。无论如何,我修改了答案并添加了另一个“hack”,使用单个箭头来实现箭头的效果。 - theozh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接