Search code examples
gnuplot

How do I indicate the starting position of a vector when drawing a function with vectors?


Take a look at this example:

set size square
set parametric
plot [0:2*pi] sin (t), cos (t) with vectors

It will draw a unit circle with vectors coming out of the origin like spokes of a wheel.

What if I want to draw vectors along the rim of the wheel, or otherwise positioned as a function of time?

Observe that adding more functions, like so:

plot [0:2*pi] sin (t), cos (t), cos (t), -sin (t) with vectors

— Makes gnuplot draw two distinct curves, one with lines and another with vectors — this is not what I want at all.

I know that I could use the fake input file +, like so:

plot "+" using (sin ($1)): (cos ($1)): (cos ($1)): (-sin ($1)) with vectors

— But it does not quite make sense.

  • Firstly, why should I use data syntax when what I want to do is draw a function?
  • Secondly, it does not quite work because the parameter $1 will range over the width of the picture, while I need it to range over ±π. For any given size of the picture, I can apply a linear transformation to $1 to get the range I want, but this means that I shall need to fine-tune the number of samples and the coëfficients of the linear transformation every time the size of the picture changes — this is not maintainable.

Note that the functions I actually want to draw are going to be significantly more complicated than a circle, so the solution should be reasonably robust.

If this is impossible, please write an answer that says so.


Solution

  • Not sure, if I fully understand your question. Check the following example and let me know if it solves your problem. If not, please clarify in more detail.

    In the first plot you simply plot a line connecting all datapoints in pseudo-file + (check help special-filenames). I suspect that the issue you're having is with samples and range. Please check help sampling 1D.

    In the second plot command you actually plot a vector from the current point (x1,y1) to the previous point (x0,y0), hence if you want an arrow at the "front" you need to specify backhead.

    As you also mentioned, if you plot a vector you have to specify (x):(y):(dx):(dy). I don't see how to do this with a parametric plot where you can only specify x,y. Maybe, you can do it somehow, but at least I'm not aware of it.

    Script:

    ### plot with lines and with vectors
    reset session
    
    fx(t) = cos(t)   # or set your special function
    fy(t) = sin(t)   # ditto
    
    set size ratio -1
    set xrange[-1.5:1.5]
    set yrange[-1.5:1.5]
    set key noautotitle
    
    set multiplot layout 1,2
    
        set title "with lines"
        plot sample [t=0:2*pi] '+' u (fx(t)):(fy(t)) w l
    
        set title "with vectors"
        set samples 17
        x1 = y1 = NaN 
        plot sample [t=0:2*pi] '+' u \
             (x0=x1, x1=fx(t)):(y0=y1,y1=fy(t)):(x0-x1):(y0-y1) w vec backhead
    
    unset multiplot
    ### end of script
    

    Result:

    resulting output graph