Gnuplot:渐变彩色箭头

Gnuplot: gradient coloured arrow

我想画一个不是单一颜色的箭头,而是沿其长度方向的颜色渐变。有谁知道如何实现这一目标?一些用于创建以红色开始并以蓝色结束的箭头的伪代码:

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

使用 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

因此需要两个命令。箭头的头是单色的,你必须指定。

除了@Friedrich 的解决方案,我想提出一个更通用的解决方案(虽然更复杂)。

我假设您想绘制除箭头之外的其他内容。 如果您的图表需要使用调色板,我猜您有麻烦了,因为我不确定 gnuplot 是否在 plot 命令中支持多个调色板 (参见 ). So, you have to implement the palette for your arrow by yourself (see e.g. ). If you want to do bent arrows using Cubic Bézier check ()。

代码:

### 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:(*) w image notitle, \
     [0:0.99] '+' u (Ax()):(Ay()):(AColor()) 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()) w vec as 1 notitle
### end of code

结果:

加法:

值得一提的是,这里有一个变体,它允许使用不同的调色板绘制多个箭头。我想它需要 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:(*) w image, \
     for [i=1:|$Arrows|] [0:0.99:0.01] '+' u (Ax(i,)):(Ay(i,)):(AColor(Palette(i),)) 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),)) w vec as 1
### end of code

结果: