KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > data > Range


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this library; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
24  * in the United States and other countries.]
25  *
26  * ----------
27  * Range.java
28  * ----------
29  * (C) Copyright 2002-2005, by Object Refinery Limited and Contributors.
30  *
31  * Original Author: David Gilbert (for Object Refinery Limited);
32  * Contributor(s): Chuanhao Chiu;
33  * Bill Kelemen;
34  * Nicolas Brodu;
35  *
36  * $Id: Range.java,v 1.6 2005/05/19 10:34:07 mungady Exp $
37  *
38  * Changes (from 23-Jun-2001)
39  * --------------------------
40  * 22-Apr-2002 : Version 1, loosely based by code by Bill Kelemen (DG);
41  * 30-Apr-2002 : Added getLength() and getCentralValue() methods. Changed
42  * argument check in constructor (DG);
43  * 13-Jun-2002 : Added contains(double) method (DG);
44  * 22-Aug-2002 : Added fix to combine method where both ranges are null, thanks
45  * to Chuanhao Chiu for reporting and fixing this (DG);
46  * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG);
47  * 26-Mar-2003 : Implemented Serializable (DG);
48  * 14-Aug-2003 : Added equals() method (DG);
49  * 27-Aug-2003 : Added toString() method (BK);
50  * 11-Sep-2003 : Added Clone Support (NB);
51  * 23-Sep-2003 : Fixed Checkstyle issues (DG);
52  * 25-Sep-2003 : Oops, Range immutable, clone not necessary (NB);
53  * 05-May-2004 : Added constrain() and intersects() methods (DG);
54  * 18-May-2004 : Added expand() method (DG);
55  *
56  */

57
58 package org.jfree.data;
59
60 import java.io.Serializable JavaDoc;
61
62 /**
63  * Represents an immutable range of values.
64  */

65 public strictfp class Range implements Serializable JavaDoc {
66
67     /** For serialization. */
68     private static final long serialVersionUID = -906333695431863380L;
69     
70     /** The lower bound of the range. */
71     private double lower;
72
73     /** The upper bound of the range. */
74     private double upper;
75
76     /**
77      * Creates a new range.
78      *
79      * @param lower the lower bound (must be <= upper bound).
80      * @param upper the upper bound (must be >= lower bound).
81      */

82     public Range(double lower, double upper) {
83         if (lower > upper) {
84             String JavaDoc msg = "Range(double, double): require lower (" + lower
85                 + ") <= upper (" + upper + ").";
86             throw new IllegalArgumentException JavaDoc(msg);
87         }
88         this.lower = lower;
89         this.upper = upper;
90     }
91
92     /**
93      * Returns the lower bound for the range.
94      *
95      * @return The lower bound.
96      */

97     public double getLowerBound() {
98         return this.lower;
99     }
100
101     /**
102      * Returns the upper bound for the range.
103      *
104      * @return The upper bound.
105      */

106     public double getUpperBound() {
107         return this.upper;
108     }
109
110     /**
111      * Returns the length of the range.
112      *
113      * @return The length.
114      */

115     public double getLength() {
116         return this.upper - this.lower;
117     }
118
119     /**
120      * Returns the central value for the range.
121      *
122      * @return The central value.
123      */

124     public double getCentralValue() {
125         return this.lower / 2.0 + this.upper / 2.0;
126     }
127
128     /**
129      * Returns <code>true</code> if the range contains the specified value and
130      * <code>false</code> otherwise.
131      *
132      * @param value the value to lookup.
133      *
134      * @return <code>true</code> if the range contains the specified value.
135      */

136     public boolean contains(double value) {
137         return (value >= this.lower && value <= this.upper);
138     }
139     
140     /**
141      * Returns <code>true</code> if the range intersects with the specified
142      * range, and <code>false</code> otherwise.
143      *
144      * @param b0 the lower bound (should be <= b1).
145      * @param b1 the upper bound (should be >= b0).
146      *
147      * @return A boolean.
148      */

149     public boolean intersects(double b0, double b1) {
150         if (b0 <= this.lower) {
151             return (b1 > this.lower);
152         }
153         else {
154             return (b0 < this.upper && b1 >= b0);
155         }
156     }
157
158     /**
159      * Returns the value within the range that is closest to the specified
160      * value.
161      *
162      * @param value the value.
163      *
164      * @return The constrained value.
165      */

166     public double constrain(double value) {
167         double result = value;
168         if (!contains(value)) {
169             if (value > this.upper) {
170                 result = this.upper;
171             }
172             else if (value < this.lower) {
173                 result = this.lower;
174             }
175         }
176         return result;
177     }
178     
179     /**
180      * Creates a new range by combining two existing ranges.
181      * <P>
182      * Note that:
183      * <ul>
184      * <li>either range can be <code>null</code>, in which case the other
185      * range is returned;</li>
186      * <li>if both ranges are <code>null</code> the return value is
187      * <code>null</code>.</li>
188      * </ul>
189      *
190      * @param range1 the first range (<code>null</code> permitted).
191      * @param range2 the second range (<code>null</code> permitted).
192      *
193      * @return A new range (possibly <code>null</code>).
194      */

195     public static Range combine(Range range1, Range range2) {
196         if (range1 == null) {
197             return range2;
198         }
199         else {
200             if (range2 == null) {
201                 return range1;
202             }
203             else {
204                 double l = Math.min(
205                     range1.getLowerBound(), range2.getLowerBound()
206                 );
207                 double u = Math.max(
208                     range1.getUpperBound(), range2.getUpperBound()
209                 );
210                 return new Range(l, u);
211             }
212         }
213     }
214     
215     /**
216      * Creates a new range by adding margins to an existing range.
217      *
218      * @param range the range (<code>null</code> not permitted).
219      * @param lowerMargin the lower margin (expressed as a percentage of the
220      * range length).
221      * @param upperMargin the upper margin (expressed as a percentage of the
222      * range length).
223      *
224      * @return The expanded range.
225      */

226     public static Range expand(Range range,
227                                double lowerMargin, double upperMargin) {
228         if (range == null) {
229             throw new IllegalArgumentException JavaDoc("Null 'range' argument.");
230         }
231         double length = range.getLength();
232         double lower = length * lowerMargin;
233         double upper = length * upperMargin;
234         return new Range(
235             range.getLowerBound() - lower, range.getUpperBound() + upper
236         );
237     }
238
239     /**
240      * Shifts the range by the specified amount.
241      *
242      * @param base the base range.
243      * @param delta the shift amount.
244      *
245      * @return A new range.
246      */

247     public static Range shift(Range base, double delta) {
248         return shift(base, delta, false);
249     }
250     
251     /**
252      * Shifts the range by the specified amount.
253      *
254      * @param base the base range.
255      * @param delta the shift amount.
256      * @param allowZeroCrossing a flag that determines whether or not the
257      * bounds of the range are allowed to cross
258      * zero after adjustment.
259      *
260      * @return A new range.
261      */

262     public static Range shift(Range base, double delta,
263                               boolean allowZeroCrossing) {
264         if (allowZeroCrossing) {
265             return new Range(
266                 base.getLowerBound() + delta, base.getUpperBound() + delta
267             );
268         }
269         else {
270             return new Range(
271                 shiftWithNoZeroCrossing(base.getLowerBound(), delta),
272                 shiftWithNoZeroCrossing(base.getUpperBound(), delta)
273             );
274         }
275     }
276     
277     private static double shiftWithNoZeroCrossing(double value, double delta) {
278         if (value > 0.0) {
279             return Math.max(value + delta, 0.0);
280         }
281         else if (value < 0.0) {
282             return Math.min(value + delta, 0.0);
283         }
284         else {
285             return value + delta;
286         }
287     }
288     
289     /**
290      * Tests this object for equality with an arbitrary object.
291      *
292      * @param obj the object to test against (<code>null</code> permitted).
293      *
294      * @return A boolean.
295      */

296     public boolean equals(Object JavaDoc obj) {
297         if (!(obj instanceof Range)) {
298             return false;
299         }
300         Range range = (Range) obj;
301         if (!(this.lower == range.lower)) {
302             return false;
303         }
304         if (!(this.upper == range.upper)) {
305             return false;
306         }
307         return true;
308     }
309
310     /**
311      * Returns a hash code.
312      *
313      * @return A hash code.
314      */

315     public int hashCode() {
316         int result;
317         long temp;
318         temp = Double.doubleToLongBits(this.lower);
319         result = (int) (temp ^ (temp >>> 32));
320         temp = Double.doubleToLongBits(this.upper);
321         result = 29 * result + (int) (temp ^ (temp >>> 32));
322         return result;
323     }
324
325     /**
326      * Returns a string representation of this Range.
327      *
328      * @return A String "Range[lower,upper]" where lower=lower range and
329      * upper=upper range.
330      */

331     public String JavaDoc toString() {
332         return ("Range[" + this.lower + "," + this.upper + "]");
333     }
334
335 }
336
Popular Tags