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    }