Draw a nested series of golden rectangles in C#

[golden rectangles]

This program draws golden rectangles, rectangles whose side ratio is equal to φ. For information on φ, see Examine the relationship between the Fibonacci sequence and phi in C#.

The program first draws a golden rectangle. It then removes the square from one end of the rectangle to produce another golden rectangle. It continues removing the squares at the ends of rectangles to make new golden rectangles until the rectangles are too small to see.

The program starts by building a Bitmap and doing some set up such as defining the largest golden rectangle that the program will draw. The most interesting part of the program is the following DrawPhiRectanglesOnGraphics method.

// Draw rectangles on a Graphics object.
private void DrawPhiRectanglesOnGraphics(Graphics gr,
    List<PointF> points, float x, float y, float wid,
    float hgt, RectOrientations orientation)
    if ((wid < 1) || (hgt < 1)) return;

    // Draw this rectangle.
    gr.DrawRectangle(Pens.Blue, x, y, wid, hgt);

    // Recursively draw the next rectangle.
    switch (orientation)
        case RectOrientations.RemoveLeft:
            points.Add(new PointF(x, y + hgt));
            x += hgt;
            wid -= hgt;
            orientation = RectOrientations.RemoveTop;
        case RectOrientations.RemoveTop:
            points.Add(new PointF(x, y));
            y += wid;
            hgt -= wid;
            orientation = RectOrientations.RemoveRight;
        case RectOrientations.RemoveRight:
            points.Add(new PointF(x + wid, y));
            wid -= hgt;
            orientation = RectOrientations.RemoveBottom;
        case RectOrientations.RemoveBottom:
            points.Add(new PointF(x + wid, y + hgt));
            hgt -= wid;
            orientation = RectOrientations.RemoveLeft;
    DrawPhiRectanglesOnGraphics(gr, points,
        x, y, wid, hgt, orientation);

If the rectangle is smaller than one pixel wide or tall, the method simply exits. Otherwise it draws the rectangle.

Next the program checks the rectangle’s orientation. The following code shows the RectOrientation enumeration.

// Orientations for the rectangles.
private enum RectOrientations

These enumerations determine which part of a golden rectangle to remove. For example, the first rectangle is wider than it is tall. The program removes the square on the rectangle’s left end to create a new smaller rectangle on the right end. That rectangle is taller than it is wide so the program removes the square from its top end.

The DrawPhiRectanglesOnGraphics method uses a switch statement to determine which part of the current rectangle it should remove to make the next one. It also updates the orientation parameter so the next call to DrawPhiRectanglesOnGraphics draws the next rectangle correctly.

The enumeration defines its values in the order in which the program removes the rectangle ends: left, top, right, bottom. That keeps the new rectangles in the center of the original rectangle.

The code in the switch statement also saves an “origin” point for each rectangle in a point list.

After calculating the new rectangle’s size, position, and orientation, the DrawPhiRectanglesOnGraphics method calls itself recursively to draw the next golden rectangle.

After the original call to DrawPhiRectanglesOnGraphics returns, the calling code connects the saved “origin” points to draw a spiral. (I tried drawing the spiral smoothly but a simple call to DrawCurve doesn’t work. More about this in my next post.)

Download Example   Follow me on Twitter   RSS feed   Donate

This entry was posted in algorithms, drawing, graphics, mathematics and tagged , , , , , , , , , , , , . Bookmark the permalink.

2 Responses to Draw a nested series of golden rectangles in C#

  1. Rohit says:

    Good one! More graphics ones please!

  2. Rod Stephens says:

    I like graphics programs, too! (I’m not sure what percentage of programmers do, though.) I tend to write them when I need a break.

Leave a Reply

Your email address will not be published. Required fields are marked *