001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.mappaint;
003
004 /**
005 * An interval of the form "lower < x <= upper" where 0 <= lower < upper.
006 * (upper can be Double.POSITIVE_INFINITY)
007 * immutable class
008 */
009 public class Range {
010 private double lower;
011 private double upper;
012
013 public Range() {
014 this.lower = 0;
015 this.upper = Double.POSITIVE_INFINITY;
016 }
017
018 public Range(double lower, double upper) {
019 if (lower < 0 || lower >= upper)
020 throw new IllegalArgumentException();
021 this.lower = lower;
022 this.upper = upper;
023 }
024
025 public boolean contains(double x) {
026 return lower < x && x <= upper;
027 }
028
029 /**
030 * provides the intersection of 2 overlapping ranges
031 */
032 public static Range cut(Range a, Range b) {
033 if (b.lower >= a.upper || b.upper <= a.lower)
034 throw new IllegalArgumentException();
035 return new Range(Math.max(a.lower, b.lower), Math.min(a.upper, b.upper));
036 }
037
038 /**
039 * under the premise, that x is within this range,
040 * and not within the other range, it shrinks this range in a way
041 * to exclude the other range, but still contain x.
042 *
043 * x |
044 *
045 * this (------------------------------]
046 *
047 * other (-------] or
048 * (-----------------]
049 *
050 * result (----------------]
051 */
052 public Range reduceAround(double x, Range other) {
053 if (!contains(x))
054 throw new IllegalArgumentException();
055 if (other.contains(x))
056 throw new IllegalArgumentException();
057
058 if (x < other.lower && other.lower < upper)
059 return new Range(lower, other.lower);
060
061 if (this.lower < other.upper && other.upper < x)
062 return new Range(other.upper, this.upper);
063
064 return this;
065 }
066
067 public double getLower() {
068 return lower;
069 }
070
071 public double getUpper() {
072 return upper;
073 }
074
075 @Override
076 public String toString() {
077 return String.format("|s%s-%s", lower, upper);
078 }
079 }