Search code examples
gnuplotcontour

gnuplot : how to have only one label of contour (interval -1 does ont work)


I am trying to get a 'contour map' of a function of 2 variables. My problem is that I would like the label to be displayed just once along the contour set (preferably in the middle of the length of the contour). I tried any combination of set cntrparam start n interval m (including <0) but I did not manage to do it (sometimes no label sometimes way too many, but never only one). I need the sample high enough to get a "smooth" figure...

Any help would be greatly appreciated, regards,

Here is my code:

set isosamples 200,200
set cntrlabel  format start 50 interval -1 font '.7' onecolor
set cntrparam levels discrete 
-50,-400,-300,-200,-100,50,20,100,200,300,400,500,0,-20
set xrange [-5:5]
set yrange [-5:5]
set title "Ensembles de niveaux "
set xlabel " X "
set ylabel "Y "
set contour base
set view map

splot 4*x**3+4*y**3 with lines  lw 3, 4*x**3+4*y**3 with labels point  pointinterval -1

And the expected output:

enter image description here


Solution

  • From gnuplot help ctrlabel:

    Setting the interval to a negative value means that the label appear only once per contour line. However if set samples or set isosamples is large then many contour lines may be created, each with a single label.

    I guess this hasn't changed with gnuplot 5.4. This means if you reduce the number for isosamples you might get the desired single label per contour line, however, with the drawback of lower accuracy of your curves. Probably, it cannot be easily "predicted" when gnuplot will start to split the contour lines into several sub-lines (although a single line would be sufficient).

    To be honest, I don't know yet of a simple and satisfying workaround.

    Code: (slightly modified)

    ### contour lines with only one label per line
    reset session
    
    set cntrlabel format start 50 interval -1 onecolor
    set cntrparam levels discrete -400,-300,-200,-100,-50,-20,0,20,50,100,200,300,400,500
    set xrange [-5:5]
    set yrange [-5:5]
    
    set contour base
    set view map
    unset surface
    set key noautotitle
    
    f(x,y) = 4*x**3+4*y**3
    
    set multiplot layout 2,1
    
        set title "isosamples 25,25"
        set isosamples 25,25 
        splot f(x,y) w l, \
              f(x,y) w labels point pi -1
    
        set title "isosamples 200,200"
        set isosamples 200,200 
        splot f(x,y) w l, \
              f(x,y) w labels point pi -1
              
    unset multiplot
    ### end of code
    

    Result:

    enter image description here

    Addition: (workaround to get high precision contours and single labels only)

    The idea of this simple but odd workaround is to plot the contour lines twice into two tables. Once with high precision for the contour lines, and once with low precision for the labels (which is good enough). Instead of splot the data is plotted with plot.

    Code:

    ### contour lines with only one label per line
    reset session
    
    set cntrlabel format start 50 interval -1 onecolor
    set cntrparam levels discrete -400,-300,-200,-100,-50,-20,0,50,20,100,200,300,400,500
    set xrange [-5:5]
    set yrange [-5:5]
    
    set contour base
    set view map
    unset surface
    set key noautotitle
    
    f(x,y) = 4*x**3+4*y**3
    
    set isosamples 25,25 
    set table $ContourLabels
        splot f(x,y)
    unset table
    
    set isosamples 200,200 
    set table $Contour
        splot f(x,y)
    unset table
    
    plot $Contour u 1:2 w l lc "web-green", \
         $ContourLabels u 1:2:3 every ::50::50 w labels
    ### end of code
    

    Result:

    enter image description here