- Draw a triangle.
- Draw a new triangle by connecting the midpoints of the three sides of your original triangle. This should split your triangle into four smaller triangles, one in the center and three around the outside.
- Repeat (2) for each of the outside triangles (not the center one). Each of them will split into four yet smaller triangles. Repeat for each of their outside triangles.. and for each of the new ones.. and so on, forever. Draw a few rounds of this on paper to see how it works, then check out the demo to see it on screen. Reload to get another triangle.

Your job is to write a Java program that draws a Sierpinski triangle. Think about the following:

- A Sierpinski triangle is a recursively defined structure -- each of the three outer triangles formed by joining the midpoints is itself a Sierpinski triangle.
- In practice you don't want to go on with the process "forever" as
suggested above, so we'll limit how deep it goes. Define the
*depth*of a Sierpinski triangle as the number of directly nested triangles at the deepest point. So a Sierpinski triangle consisting of a single triangle has depth 0; when a triangle is drawn inside of it, the resulting Sierpinski triangle has depth 1; when the three outside triangles have triangles drawn inside of them, the resulting triangle is depth 2, and so on. A depth of 10 or 11 gives a nice looking triangle in a reasonable amount of time. (The demo uses depth 10.) Smaller depths are interesting in that you can see more of the construction; higher depths generally take too long for casual viewing. - A triangle is a polygon, so you'll use the drawPolygon method of a graphics object (p 409-410). Note: this method that it takes an array containing the x coordinates, an array containing the y coordinates, and an integer indicating how many points should be drawn (3 for a triangle).
- As usual, you'll need two files: 1) a driver (Sierpinski.java) that sets up a JFrame, adds an interesting JPanel to it, and displays it, and 2) the class that defines the JPanel (SierpinskiPanel.java). You can model the driver after ones you've done before: for example look at the Circle.java and CirclePanel.java from lab3.

- Most of the work goes on
in the class that defines the JPanel:
- Use instance variables to hold the vertices of the initial
triangle and
the
triangle's color. Initialize these appropriately (choose a random
color)
in the constructor. For the vertices, I strongly recommend using the
Point class (see JavaDoc), one Point for each vertex.

- Use constants to hold the desired depth of the fractal and the height and width of the panel.
- The
*paintComponent*method should clear the screen (by calling super.paintComponent), set the drawing color and then call a method called drawGasket passing it the Graphics object, the points of the initial triangle, and the initial depth (0). The initial triangle should look like the one in the demo -- one point at the top center of the window and one point near each lower corner. - The
*sierpinski*method should draw the triangle whose points were passed in, and then check to see if the desired depth has been achieved; if not, it should draw the triangle formed by the midpoints of the given points, then call itself recursively on each of the three new outer triangles. Note that it will have to figure out what points to pass to each of these calls, and that each recursive call increases the depth by one.

- Use instance variables to hold the vertices of the initial
triangle and
the
triangle's color. Initialize these appropriately (choose a random
color)
in the constructor. For the vertices, I strongly recommend using the
Point class (see JavaDoc), one Point for each vertex.
- Your triangles may look a little different from the demo's as they draw, because the demo is an applet and you are using a JFrame.

Print your Sierpinski program.

x3 = (int) (x2 + (cosine * deltaX - sine * deltaY)/3);where cosine is the cosine of 60 degrees (which is 1/2) and sine is the sine of 60 degrees (which is the square root of 3 over 2). These equations are generalizable to angles other than 60. In this exercise you will generalize the program to work for angles other than 60. The angle will be controlled by increase and decrease buttons in the same way that the order is currently controlled. Do the following:

y3 = (int) (y2 + (cosine * deltaY + sine * deltaX)/3);

- In KochPanel.java,
- Add instance variables
*angle*,*sine*, and*cosine*. Angle will be an integer and sine and cosine type double. - In the constructor, set angle to 60 (this will be the default), and set sine to Math.sin (Math.PI / 3) and cosine to Math.cos (Math.PI / 3).
- In drawFractal, replace the current calculations for x3 and y3 with those given above.

- Add instance variables
- Compile and run the program. It should behave just as before.
- To add controls to allow the angle to change, do the following:
- In KochPanel.java, add two public methods
*getAngle()*that returns the angle (type int), and*setAngle (int newAngle)*that sets the angle to be the value of*newAngle*and sets*sine*and*cosine*of that angle. Remember that the sin and cos methods in the Math class must have arguments that are in radians not degrees so you need to multiply the angle (which is in degrees) by Math.PI divided by 180 (pi/180 is the degree to radian conversion factor). - In KochSnowflake.java, add a new panel for the buttons
to increase and decrease the angle. This panel will contain two buttons
and a label giving the current angle, and will be very
similar to the
*tools*panel that holds the buttons that increase and decrease the order. Note that the tools panel uses a horizontal box layout; you should do the same for your panel. You can read more about layout managers on p. 341, and about the box layout on p. 351. - The new tools panel should be added to the appletPanel. To accomodate it change APPLET_HEIGHT to 480.
- This applet deals with listeners in a slightly different way.
The applet itself implements ActionListener. This means that the
"actionPerformed" method required for the implementation is just part of the
KochSnowFlake class. When it comes time to add the actionListener to the
buttons - what is the instance that needs to be passed? It needs to pass
a reference to itself...
*this*Make your buttons respond to events the same way. - The method actionPerformed must be modified to take action if the event source was one of the new buttons. If the source was the button to increase the angle, increase the angle by 10 degrees (you can get the current angle using the method you added to KochPanel); if the source was the button to decrease the angle, decrease it by 10 degrees. The new angle should be between 10 and 170 (inclusive) -- you should add constants (similar to MIN and MAX) for the minimum and maximum angles.

- In KochPanel.java, add two public methods
- Compile and run the program. Play with the angles and order to see what fractal patterns are generated.

Print KochSnowflake.java and KochPanel.java to turn in.