comparison gnv-artifacts/src/main/java/de/intevation/gnv/raster/Palette.java @ 657:af3f56758f59

merged gnv-artifacts/0.5
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:13:53 +0200
parents c8089cd7d777
children 9a828e5a2390
comparison
equal deleted inserted replaced
590:5f5f273c8566 657:af3f56758f59
1 package de.intevation.gnv.raster;
2
3 import org.w3c.dom.Document;
4 import org.w3c.dom.Element;
5 import org.w3c.dom.NodeList;
6
7 import java.util.Arrays;
8
9 import java.awt.Color;
10
11 import org.apache.log4j.Logger;
12
13 import de.intevation.gnv.raster.Raster.ValueToIndex;
14
15 /**
16 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
17 */
18 public class Palette
19 implements ValueToIndex
20 {
21 private static Logger log = Logger.getLogger(Palette.class);
22
23 public static final class Entry
24 implements Comparable
25 {
26 private Entry left;
27 private Entry right;
28
29 private int index;
30
31 private int externalIndex;
32
33 private double from;
34 private double to;
35
36 private String description;
37
38 private Color color;
39
40 public Entry() {
41 }
42
43 public Entry(Entry other) {
44 index = other.index;
45 externalIndex = other.externalIndex;
46 from = other.from;
47 to = other.to;
48 description = other.description;
49 color = other.color;
50 }
51
52 public Entry(
53 int index,
54 int externalIndex,
55 double from,
56 double to,
57 Color color,
58 String description
59 ) {
60 this.index = index;
61 this.externalIndex = externalIndex;
62 this.from = from;
63 this.to = to;
64 this.color = color;
65 this.description = description;
66 }
67
68 public int compareTo(Object other) {
69 Entry e = (Entry)other;
70 if (from < e.from) return -1;
71 if (from > e.from) return +1;
72 return 0;
73 }
74
75 public double getFrom() {
76 return from;
77 }
78
79 public double getTo() {
80 return to;
81 }
82
83 public Color getColor() {
84 return color;
85 }
86
87 public int getExternalIndex() {
88 return externalIndex;
89 }
90
91 public Entry locateEntry(double value) {
92 Entry current = this;
93 while (current != null) {
94 boolean b = value >= current.from;
95 if (b && value <= current.to) {
96 return current;
97 }
98 current = b
99 ? current.right
100 : current.left;
101 }
102 return null;
103 }
104
105 public int locate(double value) {
106 Entry entry = locateEntry(value);
107 return entry != null
108 ? entry.index
109 : -1;
110 }
111
112 public Entry findByIndex(int index) {
113 Entry current = this;
114 while (current != null) {
115 if (current.index == index) {
116 break;
117 }
118 current = index < current.index
119 ? current.left
120 : current.right;
121 }
122 return current;
123 }
124
125 public String getDescription() {
126 return description;
127 }
128
129 public boolean isInfinity() {
130 return from == -Double.MAX_VALUE
131 || to == Double.MAX_VALUE;
132 }
133 } // class Entry
134
135 protected Entry [] entries;
136 protected Entry lookup;
137 protected Color [] rgbs;
138
139 private Entry buildLookup(Entry [] entries, int lo, int hi) {
140 if (lo > hi) {
141 return null;
142 }
143 int mid = (lo + hi)/2;
144 Entry entry = entries[mid];
145 entry.left = buildLookup(entries, lo, mid-1);
146 entry.right = buildLookup(entries, mid+1, hi);
147 return entry;
148 }
149
150 public Palette() {
151 }
152
153 public Palette(Document document) {
154
155 NodeList rangeNodes = document.getElementsByTagName("range");
156
157 entries = new Entry[rangeNodes.getLength()];
158 rgbs = new Color[entries.length];
159
160 for (int i = 0; i < entries.length; ++i) {
161 Element rangeElement = (Element)rangeNodes.item(i);
162 double from = doubleValue(rangeElement.getAttribute("from"));
163 double to = doubleValue(rangeElement.getAttribute("to"));
164 int extIndex = intValue(rangeElement.getAttribute("index"), i);
165 Color color = color(rangeElement.getAttribute("rgb"));
166 String desc = rangeElement.getAttribute("description");
167 if (from > to) { double t = from; from = to; to = t; }
168 entries[i] = new Entry(i, extIndex, from, to, color, desc);
169 rgbs[i] = color;
170 }
171
172 buildLookup();
173 }
174
175 public Palette(Palette original, int N) {
176 if (N < 2) {
177 throw new IllegalArgumentException("N < 2");
178 }
179
180 Entry [] origEntries = original.entries;
181
182 int newSize = 0;
183 for (int i = 0; i < origEntries.length; ++i) {
184 // cannot split infinity intervals
185 newSize += origEntries[i].isInfinity() ? 1 : N;
186 }
187
188 entries = new Entry[newSize];
189 rgbs = new Color[newSize];
190
191 for (int i = 0, j = 0; i < origEntries.length; ++i) {
192 Entry origEntry = origEntries[i];
193 if (origEntry.isInfinity()) {
194 // infinity intervals are just copied
195 Entry nEntry = new Entry(origEntry);
196 entries[j] = nEntry;
197 rgbs[j] = nEntry.color;
198 nEntry.index = j++;
199 }
200 else {
201 // split interval into N parts
202 double from = origEntry.from;
203 double to = origEntry.to;
204 double delta = (to - from)/N;
205 for (int k = 0; k < N; ++k) {
206 Entry nEntry = new Entry(origEntry);
207 nEntry.from = from;
208 nEntry.to = from + delta;
209 from += delta;
210 entries[j] = nEntry;
211 rgbs[j] = nEntry.color;
212 nEntry.index = j++;
213 }
214 } // limited interval
215 } // for all original entries
216
217 buildLookup();
218 }
219
220 private static final int intValue(String s, int def) {
221 if (s == null || (s = s.trim()).length() == 0) {
222 return def;
223 }
224 try {
225 return Integer.parseInt(s);
226 }
227 catch (NumberFormatException nfe) {
228 log.error(nfe.getLocalizedMessage(), nfe);
229 }
230 return def;
231 }
232
233 private static final double doubleValue(String s) {
234 if (s == null || (s = s.trim()).length() == 0) {
235 return 0d;
236 }
237 if ((s = s.toLowerCase()).startsWith("-inf")) {
238 return -Double.MAX_VALUE; // XXX: Not using Double.NEGATIVE_INFINITY!
239 }
240
241 if (s.startsWith("inf")) {
242 return Double.MAX_VALUE; // XXX: Not using Double.NEGATIVE_INFINITY!
243 }
244
245 return Double.parseDouble(s);
246 }
247
248 private static final Color color(String s) {
249 if (s == null || (s = s.trim()).length() == 0) {
250 return null;
251 }
252 return Color.decode(s);
253 }
254
255
256 protected void buildLookup() {
257 Arrays.sort(entries);
258 lookup = buildLookup(entries, 0, entries.length-1);
259 }
260
261 public Palette subdivide(int N) {
262 return new Palette(this, N);
263 }
264
265 public int getSize() {
266 return rgbs.length;
267 }
268
269 public Color getColor(int index) {
270 return rgbs[index];
271 }
272
273 public int indexToRGB(int index) {
274 return rgbs[index].getRGB();
275 }
276
277 public int toIndex(double value) {
278 return lookup.locate(value);
279 }
280
281 public Entry getEntry(double value) {
282 return lookup.locateEntry(value);
283 }
284
285 public Entry getEntryByIndex(int index) {
286 return lookup.findByIndex(index);
287 }
288 }
289 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org