Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / grid / Grid.java @ 12567

History | View | Annotate | Download (34 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (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 java.awt.image.DataBuffer;
22
import java.io.IOException;
23
import java.util.Arrays;
24

    
25
import org.gvsig.raster.buffer.BufferFactory;
26
import org.gvsig.raster.buffer.RasterBuffer;
27
import org.gvsig.raster.buffer.RasterBufferInvalidAccessException;
28
import org.gvsig.raster.buffer.RasterBufferInvalidException;
29
import org.gvsig.raster.dataset.IBuffer;
30
import org.gvsig.raster.dataset.MultiRasterDataset;
31
import org.gvsig.raster.datastruct.Transparency;
32
import org.gvsig.raster.grid.filter.RasterFilterList;
33

    
34
/**
35
 * Clase que representa una rejilla de datos raster. Este tipo de grid tiene el interfaz necesario
36
 * de acceso a la informaci?n raster para aplicaciones de analisis raster. Contiene m?todos de acceso al
37
 * dato tanto en lectura como en escritura y encapsula operaciones entre grids. Adem?s contiene
38
 * objetos que contienen las caracter?sticas asociadas a ese grid. Sobre un grid pueden
39
 * aplicarse tambi?n operaciones de filtrado.
40
 *
41
 * Podemos crear un Grid de cinco formas distitas:
42
 * <UL>
43
 * <LI>A partir de una fuente de datos (cargada en el constructor). Se har? una petici?n del extent pasado por par?metro con las bandas seleccionadas por par?metro.</LI>
44
 * <LI>A partir de un extensi?n de capa, una extensi?n de vista, un tipo de dato y un n?mero de datos
45
 * crea un Grid vacio util para escritura.</LI>
46
 * <LI>A partir de una fuente de datos (cargados). Datasource se usa como buffer de datos cargados y se selecciona si queremos el reader interpolado.</LI>
47
 * <LI>A partir de una fuente de datos (cargada en el constructor). Se har? una petici?n del extent completo de la fuente con las bandas seleccionadas por par?metro.</LI>
48
 * <LI>A partir de una fuente de datos (cargada en el constructor). Se har? una petici?n del extent completo de la fuente con todas las bandas disponibles.</LI>
49
 * </UL>
50
 *
51
 * @author Victor Olaya (volaya@ya.com)
52
 * @author Nacho Brodin (nachobrodin@gmail.com)
53
 */
54
public class Grid implements IQueryableGrid, IWritableGrid{
55

    
56
        //TODO: ARQUITECTURA: Estos tipos de datos no deben ser necesarios. Existiendo IBuffer se tendr?an que usar esos Hay que convertir, antes de eliminarlos, el uso de estos a los de IBuffer
57
        public static final int                 RASTER_DATA_TYPE_FLOAT = DataBuffer.TYPE_FLOAT;
58
        public static final int                 RASTER_DATA_TYPE_DOUBLE = DataBuffer.TYPE_DOUBLE;
59
        public static final int                 RASTER_DATA_TYPE_INT = DataBuffer.TYPE_INT;
60
        public static final int                 RASTER_DATA_TYPE_SHORT = DataBuffer.TYPE_SHORT;
61
        public static final int                 RASTER_DATA_TYPE_BYTE = DataBuffer.TYPE_BYTE;
62

    
63
                public final static double                 DEG_45_IN_RAD = Math.PI / 180. * 45.;
64
                public final static double                 DEG_90_IN_RAD = Math.PI / 180. * 90.;
65
                public final static double                 DEG_180_IN_RAD = Math.PI ;
66
                public final static double                 DEG_270_IN_RAD = Math.PI / 180. * 270.;
67
                public final static double                 DEG_360_IN_RAD = Math.PI * 2.;
68

    
69
        /* neighbor's address*/                        /* N  NE   E  SE   S  SW   W  NW */
70
        private final static int                 m_iOffsetX []=        {  0,  1,  1,  1,  0, -1, -1, -1};
71
        private final static int                m_iOffsetY []=        {  1,  1,  0, -1, -1, -1,  0,  1};
72

    
73
        private double                                         m_dDist[];
74
        public double                                         _2DX, _6DX, _DX_2, _4DX_2;
75

    
76
        private int[]                                         bands = null;
77
        private int                                         dataType = IBuffer.TYPE_UNDEFINED;
78

    
79
        private RasterBuffer                        rasterBuf = null;
80
        private GridReader                                 reader = null;
81
        private GridWriter                                 writer = null;
82
        private GridExtent                                 windowExtent = null;
83
        private GridExtent                                 layerExtent = null;
84
        private GridStatistic                        statistic = null;
85
        private GridTransparency                transparency = null;
86
        private GridPalette[]                        palette = null;
87
        private RasterFilterList                filterList = null;
88

    
89

    
90

    
91
        /**
92
         * Crea un grid a partir de un MultiRasterDataset. Usa el extent de la fuente de datos como
93
         * extent completo y el extent pasado como par?metro como extensi?n de ventana.
94
         *
95
         * Cuando se construye el reader se carga el buffer con la extensi?n definida en windowExtent
96
         * y las bandas especificadas en bands.
97
         *
98
         * @param MultiRasterDataset datasets que proporcionan los datos
99
         * @param bands n?mero de bandas requeridas
100
         * @param windowExtent Extensi?n de la ventana. Si este par?metro es null se usar? el
101
         * mismo que el de la capa.
102
         */
103
        public Grid(MultiRasterDataset datasets, int[] bands, GridExtent windowExtent)
104
                        throws RasterBufferInvalidException{
105
                BufferFactory bFactory = new BufferFactory(datasets);
106
                layerExtent = new GridExtent(bFactory.getExtent(), bFactory.getXCellSize());
107
                dataType = bFactory.getDataType();
108
                this.bands = bands;
109

    
110
                if(windowExtent == null)
111
                        this.windowExtent = layerExtent;
112
                else
113
                        this.windowExtent = windowExtent;
114

    
115
                rasterBuf = (RasterBuffer)bFactory.getRasterBuf();
116

    
117
                if (windowExtent.fitsIn(layerExtent))
118
                        reader = new GridNotInterpolated(bFactory, layerExtent, windowExtent, bands);
119
                else
120
                        reader = new GridInterpolated(bFactory, layerExtent, windowExtent, bands);
121
                writer = new GridWriter(layerExtent, dataType, rasterBuf);
122

    
123
                init(bFactory);
124
        }
125

    
126
        /**
127
         * Crea un grid vacio a partir de un extent y un tipo de datos. Se crea un buffer vacio en el
128
         * que puede escribirse a trav?s del writer. Los datos escritos pueden ser consultados con el
129
         * reader. No tiene una fuente de datos asociada ya que es un grid vacio basicamente para
130
         * escritura.
131
         * @param layerExtent Tama?o completo de la capa
132
         * @param windowExtent Ventana de datos.
133
         * @param dataType Tipo de datos del buffer
134
         * @param bands n?mero de bandas requeridas y orden de dibujado en el buffer
135
         */
136
        public Grid(GridExtent layerExtent,
137
                                GridExtent windowExtent,
138
                                int dataType,
139
                                int[] bands) throws RasterBufferInvalidException{
140
                this.windowExtent = windowExtent;
141
                this.layerExtent = layerExtent;
142
                this.dataType = dataType;
143

    
144
                rasterBuf = RasterBuffer.getBuffer(dataType, layerExtent.getNX(), layerExtent.getNY(), bands.length, true);
145

    
146
                if (windowExtent.fitsIn(layerExtent))
147
                        reader = new GridNotInterpolated(rasterBuf, layerExtent, windowExtent, bands);
148
                else
149
                        reader = new GridInterpolated(rasterBuf, layerExtent, windowExtent, bands);
150
                writer = new GridWriter(layerExtent, dataType, rasterBuf);
151
                init(null);
152
        }
153

    
154
        /**
155
         * Crea un grid a partir de un BufferFactory. El buffer debe estar cargado de datos y el extent
156
         * de este viene definido en el par?metro windowExtent.
157
         * @param dataSource Fuente de datos
158
         * @param windowExtent        Extent de los datos cargados en dataSource
159
         * @param notInterp Si es true fuerza a que el reader sea sin interpolaci?n. Si es false decide si
160
         * el reader es interpolado o no a partir de los extents de capa y la ventana seleccionada.
161
         */
162
        public Grid(BufferFactory dataSource, boolean notInterp) {
163
                this.layerExtent = new GridExtent(dataSource.getExtent(), dataSource.getXCellSize());
164
                dataType = dataSource.getDataType();
165
                bands = dataSource.getDrawableBands();
166

    
167
                this.windowExtent = new GridExtent(dataSource.getDataExtent(), dataSource.getXCellSize());
168

    
169
                rasterBuf = (RasterBuffer)dataSource.getRasterBuf();
170

    
171
                if(notInterp) {
172
                        reader = new GridNotInterpolated(rasterBuf, layerExtent, windowExtent, bands);
173
                } else {
174
                        if (windowExtent.fitsIn(layerExtent))
175
                                reader = new GridNotInterpolated(rasterBuf, layerExtent, windowExtent, bands);
176
                        else
177
                                reader = new GridInterpolated(rasterBuf, layerExtent, windowExtent, bands);
178
                }
179
                writer = new GridWriter(layerExtent, dataType, rasterBuf);
180
                init(dataSource);
181
        }
182

    
183
        /**
184
         * Crea un grid a partir de un BufferFactory. Se har? una petici?n del extent completo de la fuente.
185
         * dataSource tiene asociada una fuente de datos pero se ignorar? si tiene el buffer lleno. La instanciaci?n
186
         * de GridNotInterpolated har? que se haga la petici?n para cargar raster completo.
187
         * @param dataSource Fuente de datos
188
         * @param bands n?mero de bandas requeridas y orden de dibujado en el buffer
189
         */
190
        public Grid(BufferFactory dataSource, int[] bands)
191
                        throws RasterBufferInvalidException{
192
                //La petici?n es del raster completo
193
                windowExtent = layerExtent = new GridExtent(dataSource.getExtent(), dataSource.getXCellSize());
194
                dataType = dataSource.getDataType();
195
                this.bands = bands;
196

    
197
                reader = new GridNotInterpolated(dataSource, layerExtent, windowExtent, bands);
198
                rasterBuf = (RasterBuffer)dataSource.getRasterBuf();
199
                writer = new GridWriter(windowExtent, dataType, rasterBuf);
200

    
201
                init(dataSource);
202
        }
203

    
204
        /**
205
         * Crea un grid a partir de un BufferFactory. Se har? una petici?n del extent completo de la fuente.
206
         * dataSource tiene asociada una fuente de datos pero se ignorar? si tiene el buffer lleno. La instanciaci?n
207
         * de GridNotInterpolated har? que se haga la petici?n para cargar raster completo. El buffer se cargar?
208
         * con todas las bandas disponibles.
209
         * @param dataSource Fuente de datos
210
         */
211
        public Grid(BufferFactory dataSource) throws RasterBufferInvalidException {
212
                //La petici?n es del raster completo
213
                windowExtent = layerExtent = new GridExtent(dataSource.getExtent(), dataSource.getXCellSize());
214
                dataType = dataSource.getDataType();
215

    
216
                bands = new int[dataSource.getBandCount()];
217
                for(int i = 0; i < dataSource.getBandCount(); i ++)
218
                        bands[i] = i;
219
                reader = new GridNotInterpolated(dataSource, layerExtent, windowExtent, bands);
220
                rasterBuf = (RasterBuffer)dataSource.getRasterBuf();
221
                writer = new GridWriter(windowExtent, dataType, rasterBuf);
222

    
223
                init(dataSource);
224
        }
225

    
226
        /**
227
         * Selecciona la forma de obtener datos con o sin interpolaci?n. Si pasamos el par?metro
228
         * false al aplicar un m?todo de consulta de datos este ser? aplicado sin interpolaci?n.
229
         * @param interpolation
230
         */
231
        public void switchToInterpolationMethod(boolean interpolation){
232
                //GridExtent layer = new GridExtent(0, 0, rasterBuf.getWidth(), rasterBuf.getHeight(), 1);
233
                if(interpolation)
234
                        reader = new GridInterpolated(rasterBuf, layerExtent, windowExtent, bands);
235
                else
236
                        reader = new GridNotInterpolated(rasterBuf, layerExtent, windowExtent, bands);
237
                init(null);
238
        }
239

    
240
        /**
241
         * Inicializaci?n de constantes
242
         */
243
        private void init(BufferFactory ds) {
244
                int i;
245
                double dCellSize = getCellSize();
246

    
247
                statistic = new GridStatistic(this);
248
                if(ds == null)
249
                        transparency = new GridTransparency();
250
                else {
251
                        Transparency transp = ds.getMultiRasterDataset().getTransparencyFilesStatus();
252
                        if(transp != null)
253
                                transparency = new GridTransparency(transp);
254
                        this.palette = new GridPalette[ds.getColorTables().length];
255
                        for(int iPal = 0; iPal < ds.getColorTables().length; iPal++) {
256
                                if (ds.getColorTables()[iPal] != null)
257
                                        this.palette[iPal] = new GridPalette(ds.getColorTables()[iPal]);
258
                        }
259
                }
260
                filterList = new RasterFilterList();
261
                if(ds != null) {
262
                        filterList.addParam("IStatistics", ds.getMultiRasterDataset().getStatistics());
263
                        filterList.addParam("MultiRasterDataset", ds.getMultiRasterDataset());
264
                }
265
                filterList.setInitRasterBuf(rasterBuf);
266

    
267
                m_dDist = new double[8];
268

    
269
                        for (i = 0; i < 8; i++) {
270
                                        m_dDist[i] = Math.sqrt ( m_iOffsetX[i] * dCellSize * m_iOffsetX[i] * dCellSize
271
                                                                                                        + m_iOffsetY[i] * dCellSize * m_iOffsetY[i] * dCellSize );
272
                        }
273

    
274
                        _2DX =  dCellSize * 2.0;
275
                        _6DX = dCellSize * 6.0;
276
                _DX_2 = dCellSize * dCellSize;
277
                _4DX_2 = 4.0 * _DX_2;
278
        }
279

    
280
        //************* Write Services *********************
281

    
282
        /*
283
         *  (non-Javadoc)
284
         * @see org.gvsig.fmap.grid.IWritableGrid#assign(byte)
285
         */
286
        public void assign(byte value)throws RasterBufferInvalidAccessException{
287
                writer.assign(value);
288
        }
289

    
290
        /*
291
         *  (non-Javadoc)
292
         * @see org.gvsig.fmap.grid.IWritableGrid#assign(short)
293
         */
294
        public void assign(short value)throws RasterBufferInvalidAccessException{
295
                writer.assign(value);
296
        }
297

    
298
        /*
299
         *  (non-Javadoc)
300
         * @see org.gvsig.fmap.grid.IWritableGrid#assign(int)
301
         */
302
        public void assign(int value)throws RasterBufferInvalidAccessException{
303
                writer.assign(value);
304
        }
305

    
306
        /*
307
         *  (non-Javadoc)
308
         * @see org.gvsig.fmap.grid.IWritableGrid#assign(float)
309
         */
310
        public void assign(float value)throws RasterBufferInvalidAccessException{
311
                writer.assign(value);
312
        }
313

    
314
        /*
315
         *  (non-Javadoc)
316
         * @see org.gvsig.fmap.grid.IWritableGrid#assign(double)
317
         */
318
        public void assign(double value)throws RasterBufferInvalidAccessException{
319
                writer.assign(value);
320
        }
321

    
322
        /*
323
         *  (non-Javadoc)
324
         * @see org.gvsig.fmap.grid.IWritableGrid#assign(org.gvsig.fmap.dataaccess.BufferFactory)
325
         */
326
        public void assign(BufferFactory dataSource)throws RasterBufferInvalidException, OutOfGridException{
327
                Grid window = new Grid(dataSource.getMultiRasterDataset(), bands, windowExtent);
328
                write(window);
329
                writer.setNoDataValue(window.getNoDataValue());
330
        }
331

    
332
        /*
333
         *  (non-Javadoc)
334
         * @see org.gvsig.fmap.grid.IWritableGrid#assign(org.gvsig.fmap.grid.Grid)
335
         */
336
        public void assign(Grid driver)throws OutOfGridException{
337
                if (driver.getGridExtent().equals(layerExtent)){
338
                        write(driver);
339
                        writer.setNoDataValue(driver.getNoDataValue());
340
                }
341
        }
342

    
343
        /**
344
         * Sobreescribe los datos del grid actual con los datos del grid pasado por par?metro
345
         * @param g Grid desde donde se obtienen los datos
346
         */
347
        private void write(Grid g)throws OutOfGridException{
348
                try{
349
                        switch(rasterBuf.getDataType()){
350
                        case IBuffer.TYPE_BYTE: for (int x = 0; x < g.getNX(); x++){
351
                                                                                for (int y = 0; y < g.getNY(); y++){
352
                                                                                        writer.setCellValue(x, y, g.getCellValueAsByte(x, y));
353
                                                                                }
354
                                                                        }
355
                                                                        break;
356
                        case IBuffer.TYPE_SHORT:for (int x = 0; x < g.getNX(); x++){
357
                                                                                for (int y = 0; y < g.getNY(); y++){
358
                                                                                        writer.setCellValue(x, y, g.getCellValueAsShort(x, y));
359
                                                                                }
360
                                                                        }
361
                                                                        break;
362
                        case IBuffer.TYPE_INT:         for (int x = 0; x < g.getNX(); x++){
363
                                                                                for (int y = 0; y < g.getNY(); y++){
364
                                                                                        writer.setCellValue(x, y, g.getCellValueAsInt(x, y));
365
                                                                                }
366
                                                                        }
367
                                                                        break;
368
                        case IBuffer.TYPE_FLOAT:for (int x = 0; x < g.getNX(); x++){
369
                                                                                for (int y = 0; y < g.getNY(); y++){
370
                                                                                        writer.setCellValue(x, y, g.getCellValueAsFloat(x, y));
371
                                                                                }
372
                                                                        }
373
                                                                        break;
374
                        case IBuffer.TYPE_DOUBLE:for (int x = 0; x < g.getNX(); x++){
375
                                                                                for (int y = 0; y < g.getNY(); y++){
376
                                                                                        writer.setCellValue(x, y, g.getCellValueAsDouble(x, y));
377
                                                                                }
378
                                                                        }
379
                                                                        break;
380
                        }
381
                } catch (OutOfGridException e) {
382
                        //No es probable que se salga fuera ya que el bucle se controla dentro de la misma funci?n
383
                        //No hacemos nada para manejar la excepci?n
384
                        e.printStackTrace();
385
                } catch (RasterBufferInvalidAccessException e1) {
386
                        //No es probable que se salga fuera ya que el bucle se controla dentro de la misma funci?n
387
                        //No hacemos nada para manejar la excepci?n
388
                        e1.printStackTrace();
389
                }
390
        }
391

    
392
        /*
393
         *  (non-Javadoc)
394
         * @see org.gvsig.fmap.grid.IWritableGrid#assignNoData()
395
         */
396
        public void assignNoData(){
397
                try {
398
                        switch(rasterBuf.getDataType()){
399
                        case IBuffer.TYPE_BYTE: writer.assign((byte)rasterBuf.getNoDataValue());break;
400
                        case IBuffer.TYPE_SHORT: writer.assign((short)rasterBuf.getNoDataValue());break;
401
                        case IBuffer.TYPE_INT: writer.assign((int)rasterBuf.getNoDataValue());break;
402
                        case IBuffer.TYPE_FLOAT: writer.assign((float)rasterBuf.getNoDataValue());break;
403
                        case IBuffer.TYPE_DOUBLE: writer.assign((double)rasterBuf.getNoDataValue());break;
404
                        }
405
                } catch (RasterBufferInvalidAccessException e) {
406
                        //No hacemos nada. El tipo de dato al que se accede no es controlado por el usuario por lo
407
                        //que no le mandamos la excepci?n hacia arriba.
408
                        e.printStackTrace();
409
                }
410
        }
411

    
412
        /*
413
         *  (non-Javadoc)
414
         * @see org.gvsig.fmap.grid.IWritableGrid#setCellValue(int, int, byte)
415
         */
416
        public void setCellValue(int x, int y, byte value)throws OutOfGridException{
417
                writer.setCellValue(x, y, value);
418
        }
419

    
420
        /*
421
         *  (non-Javadoc)
422
         * @see org.gvsig.fmap.grid.IWritableGrid#setCellValue(int, int, short)
423
         */
424
        public void setCellValue(int x, int y, short value)throws OutOfGridException{
425
                writer.setCellValue(x, y, value);
426
        }
427

    
428
        /*
429
         *  (non-Javadoc)
430
         * @see org.gvsig.fmap.grid.IWritableGrid#setCellValue(int, int, int)
431
         */
432
        public void setCellValue(int x, int y, int value)throws OutOfGridException{
433
                writer.setCellValue(x, y, value);
434
        }
435

    
436
        /*
437
         *  (non-Javadoc)
438
         * @see org.gvsig.fmap.grid.IWritableGrid#setCellValue(int, int, float)
439
         */
440
        public void setCellValue(int x, int y, float value)throws OutOfGridException{
441
                writer.setCellValue(x, y, value);
442
        }
443

    
444
        /*
445
         *  (non-Javadoc)
446
         * @see org.gvsig.fmap.grid.IWritableGrid#setCellValue(int, int, double)
447
         */
448
        public void setCellValue(int x, int y, double value)throws OutOfGridException{
449
                writer.setCellValue(x, y, value);
450
        }
451

    
452
        /*
453
         *  (non-Javadoc)
454
         * @see org.gvsig.fmap.grid.IWritableGrid#add(org.gvsig.fmap.grid.Grid)
455
         */
456
        public void add(Grid g){
457
                if (g.getGridExtent().equals(getGridExtent())){
458
                        boolean interp = (reader instanceof GridInterpolated);
459
                        switchToInterpolationMethod(false);
460
                        try{
461
                                switch(rasterBuf.getDataType()){
462
                                case IBuffer.TYPE_BYTE: for (int x = 0; x < g.getNX(); x++){
463
                                                                                        for (int y = 0; y < g.getNY(); y++){
464
                                                                                                writer.setCellValue(x, y, reader.getCellValueAsByte(x, y) + g.getCellValueAsByte(x,y));
465
                                                                                        }
466
                                                                                }
467
                                                                                break;
468
                                case IBuffer.TYPE_SHORT:for (int x = 0; x < g.getNX(); x++){
469
                                                                                        for (int y = 0; y < g.getNY(); y++){
470
                                                                                                writer.setCellValue(x, y, reader.getCellValueAsShort(x, y) + g.getCellValueAsShort(x,y));
471
                                                                                        }
472
                                                                                }
473
                                                                                break;
474
                                case IBuffer.TYPE_INT:         for (int x = 0; x < g.getNX(); x++){
475
                                                                                        for (int y = 0; y < g.getNY(); y++){
476
                                                                                                writer.setCellValue(x, y, reader.getCellValueAsInt(x, y) + g.getCellValueAsInt(x,y));
477
                                                                                        }
478
                                                                                }
479
                                                                                break;
480
                                case IBuffer.TYPE_FLOAT:for (int x = 0; x < g.getNX(); x++){
481
                                                                                        for (int y = 0; y < g.getNY(); y++){
482
                                                                                                writer.setCellValue(x, y, reader.getCellValueAsFloat(x, y) + g.getCellValueAsFloat(x,y));
483
                                                                                        }
484
                                                                                }
485
                                                                                break;
486
                                case IBuffer.TYPE_DOUBLE:for (int x = 0; x < g.getNX(); x++){
487
                                                                                        for (int y = 0; y < g.getNY(); y++){
488
                                                                                                writer.setCellValue(x, y, reader.getCellValueAsDouble(x, y) + g.getCellValueAsDouble(x,y));
489
                                                                                        }
490
                                                                                }
491
                                                                                break;
492
                                }
493
                        } catch (OutOfGridException e) {
494
                                //No es probable que se salga fuera ya que el bucle se controla dentro de la misma funci?n
495
                                //No hacemos nada para manejar la excepci?n
496
                                e.printStackTrace();
497
                        } catch (RasterBufferInvalidAccessException e1) {
498
                                //No es probable que se salga fuera ya que el bucle se controla dentro de la misma funci?n
499
                                //No hacemos nada para manejar la excepci?n
500
                                e1.printStackTrace();
501
                        }
502
                        //Restauramos el reader que hab?a
503
                        switchToInterpolationMethod(interp);
504
                }
505
        }
506

    
507
        /*
508
         *  (non-Javadoc)
509
         * @see org.gvsig.fmap.grid.IWritableGrid#addToCellValue(int, int, byte)
510
         */
511
        public void addToCellValue(int x, int y, byte value)
512
                throws OutOfGridException, RasterBufferInvalidAccessException{
513
                writer.setCellValue(x, y, (byte)(reader.getCellValueAsByte(x, y) + value));
514
        }
515

    
516
        /*
517
         *  (non-Javadoc)
518
         * @see org.gvsig.fmap.grid.IWritableGrid#addToCellValue(int, int, short)
519
         */
520
        public void addToCellValue(int x, int y, short value)
521
                throws OutOfGridException, RasterBufferInvalidAccessException{
522
                writer.setCellValue(x, y, (short)(reader.getCellValueAsShort(x, y) + value));
523
        }
524

    
525
        /*
526
         *  (non-Javadoc)
527
         * @see org.gvsig.fmap.grid.IWritableGrid#addToCellValue(int, int, int)
528
         */
529
        public void addToCellValue(int x, int y, int value)
530
                throws OutOfGridException, RasterBufferInvalidAccessException{
531
                writer.setCellValue(x, y, (int)(reader.getCellValueAsInt(x, y) + value));
532
        }
533

    
534
        /*
535
         *  (non-Javadoc)
536
         * @see org.gvsig.fmap.grid.IWritableGrid#addToCellValue(int, int, float)
537
         */
538
        public void addToCellValue(int x, int y, float value)
539
                throws OutOfGridException, RasterBufferInvalidAccessException{
540
                writer.setCellValue(x, y, (float)(reader.getCellValueAsFloat(x, y) + value));
541
        }
542

    
543
        /*
544
         *  (non-Javadoc)
545
         * @see org.gvsig.fmap.grid.IWritableGrid#addToCellValue(int, int, double)
546
         */
547
        public void addToCellValue(int x, int y, double value)
548
                throws OutOfGridException, RasterBufferInvalidAccessException{
549
                writer.setCellValue(x, y, (double)(reader.getCellValueAsDouble(x, y) + value));
550
        }
551

    
552
        /*
553
         *  (non-Javadoc)
554
         * @see org.gvsig.fmap.grid.IWritableGrid#multiply(double)
555
         */
556
        public void multiply(double value){
557
                boolean interp = (reader instanceof GridInterpolated);
558
                switchToInterpolationMethod(false);
559
                try{
560
                        switch(rasterBuf.getDataType()){
561
                        case IBuffer.TYPE_BYTE: for (int x = 0; x < getNX(); x++){
562
                                                                                for (int y = 0; y < getNY(); y++)
563
                                                                                        writer.setCellValue(x, y, (byte)(reader.getCellValueAsByte(x, y) * value));
564
                                                                        }
565
                                                                        break;
566
                        case IBuffer.TYPE_SHORT:for (int x = 0; x < getNX(); x++){
567
                                                                                for (int y = 0; y < getNY(); y++)
568
                                                                                        writer.setCellValue(x, y, (short)(reader.getCellValueAsShort(x, y) * value));
569
                                                                        }
570
                                                                        break;
571
                        case IBuffer.TYPE_INT:         for (int x = 0; x < getNX(); x++){
572
                                                                                for (int y = 0; y < getNY(); y++)
573
                                                                                        writer.setCellValue(x, y, (int)(reader.getCellValueAsInt(x, y) * value));
574
                                                                        }
575
                                                                        break;
576
                        case IBuffer.TYPE_FLOAT:for (int x = 0; x < getNX(); x++){
577
                                                                                for (int y = 0; y < getNY(); y++)
578
                                                                                        writer.setCellValue(x, y, (float)(reader.getCellValueAsFloat(x, y) * value));
579
                                                                        }
580
                                                                        break;
581
                        case IBuffer.TYPE_DOUBLE:for (int x = 0; x < getNX(); x++){
582
                                                                                for (int y = 0; y < getNY(); y++)
583
                                                                                        writer.setCellValue(x, y, (double)(reader.getCellValueAsDouble(x, y) * value));
584
                                                                        }
585
                                                                        break;
586
                        }
587
                } catch (OutOfGridException e) {
588
                        //No es probable que se salga fuera ya que el bucle se controla dentro de la misma funci?n
589
                        //No hacemos nada para manejar la excepci?n
590
                        e.printStackTrace();
591
                } catch (RasterBufferInvalidAccessException e1) {
592
                        //No es probable que se salga fuera ya que el bucle se controla dentro de la misma funci?n
593
                        //No hacemos nada para manejar la excepci?n
594
                        e1.printStackTrace();
595
                }
596
                //Restauramos el reader que hab?a
597
                switchToInterpolationMethod(interp);
598
        }
599

    
600
        /*
601
         *  (non-Javadoc)
602
         * @see org.gvsig.fmap.grid.IWritableGrid#setNoDataValue(double)
603
         */
604
        public void setNoDataValue(double dNoDataValue){
605
                writer.setNoDataValue((float) dNoDataValue);
606
        }
607

    
608
        /*
609
         *  (non-Javadoc)
610
         * @see org.gvsig.fmap.grid.IWritableGrid#setNoData(int, int)
611
         */
612
        public void setNoData(int x, int y){
613
                writer.setNoData(x,y);
614
        }
615

    
616
        public void ExportToArcViewASCIIFile(String sFilename){
617
                try {
618
                        writer.ExportToArcViewASCIIFile(sFilename);
619
                } catch (NumberFormatException e) {
620
                        e.printStackTrace();
621
                } catch (IOException e) {
622
                        e.printStackTrace();
623
                }
624
        }
625

    
626
        //************* Query Services *********************
627

    
628
        /*
629
         *  (non-Javadoc)
630
         * @see org.gvsig.fmap.grid.IQueryableGrid#isNoDataValue(double)
631
         */
632
        public boolean isNoDataValue(double noDataValue){
633
                return (reader.getNoDataValue() == noDataValue);
634
        }
635

    
636
        /*
637
         *  (non-Javadoc)
638
         * @see org.gvsig.fmap.grid.IQueryableGrid#isInGrid(int, int)
639
         */
640
        public boolean isInGrid(int x, int y){
641
                return reader.isCellInGrid(x, y);
642
        }
643

    
644
        /*
645
         *  (non-Javadoc)
646
         * @see org.gvsig.fmap.grid.IQueryableGrid#getCellSize()
647
         */
648
        public double getCellSize() {
649
                return reader.getCellSize();
650
        }
651

    
652
        /*
653
         *  (non-Javadoc)
654
         * @see org.gvsig.fmap.grid.IQueryableGrid#getCellValueAsByte(int, int)
655
         */
656
        public byte getCellValueAsByte(int x, int y)throws RasterBufferInvalidAccessException {
657
                return  reader.getCellValueAsByte(x, y);
658
        }
659

    
660
        /*
661
         *  (non-Javadoc)
662
         * @see org.gvsig.fmap.grid.IQueryableGrid#getCellValueAsShort(int, int)
663
         */
664
        public short getCellValueAsShort(int x, int y)throws RasterBufferInvalidAccessException {
665
                return (short) reader.getCellValueAsShort(x, y);
666
        }
667

    
668
        /*
669
         *  (non-Javadoc)
670
         * @see org.gvsig.fmap.grid.IQueryableGrid#getCellValueAsInt(int, int)
671
         */
672
        public int getCellValueAsInt(int x, int y)throws RasterBufferInvalidAccessException {
673
                return (int) reader.getCellValueAsInt(x, y);
674
        }
675

    
676
        /*
677
         *  (non-Javadoc)
678
         * @see org.gvsig.fmap.grid.IQueryableGrid#getCellValueAsFloat(int, int)
679
         */
680
        public float getCellValueAsFloat(int x, int y)throws RasterBufferInvalidAccessException {
681
                return reader.getCellValueAsFloat(x, y);
682
        }
683

    
684
        /*
685
         *  (non-Javadoc)
686
         * @see org.gvsig.fmap.grid.IQueryableGrid#getCellValueAsDouble(int, int)
687
         */
688
        public double getCellValueAsDouble(int x, int y)throws RasterBufferInvalidAccessException {
689
                return (double) reader.getCellValueAsDouble(x, y);
690
        }
691

    
692
        /*
693
         *  (non-Javadoc)
694
         * @see org.gvsig.fmap.grid.IQueryableGrid#getNoDataValue()
695
         */
696
        public double getNoDataValue(){
697
                return (double) rasterBuf.getNoDataValue();
698
        }
699

    
700
        /*
701
         *  (non-Javadoc)
702
         * @see org.gvsig.fmap.grid.IQueryableGrid#getMinValue()
703
         */
704
        public double getMinValue(){
705
                if (!statistic.isStatisticsCalculated())
706
                        try {
707
                                statistic.calculateStatistics();
708
                        } catch (RasterBufferInvalidAccessException e) {
709
                                //No se calculan las estad?sticas. No hacemos nada
710
                                e.printStackTrace();
711
                        }
712
                return statistic.getMin();
713
        }
714

    
715
        /*
716
         *  (non-Javadoc)
717
         * @see org.gvsig.fmap.grid.IQueryableGrid#getMaxValue()
718
         */
719
        public double getMaxValue(){
720
                if (!statistic.isStatisticsCalculated())
721
                        try {
722
                                statistic.calculateStatistics();
723
                        } catch (RasterBufferInvalidAccessException e) {
724
                                //No se calculan las estad?sticas. No hacemos nada
725
                                e.printStackTrace();
726
                        }
727
                return statistic.getMax();
728
        }
729

    
730
        /*
731
         *  (non-Javadoc)
732
         * @see org.gvsig.fmap.grid.IQueryableGrid#getMeanValue()
733
         */
734
        public double getMeanValue(){
735
                if (!statistic.isStatisticsCalculated())
736
                        try {
737
                                statistic.calculateStatistics();
738
                        } catch (RasterBufferInvalidAccessException e) {
739
                                //No se calculan las estad?sticas. No hacemos nada
740
                                e.printStackTrace();
741
                        }
742
                return statistic.getMean();
743
        }
744

    
745
        /*
746
         *  (non-Javadoc)
747
         * @see org.gvsig.fmap.grid.IQueryableGrid#getVariance()
748
         */
749
        public double getVariance(){
750
                if (!statistic.isStatisticsCalculated())
751
                        try {
752
                                statistic.calculateStatistics();
753
                        } catch (RasterBufferInvalidAccessException e) {
754
                                //No se calculan las estad?sticas. No hacemos nada
755
                                e.printStackTrace();
756
                        }
757
                return statistic.getVariance();
758
        }
759

    
760
        /*
761
         *  (non-Javadoc)
762
         * @see org.gvsig.fmap.grid.IQueryableGrid#setInterpolationMethod(int)
763
         */
764
        public void setInterpolationMethod(int iMethod){
765
                if (reader instanceof GridInterpolated)
766
                        ((GridInterpolated) reader).setInterpolationMethod(iMethod);
767
                else{
768
                        this.switchToInterpolationMethod(true);
769
                        ((GridInterpolated) reader).setInterpolationMethod(iMethod);
770
                }
771
        }
772

    
773
        /*
774
         *  (non-Javadoc)
775
         * @see org.gvsig.fmap.grid.IQueryableGrid#getNX()
776
         */
777
        public int getNX(){
778
                return reader.getNX();
779
        }
780

    
781
        /*
782
         *  (non-Javadoc)
783
         * @see org.gvsig.fmap.grid.IQueryableGrid#getNY()
784
         */
785
        public int getNY(){
786
                return reader.getNY();
787
        }
788

    
789
        /*
790
         *  (non-Javadoc)
791
         * @see org.gvsig.fmap.grid.IQueryableGrid#getLayerNX()
792
         */
793
        public int getLayerNX(){
794
                return layerExtent.getNX();
795
        }
796

    
797
        /*
798
         *  (non-Javadoc)
799
         * @see org.gvsig.fmap.grid.IQueryableGrid#getLayerNY()
800
         */
801
        public int getLayerNY(){
802
                return layerExtent.getNY();
803
        }
804

    
805
        /*
806
         *  (non-Javadoc)
807
         * @see org.gvsig.fmap.grid.IWritableGrid#getGridExtent()
808
         */
809
        /*public GridExtent getGridExtent(){
810
                return windowExtent;
811
        }*/
812

    
813
        public int getDataType(){
814
                return dataType;
815
        }
816

    
817
        private boolean getSubMatrix3x3(int x, int y, double SubMatrix[])throws RasterBufferInvalidAccessException{
818
                int        i;
819
                int iDir;
820
                double        z, z2;
821

    
822
                z = getCellValueAsDouble(x, y);
823

    
824
                if(isNoDataValue(z)){
825
                        return false;
826
                }
827
                else{
828
                        //SubMatrix[4]        = 0.0;
829
                        for(i=0; i<4; i++){
830

    
831
                                iDir = 2 * i;
832
                                z2 = getCellValueAsDouble(x + m_iOffsetX[iDir], y + m_iOffsetY[iDir]);
833
                                if( !isNoDataValue(z2)){
834
                                        SubMatrix[i]        =  z2 - z;
835
                                }
836
                                else{
837
                                        z2 = getCellValueAsDouble(x + m_iOffsetX[(iDir + 4) % 8], y + m_iOffsetY[(iDir  + 4) % 8]);
838
                                        if( !isNoDataValue(z2)){
839
                                                SubMatrix[i]        = z - z2;
840
                                        }
841
                                        else{
842
                                                SubMatrix[i]        = 0.0;
843
                                        }
844
                                }
845
                        }
846

    
847
                        return true;
848
                }
849
        }
850

    
851
        public double getSlope(int x, int y)throws RasterBufferInvalidAccessException{
852
                double        zm[], G, H;
853

    
854
                zm = new double[4];
855

    
856
                if( getSubMatrix3x3(x, y, zm) ){
857
                        G        =  (zm[0] - zm[2])                                        / _2DX;
858
                                        H        =  (zm[1] - zm[3])                                        / _2DX;
859
                                        return Math.atan(Math.sqrt(G*G + H*H));
860
                }
861
                else{
862
                        return rasterBuf.getNoDataValue();
863
                }
864
        }
865

    
866
        public double getAspect(int x, int y)throws RasterBufferInvalidAccessException{
867
                double        zm[], G, H, dAspect;
868

    
869
                zm = new double[4];
870

    
871
                if( getSubMatrix3x3(x, y, zm) ){
872
                        G        =  (zm[0] - zm[2]) / _2DX;
873
                                        H        =  (zm[1] - zm[3]) / _2DX;
874
                        if( G != 0.0 )
875
                                dAspect = DEG_180_IN_RAD + Math.atan2(H, G);
876
                        else
877
                                dAspect = H > 0.0 ? DEG_270_IN_RAD : (H < 0.0 ? DEG_90_IN_RAD : -1.0);
878
                        return dAspect;
879
                }
880
                else
881
                        return rasterBuf.getNoDataValue();
882
        }
883

    
884
        public static int getXOffsetInDir(int iDir){
885
                return m_iOffsetX[iDir];
886
        }
887

    
888
        public static int getYOffsetInDir(int iDir){
889
                return m_iOffsetY[iDir];
890
        }
891

    
892
        public double getDistToNeighborInDir(int iDir){
893
                return m_dDist[iDir];
894
        }
895

    
896
        public static double getUnitDistToNeighborInDir(int iDir){
897
                return( (iDir % 2 != 0) ? Math.sqrt(2.0)  : 1.0 );
898
        }
899

    
900
        /*
901
         *  (non-Javadoc)
902
         * @see org.gvsig.fmap.grid.IQueryableGrid#getDirToNextDownslopeCell(int, int)
903
         */
904
        public int getDirToNextDownslopeCell(int x, int y)throws RasterBufferInvalidAccessException{
905
                return getDirToNextDownslopeCell(x, y, true);
906
        }
907

    
908
        /*
909
         *  (non-Javadoc)
910
         * @see org.gvsig.fmap.grid.IQueryableGrid#getDirToNextDownslopeCell(int, int, boolean)
911
         */
912
        public int getDirToNextDownslopeCell(int x, int y, boolean bForceDirToNoDataCell)
913
                throws RasterBufferInvalidAccessException{
914

    
915
                int                i, iDir;
916
                double        z, z2, dSlope, dMaxSlope;
917

    
918
                z = getCellValueAsDouble(x, y);
919

    
920
                if(isNoDataValue(z)){
921
                        return -1;
922
                }
923

    
924
                dMaxSlope = 0.0;
925
                for(iDir=-1, i=0; i<8; i++){
926
                        z2 = getCellValueAsDouble(x + m_iOffsetX[i], y + m_iOffsetY[i]);
927
                        if(isNoDataValue(z2)){
928
                                if (bForceDirToNoDataCell){
929
                                        return i;
930
                                }
931
                                else{
932
                                        return -1;
933
                                }
934
                        }
935
                        else{
936
                                dSlope        = (z - z2) / getDistToNeighborInDir(i);
937
                                if( dSlope > dMaxSlope ){
938
                                        iDir = i;
939
                                        dMaxSlope = dSlope;
940
                                }
941
                        }
942
                }
943

    
944
                return iDir;
945

    
946
        }
947

    
948
        public GridCell[] getSortedArrayOfCells()throws RasterBufferInvalidAccessException{
949
                int i;
950
                int iX,iY;
951
                int iNX =  getNX();
952
                int iCells = getNX() * getNY();
953
                GridCell [] cells = null;
954
                GridCell cell = null;
955

    
956
                cells = new GridCell[iCells];
957

    
958
                for (i = 0; i < iCells; i++){
959
                        iX = i % iNX;
960
                        iY = i / iNX;
961
                        switch(getDataType()){
962
                        case IBuffer.TYPE_BYTE: cell = new GridCell(iX, iY, getCellValueAsByte(iX, iY)); break;
963
                        case IBuffer.TYPE_SHORT: cell = new GridCell(iX, iY, getCellValueAsShort(iX, iY)); break;
964
                        case IBuffer.TYPE_INT: cell = new GridCell(iX, iY, getCellValueAsInt(iX, iY)); break;
965
                        case IBuffer.TYPE_FLOAT: cell = new GridCell(iX, iY, getCellValueAsFloat(iX, iY)); break;
966
                        case IBuffer.TYPE_DOUBLE: cell = new GridCell(iX, iY, getCellValueAsDouble(iX, iY)); break;
967
                        }
968

    
969
                        cells[i] = cell;
970
                }
971

    
972
                Arrays.sort(cells);
973

    
974
                return cells;
975
        }
976

    
977
        /**
978
         * Obtiene el estado de transparencia
979
         * @return Objeto con el estado de transparencia del grid
980
         */
981
        public GridTransparency getTransparency() {
982
                return transparency;
983
        }
984

    
985
        /**
986
         * Asigna el estado de transparencia
987
         * @param Objeto con el estado de transparencia del grid
988
         */
989
        public void setTransparency(GridTransparency transparency) {
990
                this.transparency = transparency;
991
        }
992

    
993
        /**
994
         * Obtiene la paleta para el caso de un MDT. Esta funci?n evita el tener que obtener
995
         * un array de paletas y buscar en el cuando se trata de un caso simple de MDT de una
996
         * sola banda. Comprueba que se trata de un raster monobanda con paleta asociada antes
997
         * de devolverla.
998
         * @return GridPalette asociada al Grid
999
         */
1000
        public GridPalette        getMDTPalette(){
1001
                if(        rasterBuf != null &&
1002
                        rasterBuf.getBandCount() == 1 &&
1003
                        palette != null)
1004
                        return palette[0];
1005
                return null;
1006
        }
1007

    
1008
        /**
1009
         * Obtiene la lista de paletas asociadas al grid
1010
         * @return Lista de objetos GridPalette
1011
         */
1012
        public GridPalette[] getPalettes() {
1013
                return palette;
1014
        }
1015

    
1016
        /**
1017
         * Obtiene el n?mero de bandas del grid o 0 si no tiene buffer de
1018
         * datos asociado.
1019
         * @return N?mero de bandas
1020
         */
1021
        public int getBandCount() {
1022
                if(rasterBuf != null)
1023
                        return rasterBuf.getBandCount();
1024
                return 0;
1025
        }
1026

    
1027
        /**
1028
         * Asigna la lista de paletas asociadas al grid
1029
         * @param palette Lista de objetos GridPalette
1030
         */
1031
        public void setPalettes(GridPalette[] palette) {
1032
                this.palette = palette;
1033
        }
1034

    
1035
        /**
1036
         * Obtiene la lista de filtros.
1037
         * @return Lista de filtros.
1038
         */
1039
        public RasterFilterList getFilterList(){
1040
                return filterList;
1041
        }
1042

    
1043
        /**
1044
         * Asigna la lista de filtros
1045
         * @param filterList
1046
         */
1047
        public void setFilterList(RasterFilterList filterList){
1048
                this.filterList = filterList;
1049
        }
1050

    
1051
        /**
1052
         *Aplica la lista de filtros sobre el buffer
1053
         * @throws InterruptedException
1054
         */
1055
        public void applyFilters() throws InterruptedException{
1056
                if (filterList == null)
1057
                        return;
1058

    
1059
                filterList.setInitRasterBuf(rasterBuf);
1060
                filterList.execute();
1061
                rasterBuf = (RasterBuffer) filterList.getResult();
1062
                dataType = rasterBuf.getDataType();
1063
        }
1064

    
1065
        /**
1066
         * Obtiene el buffer de datos del grid
1067
         * @return RasterBuf
1068
         */
1069
        public IBuffer getRasterBuf() {
1070
                return rasterBuf;
1071
        }
1072

    
1073
        /**
1074
         * Asigna la banda sobre la que se realizan las operaciones. Por defecto es la banda 0
1075
         * con lo que para el uso de MDTs no habr? que modificar este valor.
1076
         * @param band Banda sobre la que se realizan las operaciones.
1077
         */
1078
        public void setBandToOperate(int band){
1079
                if(writer != null)
1080
                        writer.setBandToOperate(band);
1081
                if(reader != null)
1082
                        reader.setBandToOperate(band);
1083
                if(statistic != null)
1084
                        statistic.setBandToOperate(band);
1085
        }
1086

    
1087
        /**
1088
         * Obtiene el extent de la ventana seleccionada para petici?n de datos
1089
         * @return GridExtent
1090
         */
1091
        public GridExtent getWindowExtent(){
1092
                return windowExtent;
1093
        }
1094

    
1095
        /**
1096
         * Obtiene el extent del grid para petici?n de datos
1097
         * @return GridExtent
1098
         */
1099
        public GridExtent getGridExtent(){
1100
                return layerExtent;
1101
        }
1102
}