Koch Snowflake

Objectives

  • Use a queue
  • Use multithreading
  • Use OOP techniques
  • Implement a GUI
  • Test and debug a complex application

Overview

This assignment involves the use of fractals, queues, threads, and a GUI interface to create the following image.

Koch Snowflake
Koch snowflake (fractal)

You should create two classes for this assignment: Line and Snowflake. You may place them both in the same source file if you wish, but Snowflake should be the only public class if you do that. The requirements for both classes are listed below:

Line class

The purpose of this class is to represent a line. A line is defined in this case by its endpoints. Use the java.awt.Point class to store your points.

  • two private Point variables
  • a constructor that accepts a start and end point
  • accessor method getP1() to return the first point
  • accessor method getP2() to return the second point
  • a "void draw(Graphics g)" method that draws the line (see the Java documentation for the Graphics class and check out the drawLine method)
  • a method named length that returns a double which is the length of the line; you can calculate the length of a line as follows:
    • lengthX = length of line in x direction
    • lengthY = length of line in y direction
    • length of line = square root of (lengthX squared plus lengthY squared)
    • Math.pow can do square roots

Snowflake class

This is where all the real work gets done. Here are the requirements:

  1. The Snowflake class should extend JFrame (so it can be a GUI) and implement Runnable (so it can be a thread)
  2. private instance fields
    1. an ArrayDeque to hold Line objects and be used as a queue
    2. a boolean to keep track of whether the application is still running
    3. a JPanel used to display the graphics
  3. static void main(String[])
    1. Create a Snowflake object
  4. default constructor
    1. Use SwingUtilities to call createAndShowGUI at a proper time
  5. private void createAndShowGUI
    1. Set the title of window
    2. Add the JPanel to draw on
    3. Create three Point objects: (150,10), (50,183), (250,183)
    4. Create a new ArrayDeque to be used as a queue
    5. Create three Line objects using the Points above
    6. Add the three lines to the queue
    7. Make sure program stops when window closes
    8. Set the window to 300 by 300 pixels
    9. Make the window non-resizable
    10. Make the window visible
    11. Make the current object into a thread and start it running
  6. public void run()
    1. set the instance variable you have to indicate the thread is running to true
    2. while the variable just mentioned is true, repeat the rest of these steps
    3. remove a line from the queue
    4. send the line to process(Line)
    5. wait a little while to slow the drawing process down (Thread.sleep(long) could be helpful here)
    6. call repaint()
  7. private void process(Line)
    1. If the length of the line passed in is less than or equal to 5, then set the instance variable that indicates the thread is running to false, add the line that was passed in back into the queue, and exit this method. You should synchronize the add based on the queue to avoid threading conflicts.
    2. Now you have to replace the line that was passed in with four new lines. The replacement will accomplish the following:
      Old line
      New line
      The line that was passed in was already removed from the queue, but the four new lines will have to be added to the queue.
    3. You can get the endpoints for the new lines as follows:
      Line segments on new line
      1. let startx be the x coordinate of the start point of the original line
      2. let starty be the y coordinate of the start point of the original line
      3. let endx be the x coordinate of the end point of the original line
      4. let endy be the y coordinate of the end point of the original line
      5. let diffx be (endx-startx) divided by 3
      6. let diffy be (endy-starty) divided by 3
      7. p1 is the same as the start point of the original line
      8. p2's x coordinate is startx + diffx
      9. p2's y coordinate is starty + diffy
      10. p3's x coordinate is startx + 1.5 * diffx - diffy
      11. p3's y coordinate is starty + 1.5 * diffy + diffx
      12. p4's x coordinate is startx + 2 * diffx
      13. p4's y coordinate is starty + 2 * diffy
      14. p5 is the same as the end point of the original line
    4. Once you have created the four new lines and added them to the queue, you are done with this method. Adding the lines to the queue should be done synchronized on the queue to avoid multithreading conflicts.
  8. public void paint(Graphics g)
    1. Get the JPanel's graphics context so you can draw to it.
    2. Erase the JPanel using the Graphic's class fillRect() method with white as the color. You can get the height and width from the object you are since you are a JFrame.
    3. Get an iterator of all the Lines in the queue and for each Line in the queue, tell the Line to draw itself. Set the drawing color before drawing any of the lines. Send the line objects the graphics context of the JPanel. You want this done synchronized on the queue.

Rubric

  • (50 pts) The fractal is computed properly, the mutithreading works, and the GUI displays properly