2

Assumed we have this kind of 3D surface:


Minimum Working Example:

\documentclass[tikz]{standalone}
\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
    \begin{axis}[zmin=0,zmax=0.5,xlabel= {\(x\)},ylabel= {\(y\)},zlabel= {\(z\)}]
    \addplot3[surf, domain=-1:1] {((0.5*x^2+0.5*y^2)-0.5*(x^2+y^2)^2)+0.4};
    \end{axis}
\end{tikzpicture}

\end{document}

Screenshot of the result:

Screenshot of the result


Description of the issue:

How can I style the marked part of the graph as invisible/respectively hide it? Only the part above z=0 should be visible, but not the rest of this "leg" which goes below z=0.

I want to hide the part of the graph in the red circle, because it goes lower than z-axis 0 and therefore would confuse the reader when remaining visible... Its visibility should end at the ground area footprint (zero area) of the z-axis.

  • 1
    Do you just want to remove this one leg? – user121799 Feb 2 at 18:43
  • @marmot: Exactly! The existence of this z<0 part of the leg would confuse the reader, because normally it couldn't be lower than 0... :-) – Dave Feb 2 at 19:08
3

Here comes a cleaner approach: clip the undesired pieces away. To accomplish this, compute the critical radius at which the function becomes 0, and then it is easier (but not necessary) to plot the function in two steps.

\documentclass[tikz]{standalone}
\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}[declare function={f(\x,\y)=((0.5*\x^2+0.5*\y^2)-0.5*(\x^2+\y^2)^2)+0.4;}]
    \pgfmathsetmacro{\rcrit}{sqrt(0.5+sqrt(1.05))}
    \begin{axis}[zmin=0,zmax=0.5,xlabel= {\(x\)},ylabel= {\(y\)},zlabel= {\(z\)}]
     \begin{scope}
      \clip plot[variable=\t,domain=0:180] 
    (axis cs:{\rcrit*cos(\t)},{\rcrit*sin(\t)},0)
     -- (axis cs:-5,0,0) -- (axis cs:-5,0,2) -- (axis cs:5,0,2) -- (axis cs:5,0,0) 
     -- cycle;
      \addplot3[surf, domain=-1:1,domain y=0:1,samples y=11]    {f(x,y)};
     \end{scope} 
     \begin{scope}
      \clip plot[variable=\t,domain=30:-150] 
    (axis cs:{\rcrit*cos(\t)},{\rcrit*sin(\t)},0)
     -- (axis cs:-5,0,0) -- (axis cs:-5,0,2) -- (axis cs:5,0,2) -- (axis cs:5,0,0) 
     -- cycle;
      \addplot3[surf, domain=-1:1,domain y=0:-1,samples y=11]   {f(x,y)};
     \end{scope}
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

I interpreted the question as the desire to clip the undesired stuff away, and not just to plot

\documentclass[tikz]{standalone}
\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
    \begin{axis}[zmin=0,zmax=0.5,xlabel= {\(x\)},ylabel= {\(y\)},zlabel= {\(z\)}]
    \addplot3[surf, domain=-1:1,restrict z to domain*=0:1,
    point meta=((0.5*x^2+0.5*y^2)-0.5*(x^2+y^2)^2)+0.4]
    {max(((0.5*x^2+0.5*y^2)-0.5*(x^2+y^2)^2)+0.4,0)};
    \end{axis}
\end{tikzpicture}

\end{document}

enter image description here

  • I knew you are going for it! :-) Thank you very much! Maybe I wrote some confusing explanation: The leg should not be removed completely, but just the part lower than the ground area of the z-axis (-> the part below z=0 should be invisible). – Dave Feb 2 at 19:07
  • You said: "This part should not be there in the first place since you are setting zmin=0. (I have checked that with version 1.16 there is no difference.)" - Yeah, I also think so. But I have no glue on how to attempt this issue... :-( – Dave Feb 2 at 20:16
1

Run with xelatex:

\documentclass[pstricks]{standalone}
\usepackage{pst-solides3d}
\begin{document}

\psset{viewpoint=30 20 8 rtp2xyz}
\begin{pspicture}(-3,-1)(3,2)
\psSurface[ngrid=.05 .05,incolor=yellow,showAxes=false,
    linewidth=0.1pt,axesboxed,hue=0 1 0.5 1,
    Zmax=1,Zmin=0](-1,-1)(1,1){x dup mul 0.5 mul y dup mul 0.5 mul add 
         x dup mul y dup mul add dup mul 0.5 mul sub 0.4 add 
         dup 0 lt { pop 0 } if }
\end{pspicture}

\begin{pspicture}(-3,-2.5)(3,2)
\psSurface[ngrid=.05 .05,incolor=yellow,showAxes=false,
   linewidth=0.1pt,axesboxed,hue=0 1 0.5 1,algebraic,
  Zmax=1,Zmin=-1](-1,-1)(1,1){(0.5*x^2+0.5*y^2)-0.5*(x^2+y^2)^2+0.4}
\end{pspicture}

\end{document}

enter image description here

enter image description here

1

This approach either undershoots z=0, overshoots, or both depending on the limits. Increasing the number of samples helps, but you quickly run out of memory. Your best bet is to compute externally and interpolate the edges.

\documentclass[tikz]{standalone}
\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
    \begin{axis}[zmin=0,zmax=0.5,xlabel= {\(x\)},ylabel= {\(y\)},zlabel= {\(z\)}]
    \addplot3[surf, domain=-1:1, restrict z to domain=0:1, samples=60] {((0.5*x^2+0.5*y^2)-0.5*(x^2+y^2)^2)+0.4};
    \end{axis}
\end{tikzpicture}

\end{document}

demo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.