CPTR 124 Fundamentals of Programming
In this lab you will design and implement two classes given some minimal requirements. You will determine the needed instance variables and implement methods that conform to a specified interface that client code expects.
- Teams
You are encouraged to work with a partner for this lab. You and your partner should begin thinking about the problems and begin writing the code before lab time.
- Preparing your working folder
Make a subfolder named Lab6 within your H:\cptr124 folder.
- Geometric Primitives. Several primitives are used in geometry:
- Two-dimensional geometric points are real number pairs (x, y). We'll approximate real numbers with double precision floating point numbers.
- A geometric line is an infinite set of colinear points. A line can be defined by two nonequal points on that line, and lines are often represented by an equation.
- Point Class. Create a Point class that
provides the functionality of a two-dimensional geometric
point. Specifically:
- You must be able to create a Point object using any of
three constructors:
- one that takes two doubles (the x and y coordinates),
- one that takes a reference to a Point object (the constructor here creates a new Point object with the same x and y coordinates as the parameter), and
- a default constuctor with no arguments that creates a point at the origin (0,0).
- Write a toString() method that takes no
arguments and returns a String object. It
shows the point in a nice human-readable form.
Whenever Java needs to convert an object to a string
(for example, when calling
System.out.println()), the object's
toString() method is called:
Point pt = new Point(3, 4); // Prints "pt = (3.0,4.0)" System.out.println("pt = " + pt); - Include accessor methods to read a point's
coordinates:
- getX(): returns the x coordinate of the point
- getY(): returns the y coordinate of the point
There should be no other way for code outside the Point class to determine a point's x or y coordinate values.
- Include a distance() method that computes the
distance to a point passed into it:
Point pt1 = new Point(3, 4); System.out.println("pt1 = " + pt1); Point pt2 = new Point(15, 10); // Prints "Distance: 13.416407864998739" System.out.println("Distance: " + pt1.distance(pt2));As you can see, to find the distance between points pt1 and pt2, use
pt1.distance(pt2)
The call
pt2.distance(pt1)
would work just as well.
In mathematics, the distance between two points (x1,y1) and (x2, y2), is given by the formula
The Math.sqrt() method can be used to compute the square root; for example, the following statement will assign 5 to d:
d = Math.sqrt(25);
To square an expression, just multiply it to itself, as in:
(x2 - x1) * (x2 - x1)
- You must be able to create a Point object using any of
three constructors:
- Line Class. Create a Line class
that provides the functionality of two-dimensional geometric lines.
Specifically:
- You must be able to create a Line object. Its only
constructor accepts two nonequal Point objects
that determine the line. The constructor's behavior is
undefined if the two points passed to it are equal. (Being
undefined means you don't have to worry what your program does
if a client attempts to create such a line.)
While clients create a Line object with two points, these actual points are not useful after the line is created. You should precompute the slope and y-intercept (or x-intercept, if it is a vertical line) and let these two values define the state of a line object. (See below for more information about intercepts.)
This information about the slope and intercept should not be directly accessible by clients. Clients can see these values via methods (see below) but cannot change them. This means that lines, like points, are immutable objects.
- Include a slope() method that returns the
slope of the line. Recall that a vertical line has an
undefined slope. We'll let our vertical lines have a slope of
Double.POSITIVE_INFINITY, a static final value
(obviously respresenting positive infinity)
publically available in the java.lang.Double class.
- Include an intercept() method that returns:
- for a non-vertical line, the y coordinate of the point of intersection with the y-axis, or
- for a vertical line, the x coordinate of the point of intersection with the x-axis.
- Write a toString() method that takes no
arguments and returns a String object. It
shows the equation of the line
in a nice human-readable form. The equation
should be in slope-intercept form: y = mx + b.
For example:
Line myLine = new Line(new Point(3, 4), new Point(15, 10)); // Prints "Line: y = 0.5x + 2.5" System.out.println("Line: " + line);Careful! Recall that a horizontal line that crosses the y-axis at 3 has the equation
y = 3 and a vertical line that crosses the x-axis at 3 has the equation
x = 3 Your program should handle these situations correctly.
- Include a satisfies() method that accepts a
single Point as a parameter and returns a
boolean value indicating whether or not the
point is on the line.
How do you determine if a point satisfies a line? If you know the line's slope and intercept (i.e., the line's equation), you simply plug in the x and/or y values of the point and see if the equality holds:
- for y = mx + b, plug in x and see if you get y
- for y = c, where c is some number, y has to equal c (x does not matter)
- for x = c, where c is some number, x has to equal c (y does not matter)
- Include an intersect() method that accepts a
single Line as a parameter and returns a
Point object indicating the point of
intersection of the two lines. If the lines are
parallel, the result is null.
How do you compute the point of intersection of two lines?
- If the two lines have the same slope, there is no single point of intersection. That's why we return a null reference.
- If neither line is horizontal or vertical, we have a pair of equations that look like
y = m1x + b1 since both righthand expression equal y, set them equal to each other:
y = m2x + b2m1x + b1 = m2x + b2 and solve for x:m1x - m2x + b1
=
m2x - m2x + b2
m1x - m2x + b1
=
b2
m1x - m2x + b1 - b1
=
b2 - b1
m1x - m2x
=
b2 - b1
(m1 - m2)x
=
b2 - b1
x
=
(b2 - b1)/ (m1 - m2)
This final equation
x = (b2 - b1)/ (m1 - m2) serves as a formula to compute x. Once you have x you can plug it into either of the original equations to compute y. The x and y values are then used to create the required point.
- If one of the lines is horizontal or vertical, you know immediately one of the coordinates (x for vertical lines and y for horizontal lines). Plug the known value into the equation for the other line to compute the other coordinate.
- If one of the lines is horizontal and the other is vertical, you know immediately both of the coordinates (the x coordinate comes from the vertical line and the y coordinate comes from the horizontal line).
- You must be able to create a Line object. Its only
constructor accepts two nonequal Point objects
that determine the line. The constructor's behavior is
undefined if the two points passed to it are equal. (Being
undefined means you don't have to worry what your program does
if a client attempts to create such a line.)
- Handling Floating Point Imprecision.
Since floating point numbers are imprecise, the == operator may not
work as expected when comparing floating point numbers. The == operator tests for
exactly matching bit patterns between its two operands. Because of the imprecise
representation, a computed value for
25 may be 24.99999 or 25.000001 instead of exactly 25. This means that a point that supposed
to be on a line (when computing satisfies()) may not really appear to be on the
line!
A better approach, for our situation,
is to test to see if the absolute
value of the difference is less than a small value. For example, if a and b
are floating point numbers, instead of using
a == b write a class method named equals() that accepts two doubles and returns the result of the following comparison:
|a - b| < 0.0001 (The vertical bars mean absolute value.) This, in effect, says "The values of a and b are so close that we consider them equal."
The Math.abs() method can be used to find the absolute value, as in: Math.abs(-5) (which equals 5).
In your equals() method treat Double.POSITIVE_INFINITY specially. Use == to see if a and b are both Double.POSITIVE_INFINITY; if so, return true. If one is == to Double.POSITIVE_INFINITY but the other is not, then return false. If neither a nor b are Double.POSITIVE_INFINITY, then proceed with the absolute value of the difference code mentioned above. This procedure will suffice for this program.
- Test Code. Your two classes should work with the
code provided
here (GeometryTest.java).
The output of
this test program can be found
here, but, more
importantly, your code should work with any Java
program that needs to use these geometric objects and
respects
the interface described above. Your class will be
tested against other Java code, not just the one
provided above. Feel free to write other test programs
to exercise your code.
- Check out
Provide your Point.java and Line.java sources files to tested by an automated test suite. If your code contains errors, you may retest it twice. After the third test, your grade will be based on the number of remaining errors. After your code passes all the tests or after three unsuccessful testing tries (whichever comes first), submit a printout of both of your source files. Be sure your name and your partner(s) names are included on the printout.
Important: All testing must be completed by the due date. Code printouts without official testing are unacceptable.