Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Write a recursive method call snowflake() that will draw a Koch snowflake(4 iterations) using turtle. Below is the code for turtle.java and world.java, world is

Write a recursive method call snowflake() that will draw a Koch snowflake(4 iterations) using turtle. Below is the code for turtle.java and world.java, world is used by turtle.

Turtle.java

import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Map; import java.util.TreeMap;

import javax.imageio.ImageIO;

public class Turtle { /// version number based on date of creation @SuppressWarnings("unused") private static final long serialVersionUID = 20140120L;

private static final Map cachedPictures = new TreeMap();

private World world; private double theta;

private Point2D.Double location; private boolean isdown; // private GeneralPath trail; // not used private Color color; private double shellSize; private int pause = 200;

private static final Color[] base = { Color.BLACK, Color.RED, Color.BLUE, Color.MAGENTA, Color.CYAN, }; private static int baseIndex = 0;

/** * Makes a new turtle in the center of the world * @param w the world */ public Turtle(World w) { this(w, 0, 0); }

/** * Makes a new turtle at the specified point within the world * @param w the world * @param x the x coordinate, in pixels; 0 is the center; bigger numbers to left * @param y the y coordinate, in pixels; 0 is the center; bigger numbers down */ public Turtle(World w, double x, double y) { this.location = new Point2D.Double(x + w.centerX, w.centerY - y); // this.trail = new GeneralPath(); // not used // this.trail.moveTo(this.location.x, this.location.y); // not used this.theta = 0; this.world = w; this.color = Turtle.base[Turtle.baseIndex]; Turtle.baseIndex = (Turtle.baseIndex+1) % Turtle.base.length; this.penWidth = 1; this.isdown = true; this.shellSize = 8;

w.addTurtle(this); } /** * Moves the turtle in the direction it is facing * @param d the number of pixels to move */ public void forward(double d) { this.cornerGoTo(this.location.x + Math.cos(this.theta)*d, this.location.y + Math.sin(this.theta)*d); } /** * Moves the turtle in the opposite direction from the one it is facing * @param d the number of pixels to move */ public void backward(double d) { this.forward(-d); } /** * Turns the turtle clockwise in place * @param degrees the number of degrees to turn */ public void right(double degrees) { this.theta += Math.PI*degrees/180; while (this.theta > Math.PI) this.theta -= Math.PI*2; while (this.theta <= -Math.PI) this.theta += Math.PI*2; world.turtleMoved(); this.pause(); } /** * Turns the turtle counterclockwise in place * @param degrees the number of degrees to turn */ public void left(double degrees) { this.right(-degrees); } /** * Stops the turtle from leaving a trail */ public void pickPenUp() { this.isdown = false; } /** * Causes the turtle to leave a trail */ public void putPenDown() { this.isdown = true; }

/** * Check the pen state * @return true if the pen is down, false otherwise */ public boolean isPenDown() { return this.isdown; }

/** * Draws the arrow that represents the turtle. * Should only be called by World class * @param g the graphics object to draw with */ void _how_world_draw_turtles(Graphics2D g) {

// // Other way to draw trails; can't change color part-way through though // g.setColor(color); // g.setStroke(new BasicStroke((float)this.width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); // g.draw(this.trail); // // end other way to draw tails

// The following draws a picture of a turtle

// three shapes GeneralPath back = new GeneralPath(); // the bigger shell GeneralPath back2 = new GeneralPath(); // the paler inner shell GeneralPath body = new GeneralPath(); // the head, legs, and tail double c = Math.cos(this.theta); double s = Math.sin(this.theta); double x = this.location.x; double y = this.location.y; double w = this.shellSize; Ellipse2D leftEye = new Ellipse2D.Double(x + 1.55*w*c + 0.15*w*s -0.1*w, y + 1.55*w*s - 0.15*w*c -0.1*w, 0.2*w, 0.2*w); Ellipse2D rightEye = new Ellipse2D.Double(x + 1.55*w*c - 0.15*w*s -0.1*w, y + 1.55*w*s + 0.15*w*c -0.1*w, 0.2*w, 0.2*w);

body.moveTo(x + w*0.9*c + w*0.4*s, y + w*0.9*s - w*0.4*c); body.curveTo( x + w*1.6*c + w*0.4*s, y + w*1.6*s - w*0.4*c, x + w*1.8*c + w*0.3*s, y + w*1.8*s - w*0.3*c, x + w*1.8*c + w*0.0*s, y + w*1.8*s - w*0.0*c ); body.curveTo( x + w*1.8*c - w*0.3*s, y + w*1.8*s + w*0.3*c, x + w*1.6*c - w*0.4*s, y + w*1.6*s + w*0.4*c, x + w*0.9*c - w*0.4*s, y + w*0.9*s + w*0.4*c ); body.lineTo(x + w*0.8*c - w*1.2*s, y + w*0.8*s + w*1.2*c); body.lineTo(x + w*0.5*c - w*1.2*s, y + w*0.5*s + w*1.2*c); body.lineTo(x + w*0.5*c - w*0.6*s, y + w*0.5*s + w*0.6*c); body.lineTo(x - w*0.5*c - w*0.6*s, y - w*0.5*s + w*0.6*c); body.lineTo(x - w*0.6*c - w*1.2*s, y - w*0.6*s + w*1.2*c); body.lineTo(x - w*0.9*c - w*1.15*s, y - w*0.9*s + w*1.15*c); body.lineTo(x - w*0.85*c - w*0.2*s, y - w*0.85*s + w*0.2*c); body.lineTo(x - w*1.6*c - w*0.0*s, y - w*1.6*s + w*0.0*c); body.lineTo(x - w*0.85*c + w*0.2*s, y - w*0.85*s - w*0.2*c); body.lineTo(x - w*0.9*c + w*1.15*s, y - w*0.9*s - w*1.15*c); body.lineTo(x - w*0.6*c + w*1.2*s, y - w*0.6*s - w*1.2*c); body.lineTo(x - w*0.5*c + w*0.6*s, y - w*0.5*s - w*0.6*c); body.lineTo(x + w*0.5*c + w*0.6*s, y + w*0.5*s - w*0.6*c); body.lineTo(x + w*0.5*c + w*1.2*s, y + w*0.5*s - w*1.2*c); body.lineTo(x + w*0.8*c + w*1.2*s, y + w*0.8*s - w*1.2*c); body.closePath();

back.moveTo(x + w*1.2*c, y + w*1.2*s); back.curveTo( x + w*1.2*c + w*0.6*s, y + w*1.2*s - w*0.6*c, x + w*0.7*c + w*s, y + w*0.7*s - w*c, x + w*s, y - w*c ); back.curveTo( x - w*0.7*c + w*s, y - w*0.7*s - w*c, x - w*1.2*c + w*0.6*s, y - w*1.2*s - w*0.6*c, x - w*1.2*c, y - w*1.2*s ); back.curveTo( x - w*1.2*c - w*0.6*s, y - w*1.2*s + w*0.6*c, x - w*0.7*c - w*s, y - w*0.7*s + w*c, x - w*s, y + w*c ); back.curveTo( x + w*0.7*c - w*s, y + w*0.7*s + w*c, x + w*1.2*c - w*0.6*s, y + w*1.2*s + w*0.6*c, x + w*1.2*c, y + w*1.2*s );

w *= 0.7; back2.moveTo(x + w*1.2*c, y + w*1.2*s); back2.curveTo( x + w*1.2*c + w*0.6*s, y + w*1.2*s - w*0.6*c, x + w*0.7*c + w*s, y + w*0.7*s - w*c, x + w*s, y - w*c ); back2.curveTo( x - w*0.7*c + w*s, y - w*0.7*s - w*c, x - w*1.2*c + w*0.6*s, y - w*1.2*s - w*0.6*c, x - w*1.2*c, y - w*1.2*s ); back2.curveTo( x - w*1.2*c - w*0.6*s, y - w*1.2*s + w*0.6*c, x - w*0.7*c - w*s, y - w*0.7*s + w*c, x - w*s, y + w*c ); back2.curveTo( x + w*0.7*c - w*s, y + w*0.7*s + w*c, x + w*1.2*c - w*0.6*s, y + w*1.2*s + w*0.6*c, x + w*1.2*c, y + w*1.2*s );

int gap = 48; Color midColor = new Color( Math.max(Math.min(color.getRed(),255-gap),gap), Math.max(Math.min(color.getGreen(),255-gap),gap), Math.max(Math.min(color.getBlue(),255-gap),gap) ); Color lightColor = new Color( midColor.getRed()+gap, midColor.getGreen()+gap, midColor.getBlue()+gap ); Color darkColor = new Color( midColor.getRed()-gap, midColor.getGreen()-gap, midColor.getBlue()-gap );

g.setColor(darkColor); g.fill(body); g.setColor(midColor); g.fill(back); g.setColor(lightColor); g.fill(back2); g.setColor(Color.WHITE); g.fill(leftEye); g.fill(rightEye);

}

/** * Place a picture on the screen where the turtle currently is * @param filename the file name or URL of the image to be drawn * @param size how big the image should be in pixels * @return true if the image was found, false otherwise */ public boolean dropPicture(String filename, double size) { try { BufferedImage pic; if (cachedPictures.containsKey(filename)) { pic = cachedPictures.get(filename); } else { try { pic = ImageIO.read(new URL(filename).openStream()); } catch (Throwable ex) { pic = ImageIO.read(new File(filename)); } cachedPictures.put(filename, pic); } double scale = size/Math.max(pic.getWidth(), pic.getHeight());

AffineTransform af = new AffineTransform(); af.translate(this.location.x, this.location.y); af.rotate(this.theta+Math.PI/2); af.translate(-size/2, -size/2); af.scale(scale, scale); this.world.drawImage(pic, af); this.pause(); return true; } catch (IOException e) { return false; } }

public Color getColor() { return color; }

public void setColor(Color color) { this.color = color; world.turtleMoved(); this.pause(); }

private double penWidth;

public double getPenWidth() { return penWidth; }

public void setPenWidth(double width) { if (width <= 0) throw new IllegalArgumentException("Width must be positive"); this.penWidth = width; }

public double getShellSize() { return shellSize; }

public void setShellSize(double shellSize) { this.shellSize = shellSize; world.turtleMoved(); this.pause(); }

/** * Find out what direction the Turtle is facing * @return angle in degrees; 0 is right, 90 is up, etc */ public double getHeading() { return theta*180/Math.PI; }

/** * Set the direction the Turtle is facing * @param angle in degrees; 0 is right, 90 is up, etc */ public void setHeading(double angle) { this.theta = angle*Math.PI/180; world.turtleMoved(); this.pause(); } /** * Find out where the turtle is located * @return The location of the turtle. (0,0) is the center of the screen, +x is rightward, +y is downward. */ public Point2D getLocation() { return new Point2D.Double(this.location.x - world.centerX, (-this.location.y - world.centerY)); }

/** * Move the turtle to a particular location. It might leave a trail depending on if the pen is down or not. * @param where The new location for the turtle. (0,0) is the top left of the screen, +x is rightward, +y is downward. */ protected void cornerGoTo(Point2D where) { this.cornerGoTo(where.getX(), where.getY()); } /** * Move the turtle to a particular location. It might leave a trail depending on if the pen is down or not. * @param where The new location for the turtle. (0,0) is the center of the screen, +x is rightward, +y is downward. */ public void goTo(Point2D where) { this.cornerGoTo(where.getX() + world.centerX, (-where.getY() + world.centerY)); }

/** * Move the turtle to a particular location. It might leave a trail depending on if the pen is down or not. * @param x The new x location for the turtle. 0 is the center of the screen, bigger numbers to the right * @param y The new y location for the turtle. 0 is the center of the screen, bigger numbers lower down */ protected void cornerGoTo(double x, double y) { double ox = this.location.x; double oy = this.location.y; this.location.x = x; this.location.y = y; if (this.isdown) { world.drawLine(this.location, ox, oy, this.penWidth, this.color); world.turtleMoved(); this.pause(); } else { world.turtleMoved(); this.pause(); }

} public void goTo(double x, double y) { this.cornerGoTo(x + world.centerX, (-y + world.centerY)); }

/** * Seconds to pause between each turtle movement * @return the seconds currently paused */ public double getDelay() { return pause * 0.001; } /** * Seconds to pause between each turtle movement * @param seconds The seconds to pause */ public void setDelay(double seconds) { this.pause = (int)(seconds*1000); }

private void pause() { try { Thread.sleep(this.pause); } catch (InterruptedException e) { } }

}

World.java

import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.event.KeyEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList;

import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel;

public class World extends JFrame { /// version number based on date of creation private static final long serialVersionUID = 20130902L; private BufferedImage overlay, ground, back, front; private Graphics2D og, gg, bg, fg; private ArrayList turtles; public final int centerX; public final int centerY; /** * Creates a new World for Turtles to play in. */ public World() { this(600, 600, Color.WHITE); } public World(int width, int height, Color backgroundColor) { super("Turtle World"); this.centerX = width/2; this.centerY = height/2; this.overlay = new BufferedImage(2*this.centerX, 2*this.centerY, BufferedImage.TYPE_INT_ARGB); this.ground = new BufferedImage(2*this.centerX, 2*this.centerY, BufferedImage.TYPE_INT_ARGB); this.back = new BufferedImage(2*this.centerX, 2*this.centerY, BufferedImage.TYPE_INT_ARGB); this.front = new BufferedImage(2*this.centerX, 2*this.centerY, BufferedImage.TYPE_INT_ARGB); this.og = (Graphics2D)this.overlay.getGraphics(); this.gg = (Graphics2D)this.ground.getGraphics(); this.bg = (Graphics2D)this.back.getGraphics(); this.fg = (Graphics2D)this.front.getGraphics(); og.setBackground(new Color(0,0,0,0)); gg.setBackground(backgroundColor); Graphics2D[] gs = {og, gg}; for(Graphics2D g : gs) { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); }

this.setContentPane(new JLabel(new ImageIcon(this.front))); this.pack(); this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.addKeyListener(new java.awt.event.KeyListener() { @Override public void keyPressed(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { World.this.dispose(); } });

this.clearOverlay(); this.eraseGround();

this.repaint(); this.setVisible(true); this.turtles = new ArrayList(); } /** * Erases all existing paths */ public void eraseGround() { this.gg.clearRect(0, 0, this.ground.getWidth(), this.ground.getHeight()); } /** * Erases all existing paths */ private void clearOverlay() { this.og.clearRect(0, 0, this.overlay.getWidth(), this.overlay.getHeight()); } /** * Should only called by the Turtle class constructor */ void addTurtle(Turtle t) { this.turtles.add(t); this.turtleMoved(); } /** * Should only called by Turtle class methods */ void drawLine(Point2D p1, Point2D p2, double width, Color color) { // draw the line this.gg.setColor(color); this.gg.setStroke(new BasicStroke((float)width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); Line2D.Double line = new Line2D.Double(p1, p2); this.gg.draw(line);

// show the drawn lines this.blit(); } private void blit() { this.bg.drawImage(this.ground,0,0, null); this.bg.drawImage(this.overlay, 0,0, null); this.fg.drawImage(this.back, 0,0, this); this.repaint(); } /** * Should only called by Turtle class methods */ void drawLine(Point2D p1, double nx, double ny, double width, Color color) { this.drawLine(p1, new Point2D.Double(nx,ny), width, color); } /** * Should only called by Turtle class methods */ void turtleMoved() { // show the drawn lines this.clearOverlay(); // add the turtles over top for(Turtle t : this.turtles) { t._how_world_draw_turtles(this.og); } // force the OS to show what's shown this.blit(); } /** * Saves the current image to the specified file * * @param filename The name of the file to write * @throws IllegalArgumentException if any parameter is null or if the filename is not an image filename * @throws IOException if an error occurs in writing the file */ public void saveAs(String filename) { try { int dot = filename.lastIndexOf('.'); if (dot < 0 || dot == filename.length()-1) { throw new IllegalArgumentException("The filename must end in a valid image extension, like .png or .jpg"); } String ext = filename.substring(dot+1).toLowerCase(); File f = new File(filename); ImageIO.write(this.front, ext, f); } catch(Throwable t) { System.err.println("Error saving file: " + t.getMessage()); } } /** * To be used by Turtle class only * @param img the Image to draw * @param placement the Affine Transform to use in drawing it */ void drawImage(Image img, AffineTransform placement) { this.gg.drawImage(img, placement, this); this.blit(); } }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions