Now that we have explicit color in pm3d, there is one last ingredient to make it easy to color a figure based on the normal vector (this is how Mathematica makes it's beautiful 3d plots and helps convey details like shape and curve more effectively than a height-map). It must be possible for gnuplot to determine the normal vector for each tile it places down for the pm3d plot, which allows us to do something like this...
plot '++' u 1:2:3:(color(nvx($1,$2),nvy($1,$2),nvz($1,$2))) w pm3d lc rgb var
An external routine could compute the functions nvx,nvy,nvz and put them in the fourth, fifth, and sixth data columns, but it would be better to be able to feed in a 3D data set and leave the coloring to gnuplot.
Since I am not a developer, I don't know what hidden conventions this would break, but it seems possible and extraordinarily useful, since now we have a platform for beautiful 2D plots, but have to go into the hideously complicated and difficult-to-adjust Mathematica to get 3D plots that convey shape effectively.
To anyone who takes this up or gives a good reason not to, thank you!
Douglas
2012-04-19
color-by-shading at surface, and color-by-palette at base
Douglas
2012-04-19
The new patch and screenshot show what I'm looking for. Palette-based shading in the base, palette+normal-vector shading on the surface. In my opinion, this suffices as a killer app. This form of display indicates the most to my eye about what exactly is going on here.
Douglas
2012-04-19
A couple updates. The patch now accepts three parameters:
set pm3d corners2color shade STRENGTH, LONGITUDE, LATTITUDE
where STRENGTH determines the strength of the shading (default 0.5), and LONGITUDE AND LATTITUDE determine the orientation of the "sun" (defaults zero, pointing from the left).
I have also attached two pictures which I think provide a good example of why such a tool is needed. The script that generated the pictures is
set xrange [-3:3]
set yrange [-3:3]
set samples 100, 100
set isosamples 100
set pm3d corners2color shade
splot '++' u 1:2:(sqrt(9-$1**2-$2**2)) w pm3d
Without the color-by-shading, it's nearly impossible to see the rough surface, but with the shading, it's now obvious.
Douglas
2012-04-19
Rough surface with color-by-palette
Douglas
2012-04-19
Rough surface with color-by-shading
Douglas
2012-04-19
Error in the script from the last comment. The plot command is:
splot '++' u 1:2:(0.1*rand(0)+sqrt(9-$1**2-$2**2)) w pm3d
Douglas
2012-04-22
Updated my patch to include the detection of whether the surface normal points towards the camera or away. This requires the normal vector shading and the realistic shading to reverse when you look at the underside of a surface. I have also attached two examples that I am using in my research. My goal was to show the graphene band structure. Part of the figure (not included) shows a "set view map" of the band structure showing and labeling the six "cones", but I also needed a 3d plot to show that they are actually cones. The normal pm3d version doesn't convey this well at all, while it is crystal clear in the shaded version. This is one of those examples where proper shading of the underbelly is necessary.
set palette defined (0 0.5 0.0 0.0, \ 1 1.0 0.0 0.0, \ 2 1.0 0.5 0.0, \ 3 1.0 1.0 0.0, \ 4 0.5 1.0 0.5, \ 5 0.0 1.0 1.0, \ 6 0.0 0.5 1.0, \ 7 0.0 0.0 1.0, \ 8 0.0 0.0 0.5, \ 9 0.0 0.0 1.0, \ 10 0.0 0.5 1.0, \ 11 0.0 1.0 1.0, \ 12 0.5 1.0 0.5, \ 13 1.0 1.0 0.0, \ 14 1.0 0.5 0.0, \ 15 1.0 0.0 0.0, \ 16 0.5 0.0 0.0 )
set view 82, 15
a=1.0
t = 2.7
set cbrange [-3*t:3*t]
g(x,y) = 2*cos(sqrt(3)*y*a)+4*cos(sqrt(3)/2.0*y*a)*cos(3*x*a/2.0)
f(x,y) = t*sqrt(3+g(1.0/sqrt(3)*y,1.0/sqrt(3)*(-x)))
set sample 200
set isosamples 200
set xrange [-2*pi/a:2*pi/a]
set yrange [-2*pi/a:2*pi/a]
set yrange [-sqrt(3)*pi/a:sqrt(3)*pi/a]
set pm3d at s
set ztics 2
set cbtics 2
#set zlabel 'Energy' rotate by 90
#set xlabel 'k_x'
#set ylabel 'k_y'
unset zlabel
unset xlabel
unset ylabel
unset xtics
unset ytics
unset ztics
unset colorbox
unset border
set hidden3d
unset key
set terminal pngcairo transparent size 5*800, 3.5*800
#set terminal x11
set size ratio -1
set output 'graphene.png'
set pm3d corners2color shade 0.4, 0, 45
splot -f(x,y) w pm3d, f(x,y) w pm3d
Douglas
2012-04-22
New patch with "set pm3d corners2color shade STRENGTH, LAT, LONG"
Douglas
2012-04-22
Graphene band structure: Old version of pm3d
Douglas
2012-04-22
Graphene band structure: New version with shading and proper identification of underbelly
Douglas
2012-04-23
One last detail: I've learned how to simulate the Mathematica-style normal-shading (see http://reference.wolfram.com/mathematica/howto/ChangeTheLightingOfPlots.html for details). This works perfectly for the spheres I've been testing, but any other surface has the following issue: the normal vector must be "normalized" according to the ranges of each axis. Otherwise the result is dependent upon the ranges being equal and will change if you multiply by a prefactor. The prefactor only affects the labels on the z-axis, but not the overall shape, but in the current implementation, it also affects the normal shading. How do I obtain the ranges for each axis in pm3d.c?
Ethan Merritt
2012-04-23
axis_array[AXIS].data_min
axis_array[AXIS].data_max
I appreciate your enthusiasm for this project, but I still would like to see a real-world example of using this coloring scheme to convey salient information. The png files you have attached to this tracker strike me as being essentially the same as the existing color-by-z default mode (but uglier). Just because the Wolfram programs use this scheme does not really prove anything; for one thing they don't (so far as I know) have an hidden-surface removal option equivalent to gnuplot's hidden3d mode.
Douglas
2012-04-30
Some more updates. The new patch file now uses "normal" to perform Mathematica-style shading, while the "shade" version has the following optional settings:
set pm3d corners2color shade STRENGTH AMBIENT SPECULAR-STRENGTH SHINYNESS LONGITUDE LATTITUDE
The idea now is that shade simulates a real light source and reflective object with adjustable specularity. This makes it vastly easier to understand the physical 3d shape of these plots, while the adjustment parameters I settled on I think are intuitive. For instance, the "shinyness" algorithm is normalized so there is the same amount of specular reflected light at all shininess settings, determined solely by SPECULAR-STRENGTH.
Also, the "normal" style is now an exact replica of the Mathematica style, which gets rid of those hideous greens. The Mathematica style essentially is a stylized normal-vector shading which I find extraordinarily pleasing.
I have attached two images of both styles using the graphene band structure.
Ethan -- I now have several individuals who are asking for this patch, so I'll keep developing it as long as I find important details to address. We find it extremely useful that a scripted graphing program like gnuplot can now give us professional results that we were otherwise having to run to Mathematica or Matlab to obtain, so for us this is very valuable.
One question: how can we get this shading to work with "set pm3d depthorder"?
Douglas
2012-04-30
New version of patch which adds specularity and Mathematica-style shading
Douglas
2012-04-30
Graphene band structure with mathematica-style shading
Douglas
2012-04-30
Improved shading algorithm is more realistic and includes specularity
Douglas
2012-05-02
I've also attached the figure in my thesis for which I wrote this patch. By adding the shading and specularity on top of the normal palette, it's now obvious how the shapes of the two band structures differ from each other while also relating them to the 2d "set view map" graphs next to them.
Douglas
2012-05-02
Figure from thesis, showing comparison between two band structures in pm3d shading AND the flat image
Douglas
2012-05-04
I've also found an interesting application from matplotlib for plotting relief images: http://matplotlib.sourceforge.net/examples/pylab_examples/shading_example.html
With the new patch, not only can we do this ("set view map"), but our solution is infinitely more flexible!
Anonymous
2012-05-15
This looks great. I'm excited to use this in my graduate research. Thanks for making this available!
Douglas
2012-05-23
Updated patch includes option "fixedshade"
Douglas
2012-05-23
The default behavior in matplotlib and matlab is to set the angle of the incoming "light" fixed against the axes, which is useful for reproducibility; while Mathematica tends to set the light according to the view window, not the axes. I have added an option "fixedshade" which fixes the light in relation to the axes; "shade" acts as before, by fixing the light in relation to the view window. In other words, "fixedshade" doesn't change the shading when you rotate the view, but "shade" does.
Lukas Jirkovsky
2014-03-17
Douglas, thank you for this patch, it looks amazing. I've updated it to apply cleanly on gnuplot 4.6.5
I found the shading very useful, because I needed to visualize various curves along a 3D surface. The surface was required for illustration purposes and I couldn't use line rendering as it was making the plot too messy and pm3d didn't provide a good sense of depth.
Devs: is there a chance that this or something similar will be accepted?
bigfooted
2014-10-31
Wow - this patch is exactly what I was looking for! That last image from the thesis is just amazing. Thank you Douglas, for this great effort. This greatly enhances the 3-dimensionality and general look of figures. This should become the default setting when plotting 3D figures in gnuplot.