001// License: GPL. For details, see LICENSE file. 002package 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 */ 009public class Range { 010 private final double lower; 011 private final double upper; 012 013 public static final Range ZERO_TO_INFINITY = new Range(0.0, Double.POSITIVE_INFINITY); 014 015 public Range(double lower, double upper) { 016 if (lower < 0 || lower >= upper) 017 throw new IllegalArgumentException(); 018 this.lower = lower; 019 this.upper = upper; 020 } 021 022 public boolean contains(double x) { 023 return lower < x && x <= upper; 024 } 025 026 /** 027 * provides the intersection of 2 overlapping ranges 028 */ 029 public static Range cut(Range a, Range b) { 030 if (b.lower >= a.upper || b.upper <= a.lower) 031 throw new IllegalArgumentException(); 032 return new Range(Math.max(a.lower, b.lower), Math.min(a.upper, b.upper)); 033 } 034 035 /** 036 * under the premise, that x is within this range, 037 * and not within the other range, it shrinks this range in a way 038 * to exclude the other range, but still contain x. 039 * 040 * x | 041 * 042 * this (------------------------------] 043 * 044 * other (-------] or 045 * (-----------------] 046 * 047 * result (----------------] 048 */ 049 public Range reduceAround(double x, Range other) { 050 if (!contains(x)) 051 throw new IllegalArgumentException(); 052 if (other.contains(x)) 053 throw new IllegalArgumentException(); 054 055 if (x < other.lower && other.lower < upper) 056 return new Range(lower, other.lower); 057 058 if (this.lower < other.upper && other.upper < x) 059 return new Range(other.upper, this.upper); 060 061 return this; 062 } 063 064 public double getLower() { 065 return lower; 066 } 067 068 public double getUpper() { 069 return upper; 070 } 071 072 @Override 073 public String toString() { 074 return String.format("|s%s-%s", lower, upper); 075 } 076 077 @Override 078 public boolean equals(Object o) { 079 if (this == o) return true; 080 if (o == null || getClass() != o.getClass()) return false; 081 082 Range range = (Range) o; 083 084 if (Double.compare(range.lower, lower) != 0) return false; 085 if (Double.compare(range.upper, upper) != 0) return false; 086 087 return true; 088 } 089 090 @Override 091 public int hashCode() { 092 int result; 093 long temp; 094 temp = Double.doubleToLongBits(lower); 095 result = (int) (temp ^ (temp >>> 32)); 096 temp = Double.doubleToLongBits(upper); 097 result = 31 * result + (int) (temp ^ (temp >>> 32)); 098 return result; 099 } 100}