1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dishevelled.color.scheme.impl;
25
26 import java.awt.Color;
27
28 import java.util.ArrayList;
29 import java.util.List;
30
31 import org.dishevelled.color.scheme.ColorFactory;
32 import org.dishevelled.color.scheme.ColorScheme;
33
34
35
36
37
38
39 public final class ContinuousDivergentColorScheme
40 implements ColorScheme
41 {
42
43 private final String name;
44
45
46 private final List<Color> colors;
47
48
49 private final List<Double> anchors;
50
51
52 private double minimumValue;
53
54
55 private double maximumValue;
56
57
58 private double zeroValue;
59
60
61 private final ColorFactory colorFactory;
62
63
64
65
66
67
68
69
70
71
72
73
74 public ContinuousDivergentColorScheme(final String name,
75 final List<Color> colors,
76 final double minimumValue,
77 final double zeroValue,
78 final double maximumValue,
79 final ColorFactory colorFactory)
80 {
81 if (colors == null)
82 {
83 throw new IllegalArgumentException("colors must not be null");
84 }
85 if (colors.size() < 2)
86 {
87 throw new IllegalArgumentException("colors must contain at least two colors");
88 }
89 if (colorFactory == null)
90 {
91 throw new IllegalArgumentException("colorFactory must not be null");
92 }
93 this.name = name;
94 this.colors = new ArrayList<Color>(colors);
95
96 this.minimumValue = minimumValue;
97 this.zeroValue = zeroValue;
98 this.maximumValue = maximumValue;
99 this.colorFactory = colorFactory;
100
101 anchors = new ArrayList<Double>(colors.size() - 1);
102 recalculateAnchors();
103 }
104
105
106
107
108
109 private void recalculateAnchors()
110 {
111 if (!anchors.isEmpty())
112 {
113 anchors.clear();
114 }
115
116
117 double z = zeroValue;
118 double mn = minimumValue;
119 double mx = maximumValue;
120 double x = (z - mn);
121 double y = (mx - z);
122 int c = colors.size();
123 int d = (c / 2);
124
125 if ((c % 2) == 0)
126 {
127 anchors.add(Math.min(mn, z));
128 for (int i = 1; i < d; i++)
129 {
130 anchors.add((2 * i * x) / (c - 1));
131 }
132 for (int i = d + 1; i < c; i++)
133 {
134 anchors.add(((2 * (i - d) - 1) * y) / (c - 1) + z);
135 }
136 anchors.add(Math.max(mx, z));
137 }
138 else
139 {
140 anchors.add(Math.min(mn, z));
141 for (int i = 1; i < d; i++)
142 {
143 anchors.add((2 * i * x) / (c - 1));
144 }
145 anchors.add(z);
146 for (int i = d + 1; i < (c - 1); i++)
147 {
148 anchors.add(((2 * (i - d) - 1) * y) / (c - 1) + z);
149 }
150 anchors.add(Math.max(mx, z));
151 }
152 }
153
154
155
156
157
158
159 public String getName()
160 {
161 return name;
162 }
163
164 @Override
165 public double getMinimumValue()
166 {
167 return minimumValue;
168 }
169
170 @Override
171 public void setMinimumValue(final double minimumValue)
172 {
173 this.minimumValue = minimumValue;
174 recalculateAnchors();
175 }
176
177 @Override
178 public double getMaximumValue()
179 {
180 return maximumValue;
181 }
182
183 @Override
184 public void setMaximumValue(final double maximumValue)
185 {
186 this.maximumValue = maximumValue;
187 recalculateAnchors();
188 }
189
190 @Override
191 public double getZeroValue()
192 {
193 return zeroValue;
194 }
195
196 @Override
197 public void setZeroValue(final double zeroValue)
198 {
199 this.zeroValue = zeroValue;
200 recalculateAnchors();
201 }
202
203 @Override
204 public ColorFactory getColorFactory()
205 {
206 return colorFactory;
207 }
208
209 @Override
210 public void setColorFactory(final ColorFactory colorFactory)
211 {
212 throw new UnsupportedOperationException("setMaximumValue operation not supported by this color scheme");
213 }
214
215
216
217
218
219
220 private Color getMinimumColor()
221 {
222 return colors.get(0);
223 }
224
225
226
227
228
229
230 private double getMinimumAnchor()
231 {
232 return anchors.get(0);
233 }
234
235
236
237
238
239
240 private Color getMaximumColor()
241 {
242 return colors.get(colors.size() - 1);
243 }
244
245 @Override
246 public Color getColor(final double value)
247 {
248 if (value < getMinimumAnchor())
249 {
250 return getMinimumColor();
251 }
252 Color lowerColor = getMinimumColor();
253 double lowerAnchor = getMinimumAnchor();
254 for (int i = 0; i < anchors.size(); i++)
255 {
256 double upperAnchor = anchors.get(i);
257 if (value == upperAnchor)
258 {
259 return colors.get(i);
260 }
261 else if (value < upperAnchor)
262 {
263 Color upperColor = colors.get(i);
264 lowerAnchor = anchors.get(i - 1);
265 lowerColor = colors.get(i - 1);
266 int r = (int) interpolate(value, lowerAnchor, upperAnchor,
267 (double) lowerColor.getRed(), (double) upperColor.getRed());
268 int g = (int) interpolate(value, lowerAnchor, upperAnchor,
269 (double) lowerColor.getGreen(), (double) upperColor.getGreen());
270 int b = (int) interpolate(value, lowerAnchor, upperAnchor,
271 (double) lowerColor.getBlue(), (double) upperColor.getBlue());
272 int a = (int) interpolate(value, lowerAnchor, upperAnchor,
273 (double) lowerColor.getAlpha(), (double) upperColor.getAlpha());
274 return colorFactory.createColor(r, g, b, ((float) a) / 255.0f);
275 }
276 }
277 return getMaximumColor();
278 }
279
280
281
282
283
284
285
286
287
288
289
290 private static double interpolate(final double value,
291 final double sourceMinimum,
292 final double sourceMaximum,
293 final double targetMinimum,
294 final double targetMaximum)
295 {
296 return targetMinimum + (targetMaximum - targetMinimum)
297 * ((value - sourceMinimum) / (sourceMaximum - sourceMinimum));
298 }
299 }