// Adapted from the example in Adam Drozdek's book: Data // Structures and Algorithms in Java. // // Rahul Simha // Sept, 2006. import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; class SnowflakePanel extends JPanel { // These values will be used in the recursion. int depth = 0; double currentAngle; // The end points of the current "fractal edge" Point currentPoint, nextPoint; // paintComponent is called whenever the screen needs to be rendered. // This is where we do all our drawing work. public void paintComponent (Graphics g) { super.paintComponent (g); if (depth == 0) { // We actually need this because there is nothing to draw // when the screen first comes up. return; } // Create a grey background and white pen color. Dimension D = this.getSize(); g.setColor (Color.white); g.fillRect (0,0, D.width, D.height); g.setColor (Color.black); // Now figure out an appropriate size for the length of // the side of the initial triangle. int minDim = D.width; if (D.height < minDim) { minDim = D.height; } int leftInset = (int) (0.2 * minDim); double initLength = (int) (0.6 * minDim); // The first point is a little inside the origin. currentPoint = new Point (leftInset, leftInset); // Start with initial angle horizontal. currentAngle = 0; // Draw three "fractal sides" next. // The first one. drawSide (initLength, depth, g); changeAngleRight (120); // After drawing the base, the next line comes at an angle of 120. // Now the second one, after which there's another 120 rotation. drawSide (initLength, depth, g); changeAngleRight (120); // Last one. drawSide (initLength, depth, g); } void drawSide (double length, int depth, Graphics g) { if (length <= 1) { // Too small: we can't draw something smaller than a pixel. System.out.println ("Length too small: depth too much"); return; } // Base case: if (depth == 1) { // Compute next point by turning the angle and using the angle // to compute the (x,y) values of the end-point. nextPoint = new Point (); double radians = currentAngle*Math.PI/180.0; nextPoint.x = currentPoint.x + (int) (Math.cos(radians) * length); nextPoint.y = currentPoint.y + (int) (Math.sin(radians) * length); // Draw. Dimension D = this.getSize(); g.drawLine (currentPoint.x, D.height-currentPoint.y, nextPoint.x, D.height-nextPoint.y); // Update. currentPoint = nextPoint; return; } // Recursive case: draw FOUR sides fractally. After each, the angle // needs to be changed to compute the new end-points. drawSide (length/3, depth-1, g); changeAngleLeft (60); drawSide (length/3, depth-1, g); changeAngleRight (120); drawSide (length/3, depth-1, g); changeAngleLeft (60); drawSide (length/3, depth-1, g); } // Methods to set the angle. void changeAngleRight (double increment) { currentAngle = currentAngle + increment; } void changeAngleLeft (double increment) { currentAngle = currentAngle - increment; } } //end-SnowflakePanel // The remainder of the code is entirely GUI-related. class SnowflakeFrame extends JFrame { // A text field where the user enters the fractal depth. JTextField depthField; // The panel on which we draw. SnowflakePanel drawPanel; public SnowflakeFrame () { this.setSize (500,500); this.setTitle ("Von Koch Snowflake"); this.setResizable (true); // This is how stuff is put into a frame. Container cPane = this.getContentPane(); drawPanel = new SnowflakePanel (); cPane.add (drawPanel, BorderLayout.CENTER); // Make the controls. JPanel panel = new JPanel (); JLabel label = new JLabel ("Enter depth: "); panel.add (label); depthField = new JTextField (5); panel.add (depthField); JButton button = new JButton ("Go"); button.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { handleButtonClick(); } } ); panel.add (button); cPane.add (panel, BorderLayout.SOUTH); this.setVisible (true); } void handleButtonClick () { // Extract the string from the textfield where the user typed the strings. String inputStr = depthField.getText (); try { int d = Integer.parseInt (inputStr.trim()); drawPanel.depth = d; drawPanel.repaint(); } catch (NumberFormatException e) { System.out.println (e); } } } public class Snowflake { public static void main (String[] argv) { SnowflakeFrame s = new SnowflakeFrame (); } }