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