001package algs12;
002
003import java.awt.Color;
004import stdlib.*;
005
006/**
007 * For this assignment, you must do two things:
008 *
009 * 1. Complete the MyRectangle class at the bottom of this file. It is not a
010 * public class, but don't worry about that. I've put two classes in one file so
011 * that you need only hand in a single file.
012 *
013 * In particular, you should get the testEquals method to work without throwing
014 * any exceptions.
015 *
016 * 2. Modify the draw method of MyRecursiveRectangles so that it behaves as
017 * demonstrated here:
018 *
019 * <pre>
020 * http://fpl.cs.depaul.edu/jriely/ds1/extras/RecursiveRectangles.mp4
021 * </pre>
022 *
023 * To do this only requires very minor modifications to the function.
024 *
025 * It is not necessary, but if you want to learn more about the drawing classes,
026 * see here:
027 *
028 * <pre>
029 * http://fpl.cs.depaul.edu/jriely/ds1/code/doc-public/stdlib/StdDraw.html
030 * http://introcs.cs.princeton.edu/java/15inout/
031 * </pre>
032 */
033
034public class MyRecursiveRectangles {
035        public static Color randomColor () {
036                int r = StdRandom.uniform (256);
037                int g = StdRandom.uniform (256);
038                int b = StdRandom.uniform (256);
039                return new Color (r, g, b);
040        }
041        public static final int VARIANCE = 60;
042        public static int randomByteAbove (int i) {
043                return StdRandom.uniform (Math.max (0, i - 1), Math.min (i + VARIANCE, 256));
044        }
045        public static int randomByteBelow (int i) {
046                return StdRandom.uniform (Math.max (0, i - VARIANCE), Math.min (i + 1, 256));
047        }
048        public static Color randomColorLight (Color c) {
049                int r = randomByteAbove (c.getRed ());
050                int g = randomByteAbove (c.getGreen ());
051                int b = randomByteAbove (c.getBlue ());
052                return new Color (r, g, b);
053        }
054        public static Color randomColorDark (Color c) {
055                int r = randomByteBelow (c.getRed ());
056                int g = randomByteBelow (c.getGreen ());
057                int b = randomByteBelow (c.getBlue ());
058                return new Color (r, g, b);
059        }
060        public static void draw (MyRect rect, int level, Color c) {
061                // TODO:
062                // edit this function so that it recursively draws levels from here down to level 0,
063                //   decrementing by 1 each time
064                // Optionally, you can also stop recursing if the area of the rectangle is less than 0.1
065
066                // The following line might help while debugging:
067                //StdOut.format ("rect=%s, height=%f width=%f area=%f xmid=%f ymid=%f\n", rect, rect.height (), rect.width (), rect.area (), rect.xmid (), rect.ymid ());
068                StdDraw.setPenColor (c);
069                rect.drawEllipse ();
070                StdDraw.show (50);
071                if (level % 2 == 0) {
072                        double xmid = StdRandom.uniform (rect.xmin (), rect.xmax ());
073                        StdDraw.setPenColor (StdDraw.BLACK);
074                        StdDraw.line (xmid, rect.ymin (), xmid, rect.ymax ());
075                        MyRect left = new MyRect (rect.xmin (), rect.ymin (), xmid, rect.ymax ());
076                        MyRect right = new MyRect (xmid, rect.ymin (), rect.xmax (), rect.ymax ());
077                        StdDraw.setPenColor (randomColorLight (c));
078                        left.drawEllipse ();
079                        StdDraw.setPenColor (randomColorDark (c));
080                        right.drawEllipse ();
081                } else {
082                        double ymid = StdRandom.uniform (rect.ymin (), rect.ymax ());
083                        StdDraw.setPenColor (StdDraw.BLACK);
084                        StdDraw.line (rect.xmin (), ymid, rect.xmax (), ymid);
085                        MyRect below = new MyRect (rect.xmin (), rect.ymin (), rect.xmax (), ymid);
086                        MyRect above = new MyRect (rect.xmin (), ymid, rect.xmax (), rect.ymax ());
087                        StdDraw.setPenColor (randomColorLight (c));
088                        below.drawEllipse ();
089                        StdDraw.setPenColor (randomColorDark (c));
090                        above.drawEllipse ();
091                }
092        }
093        public static void testEquals () {
094                // this method should not throw any exceptions!
095                MyRect r1 = new MyRect (1, 1, 2, 2);
096                if (!r1.equals (r1)) {
097                        throw new Error ();
098                }
099                if (!r1.equals (new MyRect (1, 1, 2, 2))) {
100                        throw new Error ();
101                }
102                if (r1.equals (null)) {
103                        throw new Error ();
104                }
105                if (r1.equals (new Object ())) {
106                        throw new Error ();
107                }
108                if (r1.equals (new MyRect (0, 1, 2, 2))) {
109                        throw new Error ();
110                }
111                if (r1.equals (new MyRect (1, 0, 2, 2))) {
112                        throw new Error ();
113                }
114                if (r1.equals (new MyRect (1, 1, 3, 2))) {
115                        throw new Error ();
116                }
117                if (r1.equals (new MyRect (1, 1, 2, 3))) {
118                        throw new Error ();
119                }
120        }
121
122        public static final double DIM = 1.0;
123        public static void main (String[] args) {
124                testEquals();
125
126                StdDraw.setCanvasSize (800, 800); // in pixels
127                StdDraw.setXscale (-DIM, DIM);
128                StdDraw.setYscale (-DIM, DIM);
129                MyRect rect = new MyRect (-DIM, -DIM, DIM, DIM);
130
131                //StdRandom.setSeed (0); // uncomment this if you want the same behavior every time you run the program
132                Color initialColor = randomColor (); //new Color(127,127,127)
133                //long seed = StdRandom.getSeed ();
134                for (int numLevels = 1; numLevels < 8; numLevels += 1) {
135                        //StdRandom.setSeed (seed);
136                        StdDraw.clear ();
137                        draw (rect, numLevels, initialColor);
138                        StdDraw.show (1000);
139                }
140        }
141}
142
143// An axis aligned rectangle
144class MyRect {
145        // TODO: add fields
146
147        // construct the axis-aligned rectangle "[xmin, xmax] x [ymin, ymax]"
148        public MyRect (double xmin, double ymin, double xmax, double ymax) {
149                if (xmax < xmin || ymax < ymin) {
150                        throw new IllegalArgumentException ("Invalid rectangle");
151                }
152                // TODO: set the fields
153        }
154
155        // accessor methods for 4 coordinates
156        public double xmin () {
157                return /* TODO */0;
158        }
159        public double ymin () {
160                return /* TODO */0;
161        }
162        public double xmax () {
163                return /* TODO */0;
164        }
165        public double ymax () {
166                return /* TODO */0;
167        }
168
169        // width, height, area of rectangle
170        public double width () {
171                return /* TODO */0;
172        }
173        public double height () {
174                return /* TODO */0;
175        }
176        public double area () {
177                return /* TODO */0;
178        }
179
180        // halfway between xmin and xmax
181        public double xmid () {
182                return /* TODO */0;
183        }
184        // halfway between ymin and ymax
185        public double ymid () {
186                return /* TODO */0;
187        }
188
189        // follow the recipe given in the textbook (pp 102-103) to implement equals
190        public boolean equals (Object y) {
191                return /* TODO */false;
192        }
193
194        public void drawEllipse () {
195                StdDraw.filledEllipse (xmid (), ymid (), width () / 2, height () / 2);
196        }
197        public void drawRectangle () {
198                StdDraw.filledRectangle (xmid (), ymid (), width () / 2, height () / 2);
199        }
200        public String toString () {
201                return "[" + xmin () + ", " + xmax () + "] x [" + ymin () + ", " + ymax () + "]";
202        }
203}