The spiral of Theodorus (which is also called the square root spiral, Einstein spiral, and Pythagorean spiral) was first devised by the Greek mathematician Theodorus of Cyrene during the 5th century BC. The spiral consists of a sequence of right triangles where the ith triangle has side lengths 1, √i, and √(i+1). Each triangle’s edge of length √(i+1) is shared with the next triangle as shown in the following picture from Wikipedia.

When you fill in the number of triangles that you want to draw and click Draw, the following code executes.

private void btnDraw_Click(object sender, EventArgs e) { // Get the spiral of Theodorus's points. int num_triangles = int.Parse(txtNumTriangles.Text); List<PointF> edge_points = FindTheodorusPoints(num_triangles); // Draw the spiral of Theodorus. picSpiral.Image = DrawTheodorusSpiral( edge_points, picSpiral.ClientSize, chkOutline.Checked, chkFill.Checked); }

This code gets the number of triangles that you entered. It then calls the `FindTheodorusPoints` method described shortly to get the points on the outside of the spiral of Theodorus. It finishes by calling the `DrawSpiral` method (also described shortly) to draw the spiral.

The following sections describe the `FindTheodorusPoints` and `DrawSpiral` methods and their helper routines.

# FindTheodorusPoints

The following code shows the `FindTheodorusPoints` method.

// Find points on the spiral of Theodorus. private List<PointF> FindTheodorusPoints(int num_triangles) { // Find the edge points. List<PointF> edge_points = new List<PointF>(); // Add the first point. float theta = 0; float radius = 1; for (int i = 1; i <= num_triangles; i++) { radius = (float)Math.Sqrt(i); edge_points.Add(new PointF( radius * (float)Math.Cos(theta), radius * (float)Math.Sin(theta))); theta -= (float)Math.Atan2(1, radius); } return edge_points; }

This method first creates an `edge_points` list to hold the triangles’ outer vertices.

The variable `theta` keeps track of the angle that the points make with respect to the spiral’s center. Variable `radius` keeps track of the length of the triangles’ side lengths.

The code sets `theta = 0` and `radius = 1`, and then enters a loop to find the leading edge point for each triangle. Inside the loop, the code uses `theta` and `radius` to find the triangle’s point and adds it to the list.

Each triangle’s inner angle (the one by the spiral’s center) is the arc tangent of the opposite side (which always has length 1) and the adjacent side. The adjacent side for the ith triangle has length `radius = √i`, so the program subtracts `Atan2(1, radius)` from `theta` to prepare for the next point on the spiral. (The code subtracts this value instead of adding it so the angles increase counterclockwise for the triangles.)

After it finishes finding the edge points, the method returns them.

# DrawTheodorusSpiral

The following code shows the `DrawTheodorusSpiral` method, which draws the spiral.

// Draw the spiral of Theodorus. private Bitmap DrawTheodorusSpiral(List<PointF> edge_points, Size size, bool outline_triangles, bool fill_triangles) { // Make the bitmap and associated Graphics object. int wid = size.Width; int hgt = size.Height; Bitmap bm = new Bitmap(wid, hgt); using (Graphics gr = Graphics.FromImage(bm)) { gr.SmoothingMode = SmoothingMode.AntiAlias; gr.Clear(Color.White); // Make brushes. Color[] colors = RainbowColors(255); Brush[] brushes = ColorsToBrushes(colors); // Scale and center. float xmin, xmax, ymin, ymax; GetBounds(edge_points, out xmin, out xmax, out ymin, out ymax); RectangleF drawing_rect = new RectangleF( xmin, ymin, xmax - xmin, ymax - ymin); RectangleF target_rect = new RectangleF( 5, 5, wid - 10, hgt - 10); MapDrawing(gr, drawing_rect, target_rect, false); // Draw. using (Pen pen = new Pen(Color.Black, 0)) { int num_brushes = brushes.Length; for (int i = edge_points.Count - 1; i > 0; i--) { PointF[] points = { new PointF(0, 0), new PointF( edge_points[i].X, edge_points[i].Y), new PointF( edge_points[i - 1].X, edge_points[i - 1].Y), }; if (fill_triangles) gr.FillPolygon(brushes[i % num_brushes], points); if (outline_triangles) gr.DrawPolygon(pen, points); } } } return bm; }

This method draws the spiral of Theodorus on a bitmap of a specified size and returns the bitmap.

It starts by creating a bitmap of the correct size, making an associated `Graphics` object, and clearing it.

The method then calls the `RainbowColors` method to make some colors. It then uses the `ColorsToBrushes` method to convert those colors into an array of brushes. Both of those methods are described shortly.

The code then calls the `GetBounds` method (also described shortly) to get bounds for the spiral’s edge points. It uses the bounds to make a rectangle representing the drawing area. It then passes the drawing rectangle and a rectangle that represents the bitmap’s surface (minus a margin) to the `MapDrawing` method.

The `MapDrawing` method applies translation and scaling transformations to the `Graphics` object to make drawing commands it inside the target area. For more information on this method, see the post Scale a drawing to fit a target area in C#.

Now the method draws the spiral of Theodorus. It creates a black pen with thickness 0. (Pens with thickness 0 are not scaled even if the `Graphics` object includes a scaling transformation.)

The method then enters a loop that runs from the last triangle point to the first. The loops runs last-to-first instead of first-to-last because later triangles may overlap earlier ones. The picture on the right shows the spiral of Theodorus with 30 triangles. You can see that the outer ones overlap the inner ones. Drawing the triangles last-to-first lets you see pieces of all of the triangles.

After it fills a triangle, the method outlines it.

As it draws each triangle, the code checks the `outline_triangles` and `fill_triangles` values to see whether it should outline or fill the triangles. (Draw the spiral without filling it if you want to see the overlapping outlines of the triangles.)

# RainbowColors

The following code shows the `RainbowColors` method.

// Return an array of rainbow colors. private Color[] RainbowColors(byte alpha) { return new Color[] { Color.FromArgb(alpha, 255, 0, 0), Color.FromArgb(alpha, 255, 255, 0), Color.FromArgb(alpha, 255, 128, 0), Color.FromArgb(alpha, 0, 255, 0), Color.FromArgb(alpha, 0, 255, 255), Color.FromArgb(alpha, 0, 0, 255), Color.FromArgb(alpha, 255, 0, 255), }; }

This method simply builds an array holding a predefined set of colors. The method takes an `alpha` parameter in case you want to make the colors semi-transparent. (I originally thought that would be useful in this example, but it just made the result more cluttered.)

# ColorsToBrushes

The following code shows the `ColorsToBrushes` helper method.

// Convert colors to brushes. private Brush[] ColorsToBrushes(Color[] colors) { int num_colors = colors.Length; Brush[] brushes = new Brush[num_colors]; for (int i = 0; i < num_colors; i++) brushes[i] = new SolidBrush(colors[i]); return brushes; }

This method simply loops through an array of colors and makes a `SolidBrush` for each.

# GetBounds

The following code shows the `GetBounds` method.

// Get the points' bounds. private void GetBounds(List<PointF> points, out float xmin, out float xmax, out float ymin, out float ymax) { // Find the bounds. xmin = points[0].X; xmax = xmin; ymin = points[0].Y; ymax = ymin; foreach (PointF point in points) { if (xmin > point.X) xmin = point.X; if (xmax < point.X) xmax = point.X; if (ymin > point.Y) ymin = point.Y; if (ymax < point.Y) ymax = point.Y; } }

This method simply loops through an array of `PointF` and finds their minimum and maximum X and Y values. (You could use LINQ to do something similar, but it wouldn’t be any easier to read and it would be slightly slower.)

# Summary

Download the example to see additional details and to experiment with the program. For example, you might try using semi-transparent colors, with or without the triangle outlines. If you fill around 10,000 or more triangles without outlining them, you can also see an interesting wave effect flowing through the spiral’s rings.

For more information on the spiral of Theodorus, see the Wikipedia article Spiral of Theodorus.