Change cone width

I am trying to draw some simple cones as depicted below

Using my own code this is what I have so far

• How can I make the base of the green cone narrower so it fits within the gray one
• Why are only the bottom part of the ellipses colored gray? I thought I colored both black.

Code

 \documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\def\height{-5cm}
\draw[color=black,fill=gray,opacity=0.2] (0,0) arc (170:10:2cm and 0.4cm)coordinate[pos=0] (a);
\draw (0,0) arc (-170:-10:2cm and 0.4cm)coordinate (b);

\draw[fill=gray,opacity=0.2] (a) -- ([yshift=\height]$(a)!0.5!(b)$) -- (b);
%
\def\height{-5cm}
\def\offset{1cm}
\draw[color=black,fill=green,opacity=0.2] (2cm,0) arc (170:10:1cm and 0.4cm)coordinate[pos=0] (A);
\draw (2cm,0) arc (-170:-10:1cm and 0.4cm)coordinate (B);

\draw[fill=green,opacity=0.2] (A) -- ([yshift=\height]$(A)!0.5!(B)$) -- (B);
\end{tikzpicture}
\end{document}


You could define a pic for that. The point at which the contour of the mantle attaches the projection of base circle is computed numerically in a loop. (You can find answers on this site where it is claimed that this point can be obtained by demanding that the tangent points to the tip, but IMHO this is wrong. On the other hand, this post seems correct to me.)

\documentclass[tikz,border=10pt]{standalone}
\newcounter{iloop}
\tikzset{pics/cone/.style={code={
\tikzset{cone/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/cone/##1}}
\path (0,\pv{h}) coordinate (-tip);
\setcounter{iloop}{0}%
\pgfmathsetmacro{\myangle}{0}%
\pgfmathsetmacro{\myvisangle}{0}%
\loop%
\pgfmathanglebetweenlines%
{\pgfpoint{0cm}{\pv{h}}}{\pgfpoint{0cm}{0cm}}
{\pgfpoint{0cm}{\pv{h}}}{%
\pgfpointpolar{\number\value{iloop}}{\pv{r} and \pv{aspect}*\pv{r}}}
\pgfmathparse{abs(\pgfmathresult)}%
\ifdim\pgfmathresult pt>\myangle pt\relax%
\pgfmathsetmacro{\myangle}{\pgfmathresult}%
\pgfmathsetmacro{\myvisangle}{\value{iloop}}%
\fi
\stepcounter{iloop}\ifnum\value{iloop}<91\repeat
\ifnum\pv{from top}=1
% view cone from the other angle:
\path[/tikz/cone/mantle] (\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
arc(\myvisangle:-180-\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
-- (0,\pv{h}) -- cycle;
\else
\path[/tikz/cone/mantle] (\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
arc(\myvisangle:180-\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
-- (0,\pv{h}) -- cycle;
\fi
}},cone/.cd,base/.style={draw},mantle/.style={draw},
r/.initial=1cm,aspect/.initial=0.3,
h/.initial=2cm,from top/.initial=0}
\begin{document}
\begin{tikzpicture}
\path (2,0) pic[rotate=180]
{cone={mantle/.append style={fill=gray,fill opacity=0.2},
base/.append style={fill=black,fill opacity=0.2},
r=2cm,aspect=0.2,h=5cm}}
(3,0) pic[rotate=180]
{cone={mantle/.append style={fill=green,fill opacity=0.2},
base/.append style={fill=black,fill opacity=0.2},
r=1cm,aspect=0.2,h=5cm}};
\end{tikzpicture}
\end{document}


This can be used as follows:

\documentclass[tikz,border=10pt]{standalone}
\newcounter{iloop}
\tikzset{pics/cone/.style={code={
\tikzset{cone/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/cone/##1}}
\path (0,\pv{h}) coordinate (-tip);
\setcounter{iloop}{0}%
\pgfmathsetmacro{\myangle}{0}%
\pgfmathsetmacro{\myvisangle}{0}%
\loop%
\pgfmathanglebetweenlines%
{\pgfpoint{0cm}{\pv{h}}}{\pgfpoint{0cm}{0cm}}
{\pgfpoint{0cm}{\pv{h}}}{%
\pgfpointpolar{\number\value{iloop}}{\pv{r} and \pv{aspect}*\pv{r}}}
\pgfmathparse{abs(\pgfmathresult)}%
\ifdim\pgfmathresult pt>\myangle pt\relax%
\pgfmathsetmacro{\myangle}{\pgfmathresult}%
\pgfmathsetmacro{\myvisangle}{\value{iloop}}%
\fi
\stepcounter{iloop}\ifnum\value{iloop}<91\repeat
\ifnum\pv{from top}=1
% view cone from the other angle:
\path[/tikz/cone/mantle] (\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
arc(\myvisangle:-180-\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
-- (0,\pv{h}) -- cycle;
\else
\path[/tikz/cone/mantle] (\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
arc(\myvisangle:180-\myvisangle:\pv{r} and \pv{aspect}*\pv{r})
-- (0,\pv{h}) -- cycle;
\fi
}},cone/.cd,base/.style={draw},mantle/.style={draw},
r/.initial=1cm,aspect/.initial=0.3,
h/.initial=2cm,from top/.initial=0}
\begin{document}
\begin{tikzpicture}
\path      (3,0) pic[rotate=180]
{cone={mantle/.append style={left color=green!80,right color=green!60,
base/.append style={fill=green!30},
r=1cm,aspect=0.2,h=5cm}}
(2,0) pic[rotate=180]
{cone={mantle/.append style={left color=gray!80,right color=gray!60,
base/.append style={fill=gray!30},
r=2cm,aspect=0.2,h=5cm}}
(3,0) pic[rotate=180]
{cone={mantle/.append style={draw=green},
base/.append style={draw=green},
r=1cm,aspect=0.2,h=5cm}};
\draw[dashed] (-0.5,0)  -- (5.5,0) node[right]{$O=1$}
(-0.5,-10/3)    -- (5.5,-10/3) node[right]{$O=0$}
(5.5,-5/3) node[right]{$0<O<1$};
\end{tikzpicture}
\end{document}


• Thank you very much. Now, I remove all my commens. Is there a tikz-3dplot version? Dec 18, 2019 at 16:28
• @minhthien_2016 It is straightforward to use this or your code to create one. This post, however, is an attempt to answer the question in the setting chosen by the OP. Yet I think that the \loop ... \repeat stuff will be useful for tikz-3dplot, too, because it is faster and cleaner than previous routines I used to do similar things.
– user194703
Dec 18, 2019 at 17:59

Check this one (Not professional like Schrödinger's cat):

\documentclass[border=0.5cm]{standalone}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw[draw=black,fill=green!20,xshift=1cm] (0.5,0) -- (0,-4) -- (-0.5,0) arc(180:0:0.5cm and 0.2cm)--cycle;

\draw[draw=black,fill=black!5,fill opacity=0.9] (1.5,0) -- (0,-4) -- (-1.5,0) arc(180:0:1.5cm and 0.5cm)--cycle;

\draw[draw=black,fill=black!20,fill opacity=0.9,draw opacity=1] (0,0) ellipse (1.5cm and 0.5cm);

\draw[draw=black,fill=green!50,xshift=1cm] (0,0) ellipse (0.5cm and 0.2cm);
\end{tikzpicture}

\end{document}


after compiling, you will get:

• I like this one too! Dec 18, 2019 at 0:15

I fully realize the OP seeks an answer entirely in LaTeX , but it just seems like the wrong tool for the job. In four minutes, I created a full 3D figure with transparency that can be rotated, etc., in Mathematica, which can be easily inserted (as .eps file) into a LaTeX document:

In case anyone is interested:

Graphics3D[{Opacity[0.5],
Cone[{{0, 0, 3}, {0, 0, 0}}, 1],
Green, Cone[{{.5, 0, 3}, {.5, 0, 0}}, .5],
Opacity[1], Dashing[0.02], Thickness[0.007], Black,
Line[{{1.5, 0, 3}, {-1.5, 0, 3}}],
Line[{{1.5, 0, 1}, {-1.5, 0, 1}}],
Text[Style["O = 1", Italic, 18, FontFamily -> "Times"], {1.8, 0, 3}],
Text[Style["O = 0", Italic, 18, FontFamily -> "Times"], {1.8, 0, 1}],
Text[Style["0 < O < 1", Italic, 18, FontFamily -> "Times"], {1.5, 0,
2}]}]