19

I would like to reproduce something like this in black and white using TikZ (just the figure not the writing) : enter image description here

Here is the code I have so far, but I don't know how to draw the three planes properly :

\documentclass[tikz, border=3pt]{standalone}
\usepackage{tikz,tikz-3dplot}
\tdplotsetmaincoords{80}{45}
\tdplotsetrotatedcoords{-90}{180}{-90}

%% style for surfaces
\tikzset{surface/.style={draw=black, fill=white, fill opacity=.6}}

%% macros to draw back and front of cones
%% optional first argument is styling; others are z, radius, side offset (in degrees)
\newcommand{\coneback}[4][]{
  %% start at the correct point on the circle, draw the arc, then draw to the origin of the diagram, then close the path
  \draw[canvas is xy plane at z=#2, #1] (45-#4:#3) arc (45-#4:225+#4:#3) -- (O) --cycle;
  }
\newcommand{\conefront}[4][]{
  \draw[canvas is xy plane at z=#2, #1] (45-#4:#3) arc (45-#4:-135+#4:#3) -- (O) --cycle;
  }

\begin{document}
\begin{tikzpicture}[tdplot_main_coords]
  \coordinate (O) at (0,0,0);

  %% make sure to draw everything from back to front
  \coneback[surface]{-3}{2}{-10}
  \draw (0,0,-5) -- (O);
  \conefront[surface]{-3}{2}{-10}
  \draw[->] (-6,0,0) -- (6,0,0) node[right] {$x$};
  \draw[->] (0,-6,0) -- (0,6,0) node[right] {$y$};
  \coneback[surface]{3}{2}{10}
  \draw[->] (O) -- (0,0,5) node[above] {$z$};
  \conefront[surface]{3}{2}{10}
\end{tikzpicture}
\end{document}

Update : Here is the result thanks to these two posts (@Schrödinger's cat's answer / The fix from another question). The code contains a fix to cope with outdated tikz 3d library.

\documentclass[tikz, border=3pt]{standalone}
\usepackage{tikz,tikz-3dplot}
\tdplotsetmaincoords{80}{110}

%This piece of code fixes the bug%
\usetikzlibrary{3d}
\makeatletter
\tikzoption{canvas is xy plane at z}[]{%
  \def\tikz@plane@origin{\pgfpointxyz{0}{0}{#1}}%
  \def\tikz@plane@x{\pgfpointxyz{1}{0}{#1}}%
  \def\tikz@plane@y{\pgfpointxyz{0}{1}{#1}}%
  \tikz@canvas@is@plane
}
\makeatother
%%%%%%%%%%%%

%% style for surfaces
\tikzset{surface/.style={draw=black, left color=orange,right color=orange,middle
color=orange!60!#1, fill opacity=1},surface/.default=white}

%% macros to draw back and front of cones
%% optional first argument is styling; others are z, radius, side offset (in degrees)
\newcommand{\coneback}[4][]{
  %% start at the correct point on the circle, draw the arc, then draw to the origin of the diagram, then close the path
  \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) 
  arc(\tdplotmainphi-#4:\tdplotmainphi+180+#4:#3) -- (O) --cycle;
  }
\newcommand{\conefront}[4][]{
  \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) arc
  (\tdplotmainphi-#4:\tdplotmainphi-180+#4:#3) -- (O) --cycle;
  }

\newcommand{\conetruncback}[6][]{
  \draw[line join=round,#1] plot[variable=\t,domain=\tdplotmainphi-#4:\tdplotmainphi+180+#4] 
  ({#3*cos(\t)},{#3*sin(\t)},#2)
  -- plot[variable=\t,domain=\tdplotmainphi+180-#4:\tdplotmainphi+#4] 
  ({#6*cos(\t)},{#6*sin(\t)},#5)
  --cycle;
  }

\newcommand{\conetruncfront}[6][]{
  \draw[line join=round,#1] plot[variable=\t,domain=\tdplotmainphi-#4:\tdplotmainphi-180+#4] 
  ({#3*cos(\t)},{#3*sin(\t)},#2)
  -- plot[variable=\t,domain=\tdplotmainphi-180-#4:\tdplotmainphi+#4] 
  ({#6*cos(\t)},{#6*sin(\t)},#5)
  --cycle;
  }

\begin{document}
\begin{tikzpicture}[tdplot_main_coords]
  \coordinate (O) at (0,0,0);
  \conetruncback[surface=black]{-2}{4/3}{0}{-3}{2}
  \draw (0,0,-5) -- (0,0,-2);
  \conetruncfront[surface]{-2}{4/3}{0}{-3}{2}
  \draw[canvas is xy plane at z=-2,fill=green!40!black,fill opacity=1] (-3,-3) rectangle (3,3);
  \coneback[surface=black]{-2}{4/3}{-10}
  \draw (0,0,-2) -- (O);
  \conefront[surface]{-2}{4/3}{-10}
  \draw[canvas is xy plane at z=0,fill=teal,fill opacity=1] (-3,-3) rectangle (3,3);
  \draw[->] (-6,0,0) -- (7,0,0) node[below] {$x$};
  \draw[->] (0,-6,0) -- (0,6,0) node[right] {$y$};
  \coneback[surface=white]{2}{4/3}{10}
  \draw[-] (O) -- (0,0,2);
  \conefront[surface=black]{2}{4/3}{10}
  \draw[canvas is xy plane at z=2,fill=pink,fill opacity=1] (-3,-3) rectangle (3,3);
  \conetruncback[surface=white]{2}{4/3}{0}{3}{2}
  \draw[->] (0,0,2) -- (0,0,5) node[above] {$z$};
  \conetruncfront[surface=black]{2}{4/3}{0}{3}{2}
\end{tikzpicture}
\end{document}

And the result : enter image description here

  • 3
    I recommend asymptote for 3d drawings. – Benjamin McKay Nov 3 '19 at 19:51
  • 1
    @Schrödinger'scat Done ;-) – Emperor_Udan Nov 4 '19 at 18:45
  • 1
    The cross hatching on the cone on the original book cover is nice. I wish we had a good way to do that in TikZ or asymptote. – Benjamin McKay Nov 8 '19 at 12:52
  • Yes, maybe I'll look into adding this during the week-end – Emperor_Udan Nov 8 '19 at 18:44
17

You were almost there. Drawing a plane is as simple as saying

\draw[canvas is xy plane at z=2,fill=blue,fill opacity=0.6] (-4,-4) rectangle (4,4);

Other than that you need to draw the parts of the cone below and above the planes separately, which is why I added a macro for the truncated cone, \conetruncfront. I also replaced the hard coded 45 by \tdplotmainphi.

\documentclass[tikz, border=3pt]{standalone}
\usepackage{tikz,tikz-3dplot}
\tdplotsetmaincoords{80}{45}

%% style for surfaces
\tikzset{surface/.style={draw=black, fill=white, fill opacity=.6}}

%% macros to draw back and front of cones
%% optional first argument is styling; others are z, radius, side offset (in degrees)
\newcommand{\coneback}[4][]{
  %% start at the correct point on the circle, draw the arc, then draw to the origin of the diagram, then close the path
  \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) 
  arc(\tdplotmainphi-#4:\tdplotmainphi+180+#4:#3) -- (O) --cycle;
  }
\newcommand{\conefront}[4][]{
  \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) arc
  (\tdplotmainphi-#4:\tdplotmainphi-180+#4:#3) -- (O) --cycle;
  }

\newcommand{\conetruncfront}[6][]{
  \draw[line join=round,#1] plot[variable=\t,domain=\tdplotmainphi-#4:\tdplotmainphi-180+#4] 
  ({#3*cos(\t)},{#3*sin(\t)},#2)
  -- plot[variable=\t,domain=\tdplotmainphi-180-#4:\tdplotmainphi+#4] 
  ({#6*cos(\t)},{#6*sin(\t)},#5)
  --cycle;
  }

\begin{document}
\begin{tikzpicture}[tdplot_main_coords]
  \coordinate (O) at (0,0,0);

  %% make sure to draw everything from back to front
  \coneback[surface]{-3}{2}{-10}
  \draw (0,0,-5) -- (O);
  \conefront[surface]{-3}{2}{-10}
  \draw[canvas is xy plane at z=-2,fill=green!60!black,fill opacity=0.6] (-4,-4) rectangle (4,4);
  \coneback[surface]{-2}{4/3}{-10}
  \draw (0,0,-2) -- (O);
  \conefront[surface]{-2}{4/3}{-10}
  \draw[canvas is xy plane at z=0,fill=blue,fill opacity=0.6] (-4,-4) rectangle (4,4);
  \draw[->] (-6,0,0) -- (6,0,0) node[right] {$x$};
  \draw[->] (0,-6,0) -- (0,6,0) node[right] {$y$};
  \coneback[surface]{3}{2}{10}
  \draw[->] (O) -- (0,0,5) node[above] {$z$};
  \conefront[surface]{3}{2}{10}
  \draw[canvas is xy plane at z=2,fill=purple,fill opacity=0.6] (-4,-4) rectangle (4,4);
  \draw[->] (0,0,2) -- (0,0,5) node[above] {$z$};
  \conetruncfront[surface]{2}{4/3}{0}{3}{2}
\end{tikzpicture}
\end{document}

enter image description here

However, I'd slightly change things to get

 \documentclass[tikz, border=3pt]{standalone}
    \usepackage{tikz,tikz-3dplot}
    \tdplotsetmaincoords{80}{45}

    %% style for surfaces
    \tikzset{surface/.style={draw=black, left color=yellow,right color=yellow,middle
    color=yellow!60!#1, fill opacity=.6},surface/.default=white}

    %% macros to draw back and front of cones
    %% optional first argument is styling; others are z, radius, side offset (in degrees)
    \newcommand{\coneback}[4][]{
      %% start at the correct point on the circle, draw the arc, then draw to the origin of the diagram, then close the path
      \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) 
      arc(\tdplotmainphi-#4:\tdplotmainphi+180+#4:#3) -- (O) --cycle;
      }
    \newcommand{\conefront}[4][]{
      \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) arc
      (\tdplotmainphi-#4:\tdplotmainphi-180+#4:#3) -- (O) --cycle;
      }

    \newcommand{\conetruncback}[6][]{
      \draw[line join=round,#1] plot[variable=\t,domain=\tdplotmainphi-#4:\tdplotmainphi+180+#4] 
      ({#3*cos(\t)},{#3*sin(\t)},#2)
      -- plot[variable=\t,domain=\tdplotmainphi+180-#4:\tdplotmainphi+#4] 
      ({#6*cos(\t)},{#6*sin(\t)},#5)
      --cycle;
      }

    \newcommand{\conetruncfront}[6][]{
      \draw[line join=round,#1] plot[variable=\t,domain=\tdplotmainphi-#4:\tdplotmainphi-180+#4] 
      ({#3*cos(\t)},{#3*sin(\t)},#2)
      -- plot[variable=\t,domain=\tdplotmainphi-180-#4:\tdplotmainphi+#4] 
      ({#6*cos(\t)},{#6*sin(\t)},#5)
      --cycle;
      }

    \begin{document}
    \begin{tikzpicture}[tdplot_main_coords]
      \coordinate (O) at (0,0,0);
      \conetruncback[surface=black]{-2}{4/3}{0}{-3}{2}
      \draw (0,0,-5) -- (0,0,-2);
      \conetruncfront[surface]{-2}{4/3}{0}{-3}{2}
      \draw[canvas is xy plane at z=-2,fill=green!60!black,fill opacity=0.6] (-4,-4) rectangle (4,4);
      \coneback[surface=black]{-2}{4/3}{-10}
      \draw (0,0,-2) -- (O);
      \conefront[surface]{-2}{4/3}{-10}
      \draw[canvas is xy plane at z=0,fill=blue,fill opacity=0.6] (-4,-4) rectangle (4,4);
      \draw[->] (-6,0,0) -- (6,0,0) node[right] {$x$};
      \draw[->] (0,-6,0) -- (0,6,0) node[right] {$y$};
      \coneback[surface=white]{2}{4/3}{10}
      \draw[-] (O) -- (0,0,2);
      \conefront[surface=black]{2}{4/3}{10}
      \draw[canvas is xy plane at z=2,fill=purple,fill opacity=0.6] (-4,-4) rectangle (4,4);
      \conetruncback[surface=white]{2}{4/3}{0}{3}{2}
      \draw[->] (0,0,2) -- (0,0,5) node[above] {$z$};
      \conetruncfront[surface=black]{2}{4/3}{0}{3}{2}
    \end{tikzpicture}
    \end{document}

[![enter image description here][2]][2]

Or with a slightly different view angles and opacity set to 1, and adjustments suggested by minhthien_2016.

\documentclass[tikz, border=3pt]{standalone}
\usepackage{tikz,tikz-3dplot}
\tdplotsetmaincoords{80}{60}

%% style for surfaces
\tikzset{surface/.style={draw=black, left color=yellow,right color=yellow,middle
        color=yellow!60!#1, fill opacity=1},surface/.default=white}

%% macros to draw back and front of cones
%% optional first argument is styling; others are z, radius, side offset (in degrees)
\newcommand{\coneback}[4][]{
    %% start at the correct point on the circle, draw the arc, then draw to the origin of the diagram, then close the path
    \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) 
    arc(\tdplotmainphi-#4:\tdplotmainphi+180+#4:#3) -- (O) --cycle;
}
\newcommand{\conefront}[4][]{
    \draw[canvas is xy plane at z=#2, #1] (\tdplotmainphi-#4:#3) arc
    (\tdplotmainphi-#4:\tdplotmainphi-180+#4:#3) -- (O) --cycle;
}

\newcommand{\conetruncback}[7][]{
    \draw[line join=round,#1] plot[variable=\t,domain=\tdplotmainphi-#4:\tdplotmainphi+180+#4] 
    ({#3*cos(\t)},{#3*sin(\t)},#2)
    -- plot[variable=\t,domain=\tdplotmainphi+180-#7:\tdplotmainphi+#7] 
    ({#6*cos(\t)},{#6*sin(\t)},#5)
    --cycle;
}

\newcommand{\conetruncfront}[7][]{
    \draw[line join=round,#1] plot[variable=\t,domain=\tdplotmainphi-#4:\tdplotmainphi-180+#4] 
    ({#3*cos(\t)},{#3*sin(\t)},#2)
    -- plot[variable=\t,domain=\tdplotmainphi-180-#7:\tdplotmainphi+#7] 
    ({#6*cos(\t)},{#6*sin(\t)},#5)
    --cycle;
}

\begin{document}
    \begin{tikzpicture}[tdplot_main_coords]
    \coordinate (O) at (0,0,0);
    \conetruncback[surface=black]{-2}{4/3}{-5}{-3}{2}{5}
    \draw (0,0,-5) -- (0,0,-2);
    \conetruncfront[surface]{-2}{4/3}{-5}{-3}{2}{5}
    \draw[canvas is xy plane at z=-2,fill=green!60!black,fill opacity=1] (-4,-4) rectangle (4,4);
    \coneback[surface=black]{-2}{4/3}{-10}
    \draw (0,0,-2) -- (O);
    \conefront[surface]{-2}{4/3}{-10}
    \draw[canvas is xy plane at z=0,fill=blue,fill opacity=1] (-4,-4) rectangle (4,4);
    \draw[->] (-6,0,0) -- (6,0,0) node[right] {$x$};
    \draw[->] (0,-6,0) -- (0,6,0) node[right] {$y$};
    \coneback[surface=white]{2}{4/3}{10}
    \draw[-] (O) -- (0,0,2);
    \conefront[surface=black]{2}{4/3}{10}
    \draw[canvas is xy plane at z=2,fill=purple,fill opacity=1] (-4,-4) rectangle (4,4);
    \conetruncback[surface=white]{2}{4/3}{5}{3}{2}{-5}
    \draw[->] (0,0,2) -- (0,0,5) node[above] {$z$};
    \conetruncfront[surface=black]{2}{4/3}{5}{3}{2}{-5}
    \end{tikzpicture}
\end{document}

enter image description here

| improve this answer | |
  • Thanks for your answer, however I tested the second version of your code and even after trying different values for \tdplotsetmaincoords{80}{60}, I can't get the same output as you. I've updated my post with a screenshot – Emperor_Udan Nov 3 '19 at 20:25
  • 1
    @Emperor_Udan You might have an old version of the 3d library on your machine, in which the xy plane had a bug. The cleanest solution will be to update your installation. Alternatively you could use yx plane for the planes. Please add the very precise code that you run, and indicate the compiler you are using. – user194703 Nov 3 '19 at 20:28
  • 2
    @Emperor_Udan You can also try using this fix. – user194703 Nov 3 '19 at 20:32
  • 1
    @Emperor_Udan This is up to you. Anyway, I am glad it worked. ;-) – user194703 Nov 3 '19 at 20:37
  • 1
    @minhthien_2016 Thanks! I tried to fix it. (To be honest, is this the answer that has problems with not everything being smooth? ;-) – user194703 Nov 4 '19 at 16:34
11

Run with xelatex:

\documentclass[border=10pt,pstricks]{standalone}
\usepackage{pst-solides3d}
\begin{document}

\psset{unit=0.5}
\begin{pspicture}[linewidth=0.1pt](-7,-7)(7,7)
\psset[pst-solides3d]{viewpoint=20 10 20 rtp2xyz,Decran=50,lightsrc=20 10 5,solidmemory}
\psSolid[object=grille,base=-2 2 -2 2,ngrid=30,name=A](0,0,-1.5)
\psSolid[object=grille,base=-2 2 -2 2,ngrid=30,name=B](0,0,0)
\psSolid[object=grille,base=-2 2 -2 2,ngrid=30,name=C](0,0,1.5)
\defFunction{cone}(u,v){u v Cos mul}{u v Sin mul}{u}
\psSolid[object=surfaceparametree,base=-2 2 0 2 pi mul,
  inhue=0.8 0.2,hue=0.8 0.2,function=cone,linewidth=0.1pt,ngrid=25 40,name=D]
\psSolid[object=fusion,base=A B C D,linecolor=black!10]
\axesIIID(0,0,1.5)(2,2,3)
\end{pspicture} 

\end{document}

enter image description here

enter image description here

| improve this answer | |
  • That was not exactly what I was looking for, but it looks good. I could use it in the future thanks – Emperor_Udan Nov 4 '19 at 18:47

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.