Statistics
| Revision:

gvsig-raster / org.gvsig.raster / trunk / org.gvsig.raster / org.gvsig.raster.algorithm / src / main / java / org / gvsig / raster / algorithm / util / Interpolation.java @ 1891

History | View | Annotate | Download (8.79 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22
package org.gvsig.raster.algorithm.util;
23

    
24
import org.gvsig.fmap.dal.coverage.RasterLocator;
25
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
26
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
27

    
28
/**
29
 * Calculates a pixel value using a interpolation method
30
 * @author Nacho Brodin nachobrodin@gmail.com
31
 * @author Victor Olaya
32
 */
33
public class Interpolation {
34
        private Buffer        buffer    = null;
35
        private double        nodata    = 0;
36
        
37
        public Interpolation(Buffer buf) {
38
                this.buffer = buf;
39
                NoData nodata = RasterLocator.getManager().getDataStructFactory().createDefaultNoData(
40
                                1, Buffer.TYPE_DOUBLE);
41
                this.nodata = nodata.getValue().doubleValue();
42
        }
43
        
44
        private double[] getKernel(int x, int y, int band) {
45
                if(buffer.getDataType() == Buffer.TYPE_BYTE) {
46
                        return getKernelByte(x, y, band);
47
                }
48
                if(buffer.getDataType() == Buffer.TYPE_DOUBLE) {
49
                        return getKernelByte(x, y, band);
50
                }
51
                if(buffer.getDataType() == Buffer.TYPE_FLOAT) {
52
                        return getKernelByte(x, y, band);
53
                }
54
                if(buffer.getDataType() == Buffer.TYPE_SHORT) {
55
                        return getKernelByte(x, y, band);
56
                }
57
                if(buffer.getDataType() == Buffer.TYPE_INT) {
58
                        return getKernelByte(x, y, band);
59
                }
60
                return null;
61
        }
62

    
63
        public double getNearestNeighbour(double x, double y, int band) {
64
                int dy = (int)Math.round(y);
65
                int dx = (int)Math.round(x);
66
                dy = dy < buffer.getHeight() ? dy : buffer.getHeight() - 1;
67
                dx = dx < buffer.getWidth() ? dx : buffer.getWidth() - 1;
68
                if(buffer.getDataType() == Buffer.TYPE_BYTE) {
69
                        return (double)buffer.getElemByte(dy, dx, band);
70
                }
71
                if(buffer.getDataType() == Buffer.TYPE_DOUBLE) {
72
                        return (double)buffer.getElemDouble(dy, dx, band);
73
                }
74
                if(buffer.getDataType() == Buffer.TYPE_FLOAT) {
75
                        return (double)buffer.getElemFloat(dy, dx, band);
76
                }
77
                if(buffer.getDataType() == Buffer.TYPE_SHORT) {
78
                        return (double)buffer.getElemShort(dy, dx, band);
79
                }
80
                if(buffer.getDataType() == Buffer.TYPE_INT) {
81
                        return (double)buffer.getElemInt(dy, dx, band);
82
                }
83
                return nodata;
84
        }
85

    
86
        /**
87
         * Calcula los valores N y Z para el m?todo bilinear y obtiene el valor del pixel como
88
         * Z / N
89
         * @param dx distancia en X desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
90
         * @param dy distancia en Y desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
91
         * @param kernel valor del pixel y alrededor 
92
         * @return valor del pixel
93
         */
94
        public double getBilinearValue(double x, double y, int band) {
95
                double[] kernel = getKernel((int)x, (int)y, band);
96
                double dx = x - ((int) x);
97
                double dy = y - ((int) y);
98
                
99
                double z = 0.0, n = 0.0, d;
100
                d = (1.0 - dx) * (1.0 - dy);
101
                z += d * kernel[0];
102
                n += d;
103

    
104
                d = dx * (1.0 - dy);
105
                z += d * kernel[1]; 
106
                n += d;
107

    
108
                d = (1.0 - dx) * dy;
109
                z += d * kernel[2]; 
110
                n += d;
111

    
112
                d = dx * dy;
113
                z += d * kernel[3]; 
114
                n += d;
115

    
116
                double b = 0;
117
                if(n > 0.0)
118
                        b = (z / n);
119
                return b;
120
        }
121
        
122
        /**
123
         * Calcula los valores N y Z para el m?todo de distancia inversa y calcula el valor del
124
         * pixel como Z / N.
125
         * @param dx distancia en X desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
126
         * @param dy distancia en Y desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
127
         * @param kernel valor del pixel y alrededor 
128
         * @return valor del pixel
129
         */
130
        public double getInverseDistance(double x, double y, int band) {
131
                double[] kernel = getKernel((int)x, (int)y, band);
132
                double dx = x - ((int) x);
133
                double dy = y - ((int) y);
134
                
135
                double z = 0.0, n = 0.0, d;
136
                d = 1.0 / Math.sqrt(dx * dx + dy * dy);
137
                z += d * kernel[0];
138
                n += d;
139

    
140
                d = 1.0 / Math.sqrt((1.0 - dx) * ( 1.0 - dx) + dy * dy);
141
                z += d * kernel[1]; 
142
                n += d;
143

    
144
                d = 1.0 / Math.sqrt(dx*dx + (1.0-dy)*(1.0-dy));
145
                z += d * kernel[2]; 
146
                n += d;
147

    
148
                d = 1.0 / Math.sqrt((1.0 - dx) *( 1.0 - dx) + (1.0 - dy) * (1.0 - dy));
149
                z += d * kernel[3]; 
150
                n += d;
151

    
152
                double b = 0;
153
                if(n > 0.0)
154
                        b = (z / n);
155
                return b;
156
        }
157
        
158
        /**
159
         * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
160
         * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
161
         * se tomar? x e y. 
162
         * @param x Coordenada X del pixel inicial
163
         * @param y Coordenada Y del pixel inicial
164
         * @param band N?mero de banda.
165
         * @return Kernel solicitado en forma de array.
166
         */
167
        private double[] getKernelByte(int x, int y, int band) {
168
                double[] d = new double[4];
169
                d[0] = (buffer.getElemByte(y, x, band) & 0xff);
170
                int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1);
171
                int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1);
172
                d[1] = (buffer.getElemByte(y, nextX, band) & 0xff);
173
                d[2] = (buffer.getElemByte(nextY, x, band) & 0xff);
174
                d[3] = (buffer.getElemByte(nextY, nextX, band) & 0xff);
175
                return d;
176
        }
177

    
178
        /**
179
         * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
180
         * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
181
         * se tomar? x e y. 
182
         * @param x Coordenada X del pixel inicial
183
         * @param y Coordenada Y del pixel inicial
184
         * @param band N?mero de banda.
185
         * @return Kernel solicitado en forma de array.
186
         */
187
        @SuppressWarnings("unused")
188
        private double[] getKernelShort(int x, int y, int band) {
189
                double[] d = new double[4];
190
                d[0] = (buffer.getElemShort(y, x, band) & 0xffff);
191
                int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1);
192
                int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1);
193
                d[1] = (buffer.getElemShort(y, nextX, band) & 0xffff);
194
                d[2] = (buffer.getElemShort(nextY, x, band) & 0xffff);
195
                d[3] = (buffer.getElemShort(nextY, nextX, band) & 0xffff);
196
                return d;
197
        }
198

    
199
        /**
200
         * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
201
         * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
202
         * se tomar? x e y. 
203
         * @param x Coordenada X del pixel inicial
204
         * @param y Coordenada Y del pixel inicial
205
         * @param band N?mero de banda.
206
         * @return Kernel solicitado en forma de array.
207
         */
208
        @SuppressWarnings("unused")
209
        private double[] getKernelInt(int x, int y, int band) {
210
                double[] d = new double[4];
211
                d[0] = (buffer.getElemInt(y, x, band) & 0xffffffff);
212
                int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1);
213
                int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1);
214
                d[1] = (buffer.getElemInt(y, nextX, band) & 0xffffffff);
215
                d[2] = (buffer.getElemInt(nextY, x, band) & 0xffffffff);
216
                d[3] = (buffer.getElemInt(nextY, nextX, band) & 0xffffffff);
217
                return d;
218
        }
219

    
220
        /**
221
         * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
222
         * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
223
         * se tomar? x e y. 
224
         * @param x Coordenada X del pixel inicial
225
         * @param y Coordenada Y del pixel inicial
226
         * @param band N?mero de banda.
227
         * @return Kernel solicitado en forma de array.
228
         */
229
        @SuppressWarnings("unused")
230
        private double[] getKernelFloat(int x, int y, int band) {
231
                double[] d = new double[4];
232
                d[0] = buffer.getElemFloat(y, x, band);
233
                int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1);
234
                int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1);
235
                d[1] = buffer.getElemFloat(y, nextX, band);
236
                d[2] = buffer.getElemFloat(nextY, x, band);
237
                d[3] = buffer.getElemFloat(nextY, nextX, band);
238
                return d;
239
        }
240

    
241
        /**
242
         * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
243
         * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
244
         * se tomar? x e y. 
245
         * @param x Coordenada X del pixel inicial
246
         * @param y Coordenada Y del pixel inicial
247
         * @param band N?mero de banda.
248
         * @return Kernel solicitado en forma de array.
249
         */
250
        @SuppressWarnings("unused")
251
        private double[] getKernelDouble(int x, int y, int band) {
252
                double[] d = new double[4];
253
                d[0] = buffer.getElemDouble(y, x, band);
254
                int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1);
255
                int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1);
256
                d[1] = buffer.getElemDouble(y, nextX, band);
257
                d[2] = buffer.getElemDouble(nextY, x, band);
258
                d[3] = buffer.getElemDouble(nextY, nextX, band);
259
                return d;
260
        }
261
}