// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui.mappaint;
import java.util.Objects;
/**
* A scale interval of the form "lower < x <= upper" where 0 <= lower < upper.
* (upper can be Double.POSITIVE_INFINITY)
* immutable class
*/
public class Range {
private final double lower;
private final double upper;
public static final Range ZERO_TO_INFINITY = new Range(0.0, Double.POSITIVE_INFINITY);
/**
* Constructs a new {@code Range}.
* @param lower Lower bound. Must be positive or zero
* @param upper Upper bound
* @throws IllegalArgumentException if the range is invalid ({@code lower < 0 || lower >= upper})
*/
public Range(double lower, double upper) {
if (lower < 0 || lower >= upper)
throw new IllegalArgumentException("Invalid range: "+lower+'-'+upper);
this.lower = lower;
this.upper = upper;
}
public boolean contains(double x) {
return lower < x && x <= upper;
}
/**
* provides the intersection of 2 overlapping ranges
* @param a first range
* @param b second range
* @return intersection of {@code a} and {@code b}
*/
public static Range cut(Range a, Range b) {
if (b.lower >= a.upper || b.upper <= a.lower)
throw new IllegalArgumentException("Ranges do not overlap: "+a+" - "+b);
return new Range(Math.max(a.lower, b.lower), Math.min(a.upper, b.upper));
}
/**
* under the premise, that x is within this range,
* and not within the other range, it shrinks this range in a way
* to exclude the other range, but still contain x.
*
* x |
*
* this (------------------------------]
*
* other (-------] or
* (-----------------]
*
* result (----------------]
* @param x value
* @param other other range
* @return reduced range
*/
public Range reduceAround(double x, Range other) {
if (!contains(x))
throw new IllegalArgumentException(x+" is not inside "+this);
if (other.contains(x))
throw new IllegalArgumentException(x+" is inside "+other);
if (x < other.lower && other.lower < upper)
return new Range(lower, other.lower);
if (this.lower < other.upper && other.upper < x)
return new Range(other.upper, this.upper);
return this;
}
public double getLower() {
return lower;
}
public double getUpper() {
return upper;
}
@Override
public String toString() {
return String.format("|s%s-%s", lower, upper);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Range range = (Range) o;
return Double.compare(range.lower, lower) == 0 &&
Double.compare(range.upper, upper) == 0;
}
@Override
public int hashCode() {
return Objects.hash(lower, upper);
}
}