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
045package org.jfree.chart.plot;
046
047import java.awt.Color;
048import java.awt.Paint;
049import java.io.Serializable;
050import java.util.Arrays;
051
052import org.jfree.chart.axis.ValueTick;
053import 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 */
062public 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}