    001/* ===========================================================
    002 * JFreeChart : a free chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C) Copyright 2000-2011, 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 = 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}