# 3D TikZ lines on the perimeter of a circle

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}


• Oh, and as to why the deviations occur: TikZ will assume that you want to draw in the xy-plane if You use circle. For using the xz-plane or the yz-plane, have a look here and here. – Tom Bombadil Jul 14 '12 at 20:36
• Ah I did not know that, makes sense why they don't match up then. – asm Jul 14 '12 at 20:43

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.

How about this: I make the circles grow along the z-axis. The small circles are of radius 1, the bid ones of radius 2, the z-separation of the circles is 0.6 units. From polar coordinates we know that x=r cos(phi) and y=r sin(phi). I don't know if you want this to be customizable, but this could be easily added.

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

\begin{document}

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

\begin{tikzpicture}[z={(\zx*1cm,\zy*1cm)}]
\foreach \z in {0,...,5}
{   \draw (0,0,\z*0.6) circle (1);
\draw (0,0,\z*0.6+3) circle (2);
}
\foreach \deg in {1,...,18}
{   \pgfmathsetmacro{\xval}{cos(20*\deg)}
\pgfmathsetmacro{\yval}{sin(20*\deg)}
\draw (\xval,\yval,0) -- (\xval,\yval,3);
\draw (2*\xval,2*\yval,3) -- (2*\xval,2*\yval,6);
}
\end{tikzpicture}

\end{document}


• Thanks for the response, that works for what I want. I will want it to be customizable but I was trying to get something that looked like what I wanted first. – asm Jul 14 '12 at 20:44