How to avoid pm3d surface from occluding other objects which are infront of it? - gnuplot

I am trying to plot a simple linear surface of the equation x + y + 2z = 0. This is my file:
set xrange [-4:4]
set yrange [-4:4]
set zrange [-4:4]
set xlabel 'x'
set ylabel 'y'
set zlabel 'z'
set xyplane at -4.0
unset xzeroaxis
unset yzeroaxis
unset zzeroaxis
set border 1023-128
set xtics out nomirror
set ytics out nomirror
set ztics out
set xtics add ('' -4)
set label 1 "{/:Italic x} + {/:Italic y} + 2{/:Italic z} = 0" at 4,4.2,-2 font 'Times New Roman, 11'
set arrow 1 from 0,0,-4 to 0,0,4 filled
set arrow 2 from 0,-4,0 to 0,4,0 filled
set arrow 3 from -4,0,0 to 4,0,0 filled
set arrow 4 from 3.9,4.1,-2.1 to 3.6,3.6,-2.5
unset key
set pm3d lighting primary 0.5 specular 0.6
set style fill transparent solid 1 noborder
set palette defined (0 "cyan", 1 "green")
unset colorbox
set pm3d depthorder
splot -x/2-y/2 with pm3d
The result
I'm using arrows to show the axis, since they seem to be stuck to the xy plane, and moving it causes further issues with the tics and border. But now the problem is that they are completely occluded by the surface. Is there a setting which allows to appear in front when they "pierce" the surface? I'd like to make the surface semitransparent, but the problem is clearer with these settings.

I guess your original idea, i.e. "piercing" a 3D surface with an arrow or line does not work right away in gnuplot, because gnuplot will not calculate the piercing points automatically. Please correct me if I am wrong and let me know in case there might be a simple solution to this.
As you did in your simple case, you can just split the arrow at the origin, because you already know the piercing point. However, what do you do if the surface is irregular or has several piercing points?
Solution: take the effort to create a segmented 3D arrow and let gnuplot automatically show and hide the surfaces as needed. This is probably getting close to what you had in mind. However, this solution will show surprises when you want to change the color of the arrows. So, there is still room for improvement.
Code: (simple version with arrows just along x,y,z axes)
### arrows "piercing" a 3D surface
reset session
set view equal xyz
set xyplane relative 0.0
set xrange [-4:4]
set yrange [-4:4]
set zrange [-4:4]
# create 3D arrow
r = 0.01 # radius of arrow
rHead = 0.1 # radius of arrrowhead
n = 6 # corners of arrow
set print $myArrow
do for [h=-100:90] {
do for [a=360/n:360:360/n] {
print sprintf("%g %g %g",r*cos(a),r*sin(a), h/100.)
}
print ""
}
do for [h=90:100] {
do for [a=360/n:360:360/n] {
print sprintf("%g %g %g",rHead*(100-h)/10.*cos(a), \
rHead*(100-h)/10.*sin(a), h/100.)
}
print ""
}
set print
unset key
unset colorbox
set pm3d depthorder
set samples 100
set isosamples 100
set view 65,46,1.3
# function to demonstrate "piercing"
f(x,y) = (sin(x*3)/x + sin(y*3)/y - 3)/2
splot \
f(x,y) w pm3d, \
$myArrow u 1:2:($3*4):(0) w pm3d lc rgb var, \
$myArrow u 2:($3*4):1:(0) w pm3d lc rgb var, \
$myArrow u ($3*4):1:2:(0) w pm3d lc rgb var
### end of code
Result:

gnuplot> help layer
A gnuplot plot is built up by drawing its various components in a fixed order.
This order can be modified by assigning some components to a specific layer
using the keywords `behind`, `back`, or `front`. For example, to replace the
background color of the plot area you could define a colored rectangle with the
attribute `behind`.
set object 1 rectangle from graph 0,0 to graph 1,1 fc rgb "gray" behind
The order of drawing is
behind
back
the plot itself
the plot legend (`key`)
front
Within each layer elements are drawn in the order
grid, axis, and border elements
pixmaps in numerical order
So basically you need to add the "front" attribute to the objects you want to appear in front of the plot.

Related

Gnuplot, multiple splots with different color palette [duplicate]

This question already has answers here:
Plotting multiple pm3d surfaces each having its own palettes in gnuplot
(2 answers)
Closed 2 years ago.
I have two 3d surfaces. Is it possible to use a different color palette for each surface with splot?
The script that i used and the graph that is produced follow:
set title "Thermal efficiency versus turbine inlet temperature and degree of superheating diagram"
set termopt enhanced
set grid
set key top left
set xlabel "ΔT_{super} [^{o}C]"
set ylabel "T_{3} [^{o}C]"
set zlabel "n_{th} [-]"
#set datafile missing '0.000000000000000000e+00'
#set datafile missing '0.000000'
set hidden3d
set pm3d
set view 60,60
set palette rgb 7,5,15 #black-blue-red-yellow
splot "para_sub_dtsuper_iso_dtppreg_1.txt" using ($1):($2-273.15):($5) title "Conventional ORC" with lines lt 1 lw 1.5,\
"para_sub_dtsuper_iso_dtppreg_1.txt" using ($1):($2-273.15):($6) title "Regenerative ORC" with lines lt 1 lw 1.5,\
pic_1
On a side not, i would like to know if it is possible to produced mesh color-gradient surfaces like in the picture below:
pic_2
Thank you in advance.
Here is a revised version of the plot that theozh linked to. It shows two surfaces in the same plot, one using color mapping via the built-in palette mechanism and the other effectively doing the same sort of color mapping explicitly. The development version of gnuplot has automated this so that you can construct and use multiple palettes by assigning a name to each one.
#
# Demonstrate construction and use of a separate palette
#
# This method works in 5.2 but requires "lc rgb variable"
# rather than the more natural "fillcolor rgb variable".
# "set pm3d interpolate" breaks the color mapping of this method
#
# This creates a palette equivalent to
# set palette defined (0 "dark-blue", 1 "white")
#
array blues[256]
do for [i=1:256] {
blues[i] = int( (0x7f + (i-1)/(255.) * 0xffff80) );
}
#
# This is the equivalent of
# set cbrange [0:5]
blues_min = 0
blues_max = 5
#
# This function maps z onto a palette color
#
blues(z) = (z <= blues_min) ? blues[1] \
: (z >= blues_max) ? blues[256] \
: blues[ floor(255. * (z-blues_min)/(blues_max-blues_min)) + 1]
F1(x,y) = sqrt(x*y)
F2(x,y) = (x*y)**(1./3)
set samples 41; set isosamples 41
set cbrange [0:5]; set xrange [0:5]; set yrange [0:5]
set palette cubehelix negative
unset colorbox
# Needed for proper occlusion of hidden surface
set pm3d depthorder
# Place a thin border around each facet of the surfaces
set pm3d border lc "black" lw 0.5
set title "Top surface uses hand-constructed 'blues' palette via rgb variable\n".\
"Bottom surface uses 'set palette cubehelix negative'"
set title offset 0,1
splot '++' using 1:2:(F1($1,$2)):(blues(F1($1,$2))) with pm3d lc rgb variable \
title "F1(x,y) using 1:2:3:4 with pm3d lc rgb variable", \
'++' using 1:2:(F2($1,$2)) with pm3d \
title "F2(x,y) using 1:2:3 with pm3d"
I apologize for the delayed response. This is what i was looking for. I am grateful to both of you!

Gnuplot: oscilloscope-like line style?

Is it possible in Gnuplot to emulate the drawing style of an analogue oscilloscope, meaning thinner+dimmisher lines on larger amplitudes, like this:?
The effect you see in the oscilloscope trace is not due to amplitude, it is due to the rate of change as the trace is drawn. If you know that rate of change and can feed it to gnuplot as a third column of values, then you could use it to modulate the line color as it is drawn:
plot 'data' using 1:2:3 with lines linecolor palette z
I don't know what color palette would work best for your purpose, but here is an approximation using a function with an obvious, known, derivative.
set palette gray
set samples 1000
plot '+' using ($1):(sin($1)):(abs(cos($1))) with lines linecolor palette
For thickness variations, you could shift the curve slightly up and down, and fill the area between them.
f(x) = sin(2*x) * sin(30*x)
dy = 0.02
plot '+' u 1:(f(x)+dy):(f(x)-dy) w filledcurves ls 1 notitle
This does not allow variable colour, but the visual effect is similar.
Another approach:
As #Ethan already stated, the intensity is somehow proportional to the speed of movement, i.e. the derivative. If you have sin(x) as waveform, the derivative is cos(x). But what if you have given data? Then you have to calculate the derivative numerically.
Furthermore, depending on the background the line should fade from white (minimal derivative) to fully transparent (maximum derivative), i.e. you should change the transparency with the derivative.
Code:
### oscilloscope "imitation"
reset session
set term wxt size 500,400 butt # option butt, otherwise you will get overlap points
set size ratio 4./5
set samples 1000
set xrange[-5:5]
# create some test data
f(x) = 1.5*sin(15*x)*(cos(1.4*x)+1.5)
set table $Data
plot '+' u 1:(f($1)) w table
unset table
set xtics axis 1 format ""
set mxtics 5
set grid xtics ls -1
set yrange[-4:4]
set ytics axis 1 format ""
set mytics 5
set grid ytics ls -1
ColorScreen = 0x28a7e0
set obj 1 rect from screen 0,0 to screen 1,1 behind
set obj 1 fill solid 1.0 fc rgb ColorScreen
x0=y0=NaN
Derivative(x,y) = (dx=x-x0,x0=x,x-dx/2,dy=y-y0,y0=y,dy/dx) # approx. derivative
# get min/max derivative
set table $Dummy
plot n=0 $Data u (d=abs(Derivative($1,$2)),n=n+1,n<=2? (dmin=dmax=d) : \
(dmin>d ? dmin=d:dmin), (dmax<d?dmax=d:dmax)) w table
unset table
myColor(x,y) = (int((abs(Derivative(column(x),column(y)))-dmin)/(dmax-dmin)*0xff)<<24) +0xffffff
plot $Data u 1:2:(myColor(1,2)) w l lw 1.5 lc rgb var not
### end of code
Result:

GNUPlot - Plotting a data set in polar form (r, θ, T(r,θ)) to a contour/heat map

I hope I don't get firebombed here, this is the first time I'm posting. Lol
So after a grueling simulation, I have this large data set of the form r, θ, and T(r,θ). I needed to plot a contour map for this data set. θ is in degrees.
So I ran to GNUPlot and I hoped that this will save me from my problems. I studied a bit about how it works, but I still cannot plot my 2D contour data.
I then researched about my problem then I saw this thread here in SE:
gnuplot 2D polar plot with heatmap from 3D dataset - possible?
I used both codes (that I assume to be working) in that post and NONE is working with my dataset. I hope someone can help me with my problem.
This is what I changed the code into:
reset
set terminal pngcairo size 800,800
set output '3d-polar.png'
set lmargin at screen 0.05
set rmargin at screen 0.85
set bmargin at screen 0.1
set tmargin at screen 0.9
set pm3d map
unset key
set multiplot
# plot the heatmap
set parametric
set isosamples 500
unset border
unset xtics
unset ytics
set angles degree
r = 0.05 # CHANGED THIS
set urange[0:r] # radius
set vrange[0:360] # angle
set xrange[-r:r]
set yrange[-r:r]
set colorbox user origin 0.9,0.1 size 0.03,0.8
splot 'data.dat' using 1:2:3 # CHANGED THIS
# now plot the polar grid only
set style line 11 lc rgb 'white' lw 2
set grid polar ls 11
set polar
set rrange[0:r]
unset raxis
set rtics format '' scale 0
unset parametric
set for [i=0:330:30] label at first (r+0.35)*cos(i), first (r+0.35)*sin(i)\
center sprintf('%d', i)
plot NaN w l
unset multiplot
So I had this little 'eureka' moment. Apparently I had to put dgrid3d and had to convert the coordinates from polar to cartesian.
Upon converting (and putting set dgrid3d) this ugly plot appeared:
reset
set terminal pngcairo size 800,800
set output '3d-polar.png'
set lmargin at screen 0.05
set rmargin at screen 0.85
set bmargin at screen 0.1
set tmargin at screen 0.9
set pm3d map
unset key
set multiplot
# plot the heatmap
set parametric
set isosamples 500
unset border
unset xtics
unset ytics
set angles degree
r = 0.05 # CHANGED THIS
set urange[0:r] # radius
set vrange[0:360] # angle
set xrange[-r:r]
set yrange[-r:r]
set colorbox user origin 0.9,0.1 size 0.03,0.8
set dgrid3d # ADDED THIS
splot 'data.dat' using 1:2:3 # CHANGED THIS
# now plot the polar grid only
set style line 11 lc rgb 'white' lw 2
set grid polar ls 11
set polar
set rrange[0:r]
unset raxis
set rtics format '' scale 0
unset parametric
set for [i=0:330:30] label at first (r+0.35)*cos(i), first (r+0.35)*sin(i)\
center sprintf('%d', i)
plot NaN w l
unset multiplot
The plot.
I'm at my limit here now. Three questions.
1. Am I correct to assume that I can use the mathematics in gnuplot to convert the coordinates from polar to cartesian? Or is there a way for me to use the polar coordinate data immediately?
2. How do I limit the 'colors' to the round polar plot?
3. What happened to the degree and radius readings? Where did they go?
Thanks!

Variable transparency is possible in Gnuplot?

I want to plot a filled circle in Gnuplot, but with transparency changing with the distance to the center of the circle, i.e. a transparency gradient (solid near to the center, and transparent near to the radius of circle).
Is there any way of doing this in Gnuplot?
Thank you in advance!
One option would be to define a custom function describing the gradient (e.g., a Gaussian) and then use pm3d map to visualize it:
set terminal pngcairo size 400,400
set output 'fig.png'
unset border
unset colorbox
unset xtics
unset ytics
set pm3d map
#force the plot to occupy the entire canvas
set lmargin at screen 0
set rmargin at screen 1
set tmargin at screen 1
set bmargin at screen 0
set isosamples 100,100
#specify custom palette
set palette model RGB
set palette defined ( 0 "white", 1 "royalblue" )
set xr [-10:10]
set yr [-10:10]
#a Gaussian might be a reasonable choice
splot exp(-0.2*(x*x+y*y))
This then produces:
Another choice of the defining function might be:
set xr [-pi:pi]
set yr [-pi:pi]
fn(r) = (r>(pi/2))?0:(cos(r))
splot fn(sqrt(x*x+y*y))
This yields:
Try this:
set xrange [0:10]
set yrange [0:10]
do for [i=1:100] {
set style fill transparent solid i/100. noborder
set object circle at 5,5 radius 1.-i/100. fc rgb 'blue'
}
plot -1
Not all terminals support transparency; see help transparent. I made this with the terminal x11.

Position of tic marks in Gnuplot

I am looking for a way to position tic marks in gnuplot between the axis, but so far I only found solution to put them in or out:
set tics in
puts all tic marks inside of the canvas
set tics out
puts all tic marks outide of the canvas
All I want is to place tic marks on both sides of the axis, somethink like
--l--l--
Thanks for a hint!
As said in the comments, it seems not possible to place the tics on both sides of the axis. A workaround would be to plot the axis twice, or to draw the tics by hand with the set arrow.
Drawing tics by hand:
Consider the following settings:
Xmin = -4.0 # range in x
Xmax = 4.0
Ymin = -1.2 # range in y
Ymax = 1.2
NXtics = 8 # number of Xtics
NYtics = 4 # number of Ytics
epsX = 0.05 # length of Xtics
epsY = 0.03 # length of Ytics
dX = (Xmax-Xmin)/NXtics # distance between Xtics
dY = (Ymax-Ymin)/NYtics # distance between Ytics
Next, we draw the bottom, top, left, and right tics:
# xtics and x2tics
do for [i=0:NXtics] {
posX = Xmin+i*dX
set arrow from posX,Ymin-epsY to posX,Ymin+epsY nohead front # bottom
set arrow from posX,Ymax-epsY to posX,Ymax+epsY nohead front # top
}
# ytics and y2tics
do for [i=0:NYtics] {
posY = Ymin+i*dY
set arrow from Xmin-epsX,posY to Xmin+epsX,posY nohead front # left
set arrow from Xmax-epsX,posY to Xmax+epsX,posY nohead front # right
}
Since you are drawing the tics by hand, you will need to configure the axis numbers and ranges:
set xtics Xmin,dX,Xmax scale 0 offset 0,-epsY
set ytics Ymin,dY,Ymax scale 0 offset -epsX,0
set xrange [XMIN:XMAX]
set yrange [YMIN:YMAX]
Finally, your highly complicated plot:
plot sin(x)
Result:
This method also allows you to break the axis
Drawing axis twice:
This method is easier; but you need to set set margins of the canvas, and to use the multiplot mode:
set tmargin at screen 0.9 # top margin
set bmargin at screen 0.2 # bottom
set lmargin at screen 0.2 # left
set rmargin at screen 0.9 # right
set yrange [-1.2:1.2]
set multiplot
set tics scale 0.5 # scale size of the tics
plot 2 notitle # a plot outside the canvas, just to draw the axis
set tics out # tics outside
set format xy '' # delete the numbers
unset border # delete the border
plot sin(x) # your awesome plot
unset multiplot
The result is similar :)
Quick & dirty approach:
set multi
set tics scale 0.5
plot sin(x)/x
set tics out
replot
unset multi
Beware this overprints your graph with a second one. Should be OK for bitmap output, but don't do it if you have vector output (pdf, eps), especially if your graph is complicated or contains a lot of datapoints. It blows up the resulting file to twice its size.
Gnuplot at the moment (v 5.0pl1) has no option to place the tics centered on the axis. You'll have to use one of the workarounds shown here.

Resources