001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2022, by David Gilbert. All rights reserved. 006 * 007 * https://github.com/jfree/orson-charts 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package org.jfree.chart3d.renderer; 034 035import java.awt.Color; 036 037import org.jfree.chart3d.data.Range; 038import org.jfree.chart3d.internal.Args; 039 040/** 041 * A color scale that returns all the colors of the rainbow. Instances of 042 * this class are immutable and serializable. 043 * <br><br> 044 * NOTE: This class is serializable, but the serialization format is subject 045 * to change in future releases and should not be relied upon for persisting 046 * instances of this class. 047 * 048 * @since 1.1 049 */ 050@SuppressWarnings("serial") 051public class RainbowScale extends AbstractColorScale implements ColorScale { 052 053 /** 054 * A range to include all hues. This can be used for the 055 * {@code hueSubrange} argument in the constructor. 056 */ 057 public static final Range ALL_HUES = new Range(0.0, 1.0); 058 059 /** 060 * A hue subrange that restricts colors to the blue to red range. This can 061 * be used for the {@code hueSubrange} argument in the constructor. 062 */ 063 public static final Range BLUE_TO_RED_RANGE = new Range(0.0, 0.6666); 064 065 /** Storage for the color samples. */ 066 private Color[] colors; 067 068 /** 069 * The subrange of hues (useful to restrict the scale to the range from 070 * blue to red, which is common in charts). 071 */ 072 private Range hueSubrange; 073 074 /** 075 * Creates a new rainbow scale for the specified value range, with 256 076 * color samples in the blue to red range. 077 * 078 * @param range the range ({@code null} not permitted). 079 */ 080 public RainbowScale(Range range) { 081 this(range, 256, BLUE_TO_RED_RANGE); 082 } 083 084 /** 085 * Creates a new rainbow scale for the specified value range, with the 086 * given number of samples and hues restricted to the specified range. 087 * 088 * @param range the range ({@code null} not permitted). 089 * @param samples the number of samples. 090 * @param hueSubrange the hue sub-range. 091 */ 092 public RainbowScale(Range range, int samples, Range hueSubrange) { 093 super(range); 094 Args.nullNotPermitted(hueSubrange, "hueSubrange"); 095 this.colors = new Color[samples]; 096 this.hueSubrange = hueSubrange; 097 } 098 099 /** 100 * Returns the number of samples used by this color scale. 101 * 102 * @return The number of samples. 103 */ 104 public int getSampleCount() { 105 return this.colors.length; 106 } 107 108 /** 109 * Returns the sub-range of hues used in this scale. 110 * 111 * @return The sub-range of hues. 112 */ 113 public Range getHueSubrange() { 114 return this.hueSubrange; 115 } 116 117 /** 118 * Converts a value to a color on the scale. 119 * 120 * @param value the value. 121 * 122 * @return A color (never {@code null}). 123 */ 124 @Override 125 public Color valueToColor(double value) { 126 Range r = getRange(); 127 if (value < r.getMin()) { 128 return valueToColor(r.getMin()); 129 } 130 if (value > r.getMax()) { 131 return valueToColor(r.getMax()); 132 } 133 double fraction = getRange().percent(value); 134 int i = (int) (fraction * (this.colors.length - 1)); 135 if (this.colors[i] == null) { 136 this.colors[i] = createRainbowColor(fraction); 137 } 138 return this.colors[i]; 139 } 140 141 /** 142 * Creates the rainbow color corresponding to the specified fraction along 143 * the scale range. 144 * 145 * @param fraction the fraction (0.0 to 1.0). 146 * 147 * @return The color. 148 */ 149 private Color createRainbowColor(double fraction) { 150 double inv = 1.0 - fraction; 151 double hue = this.hueSubrange.value(inv); 152 return Color.getHSBColor((float) hue, 1.0f, 1.0f); 153 } 154 155 /** 156 * Tests this color scale for equality with an arbitrary object. 157 * 158 * @param obj the object ({@code null} permitted). 159 * 160 * @return A boolean. 161 */ 162 @Override 163 public boolean equals(Object obj) { 164 if (obj == this) { 165 return true; 166 } 167 if (!(obj instanceof RainbowScale)) { 168 return false; 169 } 170 RainbowScale that = (RainbowScale) obj; 171 if (this.colors.length != that.colors.length) { 172 return false; 173 } 174 if (!this.hueSubrange.equals(that.hueSubrange)) { 175 return false; 176 } 177 return super.equals(obj); 178 } 179 180}