Mercurial > dive4elements > gnv-client
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: |