1

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!

  • I would probably make the xy plane a transparent light greyish colour, while making the circle that cut the plane thicker, however, "correct" 3D imaging needs tinkering, a lot. :) If you just want the full circle, just be sure you draw the things in the correct order, so draw the plane circle last. – zeroth Dec 5 '14 at 14:40
  • 3
    Without having tried, I guess replacing the \filldraw[fill=white] command with \draw instead should do the trick. – Benedikt Bauer Dec 5 '14 at 14:41
  • @BenediktBauer You're right! it did! :) zeroth, I have no idea how to do it, I just try staff on the above code and see how it affects the document... :) – so.very.tired Dec 5 '14 at 14:49
3

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};

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.