Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I need to draw a lot of 3D cylinders with different dimensions. Has anyone maybe already defined a command like \3Dcylinder{x}{y}{z}?

I found 3D bodies in TikZ and tried the third answer. But I don't understand how the parameters work.

Also I found Drawing simple 3D cylinders in TikZ. But I don't know how to use it to easily draw a bunch of different cylinders.

share|improve this question
    
You might be interested in tex.stackexchange.com/q/129860/5645 –  moose Feb 4 at 10:03
add comment

2 Answers

up vote 4 down vote accepted

I also once had that problem when I had to draw an explded view drawing. Andrew Stacey's answer in the second link you mentioned was the way to go, so I adapted the following macro:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\pgfmathsetmacro{\xdeg}{30}
\pgfmathsetmacro{\xx}{cos(\xdeg)}
\pgfmathsetmacro{\xy}{sin(\xdeg)}

\pgfmathsetmacro{\ydeg}{120}
\pgfmathsetmacro{\yx}{cos(\ydeg)}
\pgfmathsetmacro{\yy}{sin(\ydeg)}

\pgfmathsetmacro{\zdeg}{80}
\pgfmathsetmacro{\zx}{cos(\zdeg)}
\pgfmathsetmacro{\zy}{sin(\zdeg)}

\newcommand{\tdcyl}[5]{% origin x, origin y, origin z, radius, height
    \path (1,0,0);
    \pgfgetlastxy{\cylxx}{\cylxy}
    \path (0,1,0);
    \pgfgetlastxy{\cylyx}{\cylyy}
    \path (0,0,1);
    \pgfgetlastxy{\cylzx}{\cylzy}
    \pgfmathsetmacro{\cylt}{(\cylzy * \cylyx - \cylzx * \cylyy)/ (\cylzy * \cylxx - \cylzx * \cylxy)}
    \pgfmathsetmacro{\ang}{atan(\cylt)}
    \pgfmathsetmacro{\ct}{1/sqrt(1 + (\cylt)^2)}
    \pgfmathsetmacro{\st}{\cylt * \ct}
    \filldraw[fill=white] (#4*\ct+#1,#4*\st+#2,#3) -- ++(0,0,#5) arc[start angle=\ang,delta angle=-180,radius=#4] -- ++(0,0,-#5) arc[start angle=\ang+180,delta angle=180,radius=#4];
    \filldraw[fill=white] (#1,#2,#3+#5) circle[radius=#4];
}

\begin{document}

\begin{tikzpicture}[x={(\xx*1cm,\xy*1cm)},y={(\yx*1cm,\yy*1cm)},z={(\zx*1cm,\zy*1cm)}]
    \tdcyl{0}{0}{0}{1}{3}
    \draw (-3,0,0) -- (3,0,0) node[circle,fill=white] {x};
    \draw (0,-3,0) -- (0,3,0) node[circle,fill=white] {y};
    \draw (0,0,-3) -- (0,0,3) node[circle,fill=white] {z};
\end{tikzpicture}

\end{document}

enter image description here

Note however that this only works for cylinders growing in z-direction and "right handed" coordinate systems, e.g. when in a clockwise fashion the vectors are yzx, zxy or xyz, but not yxz, zxy or xzy.


Edit 1: As I remembered that I also had to draw y-growing cylinders, I looked it up. Being too lazy to generalize the macro, I then just redefined the coordinate axes locally thus changling the order of th input meaning (from xyzrh for z-growing to xzyrh for y-growing and yzxrh for x-growing), and I also had to modify the original macro. Probably one could unify these (probably involving something like ifthenelse from xifthen package). For now, here's the ugly hackish version, I recommaned not using it or documenting very well what you did:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\pgfmathsetmacro{\xdeg}{30}
\pgfmathsetmacro{\xx}{cos(\xdeg)}
\pgfmathsetmacro{\xy}{sin(\xdeg)}

\pgfmathsetmacro{\ydeg}{150}
\pgfmathsetmacro{\yx}{cos(\ydeg)}
\pgfmathsetmacro{\yy}{sin(\ydeg)}

\pgfmathsetmacro{\zdeg}{90}
\pgfmathsetmacro{\zx}{cos(\zdeg)}
\pgfmathsetmacro{\zy}{sin(\zdeg)}

\newcommand{\tdcyl}[5]{% origin x, origin y, origin z, radius, height
    \path (1,0,0);
    \pgfgetlastxy{\cylxx}{\cylxy}
    \path (0,1,0);
    \pgfgetlastxy{\cylyx}{\cylyy}
    \path (0,0,1);
    \pgfgetlastxy{\cylzx}{\cylzy}
    \pgfmathsetmacro{\cylt}{(\cylzy * \cylyx - \cylzx * \cylyy)/ (\cylzy * \cylxx - \cylzx * \cylxy)}
    \pgfmathsetmacro{\ang}{atan(\cylt)}
    \pgfmathsetmacro{\ct}{1/sqrt(1 + (\cylt)^2)}
    \pgfmathsetmacro{\st}{\cylt * \ct}
    \filldraw[fill=white] (#4*\ct+#1,#4*\st+#2,#3) -- ++(0,0,#5) arc[start angle=\ang,delta angle=-180,radius=#4] -- ++(0,0,-#5) arc[start angle=\ang+180,delta angle=180,radius=#4];
    \filldraw[fill=white] (#1,#2,#3+#5) circle[radius=#4];
}

\newcommand{\tdcylxy}[5]{% origin x, origin y, origin z, radius, height
    \path (1,0,0);
    \pgfgetlastxy{\cylxx}{\cylxy}
    \path (0,1,0);
    \pgfgetlastxy{\cylyx}{\cylyy}
    \path (0,0,1);
    \pgfgetlastxy{\cylzx}{\cylzy}
    \pgfmathsetmacro{\cylt}{(\cylzy * \cylyx - \cylzx * \cylyy)/ (\cylzy * \cylxx - \cylzx * \cylxy)}
    \pgfmathsetmacro{\ang}{atan(\cylt)}
    \pgfmathsetmacro{\ct}{1/sqrt(1 + (\cylt)^2)}
    \pgfmathsetmacro{\st}{\cylt * \ct}
    \filldraw[fill=white] (#4*\ct+#1,#4*\st+#2,#3) -- ++(0,0,#5) arc[start angle=\ang,delta angle=180,radius=#4] -- ++(0,0,-#5) arc[start angle=\ang+180,delta angle=180,radius=#4];
    \filldraw[fill=white] (#1,#2,#3) circle[radius=#4];
}

\begin{document}

\begin{tikzpicture}[x={(\xx*1cm,\xy*1cm)},y={(\yx*1cm,\yy*1cm)},z={(\zx*1cm,\zy*1cm)}]
    \tdcyl{0}{0}{3}{1}{3} % x y z   r h
    \begin{scope}[x={(\xx*1cm,\xy*1cm)},z={(\yx*1cm,\yy*1cm)},y={(\zx*1cm,\zy*1cm)}]
        % This is a y-growing cylinder
        \tdcylxy{0}{0}{3}{1.5}{3} % x z y r h
    \end{scope}
    \begin{scope}[z={(\xx*1cm,\xy*1cm)},x={(\yx*1cm,\yy*1cm)},y={(\zx*1cm,\zy*1cm)}]
        % This is a x-growing cylinder
        \tdcylxy{0}{0}{3}{0.5}{3} % y z x  r h
    \end{scope}
    \draw (-3,0,0) -- (3,0,0) node[circle,fill=white] {x};
    \draw (0,-3,0) -- (0,3,0) node[circle,fill=white] {y};
    \draw (0,0,-3) -- (0,0,3) node[circle,fill=white] {z};
\end{tikzpicture}

\end{document}

enter image description here

share|improve this answer
    
Thank you. Unfortunately I need them to grow in any direction. –  Jana Jul 15 '12 at 13:24
    
This is exactly what I need. Thanks. –  Jana Jul 15 '12 at 16:33
add comment

You may also use the cylinder shape. Here are two examples, taken directly from the tikz manual.

\documentclass[border=5pt]{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes.geometric}

\begin{document}

\begin{tikzpicture}
\node[cylinder, draw, shape aspect=.5] {ABC};
\end{tikzpicture}

\begin{tikzpicture}
  \node [cylinder, gray!50, rotate=30, draw,
    minimum height=2cm, minimum width=1cm] (c) {Cylinder};
  \draw[red, <->] (c.top)   -- (c.bottom)
    node [at end, below, black]   {height};
  \draw[red, <->] (c.north) -- (c.south)
    node [at start, above, black] {width};
\end{tikzpicture}

\end{document}

The result is:

enter image description here

share|improve this answer
    
Thank you a lot. –  Jana Jul 15 '12 at 16:33
    
Many many thanks! –  Daves Broadley Feb 8 at 0:17
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.