package rasj; import java.lang.*; import java.util.*; /* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . */ /** *********************************************************** *
 *
 * PURPOSE:
 * The class represents an interval with lower and upper bound.
 * Operations on the interval are defined according to the
 * ODMG-93 standard.
 * The operations union, difference, and intersection are
 * defined according to the following table:
 *
 *    | ...  fixed bound
 *    -* ...  open bound
 *
 * class   orientation       union    difference  intersection
 * -----------------------------------------------------------
 *   1     |-a-| |-b-|       error    a           error
 *
 *   2     |-a-|             [a1,b2]  [a1,b1]     [b1,a2]
 *   2        |-b-|
 *
 *   3     |--a--|           a        error       b
 *   3      |-b-|
 *
 *   4     |-b-|             [b1,a2]  [b2,a2]     [a1,b2]
 *   4        |-a-|
 *
 *   5     |--b--|           b        error       a
 *   5      |-a-|
 *
 *   6     |-b-| |-a-|       error    a           error
 *
 *   7     |-a-|-b-|         [a1,b2]  a           [a2,a2]
 *
 *   8     |-b-|-a-|         [b1,a2]  a           [b2,b2]
 *
 *   9     |--a--|           a        [a1,b1]     b
 *   9       |-b-|
 *
 *  10     |--a--|           a        [b2,a2]     b
 *  10     |-b-|
 *
 *  11     |-a-|             a        error       a
 *  11     |-b-|
 *
 *  12     |--b--|           b        error       a
 *  12     |-a-|
 *
 *  13     |--b--|           b        error       a
 *  13       |-a-|
 *
 *  -----------------------------------------------------
 *
 *  14     |--a--*           a        error       b
 *  14      |-b-|
 *
 *  15     |--a--*           a        [b2,a2]     b
 *  15     |-b-|
 *
 *  16     |-b-| |-a-*       error    a           error
 *
 *  17     |-b-|-a-*         [b1,a2]  a           [b2,b2]
 *
 *  18      |--a--*          [b1,a2]  [b2,a2]     [a1,b2]
 *  18     |-b-|
 *
 *  -----------------------------------------------------
 *
 *  19     *--a--|           a        error       b
 *  19      |-b-|
 *
 *  20     *--a--|           a        [a1,b1]     b
 *  20       |-b-|
 *
 *  21     *-a-| |-b-|       error    a           error
 *
 *  22     *-a-|-b-|         [a1,b2]  a           [a2,a2]
 *
 *  23     *--a--|           [a1,b2]  [a1,b1]     [b1,a2]
 *  23        |-b-|
 *
 *  -----------------------------------------------------
 *
 *  24     |--b--*           b        error       a
 *  24      |-a-|
 *
 *  25     |--b--*           b        error       a
 *  25     |-a-|
 *
 *  26     |-a-| |-b-*       error    a           error
 *
 *  27     |-a-|-b-*         [a1,b2]  a           [a2,a2]
 *
 *  28      |--b--*          [a1,b2]  [a1,b1]     [b1,a2]
 *  28     |-a-|
 *
 *  -----------------------------------------------------
 *
 *  29     *--b--|           b        error       a
 *  29      |-a-|
 *
 *  30     *--b--|           b        error       a
 *  30       |-a-|
 *
 *  31     *-b-| |-a-|       error    a           error
 *
 *  32     *-b-|-a-|         [b1,a2]  a           [b2,b2]
 *
 *  33     *--b--|           [b1,a2]  [b2,a2]     [a1,b2]
 *  33        |-a-|
 *
 *  -----------------------------------------------------
 *
 *  34     *-a-| |-b-*       error    a           error
 *
 *  35     *-a-|-b-*         [a1,b2]  a           [a2,a2]
 *
 *  36     *-a-|             [a1,b2]  [a1,b1]     [b1,a2]
 *  36        |-b-*
 *
 *  -----------------------------------------------------
 *
 *  37     *-b-| |-a-*       error    a           error
 *
 *  38     *-b-|-a-*         [b1,a2]  a           [b2,b2]
 *
 *  39     *-b-|             [b1,a2]  [a1,b1]     [a1,b2]
 *  39        |-a-*
 *
 *  -----------------------------------------------------
 *
 *  40     *-a-|             b        error       a
 *  40      *-b-|
 *
 *  41     *-a-|             a        error       a
 *  41     *-b-|
 *
 *  42     *-b-|             a        [b2,a2]     b
 *  42      *-a-|
 *
 *  -----------------------------------------------------
 *
 *  43     |-a-*             a        [a1,b1]     b
 *  43      |-b-*
 *
 *  44     |-a-*             a        error       a
 *  44     |-b-*
 *
 *  45     |-b-*             b        error       a
 *  45      |-a-*
 *
 *  -----------------------------------------------------
 *  46     *-a-* |-b-|       a        error       b
 *
 *  47     *-b-* |-a-|       b        error       a
 *
 *  48     *-a-*             a        [b2,a2]     b
 *  48      *-b-|
 *
 *  49     *-a-*             a        [a1,b1]     b
 *  49      |-b-*
 *
 *  50     *-b-*             b        error       a
 *  50      *-a-|
 *
 *  51     *-b-*             b        error       a
 *  51      |-a-*
 *
 *  52     *-a-*             a        error       a
 *  52     *-b-*
 *
 * Attention: The difference operation has to be reconsidered in future
 * concerning a discrete interpretation of the intervals.
 *
 * The closure operation defines an interval which is the smallest
 * interval containing the two operands.
 * The method intersectsWith() returns 0 in the error cases of the
 * intersection operation and 1 otherwise.
 *
 * @version $Revision: 1.7 $
 *
 *
 *
 *
 * COMMENTS:
 *
 * 
*********************************************************** */ public class RasSInterval { static final String rcsid = "@(#)Package rasj, class RasSInterval: $Header: /home/rasdev/CVS-repository/rasdaman/java/rasj/RasSInterval.java,v 1.7 2003/12/10 21:04:23 rasdev Exp $"; /**Attributes storing the bounds:*/ long lowerBound; long upperBound; /**Attributes specifying wheter the lower/upper bound is fixed or not:*/ boolean lowFixed; boolean highFixed; /** * The default constructor creates an interval with open bounds. **/ public RasSInterval() { lowerBound = 0; upperBound = 0; lowFixed = false; highFixed = false; } /** * Copy constructor. * @param sint SInterval to be copied **/ public RasSInterval(RasSInterval sint) { lowerBound = sint.lowerBound; upperBound = sint.upperBound; lowFixed = sint.lowFixed; highFixed = sint.highFixed; } /** * Constructor taking a string representation of the SInterval (for example "*:200"). * @param stringRep the string representation of the SInterval **/ public RasSInterval(String stringRep) throws RasResultIsNoIntervalException { lowerBound = 0; upperBound = 0; lowFixed = false; highFixed = false; /**for parsing the string*/ StringTokenizer strTok = new StringTokenizer(stringRep.trim(), ":"); String strCurTok = strTok.nextToken(); if(strCurTok.equals("*")) { setLow('*'); } else { setLow(Long.parseLong(strCurTok.trim())); } strCurTok = strTok.nextToken(); if(strCurTok.equals("*")) { setHigh('*'); } else { setHigh(Long.parseLong(strCurTok.trim())); } } /** * Constructor for an SInterval with fixed bounds. * @param low the lower bound * @param high the upper bound **/ public RasSInterval(long low, long high) throws RasResultIsNoIntervalException { lowerBound = low; upperBound = high; lowFixed = true; highFixed = true; if(low > high) throw new RasResultIsNoIntervalException(); } /** * Constructor for an SInterval with an open lower bound. * @param c arbitrary character, usually '*'. The value of this parameter is * meaningless, it's only needed in order to provide a constructor similar to * the one for fixed bounds. * @param high the upper bound **/ public RasSInterval(char c, long high) { lowerBound = 0; upperBound = high; lowFixed = false; highFixed = true; } /** * Constructor for an SInterval with an open upper bound. * @param c arbitrary character, usually '*'. The value of this parameter is * meaningless, it's only needed in order to provide a constructor similar to * the one for fixed bounds. * @param low the lower bound **/ public RasSInterval(long low, char c) { lowerBound = low; upperBound = 0; lowFixed = true; highFixed = false; } /** * Constructor for an SInterval with an open bounds. For both parameters, * arbitrary characters (usually '*') can be specified. The values of these parameters are * meaningless, they are only needed in order to provide a constructor similar to * the one for fixed bounds. * @param c1 arbitrary character * @param c2 arbitrary character **/ public RasSInterval(char c1, char c2) { lowerBound = 0; upperBound = 0; lowFixed = false; highFixed = false; } /** * Method for testing equality of two SIntervals. Two SIntervals are equal * if they have the same lower and upper bounds. * @param interval the SInterval that is compared to this SInterval * @return true if the two SIntervals are equal **/ public boolean equals(final RasSInterval interval) { boolean returnValue = true; if(lowFixed) returnValue &= interval.lowFixed && lowerBound == interval.lowerBound; else returnValue &= !interval.lowFixed; if(highFixed) returnValue &= interval.highFixed && upperBound == interval.upperBound; else returnValue &= !interval.highFixed; return returnValue; } /** * Method for testing inequality of two SIntervals. Two SIntervals are inequal * if they have different lower or upper bounds. * @param interval the SInterval that is compared to this SInterval * @return true if the two SIntervals are not equal **/ public boolean notEquals(final RasSInterval interval) { return !equals(interval); } // Read/Write methods: /** * Gets the lower bound of the interval. * @return the lower bound **/ public long low() { return lowerBound; } /** * Gets the upper bound of the interval. * @return the upper bound **/ public long high() { return upperBound; } /** * Checks if the lower bound is fix. * @return true if the lower bound is fix, false otherwise **/ public boolean isLowFixed() { return lowFixed; } /** * Checks if the upper bound is fix. * @return true if the lower bound is fix, false otherwise **/ public boolean isHighFixed() { return highFixed; } /** * Sets the lower bound to a fixed value. * @param low the new lower bound **/ public void setLow(long low) throws RasResultIsNoIntervalException { if(highFixed && low > upperBound) throw new RasResultIsNoIntervalException(); lowerBound = low; lowFixed = true; } /** * Sets the upper bound to a fixed value. * @param high the new upper bound **/ public void setHigh(long high) throws RasResultIsNoIntervalException { if(lowFixed && high < lowerBound) throw new RasResultIsNoIntervalException(); upperBound = high; highFixed = true; } /** * Sets the lower bound open. * @param c arbitrary character (usually '*') **/ public void setLow(char c) { lowerBound = 0; lowFixed = false; } /** * Sets the upper bound open. * @param c arbitrary character (usually '*') **/ public void setHigh(char c) { upperBound = 0; highFixed = false; } /** * Sets both bounds to a fixed value. * @param low the new lower bound * @param high the new upper bound **/ public void setInterval(long low, long high) throws RasResultIsNoIntervalException { if(low > high) throw new RasResultIsNoIntervalException(); lowerBound = low; upperBound = high; lowFixed = true; highFixed = true; } /** * Sets the lower bound open and the upper bound to a fixed value. * @param c arbitrary character (usually '*') * @param high the new upper bound **/ public void setInterval(char c, long high) { lowerBound = 0; upperBound = high; lowFixed = false; highFixed = true; } /** * Sets the upper bound open and the lower bound to a fixed value. * @param c arbitrary character (usually '*') * @param low the new lower bound **/ public void setInterval(long low, char c) { lowerBound = low; upperBound = 0; lowFixed = true; highFixed = false; } /** * Sets both bounds open. * @param c1 arbitrary character (usually '*') * @param c2 arbitrary character (usually '*') **/ public void setInterval(char c1, char c2) { lowerBound = 0; upperBound = 0; lowFixed = false; highFixed = false; } /** * Determines if the current interval intersects with the given one. * @param interval the interval to be compared * @return * * * *
-1 if the intervals do not intersect
<classNo> if the intervals do intersect, where <classNo> is one of the classes specified in the description for class {@link RasSInterval RasSInterval}.
**/ public int intersectsWith(RasSInterval interval) { int classnr = classify(this, interval); if(classnr != 1 && classnr != 6 && classnr != 16 && classnr != 21 && classnr != 26 && classnr != 31 && classnr != 34 && classnr != 37) { return classnr; } else { return -1; } } //Methods/Operators for the union operation: /** * Calculates the union of two SIntervals. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createUnion(RasSInterval) createUnion} instead.

* @param interval1 the first SInterval * @param interval2 the second SInterval * @return the current SInterval (representing the union of interval1 and interval2) **/ public RasSInterval unionOf(RasSInterval interval1, RasSInterval interval2) throws RasResultIsNoIntervalException { copySInterval(calcUnion(interval1, interval2),this); return this; } /** * Calculates the union of the current SIntervall with another one. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createUnion(RasSInterval) createUnion} instead.

* @param interval the SInterval to be used for the union * @return the current SInterval (after the union with interval) **/ public RasSInterval unionWith(RasSInterval interval) throws RasResultIsNoIntervalException { copySInterval(calcUnion(this, interval),this); return this; } /** * @deprecated This methdod provides just another name for the * unionWith method and might not be supported in future versions. Please * use {@link #unionWith(RasSInterval) unionWith} instead. * @param interval the SInterval to be unioned with this SInterval * @return the union of this SInterval and interval **/ public RasSInterval addToSelf(RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval retInterval = new RasSInterval(); retInterval = calcUnion(interval, this); return retInterval; } /** * Returns a new SInterval calculated from a union of the current SInterval * and the given one. * @param mint the SInterval to be unioned with this SInterval * @return the union of this SInterval and interval **/ public RasSInterval createUnion(RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval result = calcUnion(interval, this); return result; } /** * @deprecated This methdod provides just another name for the * createUnion method and might not be supported in future versions. Please * use {@link #createUnion(RasSInterval) createUnion} instead. * @param interval the SInterval to be unioned with this SInterval * @return the union of this SInterval and interval **/ public RasSInterval add(RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval result; result = calcUnion(interval, this); return result; } // Methods/Operators for the difference operation: /** * Calculates the difference of two SIntervals. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createDifference(RasSInterval) createDifference} instead.

* @param interval1 the first SInterval * @param interval2 the second SInterval * @return the current SInterval (representing the difference of interval1 and interval2) **/ public RasSInterval differenceOf(RasSInterval interval1, RasSInterval interval2) throws RasResultIsNoIntervalException { copySInterval(calcDifference(interval1, interval2),this); return this; } /** * Calculates the difference of the current SInterval and the given one. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createDifference(RasSInterval) createDifference} instead.

* @param interval the SInterval used for building the difference * @return the current SInterval (representing the difference of this SInterval and interval) **/ public RasSInterval differenceWith(RasSInterval interval) throws RasResultIsNoIntervalException { copySInterval(calcDifference(interval, this), this); return this; } /** * @deprecated This methdod provides just another name for the * differenceWith method and might not be supported in future versions. Please * use {@link #differenceWith(RasSInterval) differenceWith} instead. * @param interval the SInterval used for building the difference * @return the current SInterval (representing the difference of this SInterval and interval) **/ public RasSInterval diffFromSelf(RasSInterval interval) throws RasResultIsNoIntervalException { return differenceWith(interval); } /** * Returns a new SInterval calculated from a difference of the current SInterval * and the given one. * @param interval the SInterval used for calculating the difference with the current SInterval * @return the difference of this SInterval and interval **/ public RasSInterval createDifference(RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval result = calcDifference(interval, this); return result; } /** * @deprecated This methdod provides just another name for the * createDifference method and might not be supported in future versions. Please * use {@link #createDifference(RasSInterval) createDifference} instead. * @param interval the SInterval used for calculating the difference with the current SInterval * @return the difference of this SInterval and interval **/ public RasSInterval diff(RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval result = calcDifference(interval, this); return result; } // Methods/Operators for the intersection operation: /** * This method calculates the intersection of two SIntervals. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createIntersection(RasSInterval) createIntersection} instead.

* @param interval1 the first SInterval * @param interval2 the second SInterval * @return the current SInterval (representing the intersection of interval1 and interval2) **/ public RasSInterval intersectionOf(final RasSInterval interval1, final RasSInterval interval2) throws RasResultIsNoIntervalException { copySInterval(calcIntersection(interval1, interval2),this); return this; } /** * Calculates the intersection of the current SInterval and the given one. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createIntersection(RasSInterval) createIntersection} instead.

* @param interval the SInterval used for building the intersection * @return the current SInterval (representing the intersection of this SInterval and interval) **/ public RasSInterval intersectionWith(final RasSInterval interval) throws RasResultIsNoIntervalException { copySInterval(calcIntersection(interval, this),this); return this; } /** * @deprecated This methdod provides just another name for the * intersectionWith method and might not be supported in future versions. Please * use {@link #intersectionWith(RasSInterval) intersectionWith} instead. * @param interval the SInterval used for building the intersection * @return the intersection of this SInterval and interval **/ public RasSInterval multWithSelf(final RasSInterval interval) throws RasResultIsNoIntervalException { return intersectionWith(interval); } /** * Returns a new SInterval calculated from the intersection of the current SInterval * and the given one. * @param interval the SInterval used for calculating the intersection with the current SInterval * @return the intersection of this SInterval and interval **/ public RasSInterval createIntersection(final RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval result = calcIntersection(interval, this); return result; } /** * @deprecated This methdod provides just another name for the * createIntersection method and might not be supported in future versions. Please * use {@link #createIntersection(RasSInterval) createIntersection} instead. * @param interval the SInterval used for calculating the intersection with the current SInterval * @return the intersection of this SInterval and interval **/ public RasSInterval mult(final RasSInterval interval) throws RasResultIsNoIntervalException { return createIntersection(interval); } // Methods/Operators for the closure operation: /** * Calculates the closure of two SIntervals. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createClosure(RasSInterval) createClosure} instead.

* @param interval1 the first SInterval * @param interval2 the second SInterval * @return the current SInterval (representing the closure of interval1 and interval2) **/ public RasSInterval closureOf(final RasSInterval interval1, final RasSInterval interval2) throws RasResultIsNoIntervalException { copySInterval(calcClosure(interval1, interval2),this); return this; } /** * Calculates the closure of the current SInterval and the given one. *

Note that this operation modifies the current object. If you want to get a new SInterval, * use {@link #createClosure(RasSInterval) createClosure} instead.

* @param interval the SInterval used for building the closure * @return the current SInterval (representing the closure of this SInterval and interval) **/ public RasSInterval closureWith(final RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval retInterval = new RasSInterval(); retInterval = calcClosure(interval, this); return retInterval; } /** * Returns a new SInterval calculated from the closure of the current SInterval * and the given one. * @param interval the SInterval used for calculating the closure with the current SInterval * @return the closure of this SInterval and interval **/ public RasSInterval createClosure(final RasSInterval interval) throws RasResultIsNoIntervalException { RasSInterval result; result = calcClosure(interval, this); return result; } // Methods for internal use only: // calculate the size of the storage space occupied private long getStorageSize() { return (18); // 2 * (8 + 1) } // copy the values of source to target private void copySInterval(RasSInterval source, RasSInterval target) { target.lowerBound = source.lowerBound; target.upperBound = source.upperBound; target.highFixed = source.highFixed; target.lowFixed = source.lowFixed; } // Calculation methods for the operations: private RasSInterval calcUnion(final RasSInterval a, final RasSInterval b) throws RasResultIsNoIntervalException { RasSInterval result = new RasSInterval(); switch(classify(a, b)) { case 2: case 7: case 9: case 12: case 22: case 23: case 27: case 28: case 35: case 36: // result = [a1:b2] if(a.isLowFixed()) result.setLow(a.low()); else result.setLow('*'); if(b.isHighFixed()) result.setHigh(b.high()); else result.setHigh('*'); break; case 4: case 8: case 10: case 13: case 17: case 18: case 32: case 33: case 38: case 39: // result = [b1:a2] if(b.isLowFixed()) result.setLow(b.low()); else result.setLow('*'); if(a.isHighFixed()) result.setHigh(a.high()); else result.setHigh('*'); break; case 3: case 11: case 14: case 15: case 19: case 20: case 41: case 42: case 43: case 44: case 46: case 48: case 49: case 52: result = a; break; case 5: case 24: case 25: case 29: case 30: case 40: case 45: case 47: case 50: case 51: result = b; break; default: // case in { 1, 6, 16, 21, 26, 31, 34, 37 } throw new RasResultIsNoIntervalException(); } return result; } // private RasSInterval calcDifference(final RasSInterval a, final RasSInterval b) throws RasResultIsNoIntervalException { RasSInterval result = new RasSInterval(); switch(classify(a, b)) { case 2: case 9: case 20: case 23: case 28: case 36: case 39: case 43: case 49: // result = [a1:b1] if(a.isLowFixed()) result.setLow(a.low()); else result.setLow('*'); if(b.isLowFixed()) result.setHigh(b.low()); else result.setHigh('*'); break; case 1: case 6: case 7: case 8: case 16: case 17: case 21: case 22: case 26: case 27: case 31: case 32: case 34: case 35: case 37: case 38: result = a; break; case 4: case 10: case 15: case 18: case 33: case 42: case 48: // result = [b2:a2] if(b.isHighFixed()) result.setLow(b.high()); else result.setLow('*'); if(a.isHighFixed()) result.setHigh(a.high()); else result.setHigh('*'); break; default: // case in { 3, 5, 11, 12, 13, 14, 19, 24, 25, 29, 30, 40, 41, 44, 45, 46, 47, 50, 51, 52 } throw new RasResultIsNoIntervalException(); } return result; } // private RasSInterval calcIntersection(final RasSInterval a, final RasSInterval b) throws RasResultIsNoIntervalException { RasSInterval result = new RasSInterval(); switch(classify(a, b)) { case 4: case 18: case 33: case 39: // result = [a1:b2] if(a.isLowFixed()) result.setLow(a.low()); else result.setLow('*'); if(b.isHighFixed()) result.setHigh(b.high()); else result.setHigh('*'); break; case 2: case 23: case 28: case 36: // result = [b1:a2] if(b.isLowFixed()) result.setLow(b.low()); else result.setLow('*'); if(a.isHighFixed()) result.setHigh(a.high()); else result.setHigh('*'); break; case 5: case 11: case 12: case 13: case 24: case 25: case 29: case 30: case 40: case 41: case 44: case 45: case 47: case 50: case 51: case 52: result = a; break; case 3: case 9: case 10: case 14: case 15: case 19: case 20: case 42: case 43: case 46: case 48: case 49: result = b; break; case 7: case 22: case 27: case 35: // result = [a2:a2] if(a.isHighFixed()) result.setInterval(a.high(), a.high()); else result.setInterval('*', '*'); break; case 8: case 17: case 32: case 38: // result = [b2:b2] if(b.isHighFixed()) result.setInterval(b.high(), b.high()); else result.setInterval('*', '*'); break; default: // case in { 1, 6, 16, 21, 26, 31, 34, 37 } throw new RasResultIsNoIntervalException(); } return result; } private RasSInterval calcClosure(final RasSInterval a, final RasSInterval b) throws RasResultIsNoIntervalException { RasSInterval closure = new RasSInterval(); if(!a.isLowFixed() || !b.isLowFixed()) closure.setLow('*'); else closure.setLow(Math.min(a.low(), b.low())); if(!a.isHighFixed() || !b.isHighFixed()) closure.setHigh('*'); else closure.setHigh(Math.max(a.high(), b.high())); return closure; } // compute the class of the two operands /************************************************************* * Method name...: classify * * Arguments.....: Two intervals for the classification. * Return value..: The classification class number (1..52). * Description...: The method classifies the two intervals into * one of 13 classes according to their spatial * relationship. Based on the classification, the * result of the operations union, difference, * and intersection can be calculated as shown * in the table ************************************************************/ private int classify(final RasSInterval a, final RasSInterval b) { int classification = 0; if(a.isLowFixed() && a.isHighFixed() && b.isLowFixed() && b.isHighFixed()) { // classification 1..13 if(a.low() < b.low()) { if(a.high() < b.high()) { if(a.high() < b.low()) classification = 1; else if(a.high() == b.low()) classification = 7; else classification = 2; } else if(a.high() == b.high()) classification = 9; else classification = 3; } else if(a.low() == b.low()) { if(a.high() < b.high()) classification = 12; else if(a.high() == b.high()) classification = 11; else classification = 10; } else if(a.high() < b.high()) classification = 5; else if(a.high() == b.high()) classification = 13; else { if(a.low() < b.high()) classification = 4; else if(a.low() == b.high()) classification = 8; else classification = 6; } } else if(a.isLowFixed() && !a.isHighFixed() && b.isLowFixed() && b.isHighFixed()) { // classification 14..18 if(a.low() < b.low()) classification = 14; else if(a.low() == b.low()) classification = 15; else { if(b.high() < a.low()) classification = 16; else if(b.high() == a.low()) classification = 17; else classification = 18; } } else if(!a.isLowFixed() && a.isHighFixed() && b.isLowFixed() && b.isHighFixed()) { // classification 19..23 if(a.high() > b.high()) classification = 19; else if(a.high() == b.high()) classification = 20; else { if(a.high() < b.low()) classification = 21; else if(a.high() == b.low()) classification = 22; else classification = 23; } } else if(a.isLowFixed() && a.isHighFixed() && b.isLowFixed() && !b.isHighFixed()) { // classification 24..28 if(b.low() < a.low()) classification = 24; else if(b.low() == a.low()) classification = 25; else { if(a.high() < b.low()) classification = 26; else if(a.high() == b.low()) classification = 27; else classification = 28; } } else if(a.isLowFixed() && a.isHighFixed() && !b.isLowFixed() && b.isHighFixed()) { // classification 29..33 if(b.high() > a.high()) classification = 29; else if(b.high() == a.high()) classification = 30; else { if(b.high() < a.low()) classification = 31; else if(b.high() == a.low()) classification = 32; else classification = 33; } } else if(!a.isLowFixed() && a.isHighFixed() && b.isLowFixed() && !b.isHighFixed()) { // classification 34..36 if(a.high() < b.low()) classification = 34; else if(a.high() == b.low()) classification = 35; else classification = 36; } else if(a.isLowFixed() && !a.isHighFixed() && !b.isLowFixed() && b.isHighFixed()) { // classification 37..39 if(b.high() < a.low()) classification = 37; else if(b.high() == a.low()) classification = 38; else classification = 39; } else if(!a.isLowFixed() && a.isHighFixed() && !b.isLowFixed() && b.isHighFixed()) { // classification 40..42 if(a.high() < b.high()) classification = 40; else if(a.high() == b.high()) classification = 41; else classification = 42; } else if(a.isLowFixed() && !a.isHighFixed() && b.isLowFixed() && !b.isHighFixed()) { // classification 43..45 if(a.low() < b.low()) classification = 43; else if(a.low() == b.low()) classification = 44; else classification = 45; } else if(!a.isLowFixed() && !a.isHighFixed() && b.isLowFixed() && b.isHighFixed()) classification = 46; else if( a.isLowFixed() && a.isHighFixed() && !b.isLowFixed() && !b.isHighFixed()) classification = 47; else if(!a.isLowFixed() && !a.isHighFixed() && !b.isLowFixed() && b.isHighFixed()) classification = 48; else if(!a.isLowFixed() && !a.isHighFixed() && b.isLowFixed() && !b.isHighFixed()) classification = 49; else if(!a.isLowFixed() && a.isHighFixed() && !b.isLowFixed() && !b.isHighFixed()) classification = 50; else if( a.isLowFixed() && !a.isHighFixed() && !b.isLowFixed() && !b.isHighFixed()) classification = 51; else // !a.isLowFixed() && !a.isHighFixed() && !b.isLowFixed() && !b.isHighFixed() classification = 52; return classification; } /** gives back the string representation */ public String toString() { return (lowFixed ? Long.toString(lowerBound) : "*") + ":" + (highFixed ? Long.toString(upperBound) : "*"); } }