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;

http://dive4elements.wald.intevation.org