package org.opensha2.function;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import java.awt.geom.Point2D;
/**
* <b>Title:</b> DataPoint2DComparatorAPI<p>
*
* <b>Description:</b> Implementing comparator of DataPoint2d. The comparator
* uses a tolerance to specify that when two values are within tolerance of each
* other, they are equal<p>
*
* This class sounds more complicated that it really is. The whole purpose is
* for calling the function compare(Object o1, Object o2). The x-coordinates are
* obtained from each, then this algorythmn determines if the x-values are
* equal:<p>
*
* Math.abs( x1 - x2 ) <= tolerance)<p>
*
* A tolerance=0 is actually abaout 1e-16 due to the numerical precision of
* floating point arithmetic (1.0 + 1e-16 = 1.0 )<p>
*
* Note: In general comparators are created so that you can have more than one
* sorting for a class. Imagine that you have a Javabean with 4 fields, id,
* first name, last name, date created. Typical for a user record in a database.
* Now you can build the compareTo() function inside this Javabean, nut then you
* can only sort on 1 column. What if you present these javabeans in a GUI List,
* and you want to sort on any field by clicking on the header. You simply make
* 4 comparators, one for each field. Each header would use the particular
* comparator for the sorting function. Very nice design pattern. <p>
*
* Now let's say you add another field. You simply make a new Comparator (
* almost copy and paste). You don't have to change youre Javabean or your
* sorting function. Just pass in this new comparator. <p>
*
* @author Steven W. Rock
*/
public class Point2DToleranceComparator implements Point2DComparator {
/**
* The tolerance for determining whether two x values are different. A
* tolerance of 0.0 (the default) is really about 1e-16 due to the numerical
* precision of floating point arithmetic ( 1.0 - (1.0+1e-16) = 0.0 ). Note
* that the tolerance must be smaller than 1/2 of any desired delta between
* data points. If the tolerance is less than zero an InvalidRangeException is
* thrown
*/
protected double tolerance = 0.0;
/**
* No-Argument constructor. Does nothing but construct the class instance.
*/
public Point2DToleranceComparator() {}
/**
* Constructor that sets the tolerance when created. Throws an
* InvalidRangeException if the tolerance is less than zero. Negative
* tolerance makes no sense.
*
* @param tolerance The distance two values can be apart and still considered
* equal
*/
public Point2DToleranceComparator(double tolerance) {
setTolerance(tolerance);
}
/**
* Tolerance indicates the distance two values can be apart, but still
* considered equal. This function returns the tolerance. Any tolerance less
* than about 1e-16 is about 1e-16 due to the numerical precision of floating
* point arithmetic.
*
* @param newTolerance The new tolerance value
* @exception InvalidRangeException Thrown if tolerance is negative
*/
@Override
public void setTolerance(double newTolerance) {
// TODO WTF!! this adapted from original where it doesn't make any sense
checkArgument(tolerance >= 0, "Tolerance must be larger or equal to 0");
checkState(tolerance == 0, "Tolerance is now fixed at 0.0 until we decide what to do" +
" with it. See trac ticket #341");
tolerance = newTolerance;
}
/**
* Tolerance indicates the distance two values can be apart, but still
* considered equal. This function returns the tolerance.
*
* @return The tolerance value
*/
@Override
public double getTolerance() {
return tolerance;
}
/**
* Returns 0 if the two Objects are equal, -1 if the first object is less than
* the second, or +1 if it's greater. This function throws a
* ClassCastException if the two values are not DataPoint2Ds. Only the X-Value
* is compared, the Y-Value is ignored. If the distance between the two
* X-Values are less than or equal to the tolerance, they are considered
* equal. <P>
*
* One use for this class is to sort a DiscretizedFunction by it's X-Values
* (independent variable) ascending, to prepare the function for plotting.
*
* @param o1 First DataPoint2D
* @param o2 Second DataPoint2D
* @return -1 if o1 < 02, 0 if o1 = o2, +1 if o1 > o2
*/
@Override
public int compare(Point2D o1, Point2D o2) {
double x1 = o1.getX();
double x2 = o2.getX();
if (Math.abs(x1 - x2) <= tolerance) {
return 0;
} else if (x1 > x2) {
return 1;
} else {
return -1;
}
}
}