001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
025 * Other names may be trademarks of their respective owners.]
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;
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;
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    }
318
319    /**
320     * Sets the 'log-scale' flag.
321     *
322     * @param logscale  the new value.
323     */
324    public void setLogscale(boolean logscale) {
325        this.logscale = logscale;
326    }
327
328    /**
329     * Sets the maximum Z value.
330     *
331     * @param newMaxZ  the new value.
332     */
333    public void setMaxZ(double newMaxZ) {
334        this.maxZ = newMaxZ;
335    }
336
337    /**
338     * Sets the minimum Z value.
339     *
340     * @param newMinZ  the new value.
341     */
342    public void setMinZ(double newMinZ) {
343        this.minZ = newMinZ;
344    }
345
346    /**
347     * Sets the palette name.
348     *
349     * @param paletteName  the name.
350     */
351    public void setPaletteName (String paletteName) {
352        this.paletteName = paletteName;
353    }
354
355    /**
356     * Sets the stepped flag.
357     *
358     * @param stepped  the flag.
359     */
360    public void setStepped (boolean stepped) {
361        this.stepped = stepped;
362    }
363
364    /**
365     * Sets the tick values.
366     *
367     * @param newTickValues  the tick values.
368     */
369    public void setTickValues(double[] newTickValues) {
370        this.tickValues = newTickValues;
371    }
372
373    /**
374     * Store ticks. Required when doing stepped axis
375     *
376     * @param ticks  the ticks.
377     */
378    public void setTickValues(java.util.List ticks) {
379        this.tickValues = new double[ticks.size()];
380        for (int i = 0; i < this.tickValues.length; i++) {
381            this.tickValues[i] = ((ValueTick) ticks.get(i)).getValue();
382        }
383    }
384
385    /**
386     * Tests an object for equality with this instance.
387     *
388     * @param o  the object to test.
389     *
390     * @return A boolean.
391     */
392    @Override
393    public boolean equals(Object o) {
394        if (this == o) {
395            return true;
396        }
397        if (!(o instanceof ColorPalette)) {
398            return false;
399        }
400
401        ColorPalette colorPalette = (ColorPalette) o;
402
403        if (this.inverse != colorPalette.inverse) {
404            return false;
405        }
406        if (this.logscale != colorPalette.logscale) {
407            return false;
408        }
409        if (this.maxZ != colorPalette.maxZ) {
410            return false;
411        }
412        if (this.minZ != colorPalette.minZ) {
413            return false;
414        }
415        if (this.stepped != colorPalette.stepped) {
416            return false;
417        }
418        if (!Arrays.equals(this.b, colorPalette.b)) {
419            return false;
420        }
421        if (!Arrays.equals(this.g, colorPalette.g)) {
422            return false;
423        }
424        if (this.paletteName != null
425                ? !this.paletteName.equals(colorPalette.paletteName)
426                : colorPalette.paletteName != null) {
427            return false;
428        }
429        if (!Arrays.equals(this.r, colorPalette.r)) {
430            return false;
431        }
432        if (!Arrays.equals(this.tickValues, colorPalette.tickValues)) {
433            return false;
434        }
435
436        return true;
437    }
438
439    /**
440     * Returns a hash code.
441     *
442     * @return A hash code.
443     */
444    @Override
445    public int hashCode() {
446        int result;
447        long temp;
448        temp = Double.doubleToLongBits(this.minZ);
449        result = (int) (temp ^ (temp >>> 32));
450        temp = Double.doubleToLongBits(this.maxZ);
451        result = 29 * result + (int) (temp ^ (temp >>> 32));
452        result = 29 * result + (this.logscale ? 1 : 0);
453        result = 29 * result + (this.inverse ? 1 : 0);
454        result = 29 * result
455                 + (this.paletteName != null ? this.paletteName.hashCode() : 0);
456        result = 29 * result + (this.stepped ? 1 : 0);
457        return result;
458    }
459
460    /**
461     * Returns a clone of the palette.
462     *
463     * @return A clone.
464     *
465     * @throws CloneNotSupportedException never.
466     */
467    @Override
468    public Object clone() throws CloneNotSupportedException {
469        ColorPalette clone = (ColorPalette) super.clone();
470        return clone;
471    }
472
473}