Gasket
Height and width of gasket:  pixels   Number of dots:    Size of dots:  pixels   Start Over

What's this? Click the Create button and find out! Then click Start Over to come back here and read more.

A Sierpinsky Gasket is an equilateral triangle that is composed of smaller equilateral triangles. Each of these triangles is similarly composed of smaller triangles. The process goes on indefinitely, and it is this feature — the identical structure at any magnification — that makes this a fractal.

This example is not, in fact, a true Sierpinsky Gasket, because it does not use equilateral triangles. Instead I am taking two right triangles and pasting them together to form a square. Then I draw two gaskets within those two triangles that are mirror images of each other.

Why? I just thought it was prettier this way.

Algorithm

There are different methods for creating these things, but here's the one I use:

Begin with a triangle. It's an imaginary triangle, so there's no need to draw it; just make sure you know the coordinates of the three corners.

Choose one of those three corners at random, and put your finger on it. Then choose a point anywhere in 2-dimensional space (which in this case is limited to the applet window). Put a dot there.

Then figure out the coordinates of the point that is half-way between the dot and the corner your finger is on. Put a dot on that point.

Again, choose one of the three corners of the triangle at random. Figure out the coordinates of the point that is half-way between your current point and the corner you just chose. Put a dot there.

Continue on, putting a dot half-way between any corner of the triangle and the dot you just drew. After doing this a few thousand times, you begin to see the Sierpinsky Gasket.
Top

Code

Here, for your interest, is the Java code used to create this applet.

import java.awt.*;
import java.applet.*;
import java.awt.geom.*;
import java.util.Random;

/**
  Display modified Serpinsky Gasket
  @author Fred Coulson
  @version June 23, 2002
*/
public class chaos extends Applet {
  boolean isPainted = false;

  //We retain a copy of the drawing canvas as an instance variable,
  //so that we can quickly repaint the screen without having to go
  //through the whole gasket-drawing code every time the screen
  //gets refreshed.
  Image imgBuf;

  public void init(){
    imgBuf = createImage(getWidth(),getHeight() );
  }

  public void paint( Graphics g ){

    if( !isPainted ){
      int count, dotsize;

      //Die if non-numeric input received
      try{
        count = Integer.parseInt(getParameter("count"));
        dotsize = Integer.parseInt(getParameter("size"));
      }
      catch( RuntimeException e ){
        g.drawString( "Error: "+e.getMessage(),10,10);
        throw e;
      }

      Graphics gBuf = imgBuf.getGraphics();
      Random generator = new Random();

      //Get the width and height of the bounding box:
      int maxXY = getWidth();

      //Define the 4 corners of the box.
      int x1 = 0;
      int y1 = 0;
      int x2 = maxXY;
      int y2 = maxXY;

      //pick 2 points at random within the box.
      int x_last1 = generator.nextInt(maxXY);
      int y_last1 = generator.nextInt(maxXY);
      int x_last2 = generator.nextInt(maxXY);
      int y_last2 = generator.nextInt(maxXY);

      int red,green,blue;
      for( int i=0; i<count; i++){
        int corner_x1,corner_y1,corner_x2,corner_y2;
        int pick_point = generator.nextInt(3);
        switch( pick_point ){
          case 0 :
            corner_x1 = corner_x2 = x1;
            corner_y1 = corner_y2 = y1;
            break;
          case 1 :
      // 1 is the middle corner. First fill one side of the gasket,
      // then the other
            corner_x1 = x2;
            corner_y1 = y1;
            corner_x2 = x1;
            corner_y2 = y2;
            break;
          case 2 :
            corner_x1 = corner_x2 = x2;
            corner_y1 = corner_y2 = y2;
            break;
          default: throw new RuntimeException( "Illegal case branch." );
          // This will never happen, but providing a default case
          //  keeps the compiler happy.
        }
        int x_point1 = x_last1 - ( (x_last1 - corner_x1) / 2 );
        int y_point1 = y_last1 - ( (y_last1 - corner_y1) / 2 );
        int x_point2 = x_last2 - ( (x_last2 - corner_x2) / 2 );
        int y_point2 = y_last2 - ( (y_last2 - corner_y2) / 2 );

        //choose a color at random
        red = generator.nextInt(256);
        green = generator.nextInt(256);
        blue = generator.nextInt(256);


        //Each triangle gets two calls to drawDot() so that we can save
        // the dot to the buffer,and watch the dot be drawn on the
        // screen at the same time. That's why there are four calls
        // to drawDot() in all.
        drawDot(x_point1,y_point1,dotsize,red,green,blue,g);
        drawDot(x_point1,y_point1,dotsize,red,green,blue,gBuf);
        drawDot(x_point2,y_point2,dotsize,red,green,blue,g);
        drawDot(x_point2,y_point2,dotsize,red,green,blue,gBuf);

        // Remember the points we chose, for use in the next loop iteration.
        x_last1 = x_point1;
        y_last1 = y_point1;
        x_last2 = x_point2;
        y_last2 = y_point2;
      }
      isPainted = true;
      gBuf.dispose();
    }
    else //The screen has already been painted once; no need to go through
        //all that again.
      g.drawImage(imgBuf,0,0,null);
  }

  public void drawDot( int x, int y, int diameter, int red, int green, int blue, Graphics g ){
    Color fillColor = new Color(red,green,blue);

    Graphics2D g2 = (Graphics2D)g;

    //We have to "fix" the xy coordinates a little, to make them fall at the center of
    //the circle defined by "diameter".
    double xx = x - (diameter/2);
    double yy = y - (diameter/2);
    Ellipse2D.Double dot = new Ellipse2D.Double(xx,yy,diameter,diameter);
    g2.setColor(fillColor);
    g2.fill(dot);
    g2.draw(dot);

  }
}
Top