4

I used the result in this post to achieve a rotation of a cone about an 3D axis. I am unsure on how to implement the following to this image:

Rotated cone.

I would like the imaginary lines that run along the 'volume of the cone' to be dashed to promote a better sense of the 3D nature of the image. I also need to draw an arc between the central lines of both cones to label the rotation angle $\vartheta$. Also is there any advice to make it look more '3D-like'?

MWE

\documentclass[tikz]{standalone}
\usepackage{pgfplots} 
\usepackage{filecontents}           
\usetikzlibrary{arrows,shapes,backgrounds,fit,decorations.pathreplacing,chains,snakes,positioning,angles,quotes}  


\newcommand{\savedx}{0}
\newcommand{\savedy}{0}
\newcommand{\savedz}{0}

\tikzset{
pics/tester/.style n args={3}{
code = {%   

\def\x{1}
\def\y{3.4}
\def\R{\x+0.009}
\def\yc{\y+0.08}
\def\e{0.6}


\shade[right color=white,left color=blue,opacity=#1]
(-\x,\y) -- (-\x,\yc) arc (180:360:{\R} and \e) -- (\x,\y) -- (0,0) -- cycle;
\draw[fill=#2,#3]
(0,\yc) circle ({\R} and \e);
\draw[#3]
(-\x,\y) -- (0,0) -- (\x,\y);
\draw[#3]
(0,\yc) circle ({\R} and \e);

\draw[line width=1pt] (0,0,0) -- (0,4,0);

}}}



\newcommand{\rotateRPY}[4][0/0/0]% point to be saved to \savedxyz, roll, pitch, yaw
{   \pgfmathsetmacro{\rollangle}{#2}
\pgfmathsetmacro{\pitchangle}{#3}
\pgfmathsetmacro{\yawangle}{#4}

% to what vector is the x unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newxx}{cos(\yawangle)*cos(\pitchangle)}% a
\pgfmathsetmacro{\newxy}{sin(\yawangle)*cos(\pitchangle)}% d
\pgfmathsetmacro{\newxz}{-sin(\pitchangle)}% g
\path (\newxx,\newxy,\newxz);
\pgfgetlastxy{\nxx}{\nxy};

% to what vector is the y unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newyx}{cos(\yawangle)*sin(\pitchangle)*sin(\rollangle)-sin(\yawangle)*cos(\rollangle)}% b
\pgfmathsetmacro{\newyy}{sin(\yawangle)*sin(\pitchangle)*sin(\rollangle)+ cos(\yawangle)*cos(\rollangle)}% e
\pgfmathsetmacro{\newyz}{cos(\pitchangle)*sin(\rollangle)}% h
\path (\newyx,\newyy,\newyz);
\pgfgetlastxy{\nyx}{\nyy};

% to what vector is the z unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newzx}{cos(\yawangle)*sin(\pitchangle)*cos(\rollangle)+ sin(\yawangle)*sin(\rollangle)}
\pgfmathsetmacro{\newzy}{sin(\yawangle)*sin(\pitchangle)*cos(\rollangle)-cos(\yawangle)*sin(\rollangle)}
\pgfmathsetmacro{\newzz}{cos(\pitchangle)*cos(\rollangle)}
\path (\newzx,\newzy,\newzz);
\pgfgetlastxy{\nzx}{\nzy};

% transform the point given by #1
\foreach \x/\y/\z in {#1}
{   \pgfmathsetmacro{\transformedx}{\x*\newxx+\y*\newyx+\z*\newzx}
    \pgfmathsetmacro{\transformedy}{\x*\newxy+\y*\newyy+\z*\newzy}
    \pgfmathsetmacro{\transformedz}{\x*\newxz+\y*\newyz+\z*\newzz}
    \xdef\savedx{\transformedx}
    \xdef\savedy{\transformedy}
    \xdef\savedz{\transformedz}     
}
}

\tikzset{RPY/.style={x={(\nxx,\nxy)},y={(\nyx,\nyy)},z={(\nzx,\nzy)}}}

\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
\pic {tester={0.08}{black!6!white}{densely dashed}};
\rotateRPY{0}{0}{91}
\begin{scope}[RPY]
\pic {tester={0.2}{blue!14!white}{}};
\end{scope}
\end{tikzpicture}


\end{document}

I would like then like to overlay both of the cones with a similar one that is squashed in one direction, but stretched by an equivalent factor in the other direction. The above MWE has a few flaws in achieving this which shows for one of the cones:

Second objective

Namely, bases of the cones are not in the same plane. The red cone is stretched in one direction, but is not squeezed in the other direction.

6

I would like to argue that such things are drawn much more conveniently with the tikz-3dplot package and the 3d library.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot} 
\usetikzlibrary{3d,shadings}
\makeatletter
% small fix for canvas is xy plane at z % https://tex.stackexchange.com/a/48776/121799
 \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

\begin{document}

\tdplotsetmaincoords{110}{-165} % - because of difference between active and passive transformations...
\begin{tikzpicture}
 %\draw (-5,-2.5) rectangle (1.5,5);
 \begin{scope}[tdplot_main_coords,thick]
  % just in case you want to get an intuition for the coordinates/projections
  %  \draw[-latex] (0,0,0) -- (1,0,0) coordinate (X) node[below]{$x$};
  %  \draw[-latex] (0,0,0) -- (0,1,0) coordinate (Y) node[right]{$y$};
  %  \draw[-latex] (0,0,0) -- (0,0,1) coordinate (Z) node[left]{$z$};
  % origin
  \coordinate (O) at (0,0,0);
  % top
  \begin{scope}[canvas is xy plane at z=4,dashed]
   \draw[thick,solid] (O) -- (0,0);
   \shadedraw[fill opacity=0.3,left color=blue,right color=white] (\tdplotmainphi:1) 
   arc(\tdplotmainphi:\tdplotmainphi+180:1) -- (O) -- cycle;
   \draw[fill opacity=0.3,fill=gray!80] circle (1);
  \end{scope}
  % left
  \begin{scope}[canvas is yz plane at x=4]
   \draw[thick] (O) -- (0,0);
   \pgfmathsetmacro{\MyThetaMax}{atan(tan(\tdplotmaintheta)*sin(90+\tdplotmainphi))}
   \shadedraw[line join=bevel,fill opacity=0.3,upper right=white,lower  left=blue] 
   (\MyThetaMax:1) 
   arc(\MyThetaMax:\MyThetaMax+180:1) -- (O) -- cycle;
       \draw[fill opacity=0.3,fill=gray] circle (1);
      \end{scope}
      % arc
      \begin{scope}[canvas is xz plane at y=0,xscale=-1]
       \draw[-latex] (0,1) arc(90:180:1) node[midway,above left]{$\vartheta$};
  \end{scope}
 \end{scope}
\end{tikzpicture}
\end{document}

enter image description here

The advantage is that you can change the view angles at will.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot} 
\usetikzlibrary{3d,shadings}
\makeatletter
% small fix for canvas is xy plane at z % https://tex.stackexchange.com/a/48776/121799
 \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

\begin{document}
\foreach \X in {5,15,...,355}
{\tdplotsetmaincoords{120+20*sin(\X)}{\X} % - because of difference between active and passive transformations...
\begin{tikzpicture}
 \path[use as bounding box] (-5,-2.5) rectangle (5,5);
 \begin{scope}[tdplot_main_coords,thick]
  % just in case you want to get an intuition for the coordinates/projections
  %  \draw[-latex] (0,0,0) -- (1,0,0) coordinate (X) node[below]{$x$};
  %  \draw[-latex] (0,0,0) -- (0,1,0) coordinate (Y) node[right]{$y$};
  %  \draw[-latex] (0,0,0) -- (0,0,1) coordinate (Z) node[left]{$z$};
  % origin
  \coordinate (O) at (0,0,0);
  % left
  \begin{scope}[canvas is yz plane at x=4]
   \pgfmathtruncatemacro{\ttest}{sign(cos(\tdplotmainphi+90))}
   \ifnum\ttest=1
    \pgfmathsetmacro{\MyThetaMax}{atan(tan(\tdplotmaintheta)*sin(90+\tdplotmainphi))}
    \shadedraw[line join=bevel,fill opacity=0.3,upper right=white,lower  left=blue] 
    (\MyThetaMax:1) 
    arc(\MyThetaMax:\MyThetaMax+180:1) -- (O) -- cycle;
    \draw[fill=gray!30] circle (1);
    \draw[thick] (O) -- (0,0);
   \else
    \draw[fill=gray!30] circle (1);
    \draw[thick] (O) -- (0,0);
    \pgfmathsetmacro{\MyThetaMax}{atan(tan(\tdplotmaintheta)*sin(90+\tdplotmainphi))}
    \shadedraw[line join=bevel,fill opacity=0.3,upper right=white,lower  left=blue] 
    (\MyThetaMax:1) 
    arc(\MyThetaMax:\MyThetaMax+180:1) -- (O) -- cycle;
   \fi  
  \end{scope}
  % top
  \begin{scope}[canvas is xy plane at z=4,dashed]
   \draw[thick,solid] (O) -- (0,0);1
   \shadedraw[fill opacity=0.3,left color=blue,right color=white] (\tdplotmainphi:1) 
   arc(\tdplotmainphi:\tdplotmainphi+180:1) -- (O) -- cycle;
   \draw[fill opacity=0.3,fill=gray!80] circle (1);
  \end{scope}
  % arc
%   \begin{scope}[canvas is xz plane at y=0,xscale=-1]
%    \draw[-latex] (0,1) arc(90:180:1) node[midway,above left]{$\vartheta$};
%   \end{scope}
 \end{scope}
\end{tikzpicture}}
\end{document}

enter image description here

As for the "squashed" shape: it took me some time to derive the (hopefully) correct formula for the visibility angle \MyThetaMax. Other than that it is almost trivial: draw ellipses in the respective planes and then repeat the above.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot} 
\usetikzlibrary{3d,shadings}

\makeatletter
% small fix for canvas is xy plane at z % https://tex.stackexchange.com/a/48776/121799
 \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

\begin{document}

\tdplotsetmaincoords{110}{-165} % - because of difference between active and passive transformations...
\begin{tikzpicture}
 %\draw (-5,-2.5) rectangle (1.5,5);
 \begin{scope}[tdplot_main_coords,thick]
  % just in case you want to get an intuition for the coordinates/projections
  %  \draw[-latex] (0,0,0) -- (1,0,0) coordinate (X) node[below]{$x$};
  %  \draw[-latex] (0,0,0) -- (0,1,0) coordinate (Y) node[right]{$y$};
  %  \draw[-latex] (0,0,0) -- (0,0,1) coordinate (Z) node[left]{$z$};
  % origin
  \coordinate (O) at (0,0,0);
  % top
  \begin{scope}[canvas is xy plane at z=4,dashed]
   \draw[thick,solid] (O) -- (0,0);
   \shadedraw[fill opacity=0.3,left color=blue,right color=white] (\tdplotmainphi:1) 
   arc(\tdplotmainphi:\tdplotmainphi+180:1) -- (O) -- cycle;
   \draw[fill opacity=0.3,fill=gray!80] circle (1);
   % squashed shape
   \shadedraw[fill opacity=0.1,left color=red,right color=white] 
   (\tdplotmainphi:2 and 1) 
   arc(\tdplotmainphi:\tdplotmainphi+180:2 and 1) -- (O) -- cycle;
   \draw[fill opacity=0.1,fill=gray!80] circle (2 and 1);
  \end{scope}
  % left
  \begin{scope}[canvas is yz plane at x=4]
   \draw[thick] (O) -- (0,0);
   \pgfmathsetmacro{\MyThetaMax}{atan(tan(\tdplotmaintheta)*sin(90+\tdplotmainphi))}
   \shadedraw[line join=bevel,fill opacity=0.3,upper right=white,lower  left=blue] 
   (\MyThetaMax:1) 
   arc(\MyThetaMax:\MyThetaMax+180:1) -- (O) -- cycle;
   \draw[fill opacity=0.3,fill=gray] circle (1);
   % squash again
   \pgfmathsetmacro{\MyThetaMax}{atan(tan(\tdplotmaintheta)*sin(90+\tdplotmainphi)*2)}
   \shadedraw[line join=bevel,fill opacity=0.1,upper right=white,
   lower  left=red] 
   (\MyThetaMax:1 and 2) 
   arc(\MyThetaMax:\MyThetaMax+180:1 and 2) -- (O) -- cycle;
   \draw[fill opacity=0.1,fill=gray] circle (1 and 2);
  \end{scope}
  % arc
  \begin{scope}[canvas is xz plane at y=0,xscale=-1]
    \draw[-latex] (0,1) arc(90:180:1) node[midway,above left]{$\vartheta$};
  \end{scope}
 \end{scope}
\end{tikzpicture}
\end{document}

enter image description here

Here's another attempt. I thought the above one would match your description.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot} 
\usetikzlibrary{3d,shadings}

\makeatletter
% small fix for canvas is xy plane at z % https://tex.stackexchange.com/a/48776/121799
 \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

\begin{document}

\tdplotsetmaincoords{110}{-165} % - because of difference between active and passive transformations...
\begin{tikzpicture}
 %\draw (-5,-2.5) rectangle (1.5,5);
 \begin{scope}[tdplot_main_coords,thick]
  % just in case you want to get an intuition for the coordinates/projections
  %  \draw[-latex] (0,0,0) -- (1,0,0) coordinate (X) node[below]{$x$};
  %  \draw[-latex] (0,0,0) -- (0,1,0) coordinate (Y) node[right]{$y$};
  %  \draw[-latex] (0,0,0) -- (0,0,1) coordinate (Z) node[left]{$z$};
  % origin
  \coordinate (O) at (0,0,0);
  % top
  \begin{scope}[canvas is xy plane at z=4,dashed]
   \draw[thick,solid] (O) -- (0,0);
   % squashed shape
   \pgfmathsetmacro{\MyPhiMax}{atan(tan(\tdplotmainphi)*sin(90+\tdplotmaintheta))}
   \shadedraw[fill opacity=0.1,left color=red,right color=white] 
   (\MyPhiMax:2 and 0.5) 
   arc(\MyPhiMax:\MyPhiMax+180:2 and 0.5) -- (O) -- cycle;
   \draw[fill opacity=0.1,fill=gray!80] circle (2 and 0.5);
   % unsquashed
   \shadedraw[fill opacity=0.3,left color=blue,right color=white] (\tdplotmainphi:1) 
   arc(\tdplotmainphi:\tdplotmainphi+180:1) -- (O) -- cycle;
   \draw[fill opacity=0.3,fill=gray!80] circle (1);
  \end{scope}
  % left
  \begin{scope}[canvas is yz plane at x=4]
   \draw[thick] (O) -- (0,0);
   % squash again
   \pgfmathsetmacro{\MyThetaMax}{atan(tan(\tdplotmaintheta)*sin(90+\tdplotmainphi)*4)}
   \shadedraw[line join=bevel,fill opacity=0.1,upper right=white,
   lower  left=red] 
   (\MyThetaMax:0.5 and 2) 
   arc(\MyThetaMax:\MyThetaMax+180:0.5 and 2) -- (O) -- cycle;
   \draw[fill opacity=0.1,fill=gray] circle (0.5 and 2);
   % unsquashed
   \pgfmathsetmacro{\MyThetaMax}{atan(tan(\tdplotmaintheta)*sin(90+\tdplotmainphi))}
   \shadedraw[line join=bevel,fill opacity=0.3,upper right=white,lower  left=blue] 
   (\MyThetaMax:1) 
   arc(\MyThetaMax:\MyThetaMax+180:1) -- (O) -- cycle;
   \draw[fill opacity=0.3,fill=gray] circle (1);
  \end{scope}
  % arc
  \begin{scope}[canvas is xz plane at y=0,xscale=-1]
    \draw[-latex] (0,1) arc(90:180:1) node[midway,above left]{$\vartheta$};
  \end{scope}
 \end{scope}
\end{tikzpicture}
\end{document}

enter image description here

  • We keep crossing paths ;) Great answer. How could I change the lines running along the volume of the cone to be dashed? – Sid Aug 28 '18 at 22:00
  • Also the animation example has the function sign that isn't recognised? – Sid Aug 28 '18 at 22:02
  • @Sid In the "top" scope I just added dashed to the scope options. Does adding dashed to the left scope give you want you want? (Probably I just do not understand.) And what do you mean by sign is not recognized? On my TeXLive installation the code gives me a multipage pdf without any problems which I convert using convert to the animated gif. – user121799 Aug 28 '18 at 22:05
  • I got the 'unknown function sign' on the console. On a related question, I wanted to overlay another cone over both the dashed and non-dashed cones, but which is stretched along one of the axes and red in colour. This was why I originally had the \tikzset approach. How could I do this? – Sid Aug 28 '18 at 22:13
  • 1
    For the record: Jake's patch is now incorporated in v3.1 of TikZ. – Stefan Pinnow Jan 15 at 19:19

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.