001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
006     *
007     * Project Info:  http://www.jfree.org/jfreechart/index.html
008     *
009     * This library is free software; you can redistribute it and/or modify it
010     * under the terms of the GNU Lesser General Public License as published by
011     * the Free Software Foundation; either version 2.1 of the License, or
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022     * USA.
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025     * in the United States and other countries.]
026     *
027     * -----------------
028     * ColorPalette.java
029     * -----------------
030     * (C) Copyright 2002-2008, by David M. O'Donnell and Contributors.
031     *
032     * Original Author:  David M. O'Donnell;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *
035     * Changes
036     * -------
037     * 26-Nov-2002 : Version 1 contributed by David M. O'Donnell (DG);
038     * 26-Mar-2003 : Implemented Serializable (DG);
039     * 14-Aug-2003 : Implemented Cloneable (DG);
040     * ------------- JFREECHART 1.0.x ---------------------------------------------
041     * 31-Jan-2007 : Deprecated (DG);
042     *
043     */
044    
045    package org.jfree.chart.plot;
046    
047    import java.awt.Color;
048    import java.awt.Paint;
049    import java.io.Serializable;
050    import java.util.Arrays;
051    
052    import org.jfree.chart.axis.ValueTick;
053    import org.jfree.chart.renderer.xy.XYBlockRenderer;
054    
055    /**
056     * Defines palette used by {@link ContourPlot}.
057     *
058     * @deprecated This class is no longer supported (as of version 1.0.4).  If
059     *     you are creating contour plots, please try to use {@link XYPlot} and
060     *     {@link XYBlockRenderer}.
061     */
062    public abstract class ColorPalette implements Cloneable, Serializable {
063    
064        /** For serialization. */
065        private static final long serialVersionUID = -9029901853079622051L;
066    
067        /** The min z-axis value. */
068        protected double minZ = -1;
069    
070        /** The max z-axis value. */
071        protected double maxZ = -1;
072    
073        /** Red components. */
074        protected int[] r;
075    
076        /** Green components. */
077        protected int[] g;
078    
079        /** Blue components. */
080        protected int[] b;
081    
082        /** Tick values are stored for use with stepped palette. */
083        protected double[] tickValues = null;
084    
085        /** Logscale? */
086        protected boolean logscale = false;
087    
088        /** Inverse palette (ie, min and max colors are reversed). */
089        protected boolean inverse = false;
090    
091        /** The palette name. */
092        protected String paletteName = null;
093    
094        /** Controls whether palette colors are stepped (not continuous). */
095        protected boolean stepped = false;
096    
097        /** Constant for converting loge to log10. */
098        protected static final double log10 = Math.log(10);
099    
100        /**
101         * Default contructor.
102         */
103        public ColorPalette() {
104            super();
105        }
106    
107        /**
108         * Returns the color associated with a value.
109         *
110         * @param value  the value.
111         *
112         * @return The color.
113         */
114        public Paint getColor(double value) {
115            int izV = (int) (253 * (value - this.minZ)
116                        / (this.maxZ - this.minZ)) + 2;
117            return new Color(this.r[izV], this.g[izV], this.b[izV]);
118        }
119    
120        /**
121         * Returns a color.
122         *
123         * @param izV  the index into the palette (zero based).
124         *
125         * @return The color.
126         */
127        public Color getColor(int izV) {
128            return new Color(this.r[izV], this.g[izV], this.b[izV]);
129        }
130    
131        /**
132         * Returns Color by mapping a given value to a linear palette.
133         *
134         * @param value  the value.
135         *
136         * @return The color.
137         */
138        public Color getColorLinear(double value) {
139            int izV = 0;
140            if (this.stepped) {
141                int index = Arrays.binarySearch(this.tickValues, value);
142                if (index < 0) {
143                    index = -1 * index - 2;
144                }
145    
146                if (index < 0) { // For the case were the first tick is greater
147                                 // than minZ
148                    value = this.minZ;
149                }
150                else {
151                    value = this.tickValues[index];
152                }
153            }
154            izV = (int) (253 * (value - this.minZ) / (this.maxZ - this.minZ)) + 2;
155            izV = Math.min(izV, 255);
156            izV = Math.max(izV, 2);
157            return getColor(izV);
158        }
159    
160        /**
161         * Returns Color by mapping a given value to a common log palette.
162         *
163         * @param value  the value.
164         *
165         * @return The color.
166         */
167        public Color getColorLog(double value) {
168            int izV = 0;
169            double minZtmp = this.minZ;
170            double maxZtmp = this.maxZ;
171            if (this.minZ <= 0.0) {
172    //          negatives = true;
173                this.maxZ = maxZtmp - minZtmp + 1;
174                this.minZ = 1;
175                value = value - minZtmp + 1;
176            }
177            double minZlog = Math.log(this.minZ) / log10;
178            double maxZlog = Math.log(this.maxZ) / log10;
179            value = Math.log(value) / log10;
180            //  value = Math.pow(10,value);
181            if (this.stepped) {
182                int numSteps = this.tickValues.length;
183                int steps = 256 / (numSteps - 1);
184                izV = steps * (int) (numSteps * (value - minZlog)
185                        / (maxZlog - minZlog)) + 2;
186                //  izV = steps*numSteps*(int)((value/minZ)/(maxZlog-minZlog)) + 2;
187            }
188            else {
189                izV = (int) (253 * (value - minZlog) / (maxZlog - minZlog)) + 2;
190            }
191            izV = Math.min(izV, 255);
192            izV = Math.max(izV, 2);
193    
194            this.minZ = minZtmp;
195            this.maxZ = maxZtmp;
196    
197            return getColor(izV);
198        }
199    
200        /**
201         * Returns the maximum Z value.
202         *
203         * @return The value.
204         */
205        public double getMaxZ() {
206            return this.maxZ;
207        }
208    
209        /**
210         * Returns the minimum Z value.
211         *
212         * @return The value.
213         */
214        public double getMinZ() {
215            return this.minZ;
216        }
217    
218        /**
219         * Returns Paint by mapping a given value to a either a linear or common
220         * log palette as controlled by the value logscale.
221         *
222         * @param value  the value.
223         *
224         * @return The paint.
225         */
226        public Paint getPaint(double value) {
227            if (isLogscale()) {
228                return getColorLog(value);
229            }
230            else {
231                return getColorLinear(value);
232            }
233        }
234    
235        /**
236         * Returns the palette name.
237         *
238         * @return The palette name.
239         */
240        public String getPaletteName () {
241            return this.paletteName;
242        }
243    
244        /**
245         * Returns the tick values.
246         *
247         * @return The tick values.
248         */
249        public double[] getTickValues() {
250            return this.tickValues;
251        }
252    
253        /**
254         * Called to initialize the palette's color indexes
255         */
256        public abstract void initialize();
257    
258        /**
259         * Inverts Palette
260         */
261        public void invertPalette() {
262    
263            int[] red = new int[256];
264            int[] green = new int[256];
265            int[] blue = new int[256];
266            for (int i = 0; i < 256; i++) {
267                red[i] = this.r[i];
268                green[i] = this.g[i];
269                blue[i] = this.b[i];
270            }
271    
272            for (int i = 2; i < 256; i++) {
273                this.r[i] = red[257 - i];
274                this.g[i] = green[257 - i];
275                this.b[i] = blue[257 - i];
276            }
277        }
278    
279        /**
280         * Returns the inverse flag.
281         *
282         * @return The flag.
283         */
284        public boolean isInverse () {
285            return this.inverse;
286        }
287    
288        /**
289         * Returns the log-scale flag.
290         *
291         * @return The flag.
292         */
293        public boolean isLogscale() {
294            return this.logscale;
295        }
296    
297        /**
298         * Returns the 'is-stepped' flag.
299         *
300         * @return The flag.
301         */
302        public boolean isStepped () {
303            return this.stepped;
304        }
305    
306        /**
307         * Sets the inverse flag.
308         *
309         * @param inverse  the new value.
310         */
311        public void setInverse (boolean inverse) {
312            this.inverse = inverse;
313            initialize();
314            if (inverse) {
315                invertPalette();
316            }
317            return;
318        }
319    
320        /**
321         * Sets the 'log-scale' flag.
322         *
323         * @param logscale  the new value.
324         */
325        public void setLogscale(boolean logscale) {
326            this.logscale = logscale;
327        }
328    
329        /**
330         * Sets the maximum Z value.
331         *
332         * @param newMaxZ  the new value.
333         */
334        public void setMaxZ(double newMaxZ) {
335            this.maxZ = newMaxZ;
336        }
337    
338        /**
339         * Sets the minimum Z value.
340         *
341         * @param newMinZ  the new value.
342         */
343        public void setMinZ(double newMinZ) {
344            this.minZ = newMinZ;
345        }
346    
347        /**
348         * Sets the palette name.
349         *
350         * @param paletteName  the name.
351         */
352        public void setPaletteName (String paletteName) {
353            //String oldValue = this.paletteName;
354            this.paletteName = paletteName;
355            return;
356        }
357    
358        /**
359         * Sets the stepped flag.
360         *
361         * @param stepped  the flag.
362         */
363        public void setStepped (boolean stepped) {
364            this.stepped = stepped;
365            return;
366        }
367    
368        /**
369         * Sets the tick values.
370         *
371         * @param newTickValues  the tick values.
372         */
373        public void setTickValues(double[] newTickValues) {
374            this.tickValues = newTickValues;
375        }
376    
377        /**
378         * Store ticks. Required when doing stepped axis
379         *
380         * @param ticks  the ticks.
381         */
382        public void setTickValues(java.util.List ticks) {
383            this.tickValues = new double[ticks.size()];
384            for (int i = 0; i < this.tickValues.length; i++) {
385                this.tickValues[i] = ((ValueTick) ticks.get(i)).getValue();
386            }
387        }
388    
389        /**
390         * Tests an object for equality with this instance.
391         *
392         * @param o  the object to test.
393         *
394         * @return A boolean.
395         */
396        public boolean equals(Object o) {
397            if (this == o) {
398                return true;
399            }
400            if (!(o instanceof ColorPalette)) {
401                return false;
402            }
403    
404            ColorPalette colorPalette = (ColorPalette) o;
405    
406            if (this.inverse != colorPalette.inverse) {
407                return false;
408            }
409            if (this.logscale != colorPalette.logscale) {
410                return false;
411            }
412            if (this.maxZ != colorPalette.maxZ) {
413                return false;
414            }
415            if (this.minZ != colorPalette.minZ) {
416                return false;
417            }
418            if (this.stepped != colorPalette.stepped) {
419                return false;
420            }
421            if (!Arrays.equals(this.b, colorPalette.b)) {
422                return false;
423            }
424            if (!Arrays.equals(this.g, colorPalette.g)) {
425                return false;
426            }
427            if (this.paletteName != null
428                    ? !this.paletteName.equals(colorPalette.paletteName)
429                    : colorPalette.paletteName != null) {
430                return false;
431            }
432            if (!Arrays.equals(this.r, colorPalette.r)) {
433                return false;
434            }
435            if (!Arrays.equals(this.tickValues, colorPalette.tickValues)) {
436                return false;
437            }
438    
439            return true;
440        }
441    
442        /**
443         * Returns a hash code.
444         *
445         * @return A hash code.
446         */
447        public int hashCode() {
448            int result;
449            long temp;
450            temp = Double.doubleToLongBits(this.minZ);
451            result = (int) (temp ^ (temp >>> 32));
452            temp = Double.doubleToLongBits(this.maxZ);
453            result = 29 * result + (int) (temp ^ (temp >>> 32));
454            result = 29 * result + (this.logscale ? 1 : 0);
455            result = 29 * result + (this.inverse ? 1 : 0);
456            result = 29 * result
457                     + (this.paletteName != null ? this.paletteName.hashCode() : 0);
458            result = 29 * result + (this.stepped ? 1 : 0);
459            return result;
460        }
461    
462        /**
463         * Returns a clone of the palette.
464         *
465         * @return A clone.
466         *
467         * @throws CloneNotSupportedException never.
468         */
469        public Object clone() throws CloneNotSupportedException {
470    
471            ColorPalette clone = (ColorPalette) super.clone();
472            return clone;
473    
474        }
475    
476    }