The goal of this lab is to explore and experience good object oriented design with regards to encapsulation and information hiding. The program you are going to write is simple: it takes commands from the user and produces output. Its functionality is to keep track of the bounding box for points as they are "added". The bounding box for a set of points is the smallest rectangle (aligned with the x/y axis) that contains all the points. The commands are:
  1. add x y adds another point that the bounding box needs to include. No output.
  2. box outputs the current bounding box in the format xmin < x < xmax , ymin < y < ymax.
  3. map x y prints the point (x,y) (which should be inside the bounding box) mapped into the unit square according to the following formula: newx = (x - minX)/width and newy = (y - minY)/height, where minX is the minimum x-value in the bounding box, minY is the minimum y-value in the bounding box, and width and height are the bounding box's width and height. map should return "error" if (x,y) is not in the current bounding box.
  4. done exits the program
Here's a sample run:
~/$ java Lab03
add 4 5
add 9 3
add 6 7
4.0 < x < 9.0, 3.0 < y < 7.0
map 5 6
0.2 0.75
add 2 6
map 5 6
0.42857142857142855 0.75
2.0 < x < 9.0, 3.0 < y < 7.0

The Rules

I'm going to try and force you to use good Object Oriented Design practices. So, there are a few rules. First and foremost, in all that you do, all fields are private! Otherwise, here are my rules:

Rule 1: You must define a class Point with at least

  • the constructor
    public Point(double x, double y)
    that initializes the points x & y appropriately,
  • the method
    public static Point read(Scanner sc)
    that reads an x and a y value from the scanner and returns the associated point, and
  • the method
    public String toString()
    that returns a String consisting of the x-coordinate, a space, and the y-coordinate.
Anything else you want in point is OK except that you must declare all data-members (fields) private!

Rule 2: Your program must be able to be run as:

java Lab03
... and it must accept exactly the input syntax described above, and produce exactly the output described above. Also, Step 3 has one more rule!

Rule 3: You must define a class Box with the interface shown below, and no other public methods! Of course, all fields must be private!
public class Box
  // constructor for Box that consists of a single point
  public Box(Point p) { ... }

  // constructor for the Box containing two initial points
  public Box(Point a, Point b) { ... }

  // growBy(p) expands the bounding box (if needed) to include point p
  public void growBy(Point p) { ... }

  // given point p in the bounding box, returns associated point in the
  // unit square (see notes); returns null if p is not inside the bounding box.
  public Point mapIntoUnitSquare(Point p) { ... }

  // returns string representation like: 2.0 < x < 9.0, 3.0 < y < 7.0
  public String toString() { ... }
Note: Just to explain the one-argument constructor, the bounding box around point p should be the "empty box" around that point. For example
Point p = new Point(3,5);
Box B = new Box(p);
String s = B.toString();
... would print out 3.0 < x < 3.0, 5.0 < y < 5.0

Step 1: Get to the Point

You know you're going to want a class Point. Go ahead and write it. Think first of what operations you're likely to need, and then start writing them one-by-one. Make sure to have a
public static void main(String[] args)
you can use to test as you go. Keep adding new code that tests each new function as you add it, but don't get rid of the old tests. When you're done with the program, main() should be a complete test suite you can run to verify that Point works the way it should!

Step 2: Think inside the Box

Now start implementing the Box class. Start with the one-argument constructor and the toString() function. Be sure to include a main() that tests them. Then start adding the other methods, testing as often as you can, and never deleting tests from main(). You may find that you have to go back and add some new methods to Point as you go along. That's OK. Be sure to re-test whenever you do, though!

Step 3: Get with the Program

Finally, write the class Lab03. It should be a breeze now that you've got Box and Point written. One more rule: Inside the Lab03 class, the only class Point methods you should use are read and toString. You can use any class Box method you want.
~/$ java Lab03
Error! Unknown command "asdf"!  
add 2 2
2.0 < x < 2.0, 2.0 < y < 2.0
add 5 1.5
2.0 < x < 5.0, 1.5 < y < 2.0
add 2.5 2.5
2.0 < x < 5.0, 1.5 < y < 2.5
~/$ java Lab03
add 2.8 -1.8
add -3.0 -3.5
-3.0 < x < 2.8, -3.5 < y < -1.8
map 0 0
map -2 -2
0.1724137931034483 0.8823529411764706  
add 2.5 2.5
-3.0 < x < 2.8, -3.5 < y < 2.5
map -2 -2
0.1724137931034483 0.25

Important: You will be submitting your solution to the submit website, which will give you feedback about whether your program is functioning correctly or not. First run the following code, just once, in order to ensure you have the script submit.ic211 that you'll use to make your submission:

pushd ~/; mkdir -p bin; cd bin; curl -O http://submit.cs.usna.edu/tools/submit.ic211;chmod 700 submit.ic211; popd
After this has been done, you may submit your lab as many times as needed to get it working perfectly with the command:
~/bin/submit.ic211 lab03 Point.java Box.java Lab03.java
Your instructor may still require a demo, but you should have a submission that passes all three tests first.

Step 4: [Going Further] How well did you follow the rules?

Let's see if you followed the rule. Find a classmate who has finished the other steps as well. Copy his/her Point.java and Box.java into a new directory, and copy your Lab03.java in there as well. Compile it all and run and test. Did it work? If you followed the rules, it has to work! That's the beauty of separating interface and implmentation! As long as the interface elments you rely on stay the same, you can change the the implementation behind it as much as you like.