[Tex/LaTex] Drawing a 3D cylinder, and a circle shape on the x—y plane

technical-drawingtikz-pgf

I'm trying to draw a cylinder on the three dimensional space, and I also want its projection on the x–y plane.
I found the first answer here to be very useful. I just copy-paste it to my document, and modify it as follows (the modifications are only inside the \begin{tikzpicture} tags):

\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{tikzpicture}[x={(\xx*1cm,\xy*1cm)},y={(\yx*1cm,\yy*1cm)},z={(\zx*1cm,\zy*1cm)}]

        \tdcyl{-3}{-3}{0}{1}{3} % x y z   r h
        \tdcyl{0}{0}{0}{1}{3} % x y z   r h


        \draw (-3,0,0) -- (3,0,0) node[circle,fill=white] {x};
        \draw (0,-3,0) -- (0,3,0) node[circle] {y};
        \draw (0,0,-3) -- (0,0,3) node[circle] {z};
    \end{tikzpicture}
    \end{document}

I added another cylinder and tweaked the positions to fit what I need.
This produces the following:

enter image description here

Which is almost what I want, except that I want to see the projection of that cylinder on the x–y plane, but unfortunately, the top cylinder hides the full circle.
When I disable the top cylinder:

    \begin{tikzpicture}[x={(\xx*1cm,\xy*1cm)},y={(\yx*1cm,\yy*1cm)},z={(\zx*1cm,\zy*1cm)}]

        \tdcyl{-3}{-3}{0}{1}{3} % x y z   r h



        \draw (-3,0,0) -- (3,0,0) node[circle,fill=white] {x};
        \draw (0,-3,0) -- (0,3,0) node[circle] {y};
        \draw (0,0,-3) -- (0,0,3) node[circle] {z};
    \end{tikzpicture}

Now the projection is shown again:
enter image description here

But the top cylinder is missing…

How can I make the top cylinder transparent, or, alternatively, and even better; how do I create one long cylinder and emphasize its projection on the x–y plane?

BTW, what determines the position of the labels x,y,z in the above code? I want to reposition them so they won't overlap with the axis.
Thanks in advanced!

Best Answer

After cleaning up your code example to make it a compilable MWE and show the output it should show, I end up with the following code and its output:

\documentclass{standalone}
\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}{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}
    \draw[] (#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];
    \draw[] (#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}{-3}{1}{3} % x y z   r h
        \tdcyl{0}{0}{0}{1}{3} % x y z   r h

        \draw (-3,0,0) -- (3,0,0) node[right] {x};
        \draw (0,-3,0) -- (0,3,0) node[left] {y};
        \draw (0,0,-3) -- (0,0,3) node[above] {z};
    \end{tikzpicture}
\end{document}

enter image description here

So what did I change?

To make the projection of the cylinder in the xy plane visible, I changed the two \filldraw commands in the macro that draws the cylinder to simple \draw commands:

%Before
\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];
%After
\draw[] (#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];
\draw[] (#1,#2,#3+#5) circle[radius=#4];

The old command you had in your example drew the cylinder surfaces as opaque white areas, the changed one only draws their outlines, which leaves the cylinder transparent.

Your second issue was the interference of the axis labels with the axis lines. The reason for this is that tikZ nodes are by default placed with their center at a coordinate. This can be addressed by using the modifiers above, below, right, and left which tells tikZ to shift the node's content with respect to the coordinate. The code for this is:

\draw (-3,0,0) -- (3,0,0) node[right] {x};
\draw (0,-3,0) -- (0,3,0) node[left] {y};
\draw (0,0,-3) -- (0,0,3) node[above] {z};
Related Question