001: package com.vividsolutions.jts.geom;
002:
003: import java.util.Comparator;
004:
005: /**
006: * Compares two {@link CoordinateSequence}s.
007: * For sequences of the same dimension, the ordering is lexicographic.
008: * Otherwise, lower dimensions are sorted before higher.
009: * The dimensions compared can be limited; if this is done
010: * ordinate dimensions above the limit will not be compared.
011: * <p>
012: * If different behaviour is required for comparing size, dimension, or
013: * coordinate values, any or all methods can be overridden.
014: *
015: */
016: public class CoordinateSequenceComparator implements Comparator {
017: /**
018: * Compare two <code>double</code>s, allowing for NaN values.
019: * NaN is treated as being less than any valid number.
020: *
021: * @param a a <code>double</code>
022: * @param b a <code>double</code>
023: * @return -1, 0, or 1 depending on whether a is less than, equal to or greater than b
024: */
025: public static int compare(double a, double b) {
026: if (a < b)
027: return -1;
028: if (a > b)
029: return 1;
030:
031: if (Double.isNaN(a)) {
032: if (Double.isNaN(b))
033: return 0;
034: return -1;
035: }
036:
037: if (Double.isNaN(b))
038: return 1;
039: return 0;
040: }
041:
042: /**
043: * The number of dimensions to test
044: */
045: protected int dimensionLimit;
046:
047: /**
048: * Creates a comparator which will test all dimensions.
049: */
050: public CoordinateSequenceComparator() {
051: dimensionLimit = Integer.MAX_VALUE;
052: }
053:
054: /**
055: * Creates a comparator which will test only the specified number of dimensions.
056: *
057: * @param dimensionLimit the number of dimensions to test
058: */
059: public CoordinateSequenceComparator(int dimensionLimit) {
060: this .dimensionLimit = dimensionLimit;
061: }
062:
063: /**
064: * Compares two {@link CoordinateSequence}s for relative order.
065: *
066: * @param o1 a {@link CoordinateSequence}
067: * @param o2 a {@link CoordinateSequence}
068: * @return -1, 0, or 1 depending on whether o1 is less than, equal to, or greater than o2
069: */
070: public int compare(Object o1, Object o2) {
071: CoordinateSequence s1 = (CoordinateSequence) o1;
072: CoordinateSequence s2 = (CoordinateSequence) o2;
073:
074: int size1 = s1.size();
075: int size2 = s2.size();
076:
077: int dim1 = s1.getDimension();
078: int dim2 = s2.getDimension();
079:
080: int minDim = dim1;
081: if (dim2 < minDim)
082: minDim = dim2;
083: boolean dimLimited = false;
084: if (dimensionLimit < minDim) {
085: minDim = dimensionLimit;
086: dimLimited = true;
087: }
088:
089: // lower dimension is less than higher
090: if (!dimLimited) {
091: if (dim1 < dim2)
092: return -1;
093: if (dim1 > dim2)
094: return 1;
095: }
096:
097: // lexicographic ordering of point sequences
098: int i = 0;
099: while (i < size1 && i < size2) {
100: int ptComp = compareCoordinate(s1, s2, i, minDim);
101: if (ptComp != 0)
102: return ptComp;
103: i++;
104: }
105: if (i < size1)
106: return 1;
107: if (i < size2)
108: return -1;
109:
110: return 0;
111: }
112:
113: /**
114: * Compares the same coordinate of two {@link CoordinateSequence}s
115: * along the given number of dimensions.
116: *
117: * @param s1 a {@link CoordinateSequence}
118: * @param s2 a {@link CoordinateSequence}
119: * @param i the index of the coordinate to test
120: * @param dimension the number of dimensiosn to test
121: * @return -1, 0, or 1 depending on whether s1[i] is less than, equal to, or greater than s2[i]
122: */
123: protected int compareCoordinate(CoordinateSequence s1,
124: CoordinateSequence s2, int i, int dimension) {
125: for (int d = 0; d < dimension; d++) {
126: double ord1 = s1.getOrdinate(i, d);
127: double ord2 = s2.getOrdinate(i, d);
128: int comp = compare(ord1, ord2);
129: if (comp != 0)
130: return comp;
131: }
132: return 0;
133: }
134: }
|