Search code examples
3dgnuplotfill

How can you fill between a curve and anything other than zmin in an splot in gnuplot?


I am looking to acceive creating a 3D plot similar to this:

         z ^  **
           |     *
           |       ***                   **
           |           *               *###*
           |             *           *######**  * ***
           |               *    ****###########*#####
           |               ###*######################
           ,-----------------------------------------> y
          /   /   /   /   /   /   /   /   /   /   /
         /---0---0---0---1---1---1---0---0---0---0    1
        /   /   /   /   /   /   /   /   /   /   /
       /---0---0---0---0---1---1---1---0---0---0    2
      /   /   /   /   /   /   /   /   /   /   /
     /---0---0---0---0---0---1---1---1---1---0    3
    /   /   /   /   /   /   /   /   /   /   /
   /---0---0---0---0---0---0---0---1---1---1    4
x v   1   2   3   4   5   6   7   8   9   10

I.e. a 3D plot of an x-y-dependent surface/contour plot of a function g(x,y) and a 2D function f(y) in the y-z plane which is filled if g(x,y) > 0...

My approach was using the filledcurves option in gnuplot, but I can't quite manage to get it right.

In a 2D plot what you can do is (e.g. with f = sin(x), g = -0.5) this:

plot '+' u 1:(($1)>0?sin($1):-1/0) w filledcurves above y1=-0.5 

resulting in: 2D Version In the 3D plot however, when I try something similar:

xMIN = -1.5
xMAX = 0.5
yMIN = -0.5
yMAX = 1.5
zMIN = -4
zMAX = 8
set isosamples 100
set xyplane at 0
set xrange [xMIN:xMAX]
set yrange [yMIN:yMAX]
set zrange [zMIN:zMAX]
f(x) = 3*sin(3*x)+x**2
g(x,y) = -6*x**2 -12*y**2 - 8*x*y + 6*y+ 2
max(a,b) = a>b?a:1/0
set hidden
set view 45
splot max(g(x,y),0), \
      '++'   u 1:(1.5):(f($1)) w l, \
      ''   u 1:(1.5):(g(($1),($2)) > 0 ? f($1) : -1/0) w filledcurves

results in:

3D Version

This is almost what I want, but the filling is always done until zMIN, but I would like to specify e.g. that it shades until 0 or a curve: Adding above y1=0 after the last line gives me:

      "3D.gpl", line 22: unexpected or unrecognized token

Also, specifying a fourth datafield like

      ...:(-0) w filledcurves 

as would work in the 2D case, just changes the color here, so setting a second curve until which to fill does not seem possible...

I did see this question as well as this blog post on gnuplotting, but both answers and the post seem to have the same issue: They are all filling until zmin by default.

What I did manage to acceive after some tinkering is this:

enter image description here

Here I am using the fact that there are points in the domain for which g(x,y\') > 0 and others g(x,y\'\') ≤ 0 for any x. This results in a very hacky solution, but:

  1. To make it dense enough, you have to modify the sampling rate, affecting the surface plot of g as well... In fact simply setting a really high sampling rate appears to crash the splot entirely and I will only see part of it!

  2. Since the 'filling' now effectively is a surface plot squished into a 2D plane you see it's bottom in a different color, of course you can prevent this by setting set hidden3d offset 0 but than this option is global and holds for any other surface where you might not actually want it...

It would be interesting to see if there's a more rigorous solution!


Solution

  • Replacing the last line of your gnuplot script with

      ''   u 1:(1.5):(g(($1),($2)) > 0 ? f($1) : -1/0) w impulse lw 5
    

    gives the following. Does that help?

    enter image description here