0

I would like to know if it's possible to draw a cylinder in a 3 dimensional space in tikz, such as I'm able to turn around/ change the point of view? (cf. \begin{tikzpicture}[>=latex, x={(0:1cm)}, y={(90:1cm)}, z={(30:0.4cm)}]

I read several posts saying it's difficult.

I've already a flat drawing,

%%%%%%%%%%%%%%%%%% 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{types/f3d_figlab}

%%%%%%%%%%%%%%%%%%%% Cylinder %%%%%%%%%%%%%%%%%%%%%
    \tikzset{pics/cylinder/.style={code={%
        \tikzset{cylinder/.cd,#1}%
        \def\pv##1{\pgfkeysvalueof{/tikz/cylinder/##1}}
        % depth of the cylinder
        \newcommand{\depth}{\pv{ray}*\pv{scale}*0.25}
        \fill[baseinf] (0,0) circle (\pv{ray}*\pv{scale} cm and \depth cm);
        \fill[corps] (\pv{ray}*\pv{scale},0) -- (\pv{ray}*\pv{scale},\pv{height}*\pv{scale}) arc (360:180:\pv{ray}*\pv{scale} cm and \depth cm) -- (-\pv{ray}*\pv{scale},0) arc (180:360:\pv{ray}*\pv{scale} cm and \depth cm);
        \fill[basesup] (0,\pv{height}*\pv{scale}) circle (\pv{ray}*\pv{scale} cm and \depth cm);
        \draw[thick] (-\pv{ray}*\pv{scale},\pv{height}*\pv{scale}) -- (-\pv{ray}*\pv{scale},0) arc (180:360:\pv{ray}*\pv{scale} cm and \depth cm) -- (\pv{ray}*\pv{scale},\pv{height}*\pv{scale}) ++ (-\pv{ray}*\pv{scale},0) circle (\pv{ray}*\pv{scale} cm and \depth cm)
        ;
        \draw[thick, densely dashed] (-\pv{ray}*\pv{scale},0) arc (180:0:\pv{ray}*\pv{scale} cm and \depth cm);
        % Mesure de la hauteur
        \draw[thick,<->] 
            (\pv{ray}*\pv{scale}+0.4,0) -- (\pv{ray}*\pv{scale}+0.4,\pv{height}*\pv{scale}) node[midway, right] {\pv{height}~\pv{unit}};
        % Mesure du rayon
        \draw[thick,<->]
            (0,-\depth-0.4) -- (\pv{ray}*\pv{scale},-\depth-0.4) node[midway, below] {\pv{ray}~\pv{unit}};
        \draw (0,0) node[circle, fill=black, opacity=.8, scale=.3] {};

      }},
      cylinder/.cd,
      ray/.initial=5,
      height/.initial=5,
      fill/.initial=gray,
      unit/.initial=cm,
      scale/.initial=1,
    }

%%%%%%%%%%%%%%%%%% DOCUMENT %%%%%%%%%%%%%%%%%%
\begin{document}
\begin{tikzpicture}[font={\sansmath\sffamily},line width=0.4mm , line cap=round, line join=round, >=latex, x={(0:1cm)}, y={(90:1cm)}, z={(75:0.6cm)}]

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

%   Figures
\pic{cylinder={ray=63, height=50, scale=.07, corps/.style={draw,fill=orange!20}, basesup/.style={draw,fill=orange!20},}};

\end{tikzpicture}
\end{document}
Nilcouv
  • 539
  • 2
    Here is a rotatable version. There are more versions around. Unfortunately it is hard to try out your code because it does not contain a full example, and style definitions like baseinf, corps and basesup are missing. –  Mar 18 '20 at 18:20
  • 1
    Welcome to TeX.SX! Can you please expand the code snippet that you have posted to a full minimal working example. It is much easier to help you if we can start with some compilable code that illustrates your problem. A MWE should start with a \documentclass command, include any necessary packages and be as small as possible to demonstrate your problem. At the moment we have to guess what packages etc you are using before we can compile your code. –  Mar 18 '20 at 23:07
  • I've just done it now, sorry for the delay – Nilcouv Mar 20 '20 at 15:22

1 Answers1

1

The good news is that it is straightforward to do what you are asking. From your code fragment I infer that you want to have a cylinder that points into the y direction, and I shall assume that this direction has a positive projection on the y direction of the screen (but it will be easy to drop this assumption, if needed). All we need then to do is to compute the critical angle of visibility, and the simple computation yields that this is given by

\pgfmathsetmacro{\myan}{atan2(\pgf@zx,\pgf@xx)}

where \pgf@zx and \pgf@xx are the projections of the installed z and x unit vectors on the x direction of the screen. So far so good ... but the problem is that the coordinate system you provide is not orthographic, nor is the one predefined by TikZ. Here is how the cylinders look like in these coordinates.

\documentclass[tikz,border=3mm]{standalone}
\makeatletter
\tikzset{pics/cylinder/.style={code={%
    \tikzset{cylinder/.cd,#1}%
    \def\pv##1{\pgfkeysvalueof{/tikz/cylinder/##1}}
    \pgfmathsetmacro{\myan}{atan2(\pgf@zx,\pgf@xx)}
    \begin{scope}[local bounding box=cyl]
      \path[cylinder/corps]
       plot[smooth,variable=\t,samples=19,domain=\myan:{-1*sign(\myan)*180+\myan}]
      ({\pv{ray}*\pv{scale}*cos(\t)},
      {\pv{height}*\pv{scale}},{\pv{ray}*\pv{scale}*sin(\t)})
      -- 
      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)})
      -- cycle;
      \path[cylinder/basesup] plot[smooth cycle,variable=\t,samples=37,domain=0:360]
      ({\pv{ray}*\pv{scale}*cos(\t)},
      {\pv{height}*\pv{scale}},
      {\pv{ray}*\pv{scale}*sin(\t)});
      \draw[thick, densely dashed] 
      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}   
    \draw[|<->|] ([yshift=-4mm]cyl.south west) -- 
    ([yshift=-4mm]cyl.south east) node[midway, below] {\pv{ray}~\pv{unit}};
    \draw[|<->|,xshift=4mm] 
    ({\pv{ray}*\pv{scale}*cos(\myan)},
     {\pv{height}*\pv{scale}},{\pv{ray}*\pv{scale}*sin(\myan)})
    --
    ({\pv{ray}*\pv{scale}*cos(\myan)},
      0,{\pv{ray}*\pv{scale}*sin(\myan)})
     node[midway, right] {\pv{height}~\pv{unit}}; 
  }},
  cylinder/.cd,
  ray/.initial=5,
  height/.initial=5,
  fill/.initial=gray,
  unit/.initial=cm,
  scale/.initial=1,
  corps/.style={draw,fill=gray},
  basesup/.style={draw,fill=red}
}
\makeatother
\begin{document}
\begin{tikzpicture}
 \pic{cylinder};
\end{tikzpicture}

\begin{tikzpicture}[>=latex, x={(0:1cm)}, y={(90:1cm)}, z={(30:0.4cm)}]
 \pic{cylinder};
\end{tikzpicture}
\end{document}

enter image description here

They look skewed. Why? Simply because these are not orthographic projections. If you want orthographic projections, use either the 3d view key that comes with the perspective library or tikz-3dplot. The former has the great advantage of also allowing one to use perspective projections, and it would be IMHO a very nice (yet separate!) question to draw cylinders in perspective (the good news being that the above can be modified to do that). For tikz-3dplot there are already various examples, I shamelessly highlight my own: here and here because you seem to like pics.

So the bottom-line is that it is not difficult to provide you with what you are asking for, but chances are that you do not really want precisely that.