2

I'm using addplot3 to create a surface, but I want a particular curve of points on the surface to be highlighted. Not something as simple as a level set curve. As a result, some of the curve should be hidden behind the surface, but I see no way to do this without actually breaking down the curve into the parts that should be behind the surface and the parts that should be in front of the surface.

This is the best I can do so far, but isn't right, as the spiral is permanently in front.

enter image description here

\documentclass[border=15pt]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{colormaps,fillbetween}
\begin{document}
\pgfplotsset{compat=1.10,
  colormap/red/.style={
    colormap={red}{
      rgb=(1.0,  0.0,  0.0)
      rgb=(1.0,  0.0,  0.0)
    }
  }
}
\begin{tikzpicture}
  \pgfdeclarelayer{pre main}
  \pgfsetlayers{pre main,main}
  \begin{axis}[
      hide axis,
      colormap/bone,
      view={25}{20}
    ]
\addplot3 [surf,
           colormap/bone, %colour scheme
           domain=0*pi:4*pi, %sets range for x
           y domain=0:4*pi, %sets range for y
           samples=50, %number of samples taken
           z buffer=sort]
    (
        {cos(\x r)},
        {sin(\x r)},
        {\y}
    );
\addplot3 [surf,
           colormap/red, %colour scheme
           domain=0*pi:4*pi, %sets range for x
           y domain=0:4*pi, %sets range for y
           samples=50, %number of samples taken
           z buffer=sort]
    (
        {cos(\x r)},
        {sin(\x r)},
        {\x}
    );
  \end{axis}
\end{tikzpicture}
\end{document}
Stefan Pinnow
  • 29,535

1 Answers1

1

You need to plot parts of the plots in the appropriate order. This solution assumes that the azimuth angle, i.e. the second argument of view={25}{20}, is positive. (I also like the radial angles better but internally pgfplots uses degrees so I switched.) BTW, to draw the red curve you do not need a surface plot, but you can use samples y=1.

\documentclass[border=15pt]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{colormaps}
\begin{document}
\pgfplotsset{compat=1.17}
\begin{tikzpicture}
\begin{axis}[
      hide axis,
      colormap/bone,
      view={25}{20}]
\addplot3 [surf,
           colormap/bone, %colour scheme
           domain=\pgfkeysvalueof{/pgfplots/view/az}:\pgfkeysvalueof{/pgfplots/view/az}+180, %sets range for x
           y domain=0:4*pi, %sets range for y
           samples=25, %number of samples taken
           z buffer=sort]
    (
        {cos(\x)},
        {sin(\x)},
        {\y}
    );
\pgfplotsinvokeforeach{0,360}{% 
\addplot3 [red,thick,
           domain=#1+\pgfkeysvalueof{/pgfplots/view/az}:#1+\pgfkeysvalueof{/pgfplots/view/az}+180, %sets range for x
           samples=25, %number of samples taken
           samples y=1]
    (
        {cos(\x)},
        {sin(\x)},
        {\x*pi/180}
    );
}   
\addplot3 [surf,
           colormap/bone, %colour scheme
           domain=\pgfkeysvalueof{/pgfplots/view/az}:\pgfkeysvalueof{/pgfplots/view/az}-180, %sets range for x
           y domain=0:4*pi, %sets range for y
           samples=25, %number of samples taken
           z buffer=sort]
    (
        {cos(\x)},
        {sin(\x)},
        {\y}
    );
\pgfplotsinvokeforeach{0:\pgfkeysvalueof{/pgfplots/view/az},%
\pgfkeysvalueof{/pgfplots/view/az}+180:\pgfkeysvalueof{/pgfplots/view/az}+360,%
\pgfkeysvalueof{/pgfplots/view/az}+540:720}{%       
\addplot3 [red,thick,
           domain=#1, %sets range for x
           samples=25, %number of samples taken
           samples y=1]
    (
        {cos(\x)},
        {sin(\x)},
        {\x*pi/180}
    );
}   
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

  • Would this be able to be extended to a more general surface, and curve, or is there part of your solution that is unique to the cylinder and spiral in my example? – Allen O'Hara Apr 16 '20 at 19:54
  • 2
    @AllenO'Hara It is not unique, but you have to decompose the plots into appropriate chunks and draw them according to their 3d ordering. E.g. this plot uses the same strategy. However, there are more objects, so one needs to decompose even more, asymptote has a 3d engine and spares you from that, but AFAIK there is no fully automatic solution in pgfplots. You can use tricks like restrict expr to domain for the curve, though. –  Apr 16 '20 at 20:06