Search code examples
gnuplot

Clip vectors on circle in gnuplot


I try to draw some vector fields in a circular region. Consider the following MWE

unset grid
unset tics
unset colorbox
unset border

set size square

besselj(n, x) = n > 1 ? 2*(n-1)/x*besselj(n-1,x) - besselj(n-2,x) : (n == 1 ? besj1(x) : besj0(x))
dbesselj(n, x) = n/x*besselj(n,x) - besselj(n+1,x)

rho(x,y) = sqrt(x**2+y**2)
phi(x,y) = atan2(y,x)

d = 1.0
l = 1.0
z = l/2

q = 1

set xrange [-d/2*1.1:d/2*1.1]
set yrange [-d/2*1.1:d/2*1.1]

Erho(x,y,n,ynp) = (-1/rho(x,y)) * besselj(n, (ynp*2/d)*rho(x,y)) * (-n*sin(n*phi(x,y))) * sin(q*pi*z/l)
Ephi(x,y,n,ynp) = (ynp*2/d) * dbesselj(n, (ynp*2/d)*rho(x,y)) * (cos(n*phi(x,y))) * sin(q*pi*z/l)

Ex(x,y,n,ynp) = rho(x,y) > d/2 ? NaN : cos(phi(x,y))*Erho(x,y,n,ynp) - sin(phi(x,y))*Ephi(x,y,n,ynp)
Ey(x,y,n,ynp) = rho(x,y) > d/2 ? NaN : sin(phi(x,y))*Erho(x,y,n,ynp) + cos(phi(x,y))*Ephi(x,y,n,ynp)

mag(x,y,n,ynp) = sqrt(Ex(x,y,n,ynp)**2 + Ey(x,y,n,ynp)**2)

set object circle at 0,0 size 0.5 fc black lw 3 front

set multiplot layout 1,2

set title 'TE_{01}'
set table 'tmp.dat'
set samples 16
set isosamples 16
plot '++' u 1:2:(Ex($1,$2,0,3.832)/50):(Ey($1,$2,0,3.832)/50) w vectors
unset table
set samples 250
set isosamples 250
plot '++' u 1:2:(mag($1,$2,0,3.832)) w image notitle, \
     'tmp.dat' u 1:2:3:4 w vectors head filled lc black lw 1 notitle

set title 'TE_{11}'
set table 'tmp.dat'
set samples 16
set isosamples 16
plot '++' u 1:2:(Ex($1,$2,1,1.841)/20):(Ey($1,$2,1,1.841)/20) w vectors
unset table
set samples 250
set isosamples 250
plot '++' u 1:2:(mag($1,$2,1,1.841)) w image notitle, \
     'tmp.dat' u 1:2:3:4 w vectors head filled lc black lw 1 notitle

unset multiplot

which plots the vector field as well as its magnitude inside the circle with diameter d. The result from this is

output from the above code

which is totally okay for the left image (TE01), but the right image (TE11) looks ugly because there are some vectors which are drawn outside the circle. My actually desired result is this

desired result

where I have no vectors outside of the black circle. How can I achieve that? I know there is the clip function in gnuplot, but this does not allow to specify the shape to be used for clipping.


Solution

  • Here is what you can try. Define your own clip function, e.g. a circle. First you need to check whether a data point is outside of your circle or not. Clip(x,y) returns NaN if it is outside and 0 if it is inside. Now, when you plot simply add the value of the clip function to your value. Your data will be clipped within a circle because something +0 remains unchanged and something +NaN will be NaN and will not be plotted. It is sufficient if you do this just for x (vector start) and x + delta x (vector end).

    Code:

    ### clip function in circle form
    reset session
    set size square
    
    # create some test data
    set samples 25
    Scaling = 0.5
    set table $Data
    plot [-5:5] '++' u 1:2:(Scaling*$1/sqrt($1**2+$2**2)): \
             (Scaling*$2/sqrt($1**2+$2**2)) : (sqrt($1**2+$2**2)) with table
    unset table
    
    set palette rgb 33,13,10
    CenterX = 0
    CenterY = 0
    Radius = 3.5
    Clip(x,y) = sqrt((x-CenterX)**2 + (y-CenterY)**2) > Radius ? NaN : 0
    
    set xrange[-6:6]
    set yrange[-6:6]
    
    set multiplot layout 1,3
    
        plot $Data u 1:2:3:4:5 w vec lc pal not
    
        plot $Data u ($1+Clip($1,$2)):2:($3+Clip($1+$3,$2+$4)):4:5 w vec lc pal not
    
        CenterX = 1
        CenterY = 1
        plot $Data u ($1+Clip($1,$2)):2:($3+Clip($1+$3,$2+$4)):4:5 w vec lc pal not
    
    unset multiplot
    ### end of code
    

    Result: enter image description here