tikz add tag
Anonymous 1123
In `Tikz` can I set up like this in 3D?
```
x + y +z + 1=0 equation of plane (P);
(x-1)^2 + (y+2)^2 + (z-3)^2 = 4 equation of sphere (S);
```
Top Answer
marmot
This is more a general tool than a concrete answer to the question. This is a prototype of something that let's Ti*k*Z decide whether some stretch of a path is in the foreground or background. The basic point is that whenever you perform an orthographic projection, one can compute the normal on the screen from `\pgf@xx`, `\pgf@xy` and so on, and thus knows how far some object is in the foreground or background by projecting its 3d coordinate on the normal. One can then let Ti*k*Z decompose the path in foreground and background stretches. The following is more a proof of principle than a perfectly working code, though.

````
\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{backgrounds,fpu}
\makeatletter
\newif\iftikz@td@combinestretches
\newcommand{\PgfmathsetmacroFPU}[2]{\begingroup% https://tex.stackexchange.com/a/503835
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathsetmacro{#1}{#2}%
\pgfmathsmuggle#1\endgroup}%
\newcommand{\PgfmathtruncatemacroFPU}[2]{\begingroup% https://tex.stackexchange.com/a/503835
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathtruncatemacro{#1}{#2}%
\pgfmathsmuggle#1\endgroup}%
\pgfmathdeclarefunction{screendepth}{3}{%
\begingroup%
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathparse{%
((\the\pgf@yx)*(\the\pgf@zy)-(\the\pgf@yy)*(\the\pgf@zx))*(#1)+
((\the\pgf@zx)*(\the\pgf@xy)-(\the\pgf@xx)*(\the\pgf@zy))*(#2)+
((\the\pgf@xx)*(\the\pgf@yy)-(\the\pgf@yx)*(\the\pgf@xy))*(#3)}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%
\tikzset{record plot/.code={%
\tikzset{3d plot/.cd,#1}%
\def\pv##1{\pgfkeysvalueof{/tikz/3d plot/##1}}%
\edef\pgfutil@tempa{0}%
\expandafter\pgfmathsetmacro\csname\pv{variable}\endcsname{\tmin}%
\PgfmathsetmacroFPU{\pgfutil@tempx}{\pv{x}}%
\PgfmathsetmacroFPU{\pgfutil@tempy}{\pv{y}}%
\PgfmathsetmacroFPU{\pgfutil@tempz}{\pv{z}}%
\edef\pgfutil@templ{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
\PgfmathtruncatemacroFPU{\pgfutil@tempd}{sign(-\pv{threshold}+screendepth(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz))}%
\edef\pgfutil@tempv{0}% visible index
\edef\pgfutil@temph{0}% hidden index
\ifnum\pgfutil@tempd=-1\relax
\edef\pgfutil@temph{1}%
\expandafter\edef\csname tikz@td@lsthidcoords\pgfutil@temph\endcsname{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
\expandafter\edef\csname tikz@td@lsthidcoordsreversed\pgfutil@temph\endcsname{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
\edef\pgfutil@temps{-1}% last sign
\else
\edef\pgfutil@tempv{1}%
\expandafter\edef\csname tikz@td@lstviscoords\pgfutil@tempv\endcsname{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
\expandafter\edef\csname tikz@td@lstviscoordsreversed\pgfutil@tempv\endcsname{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
\edef\pgfutil@temps{1}% last sign
\fi
\loop
\edef\pgfutil@tempa{\the\numexpr\pgfutil@tempa+1}%
\expandafter\PgfmathsetmacroFPU\csname\pv{variable}\endcsname{\tmin+(\tmax-\tmin)*\pgfutil@tempa/\pv{steps}}%
\PgfmathsetmacroFPU{\pgfutil@tempx}{\pv{x}}%
\PgfmathsetmacroFPU{\pgfutil@tempy}{\pv{y}}%
\PgfmathsetmacroFPU{\pgfutil@tempz}{\pv{z}}%
\PgfmathtruncatemacroFPU{\pgfutil@tempd}{sign(-\pv{threshold}+screendepth(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz))}%
\ifnum\pgfutil@tempd=-1\relax
 \ifnum\pgfutil@temps=-1\relax
  \expandafter\edef\csname tikz@td@lsthidcoords\pgfutil@temph\endcsname{%
    \csname tikz@td@lsthidcoords\pgfutil@temph\endcsname (\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
  \expandafter\edef\csname tikz@td@lsthidcoordsreversed\pgfutil@temph\endcsname{%
   (\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz) \csname tikz@td@lsthidcoordsreversed\pgfutil@temph\endcsname}%
 \else
  \edef\pgfutil@temph{\the\numexpr\pgfutil@temph+1}%
  \expandafter\edef\csname tikz@td@lsthidcoords\pgfutil@temph\endcsname{\pgfutil@templ (\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
  \expandafter\edef\csname tikz@td@lsthidcoordsreversed\pgfutil@temph\endcsname{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz) \pgfutil@templ}%
  \edef\pgfutil@temps{-1}%
 \fi
\else
 \ifnum\pgfutil@temps=-1\relax
  \edef\pgfutil@tempv{\the\numexpr\pgfutil@tempv+1}%
  \expandafter\edef\csname tikz@td@lstviscoords\pgfutil@tempv\endcsname{\pgfutil@templ (\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
  \expandafter\edef\csname tikz@td@lstviscoordsreversed\pgfutil@tempv\endcsname{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)
\pgfutil@templ}%
  \edef\pgfutil@temps{1}% last sign 
 \else
  \expandafter\edef\csname tikz@td@lstviscoords\pgfutil@tempv\endcsname{%
    \csname tikz@td@lstviscoords\pgfutil@tempv\endcsname (\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}%
  \expandafter\edef\csname tikz@td@lstviscoordsreversed\pgfutil@tempv\endcsname{%
   (\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz) \csname tikz@td@lstviscoordsreversed\pgfutil@tempv\endcsname}%
 \fi
\fi
\edef\pgfutil@templ{(\pgfutil@tempx,\pgfutil@tempy,\pgfutil@tempz)}% last coord
\ifnum\pgfutil@tempa<\pv{steps}\relax
\repeat
\iftikz@td@combinestretches
 \ifnum\pgfutil@tempv>1
  \expandafter\edef\csname tikz@td@lstviscoords1\endcsname{%
   \csname tikz@td@lstviscoords\pgfutil@tempv\endcsname
   \csname tikz@td@lstviscoords1\endcsname}%
  \expandafter\edef\csname tikz@td@lstviscoordsreversed1\endcsname{%
   \csname tikz@td@lstviscoordsreversed1\endcsname
   \csname tikz@td@lstviscoordsreversed\pgfutil@tempv\endcsname
  }%
  \edef\pgfutil@tempv{\the\numexpr\pgfutil@tempv-1}%
 \fi
 \ifnum\pgfutil@temph>1
  \expandafter\edef\csname tikz@td@lsthidcoords1\endcsname{%
   \csname tikz@td@lsthidcoords\pgfutil@tempv\endcsname
   \csname tikz@td@lsthidcoords1\endcsname
  }%
  \expandafter\edef\csname tikz@td@lsthidcoordsreversed1\endcsname{%
   \csname tikz@td@lsthidcoordsreversed1\endcsname
   \csname tikz@td@lsthidcoordsreversed\pgfutil@tempv\endcsname
  }%
  \edef\pgfutil@temph{\the\numexpr\pgfutil@temph-1}%
 \fi
\fi
\tikzset{3d plot/.cd,visible stretches/.expanded=\pgfutil@tempv,
hidden stretches/.expanded=\pgfutil@temph}%
}}
\tikzset{3d plot/.cd,x/.initial=0,y/.initial=0,z/.initial=0,
tmin/.store in=\tmin,tmax/.store in=\tmax,steps/.initial=100,
domain/.code args={#1:#2}{\def\tmin{#1}\def\tmax{#2}},
domain/.initial=0:1,
variable/.code=\let#1\tikz@td@t,
variable/.initial=t,threshold/.initial=0,
visible stretches/.initial=0,hidden stretches/.initial=0,
combine stretches/.is if=tikz@td@combinestretches,
combine stretches=true,
save visible stretch/.code 2 args={\edef#2{\csname tikz@td@lstviscoords#1\endcsname}},
save hidden stretch/.code 2 args={\edef#2{\csname tikz@td@lsthidcoords#1\endcsname}},
save reversed visible stretch/.code 2 args={\edef#2{\csname tikz@td@lstviscoordsreversed#1\endcsname}},
save reversed hidden stretch/.code 2 args={\edef#2{\csname tikz@td@lsthidcoordsreversed#1\endcsname}},
}%
\makeatother

\begin{document}
\foreach \X in {5,15,...,355}
{\begin{tikzpicture}[declare function={R=5;
	Rplane(\t)=1/max(abs(cos(\t)),abs(sin(\t)));},
	bullet/.style={circle,fill,inner
sep=2pt}]
 \shade[ball color = black!80,transform canvas={rotate=-35}] (0,0,0) circle[radius=R];
 \tdplotsetmaincoords{50+20*sin(\X)}{110}
 \begin{scope}[tdplot_main_coords]
  \path[tdplot_screen_coords,use as bounding box] (-8,-8) rectangle (8,8);
  \tikzset{record plot={x={3*cos(\t)},y={3*sin(\t)},z=4,domain=0:360,variable=\t}}
  \edef\mystretches{\pgfkeysvalueof{/tikz/3d plot/visible stretches}}
  \edef\myhidstretches{\pgfkeysvalueof{/tikz/3d plot/hidden stretches}}
  \ifnum\mystretches=1
   \tikzset{3d plot/save visible stretch={1}{\LstVis}}
   \tikzset{3d plot/save reversed visible stretch={1}{\LstVisReversed}}
  \fi
  \ifnum\myhidstretches=1
   \tikzset{3d plot/save hidden stretch={1}{\LstHid}}
   \tikzset{3d plot/save reversed hidden stretch={1}{\LstHidReversed}}
  \fi
  %
  \tikzset{record
  plot={x={6*Rplane(\t)*cos(\t)},y={6*Rplane(\t)*sin(\t)},z=4,domain=45:405,variable=\t}}
  \edef\myvisstretchesPlane{\pgfkeysvalueof{/tikz/3d plot/visible stretches}}
  \edef\myhidstretchesPlane{\pgfkeysvalueof{/tikz/3d plot/hidden stretches}}
  \ifnum\myvisstretchesPlane=1
  \tikzset{3d plot/save visible stretch={1}{\LstVisPlane}}
  \fi
  \ifnum\myhidstretchesPlane=1
  \tikzset{3d plot/save hidden stretch={1}{\LstHidPlane}}
  \fi
  \pgfmathtruncatemacro\itest{\mystretches+2*\myhidstretches+4*\myvisstretchesPlane}
  \ifcase\itest % 0: nothing in foreground
  \or % 1: circle completely in foreground, plane completely in background (should not happen)
   \message{Circle is completely in foreground and the plane completely in background,
    but this should not happen.^^J}%
  \or % 2: circle completely in background, plane completely in background 
  \or % 3: circle partly in background, plane completely in background 
   \message{Circle is partly in foreground and the plane completely in background,
    but this should not happen.^^J}%
  \or % 4
   \path[fill=blue,fill opacity=0.5] plot coordinates{\LstVisPlane};
  \or % 5 circle completely in foreground
   \path[fill=blue,fill opacity=0.5,even odd rule] plot coordinates{\LstVisPlane}
   -- plot coordinates{\LstHidPlane} -- cycle
   plot[smooth cycle] coordinates{\LstVis};
  \or % 6 
  \or % 7 circle has visible and hidden stretches, so has plane
   \begin{scope}[on background layer]
	\path[fill=blue,fill opacity=0.5] plot  coordinates{\LstHidPlane}
	  --   plot coordinates{\LstHidReversed}  -- cycle;
   \end{scope}
   \path[fill=blue,fill opacity=0.5,even odd rule] plot coordinates{\LstVisPlane}
     -- plot coordinates{\LstVisReversed}  -- cycle;
  \fi  
 \end{scope}
\end{tikzpicture}}
\end{document}
````

![ani.gif](/image?hash=efa68a60d95056862544271cf775413e48b810a2efef5c93511b2b28678b9ec8)

Let me mention that similar things have been achieved for specific situations, in particular for paths on a sphere. The new thing here is that this works for arbitrary paths, also for ellipsoids and so on and so forth. I also have not had the patience of treating all possible cases.

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.