001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2005, 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-2005, 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.1 2005/11/24 16:11:49 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 * 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 054 /** 055 * Defines palette used in Contour Plots. 056 * 057 * @author David M. O'Donnell. 058 */ 059 public abstract class ColorPalette implements Cloneable, Serializable { 060 061 /** For serialization. */ 062 private static final long serialVersionUID = -9029901853079622051L; 063 064 /** The min z-axis value. */ 065 protected double minZ = -1; 066 067 /** The max z-axis value. */ 068 protected double maxZ = -1; 069 070 /** Red components. */ 071 protected int[] r; 072 073 /** Green components. */ 074 protected int[] g; 075 076 /** Blue components. */ 077 protected int[] b; 078 079 /** Tick values are stored for use with stepped palette. */ 080 protected double[] tickValues = null; 081 082 /** Logscale? */ 083 protected boolean logscale = false; 084 085 /** Inverse palette (ie, min and max colors are reversed). */ 086 protected boolean inverse = false; 087 088 /** The palette name. */ 089 protected String paletteName = null; 090 091 /** Controls whether palette colors are stepped (not continuous). */ 092 protected boolean stepped = false; 093 094 /** Constant for converting loge to log10. */ 095 protected static final double log10 = Math.log(10); 096 097 /** 098 * Default contructor. 099 */ 100 public ColorPalette() { 101 super(); 102 } 103 104 /** 105 * Returns the color associated with a value. 106 * 107 * @param value the value. 108 * 109 * @return The color. 110 */ 111 public Paint getColor(double value) { 112 int izV = (int) (253 * (value - this.minZ) 113 / (this.maxZ - this.minZ)) + 2; 114 return new Color(this.r[izV], this.g[izV], this.b[izV]); 115 } 116 117 /** 118 * Returns a color. 119 * 120 * @param izV ??. 121 * 122 * @return The color. 123 */ 124 public Color getColor(int izV) { 125 return new Color(this.r[izV], this.g[izV], this.b[izV]); 126 } 127 128 /** 129 * Returns Color by mapping a given value to a linear palette. 130 * 131 * @param value the value. 132 * 133 * @return The color. 134 */ 135 public Color getColorLinear(double value) { 136 int izV = 0; 137 if (this.stepped) { 138 int index = Arrays.binarySearch(this.tickValues, value); 139 if (index < 0) { 140 index = -1 * index - 2; 141 } 142 143 if (index < 0) { // For the case were the first tick is greater 144 // than minZ 145 value = this.minZ; 146 } 147 else { 148 value = this.tickValues[index]; 149 } 150 } 151 izV = (int) (253 * (value - this.minZ) / (this.maxZ - this.minZ)) + 2; 152 izV = Math.min(izV, 255); 153 izV = Math.max(izV, 2); 154 return getColor(izV); 155 } 156 157 /** 158 * Returns Color by mapping a given value to a common log palette. 159 * 160 * @param value the value. 161 * 162 * @return The color. 163 */ 164 public Color getColorLog(double value) { 165 int izV = 0; 166 double minZtmp = this.minZ; 167 double maxZtmp = this.maxZ; 168 if (this.minZ <= 0.0) { 169 // negatives = true; 170 this.maxZ = maxZtmp - minZtmp + 1; 171 this.minZ = 1; 172 value = value - minZtmp + 1; 173 } 174 double minZlog = Math.log(this.minZ) / log10; 175 double maxZlog = Math.log(this.maxZ) / log10; 176 value = Math.log(value) / log10; 177 // value = Math.pow(10,value); 178 if (this.stepped) { 179 int numSteps = this.tickValues.length; 180 int steps = 256 / (numSteps - 1); 181 izV = steps * (int) (numSteps * (value - minZlog) 182 / (maxZlog - minZlog)) + 2; 183 // izV = steps*numSteps*(int)((value/minZ)/(maxZlog-minZlog)) + 2; 184 } 185 else { 186 izV = (int) (253 * (value - minZlog) / (maxZlog - minZlog)) + 2; 187 } 188 izV = Math.min(izV, 255); 189 izV = Math.max(izV, 2); 190 191 this.minZ = minZtmp; 192 this.maxZ = maxZtmp; 193 194 return getColor(izV); 195 } 196 197 /** 198 * Returns the maximum Z value. 199 * 200 * @return The value. 201 */ 202 public double getMaxZ() { 203 return this.maxZ; 204 } 205 206 /** 207 * Returns the minimum Z value. 208 * 209 * @return The value. 210 */ 211 public double getMinZ() { 212 return this.minZ; 213 } 214 215 /** 216 * Returns Paint by mapping a given value to a either a linear or common 217 * log palette as controlled by the value logscale. 218 * 219 * @param value the value. 220 * 221 * @return The paint. 222 */ 223 public Paint getPaint(double value) { 224 if (isLogscale()) { 225 return getColorLog(value); 226 } 227 else { 228 return getColorLinear(value); 229 } 230 } 231 232 /** 233 * Returns the palette name. 234 * 235 * @return The palette name. 236 */ 237 public String getPaletteName () { 238 return this.paletteName; 239 } 240 241 /** 242 * Returns the tick values. 243 * 244 * @return The tick values. 245 */ 246 public double[] getTickValues() { 247 return this.tickValues; 248 } 249 250 /** 251 * Called to initialize the palette's color indexes 252 */ 253 public abstract void initialize(); 254 255 /** 256 * Inverts Palette 257 */ 258 public void invertPalette() { 259 260 int[] red = new int[256]; 261 int[] green = new int[256]; 262 int[] blue = new int[256]; 263 for (int i = 0; i < 256; i++) { 264 red[i] = this.r[i]; 265 green[i] = this.g[i]; 266 blue[i] = this.b[i]; 267 } 268 269 for (int i = 2; i < 256; i++) { 270 this.r[i] = red[257 - i]; 271 this.g[i] = green[257 - i]; 272 this.b[i] = blue[257 - i]; 273 } 274 } 275 276 /** 277 * Returns the inverse flag. 278 * 279 * @return The flag. 280 */ 281 public boolean isInverse () { 282 return this.inverse; 283 } 284 285 /** 286 * Returns the log-scale flag. 287 * 288 * @return The flag. 289 */ 290 public boolean isLogscale() { 291 return this.logscale; 292 } 293 294 /** 295 * Returns the 'is-stepped' flag. 296 * 297 * @return The flag. 298 */ 299 public boolean isStepped () { 300 return this.stepped; 301 } 302 303 /** 304 * Sets the inverse flag. 305 * 306 * @param inverse the new value. 307 */ 308 public void setInverse (boolean inverse) { 309 this.inverse = inverse; 310 initialize(); 311 if (inverse) { 312 invertPalette(); 313 } 314 return; 315 } 316 317 /** 318 * Sets the 'log-scale' flag. 319 * 320 * @param logscale the new value. 321 */ 322 public void setLogscale(boolean logscale) { 323 this.logscale = logscale; 324 } 325 326 /** 327 * Sets the maximum Z value. 328 * 329 * @param newMaxZ the new value. 330 */ 331 public void setMaxZ(double newMaxZ) { 332 this.maxZ = newMaxZ; 333 } 334 335 /** 336 * Sets the minimum Z value. 337 * 338 * @param newMinZ the new value. 339 */ 340 public void setMinZ(double newMinZ) { 341 this.minZ = newMinZ; 342 } 343 344 /** 345 * Sets the palette name. 346 * 347 * @param paletteName the name. 348 */ 349 public void setPaletteName (String paletteName) { 350 //String oldValue = this.paletteName; 351 this.paletteName = paletteName; 352 return; 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 return; 363 } 364 365 /** 366 * Sets the tick values. 367 * 368 * @param newTickValues the tick values. 369 */ 370 public void setTickValues(double[] newTickValues) { 371 this.tickValues = newTickValues; 372 } 373 374 /** 375 * Store ticks. Required when doing stepped axis 376 * 377 * @param ticks the ticks. 378 */ 379 public void setTickValues(java.util.List ticks) { 380 this.tickValues = new double[ticks.size()]; 381 for (int i = 0; i < this.tickValues.length; i++) { 382 this.tickValues[i] = ((ValueTick) ticks.get(i)).getValue(); 383 } 384 } 385 386 /** 387 * Tests an object for equality with this instance. 388 * 389 * @param o the object to test. 390 * 391 * @return A boolean. 392 */ 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 public int hashCode() { 445 int result; 446 long temp; 447 temp = Double.doubleToLongBits(this.minZ); 448 result = (int) (temp ^ (temp >>> 32)); 449 temp = Double.doubleToLongBits(this.maxZ); 450 result = 29 * result + (int) (temp ^ (temp >>> 32)); 451 result = 29 * result + (this.logscale ? 1 : 0); 452 result = 29 * result + (this.inverse ? 1 : 0); 453 result = 29 * result 454 + (this.paletteName != null ? this.paletteName.hashCode() : 0); 455 result = 29 * result + (this.stepped ? 1 : 0); 456 return result; 457 } 458 459 /** 460 * Returns a clone of the palette. 461 * 462 * @return A clone. 463 * 464 * @throws CloneNotSupportedException never. 465 */ 466 public Object clone() throws CloneNotSupportedException { 467 468 ColorPalette clone = (ColorPalette) super.clone(); 469 return clone; 470 471 } 472 473 }