5.6  Example: Is a Posn within a AComboShape

1. Data Analysis and Problem Analysis

The only data we need is this shape and the Posn in question.

2. Purpose and Contract/Header:

  // PURPOSE AND CONTRACT:
  // determine whether the given p is within this shape
  abstract boolean within(Posn p);

We develop the methods in the three classes separately, starting from the class Combo, which is the simplest, then the class Rect, and finally the class Circle. For all examples we will use the following data:

  AComboShape c1 = new Circle(new Posn(50, 20), 20);
  AComboShape c2 = new Circle(new Posn(20, 20), 10);
  AComboShape r1 = new Rect(new Posn(10, 20), 20, 40);
  AComboShape r2 = new Rect(new Posn(40, 20), 50, 10);
  AComboShape combo1 = new Combo(c1, r1);
  AComboShape combo2 = new Combo(r2, combo1);
  AComboShape combo3 = new Combo(combo2, c2);

Examples, Template, and Program for the class Combo:

3. Examples for the class Combo:

  (combo1.within(new Posn(30, 30)) == true) 
  (combo3.within(new Posn(40, 30)) == true) 
  (combo3.within(new Posn(50, 50)) == false) // below the shape
  (combo3.within(new Posn(40, 40)) == true)  // border of the shape

4. Template for the class Combo:

/* TEMPLATE for the method within in the class Combo:
// determine whether the given p is within this shape
boolean within(Posn p){ ... }
  ... this.top.within(p) ...
  ... this.bottom.within(p) ...
}
  */

5. Program for the class Combo:

We notice, that once we know whether a Posn is within either of the two shapes that comprise the Combo shape, the solution is easy.

  // PROGRAM for the class Combo: 
  // determine whether the given p is within this shape
  boolean within(Posn p){
    return ( this.top.within(p) || this.bottom.within(p) );  }    

Examples, Template, and Program for the class Rect:

3. Examples for the class Rect:

  (r1.within(new Posn(20, 20)) == true) 
  (r2.within(new Posn(20, 20)) == false)    // left of the shape
  (r1.within(new Posn(50, 20)) == false)    // right of the shape
  (r2.within(new Posn(50, 10)) == false)    // above  the shape
  (r2.within(new Posn(60, 40)) == false)    // below the shape

4. Template for the class Rect:

/* TEMPLATE for the method within for the class Rect:
// determine whether the given p is within this shape
boolean within(Posn p){
  ... this.nw ...
      ... this.nw.x ...
      ... this.nw.y
  ... this.width ...
  ... this.height ...

  ... p.x ...
  ... p.y ...
   
  ... if ((p.x > this.nw.x) && (p.x < this.nw.x + this.width) ...
  ... if ((p.y > this.nw.y) && (p.y < this.nw.y + this.height) ... 
}
*/

5. Program for the class Rect:

Writing the template we already realized that the relevant information is the relationship between the coordinates of the Posn p and the location and the size of the rectangle. The rest of the program follows easily.

  // PROGRAM for the class Rect: 
  // determine whether the given p is within this shape
  boolean within(Posn p){
    return ((p.x >= this.nw.x) && 
            (p.x <= this.nw.x + this.width)) 
        && ((p.y >= this.nw.y) && 
            (p.y <= this.nw.y + this.height));  }    

Examples, Template, and Program for the class Circle:

3. Examples for the class Circle:

  (c1.within(new Posn(40, 10)) == true) 
  (c1.within(new Posn(20, 20)) == false)    // left of the shape
  (c1.within(new Posn(80, 20)) == false)    // right of the shape
  (c1.within(new Posn(20, 0))  == false)    // above  the shape
  (c1.within(new Posn(20, 40)) == false)    // below the shape

4. Template for the class Circle:

/* TEMPLATE for the method within for the class Circle:
// determine whether the given p is within this shape
boolean within(Posn p){
  ... this.center ...
      ... this.center.x ...
      ... this.center.y
  ... this.radius ...

  ... p.x ...
  ... p.y ...
   
  ... if ((p.x > this.center.x) && (p.x < this.center.x + this.radius) ...
  ... if ((p.y > this.center.y) && (p.y < this.center.y + this.radius) ... 
}
*/

5. Program for the class Circle:

For the class Circle we compromise, and determine only whether the given Posn p is within the bounding square of our circle.

  // PROGRAM for the class Circle: 
  // determine whether the given p is within this shape
  boolean within(Posn p){
    return ((p.x >= this.center.x - this.radius) && 
            (p.x <= this.center.x + this.radius))
        && ((p.y >= this.center.y - this.radius) && 
            (p.y <= this.center.y + this.radius));  }   

6. Tests:

We had to wait with the examples until the method has been developed for all three classes. The alternative, is to provide each class with a stub of the method, that just returns an arbitrary value of the appropriate type, and then develop and test each method one step at a time. Of course, in that case, we could not start with the method for the Combo class, because the test results for that method depend on the results of the methods for the classes Circle and Rect.

We now run as tests the examples introduced earlier.