Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/raster/Raster.java @ 801:d766fe2d917a
More javadoc.
gnv-artifacts/trunk@883 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 06 Apr 2010 16:53:43 +0000 |
parents | 6cff63d0c434 |
children | 05bf8534a35a |
comparison
equal
deleted
inserted
replaced
800:db5b04ecb426 | 801:d766fe2d917a |
---|---|
1 package de.intevation.gnv.raster; | 1 package de.intevation.gnv.raster; |
2 | 2 |
3 /** | 3 /** |
4 * A 2D double valued representation of a raster array. | |
4 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> | 5 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> |
5 */ | 6 */ |
6 public class Raster | 7 public class Raster |
7 { | 8 { |
9 /** | |
10 * A kernel can be applied to a raster to fold its values. | |
11 */ | |
8 public static class Kernel { | 12 public static class Kernel { |
9 | 13 |
14 /** | |
15 * The coefficients of the folding matrix. | |
16 */ | |
10 public static final class Coeff { | 17 public static final class Coeff { |
18 /** | |
19 * i delta index of this coefficient. | |
20 */ | |
11 public int di; | 21 public int di; |
22 /** | |
23 * i delta index of this coefficient. | |
24 */ | |
12 public int dj; | 25 public int dj; |
26 /** | |
27 * The weight of this coefficient. | |
28 */ | |
13 public double c; | 29 public double c; |
14 | 30 |
31 /** | |
32 * Default constructor | |
33 */ | |
15 public Coeff() { | 34 public Coeff() { |
16 } | 35 } |
17 | 36 |
37 /** | |
38 * Constructor to set the delta position and the weight of | |
39 * the coefficient. | |
40 * @param di The i delta index. | |
41 * @param dj The j delta index. | |
42 * @param c The weight of the index. | |
43 */ | |
18 public Coeff(int di, int dj, double c) { | 44 public Coeff(int di, int dj, double c) { |
19 this.di = di; | 45 this.di = di; |
20 this.dj = dj; | 46 this.dj = dj; |
21 this.c = c; | 47 this.c = c; |
22 } | 48 } |
23 | 49 |
50 /** | |
51 * Returns a string representation of this coefficient. | |
52 * @return The string representation. | |
53 */ | |
54 @Override | |
24 public String toString() { | 55 public String toString() { |
25 return String.valueOf(c); | 56 return String.valueOf(c); |
26 } | 57 } |
27 | 58 |
28 } // class Coeff | 59 } // class Coeff |
29 | 60 |
61 /** | |
62 * The coefficients of the folding matrix. | |
63 */ | |
30 protected Coeff [] coeffs; | 64 protected Coeff [] coeffs; |
65 /** | |
66 * The width of the kernel. | |
67 */ | |
31 protected int width; | 68 protected int width; |
32 | 69 |
70 /** | |
71 * Default constrcutor. | |
72 */ | |
33 public Kernel() { | 73 public Kernel() { |
34 } | 74 } |
35 | 75 |
76 /** | |
77 * Constructor for a kernel with a given coefficient matrix | |
78 * with a given width. | |
79 * @param coeffs The coefficients. | |
80 * @param width The width of the kernel. | |
81 */ | |
36 public Kernel(Coeff [] coeffs, int width) { | 82 public Kernel(Coeff [] coeffs, int width) { |
37 this.coeffs = coeffs; | 83 this.coeffs = coeffs; |
38 this.width = width; | 84 this.width = width; |
39 } | 85 } |
40 | 86 |
87 /** | |
88 * Evaluates the 2D Gauss normal distribution a given x, y | |
89 * and a given sigma. | |
90 * @param x The x location. | |
91 * @param y The y location. | |
92 * @param sigma The sigma of the distribution. | |
93 * @return The value at point x, y. | |
94 */ | |
41 public static double gauss(double x, double y, double sigma) { | 95 public static double gauss(double x, double y, double sigma) { |
42 double s2 = sigma*sigma; | 96 double s2 = sigma*sigma; |
43 return 1.0d/(2.0d*Math.PI*s2)*Math.exp(-(x*x + y*y)/(2.0d*s2)); | 97 return 1.0d/(2.0d*Math.PI*s2)*Math.exp(-(x*x + y*y)/(2.0d*s2)); |
44 } | 98 } |
45 | 99 |
100 /** | |
101 * Creates a Gauss kernel with sigma = 1 and width 5. | |
102 * @return The new kernel. | |
103 */ | |
46 public static Kernel createGauss() { | 104 public static Kernel createGauss() { |
47 return createGauss(1.0d, 5); | 105 return createGauss(1.0d, 5); |
48 } | 106 } |
49 | 107 |
108 /** | |
109 * Creates a Gauss kernel with a given sigma and width. | |
110 * @param sigma The sigma value | |
111 * @param width The width of the kernel. | |
112 * @return The new kernel. | |
113 */ | |
50 public static Kernel createGauss(double sigma, int width) { | 114 public static Kernel createGauss(double sigma, int width) { |
51 Coeff [] coeffs = new Coeff[width*width]; | 115 Coeff [] coeffs = new Coeff[width*width]; |
52 double sum = 0d; | 116 double sum = 0d; |
53 for (int j = 0; j < width; ++j) { | 117 for (int j = 0; j < width; ++j) { |
54 int y = -width/2 + j; | 118 int y = -width/2 + j; |
64 coeffs[i].c *= sum; | 128 coeffs[i].c *= sum; |
65 } | 129 } |
66 return new Kernel(coeffs, width); | 130 return new Kernel(coeffs, width); |
67 } | 131 } |
68 | 132 |
133 /** | |
134 * Evaluates this Kernel at the raster at raster index i, j. | |
135 * @param access The accessor to the raster. | |
136 * @param i The i raster index. | |
137 * @param j The j raster index. | |
138 * @return The folded value at index i, j. | |
139 */ | |
69 public double fold(Access access, int i, int j) { | 140 public double fold(Access access, int i, int j) { |
70 | 141 |
71 double s = 0.0d; | 142 double s = 0.0d; |
72 | 143 |
73 double unused = 0d; | 144 double unused = 0d; |
84 } | 155 } |
85 | 156 |
86 return s*(1.0d - unused); | 157 return s*(1.0d - unused); |
87 } | 158 } |
88 | 159 |
160 /** | |
161 * Returns a string representation of this kernel. | |
162 * @return The string representation. | |
163 */ | |
164 @Override | |
89 public String toString() { | 165 public String toString() { |
90 StringBuilder sb = new StringBuilder(); | 166 StringBuilder sb = new StringBuilder(); |
91 | 167 |
92 int height = coeffs.length/width; | 168 int height = coeffs.length/width; |
93 | 169 |
105 | 181 |
106 return sb.toString(); | 182 return sb.toString(); |
107 } | 183 } |
108 } // class Kernel | 184 } // class Kernel |
109 | 185 |
186 /** | |
187 * Interface of allow special access patterns to the raster, | |
188 * especially at the border. | |
189 */ | |
110 public interface Access { | 190 public interface Access { |
111 | 191 |
192 /** | |
193 * Returns the raster value at a given index point. | |
194 * @param i The i index | |
195 * @param j The j index | |
196 * @return The value of the raster. | |
197 */ | |
112 double get(int i, int j); | 198 double get(int i, int j); |
113 | 199 |
114 } // interface Access | 200 } // interface Access |
115 | 201 |
202 /** | |
203 * Interface to decouple the lookup which is needed | |
204 * to map double values to integers. | |
205 */ | |
116 public interface ValueToIndex { | 206 public interface ValueToIndex { |
117 | 207 |
208 /** | |
209 * Returns the corresponding integer to a given value. | |
210 * @param value The value to be queried. | |
211 * @return The integer value or -1 if no such value was found. | |
212 */ | |
118 int toIndex(double value); | 213 int toIndex(double value); |
119 | 214 |
120 } // interface ValueToIndex; | 215 } // interface ValueToIndex; |
121 | 216 |
217 /** | |
218 * Brings raster to an integer representation with equal sized bins | |
219 * of integer vaules. | |
220 */ | |
122 public static class IsoClasses | 221 public static class IsoClasses |
123 implements ValueToIndex | 222 implements ValueToIndex |
124 { | 223 { |
224 /** | |
225 * Linear scaling factor. | |
226 */ | |
125 protected double m; | 227 protected double m; |
228 /** | |
229 * Linear offset. | |
230 */ | |
126 protected double b; | 231 protected double b; |
232 /** | |
233 * Number of classes. | |
234 */ | |
127 protected int numClasses; | 235 protected int numClasses; |
128 | 236 |
237 /** | |
238 * Constructor to build a lookup to transform | |
239 * an raster into an equals sized bin integer array. | |
240 * @param raster The original raster | |
241 * @param numClasses The number of classes. | |
242 */ | |
129 public IsoClasses(Raster raster, int numClasses) { | 243 public IsoClasses(Raster raster, int numClasses) { |
130 | 244 |
131 this.numClasses = numClasses; | 245 this.numClasses = numClasses; |
132 | 246 |
133 double min = Double.MAX_VALUE; | 247 double min = Double.MAX_VALUE; |
163 m = (numClasses - 1)/(max - min); | 277 m = (numClasses - 1)/(max - min); |
164 b = m*min; | 278 b = m*min; |
165 } | 279 } |
166 } | 280 } |
167 | 281 |
282 /** | |
283 * Implements the double to integer lookup. | |
284 * @param value The value to map. | |
285 * @return The mapped value. | |
286 */ | |
168 public int toIndex(double value) { | 287 public int toIndex(double value) { |
169 return Double.isNaN(value) | 288 return Double.isNaN(value) |
170 ? -1 | 289 ? -1 |
171 : Math.min(Math.max(0, (int)Math.round(m*value + b)), numClasses-1); | 290 : Math.min(Math.max(0, (int)Math.round(m*value + b)), numClasses-1); |
172 } | 291 } |
173 } // class IsoClasses | 292 } // class IsoClasses |
174 | 293 |
294 /** | |
295 * Internal representation of the raster. | |
296 */ | |
175 protected double [] raster; | 297 protected double [] raster; |
298 /** | |
299 * The width of the raster. | |
300 */ | |
176 protected int width; | 301 protected int width; |
177 | 302 |
303 /** | |
304 * Default constructor. Creates an 0x0 raster. | |
305 */ | |
178 public Raster() { | 306 public Raster() { |
179 this(new double[0], 0); | 307 this(new double[0], 0); |
180 } | 308 } |
181 | 309 |
310 /** | |
311 * Creates a raster with given values and width. | |
312 * @param raster | |
313 * @param width | |
314 */ | |
182 public Raster(double [] raster, int width) { | 315 public Raster(double [] raster, int width) { |
183 this.raster = raster; | 316 this.raster = raster; |
184 this.width = width; | 317 this.width = width; |
185 } | 318 } |
186 | 319 |
320 /** | |
321 * The width of the raster. | |
322 * @return The width. | |
323 */ | |
187 public int getWidth() { | 324 public int getWidth() { |
188 return width; | 325 return width; |
189 } | 326 } |
190 | 327 |
328 /** | |
329 * The height of the raster. | |
330 * @return The height. | |
331 */ | |
191 public int getHeight() { | 332 public int getHeight() { |
192 return raster.length / width; | 333 return raster.length / width; |
193 } | 334 } |
194 | 335 |
336 /** | |
337 * The values of the raster. | |
338 * @return The values. | |
339 */ | |
195 public double [] getValues() { | 340 public double [] getValues() { |
196 return raster; | 341 return raster; |
197 } | 342 } |
198 | 343 |
344 /** | |
345 * Creates an integer representation of this raster using a | |
346 * given value to index transformer. | |
347 * @param valueToIndex The transformer to map double to integer values. | |
348 * @return The new created integer representation. | |
349 */ | |
199 public int [] toIndexed(ValueToIndex valueToIndex) { | 350 public int [] toIndexed(ValueToIndex valueToIndex) { |
200 int [] dst = new int[raster.length]; | 351 int [] dst = new int[raster.length]; |
201 for (int i = 0; i < raster.length; ++i) { | 352 for (int i = 0; i < raster.length; ++i) { |
202 dst[i] = valueToIndex.toIndex(raster[i]); | 353 dst[i] = valueToIndex.toIndex(raster[i]); |
203 } | 354 } |
204 return dst; | 355 return dst; |
205 } | 356 } |
206 | 357 |
358 /** | |
359 * Creates a new raster by applying a kernel to this raster. | |
360 * Access to the raster is continuous at the border. | |
361 * The original raster is not modified. | |
362 * @param kernel The kernel to be applied. | |
363 * @return The new raster. | |
364 */ | |
207 public Raster create(Kernel kernel) { | 365 public Raster create(Kernel kernel) { |
208 double [] dst = new double[raster.length]; | 366 double [] dst = new double[raster.length]; |
209 Raster r = new Raster(dst, width); | 367 Raster r = new Raster(dst, width); |
210 r.apply(kernel, continueBorder()); | 368 r.apply(kernel, continueBorder()); |
211 return r; | 369 return r; |
212 } | 370 } |
213 | 371 |
372 /** | |
373 * Creates a new raster by applying a kernel to this raster. | |
374 * Access to the raster is given. | |
375 * @param kernel The kernel to be applied. | |
376 * @param access The access method to the raster. | |
377 */ | |
214 public void apply(Kernel kernel, Access access) { | 378 public void apply(Kernel kernel, Access access) { |
215 int height = getHeight(); | 379 int height = getHeight(); |
216 for (int j = 0; j < height; ++j) { | 380 for (int j = 0; j < height; ++j) { |
217 int row = j*width; | 381 int row = j*width; |
218 for (int i = 0; i < width; ++i) { | 382 for (int i = 0; i < width; ++i) { |
219 raster[row + i] = kernel.fold(access, i, j); | 383 raster[row + i] = kernel.fold(access, i, j); |
220 } | 384 } |
221 } | 385 } |
222 } | 386 } |
223 | 387 |
388 /** | |
389 * Returns a continuous access to the raster. Values | |
390 * at the border are repeated til infinity if indices | |
391 * are accessed outside the defined area. | |
392 * @return The accessor. | |
393 */ | |
224 public Access continueBorder() { | 394 public Access continueBorder() { |
225 return new Access() { | 395 return new Access() { |
226 int height = getHeight()-1; | 396 int height = getHeight()-1; |
227 public double get(int i, int j) { | 397 public double get(int i, int j) { |
228 if (i < 0) i = 0; | 398 if (i < 0) i = 0; |