import acm.graphics.*; import java.awt.*; import acm.program.*; /** An instance maintains a graphics window on the monitor, which can be drawn on * using pens, turtles, and other things. */ public class A5 extends GraphicsProgram { // The width and height of the graphics window. private static String[] sizeArgs= { "width=" + 500, "height=" + 500 }; /** Open the A5 GUI for the user */ public static void main(String[] pars) { A5 x= new A5(); } /** Constructor: a new Graphics Program with a canvas of size (500, 500) */ public A5() { super(); start(sizeArgs); } /** Yields: a new turtle that is at the Center of the canvas, faces west, * is not hidden, and is ready to draw in red. */ public A5Turtle newTurtle() { A5Turtle t= new A5Turtle(); add(t); // Add the turtle to the canvas. t.setLocation(getWidth()/2, getHeight()/2); t.penDown(); t.setColor(Color.red); t.setDirection(180); t.showTurtle(); return t; } /** Yields: a new pen that is at the Center of the canvas, * is not hidden, and is ready to draw in black. */ public GPen newPen() { GPen p= new GPen(); add(p); // Add the pen to the canvas. p.setLocation(getWidth()/2, getHeight()/2); p.setColor(Color.black); p.showPen(); return p; } /** In the middle of the canvas, draw a green line 100 pixels to the left (west), * and then a red line 200 pixels down (south), using a new turtle that moves * at speed sp, 0 <= sp <= 1, with 0 being slowest and 1 fastest. */ public void drawTwoLines(double sp) { A5Turtle t= newTurtle(); t.setSpeed(sp); t.setColor(Color.green); t.forward(100); // draw a line 100 pixels in the current direction t.left(90); // add 90 degrees to the angle t.setColor(Color.red); t.forward(200); } // TASK 2 /** Draw an equilateral triangle of side length s and color c at turtle t's * current position. If the turtle is facing west, the triangle points up and * the turtle starts and ends at the east end of the base line. UPON COMPLETION, * THE FOLLOWING PROPERTIES ARE THE SAME AS WHEN THE METHOD STARTED: turtle * position, turtle direction, pen color. The pen is left down. * Precondition: the pen is down. */ public void drawTriangle(A5Turtle t, double s, Color c) { // INSTRUCTIONS: fill this in // Hint: each angle in an equilateral triangle is 60 degrees. // Note: Do NOT save the turtle position and direction in the beginning // and then restore them at the end. Instead, the turtle moves should be // such that the turtle ends up where it started and facing in the same // direction. // Also, 3 lines have to be drawn. Does this suggest a for-loop that // processes the range 1..3? // Put your Code here: /* When you have completed and tested this method, do the following * instructions in the Interactions pane to learn about round-off error * caused by using type double instead of the mathematical type real: * * a= new A5(); * t= a.newTurtle(); * System.out.println(t); * a.drawTriangle(t, 200, java.awt.Color.red); * System.out.println(t); * * You will see that t's location is not the same before and after * drawing the triangle. This is due to "round-off" errors that * arise because type double uses only approximations to real numbers. * * This is OK here, because the pixels in the panel on which * the drawing takes place are given by integers: the top left one is * (0, 0), the one to its right is (0, 1), and so on. The turtle's * drawing methods round double values to ints before actually drawing. * * You also see that the direction has been changed --in our case, 720 * was added to it. That's OK. 5, 365, 725, ... are considered the same angle. * * Add a comment at the top of this file (A5.java) containing a * cut-and-paste of the results in the Interaction pane of * typing in the five lines specified in this comment. */ } // TASK 3 /** Use turtle t to draw six equilateral triangles using color Color.orange with * side lengths s to form a hexagon, starting at the turtle's current position and * direction. The middle of the hexagon is the turtle's starting position. Upon * completion, the following properties are the same as when the method started: * turtle position, color, and direction. The pen is left down. * Precondition: the pen is down. */ public void drawHex(A5Turtle t, double s) { // INSTRUCTIONS: fill this in // Note: Do not save any of the turtle's properties and then restore // them at the end. Just use 6 calls on procedures drawTriangle // and t.left. Test the procedure to make sure that t's final // location and direction are the same as t's initial location and // direction (except for roundoff error). // The procedure is supposed to draw 6 triangles. Does // that suggest a loop that processes the integers in 1..6? } // TASK 4 // TASK 4A /** Remove all objects from the canvas, then draw a spiral using * drawSpiral(t, sp, d, ang, n), where t is a newly created turtle * that starts in the middle of the canvas, facing east. At the end, * the turtle is left hidden. * Precondition: 0 <= sp <= 1, 1 <= d, 1 <= n. */ public void drawSpiral(double sp, double d, double ang, int n) { // INSTRUCTIONS: fill this in // Hint: removeAll() removes all objects from the canvas. // Hint: use the turtle's function hideTurtle() at the end. } /** Draw a spiral of n lines beginning at turtle t's current position * and direction, turning ang degrees to the left after each line. * The turtle's speed is sp (0 is slowest, 1 fastest). Line 1 is d * pixels long; line 2, 2*d pixels; ...; so each line i is i*d pixels * long. The lines alternate between red, blue, and green, in that * order, with the first one being red. At the end, t's color and * speed are the same as before the call, but its final position and * angle may be different. * Precondition: pen is down, 0 <= sp <= 1, 1 <= d, 1 <= n. */ public void drawSpiral(A5Turtle t, double sp, double d, double ang, int n) { // INSTRUCTIONS: fill this in // Note: Since n lines have to be drawn, use a for-loop that processes // a range of integers. } // TASK 4B /** Remove all objects from the canvas. Draw polygons using * multiPolygons(t, k, n, d, sp), where t is a newly created turtle that starts * in the middle of the canvas, facing north, and moves at speed sp. At the end, * the turtle is left hidden. * Precondition: k >= 1, n >= 3, d >= 1, 0 <= sp <= 1. */ public void multiPolygons(int k, int n, double d, double sp) { // INSTRUCTIONS: fill this in } /** Draw k n-sided polygons of side length d using turtle t, with t moving at speed * sp (0 <= sp <= 1). The polygons are in alternating colors between red and green. * Each polygon is drawn starting at the same place (within roundoff errors), but t * turns left 360.0/k degrees after each polygon. At the end, all properties of the * turtle are the same at the end as they were in the beginning (within roundoff * errors). * Precondition: pen is down, k >= 1, n >= 3, d >= 1, 0 <= sp <= 1. */ public void multiPolygons(A5Turtle t, int k, int n, double d, double sp) { // INSTRUCTIONS: fill this in // Hint: make sure that upon termination, t's color and speed are left // as they were at the beginning. /* Note: Since k polygons should be drawn, use a for-loop that * processes a range of integers. */ } /** Draw an n-sided polygon using turtle t. Each side is d pixels long. * The polygon is drawn with turtle speed sp. The following properties * of t end up the way they were at the beginning: position, direction, * color, speed, and pen-down. * Precondition: pen is down, 0 <= sp <= 1, 3 <= n */ public void drawPolygon(A5Turtle t, double sp, int n, double d) { double initialSpeed= t.getSpeed(); t.setSpeed(sp); // angle is the angle between 2 adjacent sides double angle= ((n-2) * 180.0) / n; // inv: j lines have been drawn. t is in position and facing // the direction to draw the next line for (int j= 0; j < n; j= j+1) { t.forward(d); t.left(180 - angle); } t.setDirection(t.getDirection()%360); t.setSpeed(initialSpeed); } // TASK 4C /** Remove all objects from the window, then draw n straight radiating * lines using radiate(t, sp, d, n), where t is a new turtle starting * at the middle of the screen and facing east. At the end, the turtle * is left hidden. * Precondition: 2 <= n, 0 <= sp <= 1, 1 <= d, 0 <= n, and pen is down.*/ public void radiate(double sp, double d, int n) { // INSTRUCTIONS: fill this in } /** Draw n straight radiating lines of length d at equal angles using * Turtle t with the turtle moving at speed sp. A line drawn at * angle ang, 0 <= ang < 360, is drawn with HSV color (ang, 1, 1). * The turtle ends up with its initial color and speed, but * its final position and angle may be different at the end of drawing. * Precondition: 2 <= n, 0 <= sp <= 1, 1 <= d, 0 <= n, and pen is down. */ public void radiate(A5Turtle t, double sp, double d, int n){ /* Notes: 1. Drawing n lines should be done with a loop that processes a certain range of integers. 2. You must keep the direction of the turtle in the range 0 <= direction < 360. The directions ds and 360 + ds are considered to be the same. 3. Use new HSV(t.getDirection(),1,1) to create an HSV object that gives the color represented by turtle t's direction. 4. For HSV object hsv, use hsv.toRGB() to get a Color object with the same color as hsv. */ // INSTRUCTIONS: fill this in } // TASK 5 // TASK 5A /** Remove all objects from the graphics window and draw a Sierpinski * triangle with side length s and bottom left corner (x, y), using a * newly created pen. The pen is left hidden. * Precondition: d >= 0 and s > 0. */ public void sierpinski(double x, double y, int d, double s) { // INSTRUCTIONS: fill this in } /* Using pen p, draw a Sierpinksi triangle of depth d with side length s and bottom left corner (x, y). Precondition: d >= 0 and s > 0 and pen is down. */ private void sierpinski(GPen p, double x, double y, int d, double s){ // INSTRUCTIONS: fill this in // Hint: Don't set p's location until you have to. } // TASK 5B /** Remove all objects from the window and draw a Grisly snowflake of * depth d with side length s and left point of base line at (s, 2s), * using a newly created pen. The pen is hidden during drawing and * left hidden at the end. * Precondition: d >= 0 and s > 0. */ public void grisly(double s, int d) { // INSTRUCTIONS: fill this in } /* Using pen p, draw a Grisly snowflake of depth d with side length s * and left point of base line at (x, y). * Precondition: d >= 0 and s > 0 and pen is down. */ private void grisly(GPen p, double x, double y, int d, double s) { // INSTRUCTIONS: fill this in } // TASK 5C /** Remove all objects from the window and draw an H-tree with a newly * created pen. The pen is hidden during drawing and * left hidden at the end. * Precondition: d >= 0 and s > 0. */ public void Htree(double x, double y, int d, double s) { // INSTRUCTIONS: fill this in } /* Draw an H-tree of depth d and size s with center (x, y) using pen p. * Precondition: d >= 0 and s > 0 and pen is down. */ private void Htree(GPen p, double x, double y, int d, double s) { // INSTRUCTIONS: fill this in } /* Draw an H at center (x, y) of size s using pen p. */ private void drawH(GPen p, double x, double y, double s) { // INSTRUCTIONS: fill this in } // HELPER METHODS FOR THE RECURSIVE PROCEDURES /** Remove all objects from the window and draw a Sierpinksi carpet of * depth d with side length s with top-left corner the top of left of the window. * Use a new pen. Precondition: d >= 0 and s > 0. */ public void sierpinskiCarpet(int d, double s) { removeAll(); GPen p= newPen(); sierpinskiCarpet(p, 0, 0, d, s); } /* Using pen p, draw a Sierpinksi carpet of depth d with side length s and * top left corner (x, y). * Precondition: d >= 0 and s > 0 and pen is down. */ private void sierpinskiCarpet(GPen p, double x, double y, int d, double s){ p.setLocation(x,y); fillSquare(p,s); if (d==0) return; p.setColor(Color.white); p.setLocation(x+s/3, y+s/3); fillSquare(p,s/3); p.setColor(Color.black); // Fill in the 8 squares with d-1-level carpets // They are 00 01 02 // 10 12 // 20 21 22 for (int a=0; a <=2; a++) { for (int b=0; b <=2; b++) { if (!(a==1 && b ==1)) { sierpinskiCarpet(p, x+a*s/3, y+b*s/3, d-1, s/3); } } } } /* Fill the equilateral triangle of side length s with * left point of its base given by p and triangle pointing up. * When done, the position of p should be as it was initially. */ private void fillTriangle(GPen p, double s) { double h= s * Math.sqrt(.75); p.startFilledRegion(); p.drawLine(s, 0); p.drawLine(-s/2, - h); p.drawLine(-s/2, h); p.endFilledRegion(); } /* Using pen p, fill a square with side length s, with top-left corner given * by p's current position. */ private void fillSquare(GPen p, double s) { p.startFilledRegion(); p.drawLine(s, 0); p.drawLine(0, s); p.drawLine(-s, 0); p.drawLine(0, -s); p.endFilledRegion(); } /* Fill a hexagon of side length s, with center (x, y), * using pen p. */ private void fillHex(GPen p, double s, double x, double y) { p.setLocation(x + s, y); double dx= s*GMath.cosDegrees(60); double dy= s*GMath.sinDegrees(60); p.startFilledRegion(); p.drawLine(-dx, dy); p.drawLine(-s, 0); p.drawLine(-dx, -dy); p.drawLine(dx, -dy); p.drawLine(s, 0); p.drawLine(dx, dy); p.endFilledRegion(); } } // This is a helper class which is "package" access, not public access /** an instance is an GTurtle whose toString includes the direction */ class A5Turtle extends GTurtle { // TASK 1 /** Yields: a representation of the turtle, giving its location, color, and direction*/ public String toString() { /* Instructions: Modify the output of super.toString() to include * * , direction= * * just before the closing bracket. */ return ""; } }