BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Algorithms and Data Structures
.NET 1.1+

The Chaos Game and the Sierpinski Triangle

The chaos game is a method for generating fractal images by plotting randomised points inside a polygon according to a simple set of rules. In this article we will use the chaos game to generate the Sierpinski triangle using C# and Windows Forms.

Setting the Vertex Locations

The next method will calculate the positions of each of the three attractors, each being located at a vertex of the triangle. These values will be based upon the size of the triangle and the midpoint of the form's client area. The midpoint is calculated first by using half of the height and width of the form. We then add the top vertex, which will be point zero, whose X co-ordinate is vertically aligned with the midpoint and whose Y co-ordinate is half of the height of the triangle above the midpoint.

The two lower vertices are positioned at half of the triangle's height below the centre of the form and half of its width to either side of this point. These are points one and two within the array.

private void SetPointLocations(int sideLength)
{
    Point midPoint = new Point(ClientSize.Width / 2, ClientSize.Height / 2);
    _points = new Point[3];
    _points[0] = new Point(midPoint.X,
        midPoint.Y - (int)(sideLength * HeightWidthRatio() / 2));
    _points[1] = new Point(midPoint.X - sideLength / 2,
        midPoint.Y + (int)(sideLength * HeightWidthRatio() / 2));
    _points[2] = new Point(midPoint.X + sideLength / 2,
        midPoint.Y + (int)(sideLength * HeightWidthRatio() / 2));
}

Plotting the Vertices

The next task is to create a method to plot the positions of the vertices. This is achieved by using a for-each loop to plot the positions of each point in turn. The actual drawing will be done by another method, in this case named "PlotPoint", as this will be reused for the plotting of the points during the production of the fractal. Note that these two methods both accept a parameter containing the graphics surface to be drawn upon. This will be created when the user clicks the button.

private void PlotPointLocations(Graphics g)
{
    foreach (Point p in _points)
    {
        PlotPoint(p, g);
    }
}

private void PlotPoint(Point p, Graphics g)
{
    Brush b = new SolidBrush(Color.Black);
    g.FillRectangle(b, p.X, p.Y, 1, 1);
}

Plotting a Random Point

The previous methods control the initialisation of the triangle. Now we can create the methods that are used within the algorithm's loop to draw the fractal. The DrawNextPoint method will control this process by calling a new method named "MoveTowardsRandomPoint", followed by a call to PlotPoint to place a dot at the current position. Finally, it calls Application.DoEvents so that the updated drawing is visible.

MoveTowardsRandomPoint selects one of the three vertices using the randomiser object. It then calculates the position that is half way between the current position and the selected attractor and moves to that point. Add the two methods below to the form's class:

private void DrawNextPoint(Graphics g)
{
    MoveTowardsRandomPoint();
    PlotPoint(_currentLocation, g);
    Application.DoEvents();
}

private void MoveTowardsRandomPoint()
{
    int moveTowards = _randomiser.Next(0,3);
    _currentLocation.X = (_currentLocation.X + _points[moveTowards].X) / 2;
    _currentLocation.Y = (_currentLocation.Y + _points[moveTowards].Y) / 2;
}

Creating the Loop

The final job is to bring all of the methods together within the Click event of the form's button. Add the code below to the button's event. This starts by obtaining the form's graphics area and the size of the triangle. The size is used to calculate the positions of the three vertices and store them in the array. Once the three points have been plotted, the initial location is set. In this case I have used the position of the top vertex as the starting point.

An infinite loop is created with a while loop with a condition that will always be true. In this loop, the DrawNextPoint method is repeatedly called. Ideally, you would create a loop that could be stopped by the user. This is demonstrated in the sample that can be downloaded from the link at the top of the page.

Graphics g = CreateGraphics();
int sideLength = SideLength();
SetPointLocations(sideLength);
PlotPointLocations(g);
_currentLocation = new Point(_points[0].X, _points[0].Y);

while (true)
{
    DrawNextPoint(g);
}
17 May 2009