Statistics
| Revision:

gvsig-geoprocess / org.gvsig.sextante / trunk / org.gvsig.sextante.app / org.gvsig.sextante.app.extension / src / main / java / org / gvsig / sextante / app / extension / core / gvRasterLayer.java @ 119

History | View | Annotate | Download (18.9 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.sextante.app.extension.core;
23

    
24
import java.awt.geom.AffineTransform;
25
import java.awt.geom.Rectangle2D;
26
import java.io.BufferedWriter;
27
import java.io.File;
28
import java.io.FileWriter;
29
import java.io.IOException;
30
import java.text.DecimalFormat;
31
import java.text.DecimalFormatSymbols;
32
import java.util.Locale;
33

    
34
import es.unex.sextante.dataObjects.AbstractRasterLayer;
35
import es.unex.sextante.dataObjects.IRasterLayer;
36
import es.unex.sextante.rasterWrappers.GridExtent;
37

    
38
import org.cresques.cts.IProjection;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

    
42
import org.gvsig.andami.Utilities;
43
import org.gvsig.fmap.dal.store.raster.RasterStoreParameters;
44
import org.gvsig.fmap.raster.layers.FLyrRasterSE;
45
import org.gvsig.raster.buffer.RasterBufferInvalidException;
46
import org.gvsig.raster.buffer.WriterBufferServer;
47
import org.gvsig.raster.dataset.GeoRasterWriter;
48
import org.gvsig.raster.dataset.IBuffer;
49
import org.gvsig.raster.dataset.NotSupportedExtensionException;
50
import org.gvsig.raster.dataset.Params;
51
import org.gvsig.raster.dataset.RasterDriverException;
52
import org.gvsig.raster.grid.Grid;
53
import org.gvsig.raster.grid.GridException;
54

    
55
/**
56
 * {@link IRasterLayer} implementation to be used in gvSIG.
57
 * Allows to read information from a {@link FLyrRasterSE} or to create
58
 * a new Grid to be written.
59
 * 
60
 * @author gvSIG Team
61
 * @version $Id$
62
 */
63
public class gvRasterLayer extends AbstractRasterLayer {
64

    
65
    private static final Logger LOG = LoggerFactory
66
        .getLogger(gvRasterLayer.class);
67

    
68
    private IProjection projection = null;
69
    private FLyrRasterSE rasterLayer;
70
    private Grid grid = null;
71
    private int dataType = -1;
72
    /**
73
     * Cached value optimization: the getNoDataValue() method seems to be
74
     * called by sextante for each pixel.
75
     */
76
    private double noDataValue;
77
    /**
78
     * Cached value optimization: the getBandsCount() method seems to be
79
     * called by sextante for each pixel.
80
     */
81
    private int bandsCount;
82

    
83
    private String filename = null;
84
    private String name;
85

    
86
    private GridExtent sextanteExtent;
87

    
88
    private double DEFAULT_NO_DATA_VALUE = -99999.0D;
89

    
90
    public void create(Grid grid, int bandsCount, double noDataValue,
91
        IProjection projection, String name, String fileName) {
92

    
93
        LOG.debug("Create with grid = {}, bandsCount = {}, noDataValue = {}"
94
            + ", projection = {}, name = {}, fileName = {}", new Object[] {
95
            grid, bandsCount, noDataValue, projection, name, fileName });
96

    
97
        this.grid = grid;
98
        this.bandsCount = bandsCount;
99
        this.noDataValue = noDataValue;
100
        this.projection = projection;
101
        this.name = name;
102
        this.filename = fileName;
103
        if (grid != null) {
104
            this.dataType = grid.getDataType();
105
        }
106
    }
107

    
108
    public void create(FLyrRasterSE rasterLayer) {
109

    
110
        LOG.debug("Create with a rasterLayer: {}", rasterLayer);
111

    
112
        Grid grid = createReadOnlyGrid(rasterLayer);
113
        create(grid, rasterLayer.getBandCount(), rasterLayer.getNoDataValue(),
114
            rasterLayer.getProjection(), rasterLayer.getName(), rasterLayer
115
                .getDataSource().getDataset(0)[0].getFName());
116
        this.rasterLayer = rasterLayer;
117
        this.m_BaseDataObject = rasterLayer;
118
    }
119

    
120
    public void create(String sName, Object inputParams, GridExtent ge,
121
        int iDataType, int iNumBands, Object crs) {
122

    
123
        LOG.debug("Create with name = {}, inputParams = {}, grid extent = {}"
124
            + ", data type = {}, bands = {}, crs = {}", new Object[] { sName,
125
            inputParams, ge, iDataType, iNumBands, crs });
126

    
127
        if (inputParams instanceof RasterStoreParameters) {
128
            create(sName, ((RasterStoreParameters) inputParams).getFileName(),
129
                ge, iDataType, iNumBands, crs);
130
        }
131
    }
132

    
133
    public void create(String sName, String sFilename, GridExtent ge,
134
        int iDataType, int iNumBands, Object crs) {
135

    
136
        LOG.debug("Create with name = {}, fileName = {}, grid extent = {}"
137
            + ", data type = {}, bands = {}, crs = {}", new Object[] { sName,
138
            filename, ge, iDataType, iNumBands, crs });
139

    
140
        int[] bands = new int[iNumBands];
141
        for (int i = 0; i < bands.length; i++) {
142
            bands[i] = i;
143
        }
144
        org.gvsig.raster.grid.GridExtent gridExtent =
145
            new org.gvsig.raster.grid.GridExtent(ge.getXMin(), ge.getYMin(),
146
                ge.getXMax(), ge.getYMax(), ge.getCellSize());
147
        try {
148
            grid = new Grid(gridExtent, gridExtent, iDataType, bands);
149
        } catch (RasterBufferInvalidException e) {
150
            throw new RuntimeException(
151
                "Error creating a new empty writable Grid with: GridExtent = "
152
                    + gridExtent + ", data type = " + iDataType + ", bands = "
153
                    + iNumBands, e);
154
        }
155
        grid.setNoDataValue(DEFAULT_NO_DATA_VALUE);
156

    
157
        IProjection projection =
158
            crs instanceof IProjection ? (IProjection) crs : null;
159

    
160
        this.sextanteExtent = ge;
161
        create(grid, iDataType, iNumBands, projection, sName, sFilename);
162
    }
163

    
164
    public void create(String sName, String sFilename, GridExtent ge,
165
        int iDataType, Object crs) {
166

    
167
        LOG.debug("Create with name = {}, fileName = {}, grid extent = {}"
168
            + ", data type = {}, crs = {}", new Object[] { sName, filename, ge,
169
            iDataType, crs });
170

    
171
        create(sName, sFilename, ge, iDataType, 1, crs);
172
    }
173

    
174
    public int getDataType() {
175
        return grid.getDataType();
176
    }
177

    
178
    @Override
179
    public void assign(double dValue) {
180
        if (isWritable()) {
181
            super.assign(dValue);
182
        }
183
    }
184

    
185
    @Override
186
    public void assign(IRasterLayer layer) {
187
        if (isWritable()) {
188
            super.assign(layer);
189
        }
190
    }
191

    
192
    /**
193
     * If the contained grid is a writable one.
194
     * 
195
     * @return if the contained grid is a writable one
196
     */
197
    private final boolean isWritable() {
198
        return rasterLayer == null;
199
    }
200

    
201
    @Override
202
    public void setNoData(int x, int y) {
203
        if (isWritable()) {
204
            grid.setNoData(x, y);
205
        }
206
    }
207

    
208
    public void setNoDataValue(double dNoDataValue) {
209
        grid.setNoDataValue(dNoDataValue);
210
        this.noDataValue = dNoDataValue;
211
    }
212

    
213
    public double getNoDataValue() {
214
        // Safer approach:
215
        // return isWritable() ? noDataValue : rasterLayer.getNoDataValue();
216
        // More efficient approach:
217
        return noDataValue;
218
    }
219

    
220
    public double getCellValueInLayerCoords(int x, int y, int band) {
221

    
222
        IBuffer buffer = grid.getRasterBuf();
223
        switch (dataType) {
224
        case IBuffer.TYPE_DOUBLE:
225
            return buffer.getElemDouble(y, x, band);
226
        case IBuffer.TYPE_FLOAT:
227
            return buffer.getElemFloat(y, x, band);
228
        case IBuffer.TYPE_INT:
229
            return buffer.getElemInt(y, x, band);
230
        case IBuffer.TYPE_SHORT:
231
        case IBuffer.TYPE_USHORT:
232
            return buffer.getElemShort(y, x, band);
233
        case IBuffer.TYPE_BYTE:
234
            return (buffer.getElemByte(y, x, band) & 0xff);
235
        default:
236
            return grid.getNoDataValue();
237
        }
238
    }
239

    
240
    public void setCellValue(int x, int y, int band, double dValue) {
241
        if (isWritable()) {
242
            switch (grid.getDataType()) {
243
            case IBuffer.TYPE_DOUBLE:
244
                grid.getRasterBuf().setElem(y, x, band, dValue);
245
                break;
246
            case IBuffer.TYPE_FLOAT:
247
                grid.getRasterBuf().setElem(y, x, band, (float) dValue);
248
                break;
249
            case IBuffer.TYPE_INT:
250
                grid.getRasterBuf().setElem(y, x, band, (int) dValue);
251
                break;
252
            case IBuffer.TYPE_SHORT:
253
            case IBuffer.TYPE_USHORT:
254
                grid.getRasterBuf().setElem(y, x, band, (short) dValue);
255
                break;
256
            case IBuffer.TYPE_BYTE:
257
                grid.getRasterBuf().setElem(y, x, band, (byte) dValue);
258
                break;
259
            }
260
        }
261
    }
262

    
263
    public int getBandsCount() {
264
        return isWritable() ? bandsCount : rasterLayer.getBandCount();
265
    }
266

    
267
    public void fitToGridExtent(GridExtent ge) {
268
        if (isWritable()) {
269
            int iNX, iNY;
270
            int x, y;
271
            int iBand;
272

    
273
            if (ge != null) {
274
                if (!ge.equals(getWindowGridExtent())) {
275
                    if (isWritable()) {
276

    
277
                        FLyrRasterSE gvSIGLayer =
278
                            getRasterLayer(
279
                                Long.toString(System.currentTimeMillis())
280
                                    .toString(), projection);
281
                        gvRasterLayer orgLayer = new gvRasterLayer();
282
                        orgLayer.create(gvSIGLayer);
283

    
284
                        iNX = ge.getNX();
285
                        iNY = ge.getNY();
286

    
287
                        m_BaseDataObject = null;
288

    
289
                        create(this.getName(), getFilename(), ge,
290
                            this.getDataType(), this.getBandsCount());
291
                        for (iBand = 0; iBand < this.getBandsCount(); iBand++) {
292
                            for (y = 0; y < iNY; y++) {
293
                                for (x = 0; x < iNX; x++) {
294
                                    setCellValue(x, y, iBand,
295
                                        orgLayer.getCellValueAsDouble(x, y,
296
                                            iBand));
297
                                }
298
                            }
299
                        }
300
                    }
301
                }
302
            }
303
        }
304
    }
305

    
306
    public FLyrRasterSE getRasterLayer(String sDescription,
307
        IProjection projection) {
308

    
309
        FLyrRasterSE layer;
310
        String sFilename = getFilename(sDescription, "tif");
311
        try {
312
            exportToGeoTiff(sFilename, projection);
313
            layer =
314
                FLyrRasterSE.createLayer(sDescription, new File(sFilename),
315
                    projection);
316
            layer.setNoDataValue(this.getNoDataValue());
317
            return layer;
318
        } catch (Exception e) {
319
            e.printStackTrace();
320
            return null;
321
        }
322

    
323
    }
324

    
325
    public static String getFilename(String sRoot, String sExtension) {
326

    
327
        String sFilename;
328
        int i = 1;
329

    
330
        sRoot = sRoot.toLowerCase();
331
        sRoot = sRoot.replaceAll(" ", "_");
332
        sRoot = sRoot.replaceAll("\\)", "");
333
        sRoot = sRoot.replaceAll("\\(", "_");
334
        sRoot = sRoot.replaceAll("\\[", "_");
335
        sRoot = sRoot.replaceAll("\\]", "");
336
        sRoot = sRoot.replaceAll("<", "_");
337
        sRoot = sRoot.replaceAll(">", "_");
338
        sRoot = sRoot.replaceAll("__", "_");
339

    
340
        while (true) {
341
            sFilename =
342
                Utilities.createTempDirectory() + File.separator + sRoot
343
                    + Integer.toString(i) + "." + sExtension;
344
            File file = new File(sFilename);
345
            if (file.exists()) {
346
                i++;
347
            } else {
348
                return sFilename;
349
            }
350
        }
351

    
352
    }
353

    
354
    public void postProcess() {
355
        LOG.debug("postProcess: writable? = {}", isWritable());
356
        if (isWritable()) {
357
            export(getFilename(), projection);
358
            FLyrRasterSE rasterLayer =
359
                (FLyrRasterSE) FileTools.openLayer(getFilename(), getName(),
360
                    null);
361
            create(rasterLayer);
362
            rasterLayer.setNoDataValue(getNoDataValue());
363
        }
364
    }
365

    
366
    private Grid createReadOnlyGrid(FLyrRasterSE rasterLayer) {
367
        try {
368
            return rasterLayer.getReadOnlyFullGrid(false);
369
        } catch (GridException e) {
370
            throw new RuntimeException(
371
                "Error getting a read only grid from the FlyrRasterSE: "
372
                    + rasterLayer, e);
373
        } catch (InterruptedException e) {
374
            throw new RuntimeException(
375
                "Error getting a read only grid from the FlyrRasterSE: "
376
                    + rasterLayer, e);
377
        }
378
    }
379

    
380
    public void open() {
381
        LOG.debug("open: writable? = {}", isWritable());
382
        if (!isWritable() && grid == null) {
383
            this.grid = createReadOnlyGrid(this.rasterLayer);
384
            this.dataType = grid.getDataType();
385
        }
386
    }
387

    
388
    public void close() {
389
        LOG.debug("close: writable? = {}", isWritable());
390
        if (grid != null) {
391
            grid.getRasterBuf().free();
392
        }
393
        grid = null;
394
        dataType = -1;
395
        // bandsCount = -1;
396
        // projection = null;
397
        // name = null;
398
        // rasterLayer = null;
399
        // m_BaseDataObject = null;
400
        // noDataValue = DEFAULT_NO_DATA_VALUE;
401
        // filename = null;
402
    }
403

    
404
    public Rectangle2D getFullExtent() {
405
        org.gvsig.raster.grid.GridExtent extent = grid.getGridExtent();
406
        return new Rectangle2D.Double(extent.getULX(), extent.getULY(),
407
            extent.getURX() - extent.getULX(), extent.getULY()
408
                - extent.getLLY());
409
    }
410

    
411
    public GridExtent getLayerGridExtent() {
412
        final GridExtent extent = new GridExtent();
413
        if (isWritable()) {
414
            return sextanteExtent;
415
        } else {
416
            extent.setXRange(rasterLayer.getMinX(), rasterLayer.getMaxX());
417
            extent.setYRange(rasterLayer.getMinY(), rasterLayer.getMaxY());
418
            extent.setCellSize(rasterLayer.getCellSize());
419
        }
420
        return extent;
421
    }
422

    
423
    public double getLayerCellSize() {
424
        return grid.getCellSize();
425
    }
426

    
427
    public String getFilename() {
428
        return isWritable() ? filename : rasterLayer.getFileName()[0];
429
    }
430

    
431
    public Object getCRS() {
432
        return isWritable() ? projection : rasterLayer.getProjection();
433
    }
434

    
435
    public String getName() {
436
        return isWritable() ? name : rasterLayer.getName();
437
    }
438

    
439
    public void setName(String name) {
440
        this.name = name;
441
        if (rasterLayer != null) {
442
            rasterLayer.setName(name);
443
        }
444
    }
445

    
446
    private void export(String sFilename, IProjection projection) {
447

    
448
        if (sFilename.endsWith("asc")) {
449
            exportToArcInfoASCIIFile(sFilename);
450
        } else {
451
            exportToGeoTiff(sFilename, projection);
452
        }
453

    
454
    }
455

    
456
    private void exportToArcInfoASCIIFile(String sFilename) {
457

    
458
        try {
459
            FileWriter f = new FileWriter(sFilename);
460
            BufferedWriter fout = new BufferedWriter(f);
461
            DecimalFormat df = new DecimalFormat("##.###");
462
            df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
463
            df.setDecimalSeparatorAlwaysShown(true);
464

    
465
            GridExtent m_GridExtent = getLayerGridExtent();
466

    
467
            fout.write("ncols " + Integer.toString(m_GridExtent.getNX()));
468
            fout.newLine();
469
            fout.write("nrows " + Integer.toString(m_GridExtent.getNY()));
470
            fout.newLine();
471
            fout.write("xllcorner " + Double.toString(m_GridExtent.getXMin()));
472
            fout.newLine();
473
            fout.write("yllcorner " + Double.toString(m_GridExtent.getYMin()));
474
            fout.newLine();
475
            fout.write("cellsize "
476
                + Double.toString(m_GridExtent.getCellSize()));
477
            fout.newLine();
478
            fout.write("nodata_value " + Double.toString(getNoDataValue()));
479
            fout.newLine();
480

    
481
            for (int i = 0; i < m_GridExtent.getNY(); i++) {
482
                for (int j = 0; j < m_GridExtent.getNX(); j++) {
483
                    fout.write(df.format(getCellValueAsDouble(j, i)) + " ");
484
                }
485
                fout.newLine();
486
            }
487
            fout.close();
488
            f.close();
489
        } catch (IOException e) {
490
            throw new RuntimeException(
491
                "Error exporting the generated raster to the file: "
492
                    + sFilename, e);
493
        }
494
    }
495

    
496
    private void exportToGeoTiff(String sFilename, IProjection projection) {
497

    
498
        IBuffer buf = grid.getRasterBuf();
499
        WriterBufferServer writerBufferServer = new WriterBufferServer();
500
        writerBufferServer.setBuffer(buf, -1);
501

    
502
        GridExtent m_GridExtent = getLayerGridExtent();
503
        /*
504
         * Extent ext = new Extent(m_GridExtent.getAsRectangle2D());
505
         * ViewPortData vpData = new ViewPortData(projection, ext,
506
         * new Dimension(m_GridExtent.getNX(),m_GridExtent.getNY()));
507
         */
508
        try {
509
            Params params = GeoRasterWriter.getWriter(sFilename).getParams();
510
            AffineTransform affineTransform =
511
                new AffineTransform(m_GridExtent.getCellSize(), 0, 0,
512
                    -m_GridExtent.getCellSize(), m_GridExtent.getXMin(),
513
                    m_GridExtent.getYMax());
514
            GeoRasterWriter writer =
515
                GeoRasterWriter
516
                    .getWriter(writerBufferServer, sFilename,
517
                        buf.getBandCount(), affineTransform,
518
                        m_GridExtent.getNX(), m_GridExtent.getNY(),
519
                        buf.getDataType(), params, projection);
520
            writer.dataWrite();
521
            writer.writeClose();
522
        } catch (NotSupportedExtensionException e) {
523
            throw new RuntimeException(
524
                "Error exporting the generated raster to the file: "
525
                    + sFilename, e);
526
        } catch (RasterDriverException e) {
527
            throw new RuntimeException(
528
                "Error exporting the generated raster to the file: "
529
                    + sFilename, e);
530
        } catch (IOException e) {
531
            throw new RuntimeException(
532
                "Error exporting the generated raster to the file: "
533
                    + sFilename, e);
534
        } catch (InterruptedException e) {
535
            throw new RuntimeException(
536
                "Error exporting the generated raster to the file: "
537
                    + sFilename, e);
538
        }
539

    
540
    }
541

    
542
}