Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / grid / GridInterpolated.java @ 20871

History | View | Annotate | Download (14 KB)

1
/*******************************************************************************
2
    GridWrapperInterpolated
3
    Copyright (C) Victor Olaya
4
    
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9

10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14

15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*******************************************************************************/ 
19
package org.gvsig.raster.grid;
20

    
21
import org.gvsig.raster.buffer.BufferFactory;
22
import org.gvsig.raster.buffer.BufferInterpolation;
23
import org.gvsig.raster.buffer.RasterBuffer;
24
import org.gvsig.raster.buffer.RasterBufferInvalidAccessException;
25
import org.gvsig.raster.buffer.RasterBufferInvalidException;
26
import org.gvsig.raster.dataset.InvalidSetViewException;
27
import org.gvsig.raster.dataset.io.RasterDriverException;
28

    
29
/**
30
 * A grid wrapper that performs interpolation to calculate
31
 * cell values. This should be used when the window extent
32
 * does not 'fit' into the structure (coordinates and cellsize)
33
 * of the grid.
34
 * 
35
 * @author Victor Olaya
36
 */
37

    
38
public class GridInterpolated extends GridReader {
39

    
40
        public static final int INTERPOLATION_NearestNeighbour = BufferInterpolation.INTERPOLATION_NearestNeighbour;
41
        public static final int INTERPOLATION_Bilinear = BufferInterpolation.INTERPOLATION_Bilinear;
42
        public static final int INTERPOLATION_InverseDistance = BufferInterpolation.INTERPOLATION_InverseDistance;
43
        public static final int INTERPOLATION_BicubicSpline = BufferInterpolation.INTERPOLATION_BicubicSpline;
44
        public static final int INTERPOLATION_BSpline = BufferInterpolation.INTERPOLATION_BSpline;
45
        
46
        double m_dXMin , m_dYMax; //coordinates of the layer, not the window
47
        double m_dCellSizeX; //cellsize of the layer, not the window
48
        double m_dCellSizeY; //cellsize of the layer, not the window
49
        int m_iInterpolationMethod = INTERPOLATION_BSpline;
50

    
51
        /**
52
         * Crea un objeto lector a partir de un buffer de datos y el extent de la extensi?n
53
         * completa y de la ventana accedida.
54
         * @param rb Buffer de datos
55
         * @param layerExtent extent de la capa completa
56
         * @param windowExtent Extent
57
         * @param bands N?mero de bandas del origen
58
         */
59
        public GridInterpolated(        RasterBuffer rb, 
60
                                                                GridExtent layerExtent,
61
                                                                GridExtent windowExtent,
62
                                                                int[] bands){
63
                super(rb, layerExtent, windowExtent, bands);
64
                m_dXMin = layerExtent.minX();
65
                m_dYMax = layerExtent.maxY();
66
                
67
                m_dCellSizeX = layerExtent.getCellSizeX();
68
                m_dCellSizeY = layerExtent.getCellSizeY();
69
        }
70
        
71
        /**
72
         * Crea un objeto lector a partir de una fuente de datos y el extent de la extensi?n
73
         * completa y de la ventana accedida.
74
         * @param ds Fuente de datos
75
         * @param layerExtent extent de la capa completa
76
         * @param windowExtent Extent
77
         * @param bands N?mero de bandas del origen
78
         */
79
        public GridInterpolated(        BufferFactory ds, 
80
                                                                GridExtent layerExtent,
81
                                                                GridExtent windowExtent,
82
                                                                int[] bands){
83
                super(ds, layerExtent, windowExtent, bands);
84
                init();
85
        }
86
        
87
        /**
88
         * Inicializaci?n de la fuente de datos y carga del buffer.
89
         */
90
        private void init(){
91
                m_dXMin = bufferFactory.getDataSource().getExtent().minX();
92
                m_dYMax = bufferFactory.getDataSource().getExtent().maxY();
93
                
94
                m_dCellSizeX = bufferFactory.getDataSource().getAffineTransform().getScaleX();
95
                m_dCellSizeY = bufferFactory.getDataSource().getAffineTransform().getScaleY();
96
                
97
                bufferFactory.setDrawableBands(bands);
98
        }
99
                
100
        /**
101
         * Asigna el m?todo de interpolaci?n 
102
         * @param iMethod
103
         */
104
        public void setInterpolationMethod(int iMethod){
105
                m_iInterpolationMethod = iMethod;
106
        }
107

    
108
        /*
109
         *  (non-Javadoc)
110
         * @see org.gvsig.fmap.grid.GridReader#getCellValueAsByte(int, int)
111
         */
112
        public byte getCellValueAsByte(int x, int y) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
113
                return  (byte)_getValueAt(x, y);
114
        }
115
        
116
        /*
117
         *  (non-Javadoc)
118
         * @see org.gvsig.fmap.grid.GridReader#getCellValueAsShort(int, int)
119
         */
120
        public short getCellValueAsShort(int x, int y) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
121
                return (short) _getValueAt(x, y);
122
        }
123
        
124
        /*
125
         *  (non-Javadoc)
126
         * @see org.gvsig.fmap.grid.GridReader#getCellValueAsInt(int, int)
127
         */
128
        public int getCellValueAsInt(int x, int y) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {                
129
                return (int) _getValueAt(x, y);
130
        }
131

    
132
        /*
133
         *  (non-Javadoc)
134
         * @see org.gvsig.fmap.grid.GridReader#getCellValueAsFloat(int, int)
135
         */
136
        public float getCellValueAsFloat(int x, int y)  throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
137
                return (float) _getValueAt(x, y);
138
        }
139
        
140
        /*
141
         *  (non-Javadoc)
142
         * @see org.gvsig.fmap.grid.GridReader#getCellValueAsDouble(int, int)
143
         */
144
        public double getCellValueAsDouble(int x, int y) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
145
                return _getValueAt(x, y);
146
        }
147
        
148
        private double _getValueAt(int x, int y) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
149
                double dX = windowExtent.minX() + windowExtent.getCellSize() * (x + 0.5);
150
                double dY = windowExtent.maxY() - windowExtent.getCellSize() * (y + 0.5);
151
                return getValueAt(dX, dY);
152
        }
153

    
154
        
155
        /** Devuelve el valor interpolado para unas coordenadas de la imagen no enteras
156
         *  la distancia se toma al vertice superior izquierdo del pixel
157
         * */
158
        public double _getValueAt(double x, double y) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
159
                int x_int, y_int;
160
                x_int= (int)Math.floor(x);
161
                y_int= (int)Math.floor(y);
162
                double dX = windowExtent.minX() + windowExtent.getCellSize() * (x_int + (x-x_int));
163
                double dY = windowExtent.maxY() - windowExtent.getCellSize() * (y_int + (y-y_int));
164
                return getValueAt(dX, dY);
165
        }
166
        
167
        
168
        private double getValueAt(double xPosition, double yPosition) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
169
                int        x, y;
170
                double        dx, dy;
171
                double dValue;
172

    
173
                x        = (int) Math.floor(xPosition = (xPosition - m_dXMin) / m_dCellSizeX);
174
                y        = (int)Math.floor(yPosition        = ( m_dYMax-yPosition) / m_dCellSizeY);
175

    
176
                dValue = _getCellValueInLayerCoords(x,y);
177
                
178
                if(        !isNoDataValue(dValue) ){
179

    
180
                        dx        = xPosition - x;
181
                        dy        = yPosition - y;
182
                        
183
                        switch( m_iInterpolationMethod ){
184
                        case INTERPOLATION_NearestNeighbour:
185
                                dValue = _getValueNearestNeighbour (x, y, dx, dy);
186
                                break;
187

    
188
                        case INTERPOLATION_Bilinear:
189
                                dValue        = _getValueBiLinear (x, y, dx, dy);
190
                                break;
191

    
192
                        case INTERPOLATION_InverseDistance:
193
                                dValue        = _getValueInverseDistance(x, y, dx, dy);
194
                                break;
195

    
196
                        case INTERPOLATION_BicubicSpline:
197
                                dValue        = _getValueBiCubicSpline (x, y, dx, dy);
198
                                break;
199

    
200
                        case INTERPOLATION_BSpline:
201
                                dValue        = _getValueBSpline (x, y, dx, dy);
202
                                break;
203
                        }
204
                }
205
                else{
206
                        dValue = getNoDataValue();
207
                }
208

    
209
                return dValue;
210
        }
211

    
212
        private double _getValueNearestNeighbour(int x, int y, double dx, double dy) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
213
                x += (int)(0.5 + dx);
214
                y += (int)(0.5 + dy);
215

    
216
                return _getCellValueInLayerCoords(x, y);
217
        }
218

    
219
        private  double _getValueBiLinear(int x, int y, double dx, double dy) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
220
                double        z = 0.0, n = 0.0, d;
221
                double dValue;
222
                
223
                dValue = _getCellValueInLayerCoords(x, y);
224
                if (!isNoDataValue(dValue)){
225
                         d = (1.0 - dx) * (1.0 - dy);
226
                         z += d * dValue; 
227
                         n += d;
228
                }
229
                
230
                dValue = _getCellValueInLayerCoords(x + 1, y);
231
                if (!isNoDataValue(dValue)){
232
                         d = (dx) * (1.0 - dy);
233
                         z += d * dValue; 
234
                         n += d;
235
                }
236
                
237
                dValue = _getCellValueInLayerCoords(x, y + 1);
238
                if (!isNoDataValue(dValue)){
239
                         d = (1.0 - dx) * (dy);
240
                         z += d * dValue; 
241
                         n += d;
242
                }
243
                
244
                dValue = _getCellValueInLayerCoords(x + 1, y + 1);
245
                if (!isNoDataValue(dValue)){
246
                         d = (dx) * (dy);
247
                         z += d * dValue; 
248
                         n += d;
249
                }
250

    
251
                if( n > 0.0 ){
252
                        return( z / n );
253
                }
254

    
255
                return( getNoDataValue() );
256
        }
257

    
258
        private double _getValueInverseDistance(int x, int y, double dx, double dy) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
259
                double        z = 0.0, n = 0.0, d;
260
                double dValue;
261
                
262
                if( dx > 0.0 || dy > 0.0 ){
263

    
264
                        dValue = _getCellValueInLayerCoords(x, y);
265
                        if (!isNoDataValue(dValue)){
266
                                d = 1.0 / Math.sqrt(dx*dx + dy*dy); 
267
                                z += d * dValue; 
268
                                n += d;
269
                        }
270
                        
271
                        dValue = _getCellValueInLayerCoords(x + 1, y);
272
                        if (!isNoDataValue(dValue)){
273
                                d = 1.0 / Math.sqrt((1.0-dx)*(1.0-dx) + dy*dy); 
274
                                z += d * dValue; 
275
                                n += d;
276
                        }
277
                        
278
                        dValue = _getCellValueInLayerCoords(x, y + 1);
279
                        if (!isNoDataValue(dValue)){
280
                                d = 1.0 / Math.sqrt(dx*dx + (1.0-dy)*(1.0-dy)); 
281
                                z += d * dValue; 
282
                                n += d;
283
                        }
284
                        
285
                        dValue = _getCellValueInLayerCoords(x + 1, y + 1);
286
                        if (!isNoDataValue(dValue)){
287
                                d = 1.0 / Math.sqrt((1.0-dx)*(1.0-dx) + (1.0-dy)*(1.0-dy)); 
288
                                z += d * dValue; 
289
                                n += d;
290
                        }
291

    
292
                        if( n > 0.0 ){
293
                                return( z / n );
294
                        }
295
                }else
296
                        return( _getCellValueInLayerCoords(x, y) );
297
                
298
                return( getNoDataValue());
299
        }
300

    
301
        private double _getValueBiCubicSpline(int x, int y, double dx, double dy) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
302
                int                i;
303
                double        a0, a2, a3, b1, b2, b3, c[], z_xy[][];
304

    
305
                c = new double[4];
306
                z_xy = new double[4][4];
307
                
308
                if( _get4x4Submatrix(x, y, z_xy) ){
309
                        
310
                        for(i=0; i<4; i++){
311
                                a0                = z_xy[0][i] - z_xy[1][i];
312
                                a2                = z_xy[2][i] - z_xy[1][i];
313
                                a3                = z_xy[3][i] - z_xy[1][i];
314

    
315
                                b1                = -a0 / 3.0 + a2       - a3 / 6.0;
316
                                b2                =  a0 / 2.0 + a2 / 2.0;
317
                                b3                = -a0 / 6.0 - a2 / 2.0 + a3 / 6.0;
318

    
319
                                c[i]        = z_xy[1][i] + b1 * dx + b2 * dx*dx + b3 * dx*dx*dx;
320
                        }
321

    
322
                        a0                = c[0] - c[1];
323
                        a2                = c[2] - c[1];
324
                        a3                = c[3] - c[1];
325

    
326
                        b1                = -a0 / 3.0 + a2       - a3 / 6.0;
327
                        b2                =  a0 / 2.0 + a2 / 2.0;
328
                        b3                = -a0 / 6.0 - a2 / 2.0 + a3 / 6.0;
329

    
330
                        return( c[1] + b1 * dy + b2 * dy*dy + b3 * dy*dy*dy );
331
                }
332

    
333
                return( _getValueBiLinear(x, y, dx, dy) );
334
        }
335

    
336
        private double _getValueBSpline(int x, int y, double dx, double dy) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
337
                int                i, ix, iy;
338
                double        z, px, py, Rx[], Ry[], z_xy[][];
339
                
340
                Rx = new double[4];
341
                Ry = new double[4];
342
                z_xy = new double [4][4];
343

    
344
                if( _get4x4Submatrix(x, y, z_xy) ) {
345
                        for(i=0, px=-1.0-dx, py=-1.0-dy; i<4; i++, px++, py++) {
346
                                Rx[i]        = 0.0;
347
                                Ry[i]        = 0.0;
348

    
349
                                if( (z = px + 2.0) > 0.0 )
350
                                        Rx[i]        +=        z*z*z;
351
                                if( (z = px + 1.0) > 0.0 )
352
                                        Rx[i]        += -4.0 * z*z*z;
353
                                if( (z = px + 0.0) > 0.0 )
354
                                        Rx[i]        +=  6.0 * z*z*z;
355
                                if( (z = px - 1.0) > 0.0 )
356
                                        Rx[i]        += -4.0 * z*z*z;
357
                                if( (z = py + 2.0) > 0.0 )
358
                                        Ry[i]        +=        z*z*z;
359
                                if( (z = py + 1.0) > 0.0 )
360
                                        Ry[i]        += -4.0 * z*z*z;
361
                                if( (z = py + 0.0) > 0.0 )
362
                                        Ry[i]        +=  6.0 * z*z*z;
363
                                if( (z = py - 1.0) > 0.0 )
364
                                        Ry[i]        += -4.0 * z*z*z;
365

    
366
                                Rx[i]        /= 6.0;
367
                                Ry[i]        /= 6.0;
368
                        }
369

    
370
                        for(iy=0, z=0.0; iy<4; iy++) {
371
                                for(ix=0; ix<4; ix++){
372
                                        z        += z_xy[ix][iy] * Rx[ix] * Ry[iy];
373
                                }
374
                        }
375
                        return( z );
376
                }
377
                return( _getValueBiLinear(x, y, dx, dy) );
378
        }
379

    
380
        private boolean _get4x4Submatrix(int x, int y, double z_xy[][]) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
381
                int        ix, iy, px, py;
382
                double dValue;
383

    
384
                for(iy=0, py=y-1; iy<4; iy++, py++) {
385
                        for(ix=0, px=x-1; ix<4; ix++, px++) {
386
                                dValue = _getCellValueInLayerCoords(px, py);
387
                                if (isNoDataValue(dValue)) {
388
                                        return false;
389
                                } else {
390
                                        z_xy[ix][iy] = dValue;
391
                                }
392
                        }
393
                }
394
                return( true );
395
        }
396

    
397
        private double _getCellValueInLayerCoords(int x, int y) throws RasterBufferInvalidAccessException, RasterBufferInvalidException {
398
                int w = 0, h = 0;
399
                int pX = 0, pY = 0;
400
                if(bufferFactory != null) { 
401
                        w = bufferFactory.getSourceWidth();
402
                        h = bufferFactory.getSourceHeight();
403
                        try {
404
                                bufferFactory.setAreaOfInterest(x, y, 1, 1);
405
                        } catch (InvalidSetViewException e) {
406
                                throw new RasterBufferInvalidAccessException("");
407
                        } catch (RasterDriverException e) {
408
                                throw new RasterBufferInvalidException("");
409
                        } catch (InterruptedException e) {
410
                                //La cancelaci?n de la lectura de un pixel no es significativa 
411
                        }
412
                        pX = 1; 
413
                        pY = 1;
414
                } else {
415
                        w = rasterBuf.getWidth();
416
                        h = rasterBuf.getHeight();
417
                        pX = x;
418
                        pY = y;
419
                }
420
        
421
                if ( x >= 0 && y >= 0 && x < w && y < h) {
422
                        if (dataType == RasterBuffer.TYPE_DOUBLE) {
423
                                return rasterBuf.getElemDouble(pY, pX, bandToOperate);
424
                        } else if (dataType == RasterBuffer.TYPE_INT) {
425
                                return (double) rasterBuf.getElemInt(pY, pX, bandToOperate);
426
                        } else if (dataType == RasterBuffer.TYPE_FLOAT) {
427
                                return (double) rasterBuf.getElemFloat(pY, pX, bandToOperate);
428
                        } else if (dataType == RasterBuffer.TYPE_BYTE) {
429
                                return ((byte)(rasterBuf.getElemByte(pY, pX, bandToOperate))&0xff);
430
                        } else if ((dataType == RasterBuffer.TYPE_SHORT) | (dataType == RasterBuffer.TYPE_USHORT)) {
431
                                return (double) rasterBuf.getElemShort(pY, pX, bandToOperate);
432
                        }
433
                }
434
                return getNoDataValue();
435
        }
436

    
437
        public byte[] getBandsValuesAsByte(int x, int y) {
438
                //TODO: FUNCIONALIDAD: getBandsValuesAsByte:Obtener los valores interpolados en todas las bandas
439
                return null;
440
        }
441

    
442
        public short[] getBandsValuesAsShort(int x, int y) {
443
                //TODO: FUNCIONALIDAD: getBandsValuesAsShort:Obtener los valores interpolados en todas las bandas
444
                return null;
445
        }
446

    
447
        public int[] getBandsValuesAsInt(int x, int y) {
448
                //TODO: FUNCIONALIDAD: getBandsValuesAsInt:Obtener los valores interpolados en todas las bandas
449
                return null;
450
        }
451

    
452
        public float[] getBandsValuesAsFloat(int x, int y) {
453
                //TODO: FUNCIONALIDAD: getBandsValuesAsFloat:Obtener los valores interpolados en todas las bandas
454
                return null;
455
        }
456

    
457
        public double[] getBandsValuesAsDouble(int x, int y) {
458
                //TODO: FUNCIONALIDAD: getBandsValuesAsDouble:Obtener los valores interpolados en todas las bandas
459
                return null;
460
        }
461
}