2

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.

2 Answers2

1

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:

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72
  • Ah, excellent answer. I increased the points around each arrow to give it a smoother look. My first instinct would be to set the parametric mode. If it is already another 3d object, then changing its colours is tedious, but easy using an example such as this one: https://stackoverflow.com/questions/57465513/gnuplot-5-2-splot-multiple-pm3d-palette-in-one-plot-call – Ottmar Schaub Jan 01 '21 at 09:28
  • Thanks :). Yes, I forgot to include the answer you mentioned and another of my answers a few months ago: https://stackoverflow.com/a/64092310/7295599. It would be nice to just either give the starting/end point of the 3D vector/arrow or alternatively starting point and vector direction and length. Maybe something similar like ("tedious" vector operations) used here: https://stackoverflow.com/a/58468236/7295599 – theozh Jan 01 '21 at 10:21
0
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.

Ethan
  • 13,715
  • 2
  • 12
  • 21
  • I mean. I guess. The problem still remains as now all arrows are at the front. I'd think my best chance is having two objects, the back of the arrow, simply a line up to where the intersection occurs and another from the intersection up to the tip and having the tips be at the front. Let me try that. – Ottmar Schaub Dec 26 '20 at 06:02
  • Yes, what you suggested along with breaking each arrow into 2 was what worked in the end. Thank you for your answer, Ethan. – Ottmar Schaub Dec 26 '20 at 06:52