Charlie
Charlie

Reputation: 329

gnuplot: how to make xy, xz, and yz planes opaque/solid in 3D plot?

I have recently picked up GNUplot, and am plotting some 3D data sets using the "matrix" data format. After a mashup of some command files I found on the web, it's working pretty well, however I haven't found anything on how to do the following:

I'd like to plot my data as a 3D surface with solid/opaque surfaces in the xy plane at the z-minimum and the xz and yz planes at the x and y data limits. For instance, my plot currently looks like this:

http://audio.claub.net/temp/waterfall__plot_normalized_to_on-axis.JPG

I would prefer that it has opaque planes like the image below:

http://www.musicanddesign.com/images/NOTE_Polar_surface_SE_Datadata.gif

(Sorry for not posting the actual images, but I am too new to this forum and don't have that privilage yet).

I'm guessing that I need to manually add the planes as additional 3D surfaces with their own matrix data structure, but I am not sure how to do that.

I am currently plotting the data using the commands:

reset
set xrange [100:20000]
#set yrange [-60:60]
#set zrange [-25:3]
set logscale x
set cntrparam levels increment GPVAL_DATA_Z_MAX-2,-2,-30
# GPVAL_DATA_Z_MAX above contains the max z value in the data set
set surface
set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency  [Hz]' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle\n[deg]" offset -12,0
set view 60,20
set clabel
set tics out
set key at 120000,-20 noautotitle title "SPL level"
set hidden3d offset 3
set isosamples 200,100
splot 'data.dat' nonuniform matrix using 2:1:3 lt 9

Can someone suggest how I can generate the opaque surfaces in the plot?

Thanks for any help on this.

.

Upvotes: 4

Views: 4913

Answers (3)

Christoph
Christoph

Reputation: 48390

Here is how you can draw these planes (first the code and the result, then the explanation):

reset
set terminal pngcairo size 1000,800
set output 'test.png'
set xrange [100:20000]
set logscale x
set cntrparam levels increment -2,-2,-30

set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency (in Hz)' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle (in deg)" rotate parallel
set view 60,20
set tics out
set key at screen 0.94, screen 0.5 noautotitle title "SPL level"
set hidden3d offset 3

splot 'data.dat' nonuniform matrix using 2:1:3 lt 9, \
      '' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) lt -3 nocontour,\
      '' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt -3 nocontour

This gives:

enter image description here

To create the xz-plane (2nd row in the splot command), I did the following:

  • If the y value equals to the first value (-60), then the z-value of the file are used (the -0.02 is only for cosmetics, just remove that to see the difference). If the y-value equals to the second value (-50), then the z-value is set to the minimum (-40). For all other points of the surface 1/0 is used, which generates undefined data points which are skipped.

  • The lt -3 means that no surface lines are drawn.

  • nocontour omits the contours for this plane

The yz-plane is generated accordingly, but now the x-values must be checked. This assumes, that you known the limits and increments of your data files. I you don't, or if these change often, some more tricking is required.

As you may have noted, I also changed some other parts of your file:

  • GPVAL_DATA_Z_MAX is available only after plotting, so you cannot use it to set the increment. (Only if you call the script twice, without the reset). You could use the stats command to extract minimum and maximum data values.

  • You can use screen coordinates to position the key.

  • The ylabel can be positioned parallel to the axis with rotate parallel.

Edit: How to add contour lines with the same colors on the planes

Here is the code:

reset
set terminal pngcairo size 1000,800
set output 'test.png'
set xrange [100:20000]

# added following block:
set yrange [-60:60]
set zrange [-40:5]
set lmargin screen 0.2
set tmargin screen 0.8
set rmargin screen 0.8
set bmargin screen 0.2

set logscale x
set cntrparam levels increment -2,-2,-30

set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency (in Hz)' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle (in deg)" rotate parallel
set view 60,20
set tics out
unset key

set hidden3d nooffset
set multiplot
splot 'data.dat' nonuniform matrix using 2:1:3 lt 9,\
      '' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) lt -3 nocontour, \
      '' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt -3 nocontour

unset tics
unset xlabel
unset ylabel
unset border

unset surface
unset hidden3d
splot 'data.dat' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) lt 9,\
      '' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt 9
unset multiplot

which gives:

enter image description here

I did the following additions compared to the first example:

  • I added explicit margins and set manual yrange and zrange. This is required because the contour lines of the planes are drawn with a second splot command in multiplot mode, but after unsetting border, tics and labels (otherwise the plot might lock jagged because of different anti-aliasing).

  • Draw only the contours of the planes. I need to unset surface before plotting them, because the contour line types are taken relative the the surface line type. So I need to use lt 9, but don't want the surface itself to be drawn.

Upvotes: 5

Charlie
Charlie

Reputation: 329

Thanks to the great answer by Christoph I am now able to see how to add the "sides" to the plot so that the result looks like a 3D object.

I modified the commands a bit. Now that I can add sides, it would be nice to also have the contour lines run from the z-axis tics across the "side" and meet the falling edge of the surface. Doing that means that I do not need the key, since the viewer can read off the position of the line from its z-axis intersection. The code I am using, and a link to the resulting plot, are given below. I want all mesh surfaces to be the same color and the contour lines must have the same color on the surface and the sides. If I used the multi-color countour lines, the color was always different on each face. So I have come up with this method that uses only one color for all contour lines, but that should be OK for my needs.

Here is the code:

reset
set terminal pngcairo size 1000,800 #I use a ported windows version, so I use the win term
set output 'test.png'
set xrange [100:20000]
set logscale x
set cntrparam levels increment 0,-5,-40
set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency (in Hz)' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle (in deg)"
set view 60,20
set tics out
unset key
unset clabel
set hidden3d offset 3
splot 'test.dat' nonuniform matrix using 2:1:3 w l lt 1 lc rgb "#3D59AB", \
      '' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) w l lt 1 lc rgb "#3D59AB" ,\
      '' nonuniform matrix using 2:(60):($1 == 60 ? $3-0.02 : ($1 == 50 ? -40 : 1/0)) w l lt 1 lc rgb "#3D59AB" ,\
      '' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt -999 

.

Finally, here is the resulting plot:

enter image description here

Upvotes: 1

jambono
jambono

Reputation: 408

Try to change the last line by

set pm3d
splot 'data.dat' nonuniform matrix using 2:1:3 lt 9 with pm3d at s

to change the color add

set palette rgbformulae 33,13,10

before splot

Upvotes: 0

Related Questions