如何使用gnuplot为一组曲线添加一致箭头

时间:2014-10-23 20:40:39

标签: gnuplot

我想在gnuplot中为一系列曲线添加箭头。问题是如何将箭头放在曲线的中心。我的解决方案是在点序列中找到线段,并为该线段绘制一个箭头。它有效,但箭头的大小不同。

我已经用python + gnuplot编写了一个代码,但它看起来很丑陋

#!/bin/python

import numpy as np
import Gnuplot

def middleArrowCurve(g, x,y, percent, reverse=False):
    d = Gnuplot.Data(x,y,with_='l')
    index = int(len(x)*percent)
    fromx,tox = x[index],x[index+1]
    fromy,toy = y[index],y[index+1]
    g('set style arrow 1 front head filled size screen 0.03,15 lt 1 lw 1')
    if reverse:
        g('set arrow from ' + str(tox) + ',' + str(toy) + ' to ' + str(fromx) + ',' + str(fromy) + '  as 1')
    else :
        g('set arrow from ' + str(fromx) + ',' + str(fromy) + ' to ' + str(tox) + ',' + str(toy) + '  as 1')
    return d


def stableNode2():
    g = Gnuplot.Gnuplot(persist=1)
    g('set term png')
    g('set output "stableNode2.png"')
    g('unset key')
    g('unset tics')
    g('unset border')
    g('set xrange [-1:1]')
    g('set yrange [-1:1]')
    data = []
    reverse = False 
    for s in [-1,1]:
        x = np.linspace(s,0,20)
        data.append(middleArrowCurve(g,x,0.6*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,-0.6*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,2*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,-2*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,x*0,0.5,reverse))
        data.append(middleArrowCurve(g,x*0,x,0.5,reverse))

    g.plot(*data)

stableNode2()

enter image description here

2 个答案:

答案 0 :(得分:2)

从版本4.6开始,如果箭头长度小于头部长度的两倍,gnuplot会自动缩放箭头。在5.0版本中(几乎稳定,5.0RC2已经用完),引入了一个额外的箭头参数fixed来防止这种缩放。所以使用

g('set style arrow 1 front head filled size screen 0.03,15 fixed lt 1 lw 1')

给出了结果:

arrow with all the same length

在版本4.6中,我不知道任何其他解决方法,而不是增加某些箭头的长度。

答案 1 :(得分:1)

使用set object poly可以解决此问题。

#!/bin/python

import numpy as np
import Gnuplot

arrowCount = 0
def addArrow(g, x,y, dx, dy, width=0.01,angle=15):
    def normal(v):
        s = 1.0/np.sqrt(v[0]**2+v[1]**2)
        v[0] *= s
        v[1] *= s
    l = [dx,dy]
    n = [-dy,dx]
    normal(l)
    normal(n)
    length = width/np.tan(angle*np.pi/360)
    coords = []
    coords.append((x,y))
    coords.append((x+n[0]*width,y+n[1]*width))
    coords.append((x+l[0]*length,y+l[1]*length))
    coords.append((x-n[0]*width,y-n[1]*width))
    coords.append((x,y))
    coordsStr = "from " 
    coordsStr += " to ".join([str(c[0])+","+str(c[1]) for c in coords])
    global arrowCount
    arrowCount += 1
    return 'set object ' + str(arrowCount) + ' polygon ' + coordsStr + ';set object ' + str(arrowCount) + ' fc rgb "red" fs solid '

def middleArrowCurve(g, x,y, percent, reverse=False):
    d = Gnuplot.Data(x,y,with_='l')
    index = int(len(x)*percent)
    fromx,tox = x[index],x[index+1]
    fromy,toy = y[index],y[index+1]
    if reverse:
        return d,addArrow(g, tox,toy, -tox+fromx, -toy+fromy)
    else:
        return d,addArrow(g, fromx,fromy, tox-fromx, toy-fromy)

def stableNode2():
    g = Gnuplot.Gnuplot(persist=1)
    g('set term png')
    g('set output "stableNode2.png"')
    g('unset key')
    g('unset tics')
    g('unset border')
    g('set xrange [-1:1]')
    g('set yrange [-1:1]')
    data = []
    reverse = False 
    for s in [-1,1]:
        x = np.linspace(s,0,20)
        data.append(middleArrowCurve(g,x,0.6*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,-0.6*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,2*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,-2*x**2,0.5,reverse))
        data.append(middleArrowCurve(g,x,x*0,0.5,reverse))
        data.append(middleArrowCurve(g,x*0,x,0.5,reverse))

    for a in data:
        g(a[1])
    g.plot(*[d[0] for d in data])

stableNode2()

剩下的问题是多边形箭头被线图覆盖的原因?如果我在线图之后放置多边形绘图,则只会忽略它们。

enter image description here