Statistics
| Revision:

gvsig-raster / org.gvsig.raster.netcdf / trunk / org.gvsig.raster.netcdf / org.gvsig.raster.netcdf.io / src / main / java / org / gvsig / raster / netcdf / io / NetCDFProvider.java @ 1074

History | View | Annotate | Download (29.4 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.netcdf.io;
23

    
24
import java.awt.geom.AffineTransform;
25
import java.awt.geom.Point2D;
26
import java.io.IOException;
27
import java.util.List;
28

    
29
import org.gvsig.fmap.dal.DALFileLocator;
30
import org.gvsig.fmap.dal.DALLocator;
31
import org.gvsig.fmap.dal.DataStore;
32
import org.gvsig.fmap.dal.coverage.RasterLocator;
33
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
34
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
35
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
36
import org.gvsig.fmap.dal.coverage.exception.BandAccessException;
37
import org.gvsig.fmap.dal.coverage.exception.FileNotOpenException;
38
import org.gvsig.fmap.dal.coverage.exception.InvalidSetViewException;
39
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
40
import org.gvsig.fmap.dal.coverage.exception.ParsingException;
41
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
42
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
43
import org.gvsig.fmap.dal.coverage.store.parameter.RasterFileStoreParameters;
44
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
45
import org.gvsig.fmap.dal.exception.OpenException;
46
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
47
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
48
import org.gvsig.metadata.MetadataLocator;
49
import org.gvsig.raster.cache.tile.provider.TileListener;
50
import org.gvsig.raster.cache.tile.provider.TileServer;
51
import org.gvsig.raster.impl.DefaultRasterManager;
52
import org.gvsig.raster.impl.datastruct.DefaultNoData;
53
import org.gvsig.raster.impl.datastruct.ExtentImpl;
54
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
55
import org.gvsig.raster.impl.provider.RasterProvider;
56
import org.gvsig.raster.impl.provider.tile.FileTileServer;
57
import org.gvsig.raster.impl.store.DefaultStoreFactory;
58
import org.gvsig.raster.impl.store.properties.DataStoreColorInterpretation;
59
import org.gvsig.raster.impl.store.properties.DataStoreTransparency;
60
import org.gvsig.tools.ToolsLocator;
61
import org.gvsig.tools.task.Cancellable;
62
import org.gvsig.tools.task.TaskStatus;
63
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65

    
66
import ucar.ma2.Array;
67
import ucar.ma2.DataType;
68
import ucar.ma2.InvalidRangeException;
69
import ucar.ma2.Range;
70
import ucar.nc2.dt.GridDatatype;
71
import ucar.nc2.dt.grid.GridDataset;
72
import ucar.unidata.geoloc.ProjectionRect;
73
/**
74
 * Data provider for NetCDF files with raster data
75
 *
76
 * @author Nacho Brodin (nachobrodin@gmail.com)
77
 */
78
@SuppressWarnings("deprecation")
79
public class NetCDFProvider extends DefaultRasterProvider {
80
        public static String                     NAME                     = "NetCDF Raster";
81
        public static String                     DESCRIPTION              = "NetCDF Raster file";
82
        public final String                      METADATA_DEFINITION_NAME = NAME;
83
        private Extent                           viewRequest              = null;
84
        private TileServer                       tileServer               = null;
85
        private boolean                          open                     = false;
86
        
87
    private GridDataset                      gridNetCDF               = null;
88
    private List<GridDatatype>               gridList                 = null;
89
    private GridDatatype                     selectedGridDataType     = null;
90
    private DataStoreTransparency            fileTransparency         = null;
91
    private static final Logger              logger                   = LoggerFactory.getLogger(NetCDFProvider.class);
92
    protected static String[]                formatList               = null;
93
    
94
        public static void register() {
95
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
96
                RasterLocator.getManager().registerFileProvidersTiled(NetCDFProvider.class);
97
                registerFormats();
98
                
99
                if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
100
                        dataman.registerStoreProvider(NAME,
101
                                        NetCDFProvider.class, NetCDFDataParametersImpl.class);
102
                }
103
        
104

    
105
                /*if (!dataman.getExplorerProviders().contains(NetCDFFilesystemServerExplorer.NAME)) {
106
                        dataman.registerExplorerProvider(NetCDFFilesystemServerExplorer.NAME, NetCDFFilesystemServerExplorer.class, NetCDFServerExplorerParameters.class);
107
                }*/
108
                
109
                if(DALFileLocator.getFilesystemServerExplorerManager() != null)
110
                        DALFileLocator.getFilesystemServerExplorerManager().registerProvider(
111
                                        NAME, DESCRIPTION,
112
                                        NetCDFFilesystemServerExplorer.class);
113
                
114
                
115
                dataman.registerStoreFactory(NAME, DefaultStoreFactory.class);
116
        }
117
        
118
        private static void registerFormats() {
119
                formatList      = new String[] {"nc"};
120
                for (int i = 0; i < formatList.length; i++) 
121
                        RasterLocator.getManager().addFormat(formatList[i], NetCDFProvider.class);
122
        }
123
        
124
        /*
125
         * (non-Javadoc)
126
         * @see org.gvsig.raster.impl.provider.RasterProvider#getFormatList()
127
         */
128
        public String[] getFormatList() {
129
                return formatList;
130
        }
131
        
132
        /**
133
         * Returns true if the extension is supported and false if doesn't
134
         * @param ext
135
         * @return
136
         */
137
        public boolean isExtensionSupported(String ext) {
138
                if(ext.indexOf(".") != -1)
139
                        ext = ext.substring(ext.lastIndexOf(".") + 1, ext.length());
140
                for (int i = 0; i < formatList.length; i++) {
141
                        if(formatList[i].compareTo(ext) == 0)
142
                                return true;
143
                }
144
                return false;
145
        }
146
        
147
        public NetCDFProvider() {
148
        }
149
        
150
        /**
151
         * Opens the dataset.
152
         * @param proj Projection
153
         * @param fName File name
154
         * @throws NotSupportedExtensionException
155
         */
156
        public NetCDFProvider(String params) throws NotSupportedExtensionException, OpenException {
157
                super(params);
158
                if(params instanceof String) {
159
                        NetCDFDataParameters p = new NetCDFDataParametersImpl();
160
                        p.setURI((String)params);
161
                        super.init(p, null, ToolsLocator.getDynObjectManager()
162
                                        .createDynObject(
163
                                                        MetadataLocator.getMetadataManager().getDefinition(
164
                                                                        DataStore.METADATA_DEFINITION_NAME)));
165
                        init(p, null);
166
                }
167
        }
168
        
169
        public NetCDFProvider (NetCDFDataParameters params,
170
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException, OpenException {
171
                super(params, storeServices, ToolsLocator.getDynObjectManager()
172
                                .createDynObject(
173
                                                MetadataLocator.getMetadataManager().getDefinition(
174
                                                                DataStore.METADATA_DEFINITION_NAME)));
175
                init(params, storeServices);
176
        }
177

    
178
        /**
179
         * Build file references
180
         * @param proj Projection
181
         * @param param Load parameters
182
         * @throws NotSupportedExtensionException
183
         */
184
        public void init (NetCDFDataParameters params,
185
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException, OpenException {
186
                
187
                if(((RasterFileStoreParameters)params).getFile().exists()) {
188
                        String fileName = ((RasterFileStoreParameters)params).getFile().getAbsolutePath();
189
            try { 
190
                    gridNetCDF = GridDataset.open(fileName);
191
                    gridList = gridNetCDF.getGrids();
192
                    if(gridList.size() == 0)
193
                            throw new OpenException("There is not a grid variable", null);
194
                    selectedGridDataType = gridList.get(0);
195
                //netCDFFile = NetcdfFile.open(((RasterFileStoreParameters)params).getFile().getAbsolutePath());
196
            } catch (IOException e) {
197
                throw new OpenException("Imposible to read the file", e);
198
            }  
199
            
200
            /*List<Variable> variableList = netCDFFile.getVariables();
201
            Iterator<Variable> it = variableList.iterator();
202
            while(it.hasNext()) {
203
                    Variable var = it.next();
204
                    System.out.println("===>>" + var.getName());
205
            }*/
206
            
207
                        setParam(storeServices, params);
208
                        reloadMetadataFromGrid();
209
                        
210
                        noData = new DefaultNoData(Double.NaN, Double.NaN, fileName);
211
                        load();
212
                } else
213
                        setParam(storeServices, params);
214
                
215
                super.init();
216
                selectSubdataset(getId(0, 0, 0));
217
                try {
218
                        loadFromRmf(getRmfBlocksManager());
219
                } catch (ParsingException e) {
220
                        //No lee desde rmf
221
                }
222
                open = true;
223
        }
224
        
225
        /**
226
         * Reloads metadata using the selected grid
227
         */
228
        private void reloadMetadataFromGrid() {
229
                wktProjection = null;
230
                //CrsWkt crs = new CrsWkt(wktProjection);
231
                //IProjection proj = CRSFactory.getCRS("EPSG:23030");
232
                
233
                /*LatLonRect gcs = selectedGridDataType.getCoordinateSystem().getLatLonBoundingBox();
234
                getColorInterpretation();
235
                double scaleX = gcs.getWidth() / selectedGridDataType.getXDimension().getLength();
236
                double scaleY = gcs.getHeight() / selectedGridDataType.getYDimension().getLength();
237
                ownTransformation = new AffineTransform(
238
                                scaleX, 0, 
239
                                0, -scaleY, 
240
                                gcs.getLonMin(), 
241
                                gcs.getLatMax());*/
242
                
243
                ProjectionRect pRect = selectedGridDataType.getCoordinateSystem().getBoundingBox();
244
                double scaleX = pRect.getWidth() / selectedGridDataType.getXDimension().getLength();
245
                double scaleY = pRect.getHeight() / selectedGridDataType.getYDimension().getLength();
246
                ownTransformation = new AffineTransform(
247
                                scaleX, 0, 
248
                                0, -scaleY, 
249
                                pRect.getMinX(), 
250
                                pRect.getMaxY());
251
                externalTransformation = (AffineTransform)ownTransformation.clone();
252
                bandCount = 1; //One variable is always shown
253
                setDataType();
254
        }
255
        
256
        /**
257
         * @param dataType The dataType to set.
258
         */
259
        private void setDataType() {
260
                DataType dt = selectedGridDataType.getDataType();
261
                int type = Buffer.TYPE_UNDEFINED;
262
                if(dt.name() == DataType.BYTE.name()) {
263
                        type = Buffer.TYPE_BYTE;
264
                }
265
                if(dt.name() == DataType.SHORT.name()) {
266
                        type = Buffer.TYPE_SHORT;
267
                }
268
                if(dt.name() == DataType.INT.name()) {
269
                        type = Buffer.TYPE_INT;
270
                }
271
                if(dt.name() == DataType.DOUBLE.name()) {
272
                        type = Buffer.TYPE_DOUBLE;
273
                }
274
                if(dt.name() == DataType.FLOAT.name()) {
275
                        type = Buffer.TYPE_FLOAT;
276
                }
277
                if(dt.name() == DataType.LONG.name()) {
278
                        type = Buffer.TYPE_DOUBLE;
279
                }
280
                
281
                int[] dtype = new int[getBandCount()];
282
                for (int i = 0; i < dtype.length; i++)
283
                        dtype[i] = type;
284
                setDataType(dtype);
285
        }
286
        
287
        /*
288
         * (non-Javadoc)
289
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#load()
290
         */
291
        public RasterProvider load() {
292
                return this;
293
        }
294
        
295
        /*
296
         * (non-Javadoc)
297
         * @see org.gvsig.raster.impl.provider.RasterProvider#isOpen()
298
         */
299
        public boolean isOpen() {
300
                return open;
301
        }
302

    
303
        /*
304
         * (non-Javadoc)
305
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#close()
306
         */
307
        public void close() {
308
                try {
309
                        gridNetCDF.close();
310
                } catch (IOException e) {
311
                        logger.error("Error closing file", e);
312
                }
313
        }
314

    
315
        /*
316
         * (non-Javadoc)
317
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#translateFileName(java.lang.String)
318
         */
319
        public String translateFileName(String fileName) {
320
                return fileName;
321
        }
322

    
323
        /**
324
         * Asigna el extent de la vista actual. existe un fichero .rmf debemos hacer una transformaci�n
325
         * de la vista asignada ya que la petici�n viene en coordenadas del fichero .rmf y la vista (v)
326
         * ha de estar en coordenadas del fichero.
327
         */
328
        public void setView(Extent e) {
329
                viewRequest = new ExtentImpl(e);
330
        }
331

    
332
        /*
333
         * (non-Javadoc)
334
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getView()
335
         */
336
        public Extent getView() {
337
                return viewRequest;
338
        }
339

    
340
        /*
341
         * (non-Javadoc)
342
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWidth()
343
         */
344
        public double getWidth() {
345
                return selectedGridDataType.getXDimension().getLength();
346
        }
347

    
348
        /*
349
         * (non-Javadoc)
350
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getHeight()
351
         */
352
        public double getHeight() {
353
                return selectedGridDataType.getYDimension().getLength();
354
        }
355

    
356
        /*
357
         *  (non-Javadoc)
358
         * @see org.gvsig.raster.dataset.RasterDataset#readBlock(int, int, double)
359
         */
360
        public Object readBlock(int pos, int blockHeight, double scale)
361
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException, ProcessInterruptedException {
362
                NetCDFDataParameters p = (NetCDFDataParameters)param;
363
                if(pos < 0)
364
                        throw new InvalidSetViewException("Request out of grid");
365

    
366
                if((pos + blockHeight) > getHeight())
367
                        blockHeight = Math.abs(((int)getHeight()) - pos);
368
                
369
                Buffer buf = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], (int)getWidth(), blockHeight, 1, true);
370
                try {
371
                        int time = p.getFieldTime();
372
                        int level = getLevelValue();
373
                        Range rangeY = new Range(pos, pos + blockHeight - 1, 1);
374
                        Range rangeX = new Range(0, (int)(getWidth() - 1), 1);
375
                        GridDatatype dt = selectedGridDataType.makeSubset(null, null, null, null /*getTime(1), getLevel(1)*/, rangeY, rangeX);
376
                        Array values = dt.readDataSlice(time, level, -1, -1);
377
                        return arrayValuesToBuffer(values, buf, rangeX.length(), rangeY.length(), null);
378
                } catch (IOException e) {
379
                        throw new RasterDriverException("Error reading a slice", e);
380
                } catch (InvalidRangeException e) {
381
                        throw new RasterDriverException("Error reading a slice", e);
382
                }
383
        }
384

    
385
        /*
386
         * (non-Javadoc)
387
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getData(int, int, int)
388
         */
389
        public Object getData(int x, int y, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
390
                NetCDFDataParameters p = (NetCDFDataParameters)param;
391
                if(x < 0 || y < 0 || x >= getWidth() || y >= getHeight())
392
                        throw new InvalidSetViewException("Request out of grid");
393
                try {
394
                        int strideX = 1;
395
                        int strideY = 1;
396
                        Range rangeY = new Range((int)(getHeight() - y), (int)(getHeight() - y), strideY);
397
                        Range rangeX = new Range(x, x, strideX);
398
                        
399
                        selectSubdataset();
400
                        int time = p.getFieldTime();
401
                        int level = getLevelValue();
402
                        GridDatatype dt = selectedGridDataType.makeSubset(null, null, null, null, rangeY, rangeX);
403
                        Array values = dt.readDataSlice(time, level, -1, -1);
404
                        Object data = null;
405
                        
406
                        if(getDataType()[0] == Buffer.TYPE_BYTE) {
407
                                data = new java.lang.Integer(values.getByte(0));
408
                        }
409

    
410
                        if(getDataType()[0] == Buffer.TYPE_SHORT) {
411
                                data = new java.lang.Integer(values.getShort(0));
412
                        }
413

    
414
                        if(getDataType()[0] == Buffer.TYPE_INT) {
415
                                data = new java.lang.Integer(values.getInt(0));
416
                        }
417

    
418
                        if(getDataType()[0] == Buffer.TYPE_FLOAT) {
419
                                data = new java.lang.Float(values.getFloat(0));
420
                        }
421
                        if(getDataType()[0] == Buffer.TYPE_DOUBLE) {
422
                                data = new java.lang.Double(values.getDouble(0));
423
                        }
424
                        return data;
425
                } catch (IOException e) {
426
                        throw new RasterDriverException("Error reading a slice", e);
427
                } catch (InvalidRangeException e) {
428
                        throw new RasterDriverException("Error reading a slice", e);
429
                }
430
        }
431

    
432
        /*
433
         * (non-Javadoc)
434
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.raster.cache.tile.provider.TileListener)
435
         */
436
        public void getWindow(Extent ex, int bufWidth, int bufHeight, 
437
                        BandList bandList, TileListener listener, Cancellable status) throws ProcessInterruptedException, RasterDriverException {
438
        }
439

    
440
        /*
441
         * (non-Javadoc)
442
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(org.gvsig.fmap.dal.coverage.datastruct.Extent, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
443
         */
444
        public Buffer getWindow(Extent extent, BandList bandList, Buffer rasterBuf, TaskStatus status) 
445
                throws ProcessInterruptedException, RasterDriverException {
446
                NetCDFDataParameters p = (NetCDFDataParameters)param;
447
                setView(extent);
448

    
449
                Point2D ul = new Point2D.Double(viewRequest.getULX(), viewRequest.getULY());
450
                Point2D lr = new Point2D.Double(viewRequest.getLRX(), viewRequest.getLRY());
451
                ul = worldToRaster(ul);
452
                lr = worldToRaster(lr);
453
                ul.setLocation(ul.getX() < 0 ? 0 : ul.getX(), ul.getY() < 0 ? 0 : ul.getY());
454
                lr.setLocation(lr.getX() < 0 ? 0 : lr.getX(), lr.getY() < 0 ? 0 : lr.getY());
455
                ul.setLocation(ul.getX() > getWidth() ? getWidth() : ul.getX(), ul.getY() > getHeight() ? getHeight() : ul.getY());
456
                lr.setLocation(lr.getX() > getWidth() ? getWidth() : lr.getX(), lr.getY() > getHeight() ? getHeight() : lr.getY());
457
                
458
                adjustPoints(ul, lr);
459
                 
460
                try {
461
                        int strideX = 1;
462
                        int strideY = 1;
463
                        Range rangeY = new Range((int)(getHeight() - lr.getY()), (int)(getHeight() - ul.getY() - 1), strideY);
464
                        Range rangeX = new Range((int)ul.getX(), (int)(lr.getX() - 1), strideX);
465
                        
466
                        selectSubdataset();
467
                        int time = p.getFieldTime();
468
                        int level = getLevelValue();
469
                        GridDatatype dt = selectedGridDataType.makeSubset(null, null, null, null /*getTime(strideX), getLevel(strideX)*/, rangeY, rangeX);
470
                        Array values = dt.readDataSlice(time, level, -1, -1);
471
                        rasterBuf = arrayValuesToBuffer(values, rasterBuf, rangeX.length(), rangeY.length(), bandList);
472
                } catch (IOException e) {
473
                        throw new RasterDriverException("Error reading a slice", e);
474
                } catch (InvalidRangeException e) {
475
                        throw new RasterDriverException("Error reading a slice", e);
476
                }
477
                
478
                return rasterBuf;
479
        }
480
        
481
        /**
482
         * Gets the Range of the selected time or null if there is not a selected time
483
         * @param strideX
484
         * @return
485
         * @throws InvalidRangeException
486
         */
487
        @SuppressWarnings("unused")
488
        private Range getTime(int strideX) throws InvalidRangeException {
489
                NetCDFDataParameters p = (NetCDFDataParameters)param;
490
                int time = p.getFieldTime();
491
                return new Range(time, time, strideX);
492
        }
493
        
494
        /*private int getTimeValue() {
495
                int time = 0;
496
                if(param.hasDynValue(NetCDFDataParameters.FIELD_TIME))
497
                        time = ((Integer)param.getDynValue(NetCDFDataParameters.FIELD_TIME)).intValue();
498
                return time;
499
        }*/
500
        
501
        /**
502
         * Gets the Range of the selected level or null if there is not a selected level
503
         * @param strideX
504
         * @return
505
         * @throws InvalidRangeException
506
         */
507
        @SuppressWarnings("unused")
508
        private Range getLevel(int strideX) throws InvalidRangeException {
509
                int level = getLevelValue();
510
                return new Range(level, level, strideX);
511
        }
512
        
513
        private int getLevelValue() {
514
                int level = 0;
515
                if(param.hasDynValue(NetCDFDataParameters.FIELD_LEVEL))
516
                        level = ((Integer)param.getDynValue(NetCDFDataParameters.FIELD_LEVEL)).intValue();
517
                return level;
518
        }
519
        
520
        
521
        /**
522
         * Selects the GridDataType using the selected variable in the parameters
523
         */
524
        public void selectSubdataset() {
525
                if(param.hasDynValue(NetCDFDataParameters.FIELD_VARIABLE)) {
526
                        NetCDFDataParameters p = (NetCDFDataParameters)param;
527
                        String variable = (String)param.getDynValue(NetCDFDataParameters.FIELD_VARIABLE);
528
                        if(variable != null) {
529
                                for (int j = 0; j < gridList.size(); j++) {
530
                                        if(gridList.get(j).getName().compareTo(variable) == 0) {
531
                                                selectedGridDataType = gridList.get(j);
532
                                                reloadMetadataFromGrid();
533
                                                super.selectSubdataset(getId(j, getLevelValue(), p.getFieldTime()));
534
                                        }
535
                                }
536
                        }
537
                }
538
        }
539

    
540
        /**
541
         * Gets the identifier of a subdataset
542
         * @param grid
543
         * @param level
544
         * @param time
545
         * @return
546
         */
547
        private String getId(int grid, int level, int time) {
548
                return grid + "-" + level + "-" +  time;
549
        }
550
        
551
        /**
552
         * Loads a Buffer object from an netCDF Array. 
553
         * @param values
554
         * @param rasterBuf
555
         * @param w
556
         * @param h
557
         * @return
558
         */
559
        private Buffer arrayValuesToBuffer(Array values, Buffer rasterBuf, int w, int h, BandList bandList) {
560
                Buffer buf = null;
561
                boolean resampling = false;
562
                
563
                if((rasterBuf.getWidth() * rasterBuf.getHeight()) != values.getSize()) {
564
                        buf = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], w, h, rasterBuf.getBandCount(), true);
565
                        resampling = true;
566
                } else
567
                        buf = rasterBuf;
568
                
569
                int[] drawableBands = bandList != null ? bandList.getBufferBandToDraw(getURIOfFirstProvider(), 0) : new int[1];
570
                if(drawableBands == null || (drawableBands.length == 1 && drawableBands[0] == -1))
571
                        return rasterBuf;
572
                
573
                if(getDataType()[0] == Buffer.TYPE_BYTE) {
574
                        for (int i = 0; i < values.getSize(); i++) {
575
                                int[] rc = getColAndRow(i, buf);
576
                                for (int iBands = 0; iBands < drawableBands.length; iBands++) 
577
                                        buf.setElem(rc[0], rc[1], drawableBands[iBands], values.getByte(i));
578
                        }
579
                }
580

    
581
                if(getDataType()[0] == Buffer.TYPE_SHORT) {
582
                        for (int i = 0; i < values.getSize(); i++) {
583
                                int[] rc = getColAndRow(i, buf);
584
                                for (int iBands = 0; iBands < drawableBands.length; iBands++) 
585
                                        buf.setElem(rc[0], rc[1], drawableBands[iBands], values.getShort(i));
586
                        }
587
                }
588

    
589
                if(getDataType()[0] == Buffer.TYPE_INT) {
590
                        for (int i = 0; i < values.getSize(); i++) {
591
                                int[] rc = getColAndRow(i, buf);
592
                                for (int iBands = 0; iBands < drawableBands.length; iBands++) 
593
                                        buf.setElem(rc[0], rc[1], drawableBands[iBands], values.getInt(i));
594
                        }
595
                }
596

    
597
                if(getDataType()[0] == Buffer.TYPE_FLOAT) {
598
                        for (int i = 0; i < values.getSize(); i++) {
599
                                int[] rc = getColAndRow(i, buf);
600
                                for (int iBands = 0; iBands < drawableBands.length; iBands++) 
601
                                        buf.setElem(rc[0], rc[1], drawableBands[iBands], values.getFloat(i));
602
                        }
603
                }
604

    
605
                if(getDataType()[0] == Buffer.TYPE_DOUBLE) {
606
                        for (int i = 0; i < values.getSize(); i++) {
607
                                int[] rc = getColAndRow(i, buf);
608
                                for (int iBands = 0; iBands < drawableBands.length; iBands++) 
609
                                        buf.setElem(rc[0], rc[1], drawableBands[iBands], values.getDouble(i));
610
                        }
611
                }
612
                if(resampling) {
613
                        try {
614
                                Buffer result = null;
615
                                result = buf.getAdjustedWindow(rasterBuf.getWidth(), rasterBuf.getHeight(), Buffer.INTERPOLATION_NearestNeighbour);
616
                                if(result != buf)
617
                                        buf.dispose();
618
                                return result;
619
                        } catch (ProcessInterruptedException e) {
620
                                return buf;
621
                        }
622
                }
623
                return buf;
624
        }
625
        
626
        /**
627
         * Calculates the row and column number for the position i in the
628
         * array of data
629
         * @param i
630
         * @param buf
631
         * @return
632
         */
633
        private int[] getColAndRow(int i, Buffer buf) {
634
                int auxRow = (int)(i / buf.getWidth());
635
                return new int[]{ 
636
                                (int)buf.getHeight() - auxRow - 1,
637
                                i - (auxRow * buf.getWidth())
638
                                };
639
        }
640

    
641
        /*
642
         * (non-Javadoc)
643
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer, boolean)
644
         */
645
        public Buffer getWindow(double ulx, double uly, double w, double h, 
646
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
647
                return rasterBuf;
648
        }
649

    
650
        /*
651
         * (non-Javadoc)
652
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer, boolean)
653
         */
654
        public Buffer getWindow(Extent extent, int bufWidth, int bufHeight, 
655
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
656
                NetCDFDataParameters p = (NetCDFDataParameters)param;
657
                setView(extent);
658

    
659
                Point2D ul = new Point2D.Double(viewRequest.getULX(), viewRequest.getULY());
660
                Point2D lr = new Point2D.Double(viewRequest.getLRX(), viewRequest.getLRY());
661
                ul = worldToRaster(ul);
662
                lr = worldToRaster(lr);
663
                ul.setLocation(ul.getX() < 0 ? 0 : ul.getX(), ul.getY() < 0 ? 0 : ul.getY());
664
                lr.setLocation(lr.getX() < 0 ? 0 : lr.getX(), lr.getY() < 0 ? 0 : lr.getY());
665
                ul.setLocation(ul.getX() >= getWidth() ? getWidth() - 1 : ul.getX(), ul.getY() >= getHeight() ? getHeight() - 1 : ul.getY());
666
                lr.setLocation(lr.getX() >= getWidth() ? getWidth() - 1 : lr.getX(), lr.getY() >= getHeight() ? getHeight() - 1 : lr.getY());
667
                
668
                adjustPoints(ul, lr);
669
                
670
                int width = Math.abs(((int)lr.getX()) - ((int)ul.getX()));
671
                int height = Math.abs(((int)lr.getY()) - ((int)ul.getY()));
672
                
673
                try {
674
                        int strideX = width / rasterBuf.getWidth();
675
                        int strideY = height / rasterBuf.getHeight();
676
                        Range rangeY = new Range((int)(getHeight() - lr.getY()), (int)(getHeight() - ul.getY() - 1), strideY <= 0 ? 1 : strideY);
677
                        Range rangeX = new Range((int)ul.getX(), (int)(lr.getX() - 1), strideX <= 0 ? 1 : strideX);
678
                        
679
                        selectSubdataset();
680
                        int time = p.getFieldTime();
681
                        int level = getLevelValue();
682
                        GridDatatype dt = selectedGridDataType.makeSubset(null, null, null, null /*getTime(strideX), getLevel(strideX)*/, rangeY, rangeX);
683
                        Array values = dt.readDataSlice(time, level, -1, -1);
684
                        rasterBuf = arrayValuesToBuffer(values, rasterBuf, rangeX.length(), rangeY.length(), bandList);
685
                } catch (IOException e) {
686
                        throw new RasterDriverException("Error reading a slice", e);
687
                } catch (InvalidRangeException e) {
688
                        throw new RasterDriverException("Error reading a slice", e);
689
                }
690
                
691
                return rasterBuf;
692
        }
693
        
694
        private void adjustPoints(Point2D ul, Point2D lr) {
695
                double a = (ul.getX() - (int)ul.getX());
696
                double b = (ul.getY() - (int)ul.getY());
697
                ul.setLocation(        (a > 0.95 || a < 0.05) ? Math.round(ul.getX()) : ul.getX(), 
698
                                                (b > 0.95 || b < 0.05) ? Math.round(ul.getY()) : ul.getY());
699
                lr.setLocation(        (a > 0.95 || a < 0.05) ? Math.round(lr.getX()) : lr.getX(), 
700
                                                (b > 0.95 || b < 0.05) ? Math.round(lr.getY()) : lr.getY());
701
        }
702

    
703
        /*
704
         * (non-Javadoc)
705
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(int, int, int, int, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
706
         */
707
        public Buffer getWindow(int x, int y, int w, int h, 
708
                        BandList bandList, Buffer rasterBuf, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
709
                try {
710
                        NetCDFDataParameters p = (NetCDFDataParameters)param;
711
                        int strideX = 1;
712
                        int strideY = 1;
713
                        Range rangeY = new Range((int)(h - y), (int)(h - y - 1), strideY);
714
                        Range rangeX = new Range((int)x, (int)(x + w - 1), strideX);
715
                        
716
                        selectSubdataset();
717
                        int time = p.getFieldTime();
718
                        int level = getLevelValue();
719
                        GridDatatype dt = selectedGridDataType.makeSubset(null, null, null, null, rangeY, rangeX);
720
                        Array values = dt.readDataSlice(time, level, -1, -1);
721
                        rasterBuf = arrayValuesToBuffer(values, rasterBuf, rangeX.length(), rangeY.length(), bandList);
722
                } catch (IOException e) {
723
                        throw new RasterDriverException("Error reading a slice", e);
724
                } catch (InvalidRangeException e) {
725
                        throw new RasterDriverException("Error reading a slice", e);
726
                }
727
                
728
                return rasterBuf;
729
        }
730

    
731
        /*
732
         * (non-Javadoc)
733
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getBlockSize()
734
         */
735
        public int getBlockSize(){
736
                return 0;
737
        }
738

    
739
        /*
740
         * (non-Javadoc)
741
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getColorInterpretation()
742
         */
743
        public ColorInterpretation getColorInterpretation() {
744
                if(super.getColorInterpretation() == null) {
745
                        setColorInterpretation(new DataStoreColorInterpretation(new String[]{ColorInterpretation.GRAY_BAND}));
746
                }
747
                return super.getColorInterpretation();
748
        }
749

    
750
        /*
751
         * (non-Javadoc)
752
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTransparency()
753
         */
754
        public DataStoreTransparency getTransparency() {
755
                if(fileTransparency == null)
756
                        fileTransparency = new DataStoreTransparency();
757
                return fileTransparency;
758
        }
759

    
760
        /**
761
         * Informa de si el driver ha supersampleado en el �ltimo dibujado. Es el driver el que colocar�
762
         * el valor de esta variable cada vez que dibuja.
763
         * @return true si se ha supersampleado y false si no se ha hecho.
764
         */
765
        public boolean isSupersampling() {
766
                return false;
767
        }
768

    
769
        /*
770
         * (non-Javadoc)
771
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setAffineTransform(java.awt.geom.AffineTransform)
772
         */
773
        public void setAffineTransform(AffineTransform t){
774
                super.setAffineTransform(t);
775
        }
776

    
777
        /*
778
         * (non-Javadoc)
779
         * @see org.gvsig.raster.impl.provider.RasterProvider#getOverviewCount(int)
780
         */
781
        public int getOverviewCount(int band) throws BandAccessException, RasterDriverException {
782
                if(band >= getBandCount())
783
                        throw new BandAccessException("Wrong band");
784
                return 0;
785
        }
786

    
787
        /*
788
         * (non-Javadoc)
789
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewWidth(int, int)
790
         */
791
        public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException {
792
                if (band >= getBandCount())
793
                        throw new BandAccessException("Wrong band");
794
                return 0;
795
        }
796

    
797
        /*
798
         * (non-Javadoc)
799
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewHeight(int, int)
800
         */
801
        public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException {
802
                if (band >= getBandCount())
803
                        throw new BandAccessException("Wrong band");
804
                return 0;
805
        }
806

    
807
        /*
808
         * (non-Javadoc)
809
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isOverviewsSupported()
810
         */
811
        public boolean isOverviewsSupported() {
812
                return true;
813
        }
814

    
815
        /*
816
         * (non-Javadoc)
817
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isReproyectable()
818
         */
819
        public boolean isReproyectable() {
820
                return true;
821
        }
822

    
823
        /*
824
         * (non-Javadoc)
825
         * @see org.gvsig.fmap.dal.spi.DataStoreProvider#getName()
826
         */
827
        public String getName() {
828
                return NAME;
829
        }
830
        
831
        /*
832
         * (non-Javadoc)
833
         * @see org.gvsig.raster.impl.provider.RasterProvider#setStatus(org.gvsig.raster.impl.provider.RasterProvider)
834
         */
835
        public void setStatus(RasterProvider provider) {
836
                if(provider instanceof NetCDFProvider) {
837
                        //Not implemented yet
838
                }
839
        }
840
        
841
        /*
842
         * (non-Javadoc)
843
         * @see org.gvsig.raster.impl.provider.RasterProvider#isTimeSupported()
844
         */
845
        public boolean isTimeSupported() {
846
                return true;
847
        }
848
        
849
        /*
850
         * (non-Javadoc)
851
         * @see org.gvsig.raster.impl.provider.RasterProvider#getTileServer()
852
         */
853
        public TileServer getTileServer() {
854
                if(tileServer == null)
855
                        tileServer = new FileTileServer(this);
856
                return tileServer;
857
        }
858
}