[Tex/LaTex] 3D TikZ lines on the perimeter of a circle

3dgraphicstikz-pgf

I'm just learning TikZ, I've done a few 2D images and I wanted to make a 3D wire frame of the Hubble telescope. The body of the telescope is basically a pair of tubes, the front one slightly narrower than the other. I had thought to draw a series of circles and then put lines along them to create a cylinder.

The problem is, my lines don't fall on the perimeter of the circles. I the circle command to draw the circles on the (y,z) plane while x varies along the length of the telescope. I had thought to calculate end points for the lines use the equations y = radius * cos(\theta) and z = radius * sin(\theta) but the lines turn out to be slightly off the surface of the cylinder. I've tried a bunch of different things. One really strange thing ( to me) is that if I specify the radius in centimetres for the line calculations the lines are Way off the cylinder. Even though the radius is specified in cm for the circles.


\tikzset{
    MyPersp/.style={scale=1.8,x={(-0.8cm,-0.4cm)},y={(0.8cm,-0.4cm)},z={(0cm,1cm)}}
}

\newcommand{\hubble}[0] {%
    \foreach \x in {0,0.25,...,1.0} {
        \draw[very thick] (\x,0,0) circle (0.75cm);
    }
    \draw[very thick] (1.25,0,0) circle ({1.25cm / 2});
    \foreach \x in {1.5,1.75,...,2.25} {
        \draw[very thick] (\x,0,0) circle (0.5cm);
    }

    \foreach \r/\x/\xx in {0.75/0/1,0.5/1.5/2.25}{
        \foreach \theta in {0,30,...,360}{
            \def\y{{\r*cos(\theta)}}
            \def\z{{\r*sin(\theta)}}
            \draw[very thick](\x,\y,\z) -- (\xx,\y,\z);
        }
    }
}

\begin{tikzpicture}[MyPersp]

\hubble

\end{tikzpicture}

Resulting Image

Best Answer

This is probably the solution that requires the minimal amount of modification to your original code:

\newcommand{\hubble}[0] {%
    \foreach \x in {0,0.25,...,1} {
       \begin{scope}[canvas is yz plane at x=\x]
        \draw[very thick] (0,0) circle (0.75cm);
       \end{scope}
    }
    %\draw[very thick] (1.25,0,0) circle ({1.25cm / 2});
    \foreach \x in {1.5,1.75,...,2.25} {
          \begin{scope}[canvas is yz plane at x=\x]
        \draw[very thick] (0,0) circle (0.5cm);
       \end{scope}
    }

    \foreach \r/\x/\xx in {0.75/0/1,0.5/1.5/2.25}{
        \foreach \theta in {0,30,...,360}{
            \def\y{{\r*cos(\theta)}}
            \def\z{{\r*sin(\theta)}}
            \draw[very thick](\x,\y,\z) -- (\xx,\y,\z);
        }
    }

}

A you can see, the trick is to specify as the 'active canvas' the yz plane each time you draw a circle at a new x coordinate. Now the radius and the center of the circle can be specified in the usual 2d fashion.

You will need to load the the 3d TikZ library to make it work (insert the line \usetikzlibrary{3d} in the preamble, naturally after loading the TikZ package).

The lines will remain consistently on the circles even if you change the perspective parameters.