2

I'm trying to plot a cone in 3D, but I'm a little stuck.

I plotted a densely dashed, then I'm trying to plot the border of the cone, divided in 3 part:

  • The green part is static
  • The blue part change depending on the height of the cone
  • The red part is just a connection between a dot "h" and the blue part.

enter image description here

I'm unable to plot the red left part of the cone, and the there is a black line when "height=0"

enter image description here

%%%%%%%%%%%%%%%%%% INTRODUCTION %%%%%%%%%%%%%%%%%%
\documentclass[border=10pt]{standalone}

%%%%%%%%%%%%%%%%%% PACKAGE %%%%%%%%%%%%%%%%%%
\usepackage{tikz, tkz-euclide}%  permet de dessiner des figures, des graphiques
\usepackage{adjustbox}% permet de déterminer une taille de fenêtre
%%  FONT
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{tgadventor}% paquet de police de caractère TGadventor
\usepackage{sansmath}%  Copie-colle la police active dans 
%                       \sfdefault (/!\ N'EST PAS UNE POLICE DE CARACTÈRES)
\usepackage{xcolor}
%%%%%%%%%%%%%%%%%% INPUT %%%%%%%%%%%%%%%%%%
%\input{preamble}
%\input{parameters}
%\input{types/f3d_fig}
%%%%%%%%%%%%%%%%%% SETUP %%%%%%%%%%%%%%%%%%
\tikzset{volum3D/.style={font={\sansmath\sffamily\large}, line width=0.4mm, line cap=round, line join=round, >=latex,}} 

%%%%%%%%%%%%%%%%%%%%%%%% CONE %%%%%%%%%%%%%%%%%%%%%%%%
\makeatletter
\tikzset{pics/cone/.style={code={%
    \tikzset{cone/.cd,#1}%
    \def\pv##1{\pgfkeysvalueof{/tikz/cone/##1}}%
    \pgfmathsetmacro{\myan}{atan2(\pgf@zx,\pgf@xx)}%
    \begin{scope}[local bounding box=sph]%
        %%%     Compute the angle
        \pgfmathsetmacro\angle{acos(1/\pv{height})}
        \path[cone/corps]
        %%%     Patrie supérieur
        (0,
        \pv{height}*\pv{scale},
        0) coordinate (h) 
        node[above] {\angle}
        node[below] {\myan}
        %%%     Patrie droite
        (h) -- 
        plot[smooth,variable=\t,samples=19,domain={(sign(\myan)*90+\myan)-\angle}:\myan]
        ({\pv{ray}*\pv{scale}*cos(\t)},
        0,
        {\pv{ray}*\pv{scale}*sin(\t)})
        %%%     Patrie Inférieur
        -- plot[smooth,variable=\t,samples=19,domain=\myan:{-1*sign(\myan)*180+\myan}]
        ({\pv{ray}*\pv{scale}*cos(\t)},
        0,
        {\pv{ray}*\pv{scale}*sin(\t)})
        %%%     Patrie gauche
        %-- plot[smooth,variable=\t,samples=19,domain={180*\myan-\myan}:\myan]
        %({\pv{ray}*\pv{scale}*cos(\t)},
        %0,
        %{\pv{ray}*\pv{scale}*sin(\t)})
        -- cycle
        ;
        %%%     CERCLE EN POINTILLÉ
        \draw[thick, densely dashed]
        %%%       Arc Avant
        plot[smooth,variable=\t,samples=19,domain={-1*sign(\myan)*180+\myan}:\myan]
        ({\pv{ray}*\pv{scale}*cos(\t)},
        0,
        {\pv{ray}*\pv{scale}*sin(\t)})
        %%%       Arc Arrière
        plot[smooth,variable=\t,samples=19,domain={sign(\myan)*180+\myan}:\myan]
        ({\pv{ray}*\pv{scale}*cos(\t)},
        0,
        {\pv{ray}*\pv{scale}*sin(\t)})
        ;
    \end{scope}
    %%  Dot (0,0)
    \draw 
    (0,0,0) node[circle, fill=black, inner sep=1pt] {} coordinate (o)
    ;
  }},
  cone/.cd,
  ray/.initial=5,
  height/.initial=3,
  scale/.initial=1,
  corps/.style={draw,fill=black!15},
}
\makeatother
%%%%%%%%%%%%%%%%%% DOCUMENT %%%%%%%%%%%%%%%%%%
\begin{document}
\begin{tikzpicture}[volum3D, x={(0:1cm)}, y={(90:1cm)}, z={(89:0.4cm), scale=0.5}]

% calibration cross
%\pic at (5,0,0) {calcross};

%   Figures
\foreach \h in {0.5,1,...,8}{
    \begin{scope}[shift={(6.2*\h,0)}]
        \pic{cone={ray=3, height=\h, scale=0.5}};
    \end{scope}
  }

\end{tikzpicture}
\end{document}
2
  • 2
    You are taking the arccos of 0.5.
    – user194703
    Apr 21, 2020 at 16:46
  • I still haven't properly understood how to draw a 3D curve on latex. If I'm not mistaken, you're using functions. The problem is that I would need to refresh this point to be able to understand. As a result, my actions are quite random, that's why I used "arccos". I'm just trying to find something working :/ .
    – Nilcouv
    Apr 22, 2020 at 11:00

1 Answer 1

4

Unfortunately I do not understand your construction, but you take the arccos of 0.5. I also do not understand

x={(0:1cm)}, y={(90:1cm)}, z={(89:0.4cm), scale=0.5}

Apart from the fact that I have never seen z={(89:0.4cm), scale=0.5} before I think that if you project a cone using these vectors it will look awkward.

All I can offer here is something that provides you with an orthographic projection of a cone. My previous post on this was not entirely correct. Notice that, even though I am using tikz-3dplot here, this does not rely on its specific parametrization. As long as you load the calc library and install an orthonormal projection, you will be fine. (The shading has not been tuned infinitely. There are basically four cases, either the projection of the tip is inside or outside the projection of the base, and the tip can point "out of the screen" or into it. These cases are distinguished automatically, but each of them has a somewhat different prescription for the shading.)

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{fpu}
\makeatletter
\pgfmathdeclarefunction{screendepth}{3}{%
\begingroup%
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathparse{%
((\the\pgf@yx/1cm)*(\the\pgf@zy/1cm)-(\the\pgf@yy/1cm)*(\the\pgf@zx/1cm))*(#1)+
((\the\pgf@zx/1cm)*(\the\pgf@xy/1cm)-(\the\pgf@xx/1cm)*(\the\pgf@zy/1cm))*(#2)+
((\the\pgf@xx/1cm)*(\the\pgf@yy/1cm)-(\the\pgf@yx/1cm)*(\the\pgf@xy/1cm))*(#3)}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%
\makeatother
\tikzset{pics/3d cone/.style={code={
    \tikzset{3d cone/.cd,#1}
    \def\pv##1{\pgfkeysvalueof{/tikz/3d cone/##1}}%
    \pgfmathsetmacro{\sdtip}{screendepth(0,0,\pv{h})}
    \pgfmathsetmacro{\aspectangle}{atan2(\sdtip,sqrt(\pv{h}*\pv{h}-\sdtip*\sdtip))}
    \path (0,0,\pv{h}) coordinate (-tip);
    \begin{scope}[x={(0,0,tan(\aspectangle))},y={($(0,0,0)!1cm!90:(0,0,\pv{h})$)}]
     \pgfmathtruncatemacro{\itest}{abs(tan(\aspectangle)*\pv{r}/\pv{h})<1}
     \ifnum\itest=1
      \pgfmathsetmacro{\alphacrit}{acos(tan(\aspectangle)*\pv{r}/\pv{h})}
      \ifdim\sdtip pt>0pt
       \path[/tikz/3d cone/base] circle[radius=\pv{r}];
       \path[/tikz/3d cone/hidden] (\alphacrit:\pv{r}) arc[start angle=\alphacrit,end
       angle=-\alphacrit,radius=\pv{r}];
       \path let \p1=(1,0),\n1={atan2(\y1,\x1)} in 
       [/tikz/3d cone/mantle,shading angle=\n1] (\alphacrit:\pv{r}) 
       arc[start angle=\alphacrit,end
       angle=360-\alphacrit,radius=\pv{r}] -- (-tip) -- cycle;
       \foreach \XX in {0,2,...,42}
        {\path[fill opacity=0.05,fill=white] (\XX:\pv{r}) 
        arc[start angle=\XX,end angle=-\XX,radius=\pv{r}] -- (-tip) -- 
        cycle;}
      \else
       \path[/tikz/3d cone/base,/tikz/3d cone/visible] circle[radius=\pv{r}];
       \path let \p1=(1,0),\n1={atan2(\y1,\x1)} in 
       [/tikz/3d cone/mantle,shading angle=\n1] (\alphacrit:\pv{r}) arc[start angle=\alphacrit,end
       angle=360-\alphacrit,radius=\pv{r}] -- (-tip) -- cycle;
       \foreach \XX in {0,2,...,42}
        {\path[fill opacity=0.05,fill=white] (180+\XX:\pv{r}) 
        arc[start angle=180+\XX,end angle=180-\XX,radius=\pv{r}] -- (-tip) -- 
        cycle;}
      \fi
     \else 
      \ifdim\sdtip pt>0pt
       \path[/tikz/3d cone/base,/tikz/3d cone/visible] circle[radius=\pv{r}];
       \foreach \YY in {0,180}
       {\foreach \XX in {0,2,...,42}
       {\path[fill opacity=0.05,fill=white] (\YY+\XX:\pv{r}) 
        arc[start angle=\YY+\XX,end angle=\YY-\XX,radius=\pv{r}] -- (-tip) -- 
        cycle;
        \path[fill opacity=0.05,fill=black] (90+\YY+\XX:\pv{r}) 
        arc[start angle=90+\YY+\XX,end angle=90+\YY-\XX,radius=\pv{r}] -- (-tip) -- 
        cycle;}}
      \else
       \foreach \YY in {0,180}
       {\foreach \XX in {0,2,...,42}
       {\path[fill opacity=0.05,fill=white] (\YY+\XX:\pv{r}) 
        arc[start angle=\YY+\XX,end angle=\YY-\XX,radius=\pv{r}] -- (-tip) -- 
        cycle;
        \path[fill opacity=0.05,fill=black] (90+\YY+\XX:\pv{r}) 
        arc[start angle=90+\YY+\XX,end angle=90+\YY-\XX,radius=\pv{r}] -- (-tip) -- 
        cycle;}}
       \path[/tikz/3d cone/base] circle[radius=\pv{r}];
      \fi
     \fi
    \end{scope}
    }},
    3d cone/.cd,r/.initial=1,h/.initial=1,
    base/.style={fill=gray},mantle/.style={left color=black,right
    color=black,middle color=gray!20,fill opacity=0.7},
    hidden/.style={draw,very thin,densely dashed},
    visible/.style=draw}
\begin{document}
\foreach \Angle in {5,15,...,355}
{\begin{tikzpicture}
 \path[use as bounding box] (-2.5,-2.5) rectangle (2.5,2.5);
 \tdplotsetmaincoords{70}{110}
 \tdplotsetrotatedcoords{2*\Angle+45}{\Angle}{0}
 \begin{scope}[tdplot_rotated_coords,fill opacity=0.6,text opacity=1]
 \pic{3d cone={r=1.5,h=2}};
 \end{scope}
\end{tikzpicture}}
\end{document}

enter image description here

3
  • @Schrödingers cat I have to keep the same graphical chart than the others shapes, and I may have to use it in the same environment. That's why I try to keep it consistent. But the problem is that some of my choices lack flexibility... do you have any advice on what would be the best way to generate a wide variety of 3-dimensional shapes for math exercices. I really need something that is flexible and allows me to work quickly.
    – Nilcouv
    Apr 22, 2020 at 14:02
  • 1
    @Nilcouv Not sure what I can do. However, I feel you should really use orthographic projections and then take it from there. I also do not understand the blue part story in the updated question. How does that arise?
    – user194703
    Apr 22, 2020 at 16:01
  • @Schrödingers cat i'm not the one who choose. In belgium, we use the "perspective cavalière" to represent shapes, which equates to your "Parallel projections > Oblique > Cabinet". The blue part is a segment which has a variable lenght depending the height of the cone. The idea would be to plot a horizontal arc in 3D, and to change the domain depending on the height of the cone (shorter is the height, wider is the domain, and longer is the height, smaller is the domain)
    – Nilcouv
    Apr 23, 2020 at 11:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .