Statistics
| Revision:

gvsig-raster / org.gvsig.raster / trunk / org.gvsig.raster / org.gvsig.raster.algorithm / src / main / java / org / gvsig / raster / algorithm / process / ProcessUtils.java @ 5462

History | View | Annotate | Download (19 KB)

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

    
24
import java.awt.Component;
25
import java.awt.Rectangle;
26
import java.awt.geom.AffineTransform;
27
import java.awt.geom.Point2D;
28
import java.awt.geom.Rectangle2D;
29
import java.util.ArrayList;
30
import java.util.List;
31

    
32
import javax.swing.JOptionPane;
33

    
34
import org.cresques.cts.IProjection;
35
import org.gvsig.fmap.dal.DALLocator;
36
import org.gvsig.fmap.dal.DataManager;
37
import org.gvsig.fmap.dal.DataServerExplorer;
38
import org.gvsig.fmap.dal.DataServerExplorerParameters;
39
import org.gvsig.fmap.dal.coverage.RasterLocator;
40
import org.gvsig.fmap.dal.coverage.RasterManager;
41
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
42
import org.gvsig.fmap.dal.coverage.dataset.BufferParam;
43
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
44
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
45
import org.gvsig.fmap.dal.coverage.datastruct.Params;
46
import org.gvsig.fmap.dal.coverage.exception.BufferCreationException;
47
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
48
import org.gvsig.fmap.dal.coverage.exception.QueryException;
49
import org.gvsig.fmap.dal.coverage.store.DataServerWriter;
50
import org.gvsig.fmap.dal.coverage.store.RasterDataStore;
51
import org.gvsig.fmap.dal.coverage.store.RasterQuery;
52
import org.gvsig.fmap.dal.coverage.store.RasterWriter;
53
import org.gvsig.fmap.dal.coverage.store.parameter.NewRasterStoreParameters;
54
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
55
import org.gvsig.fmap.dal.exception.DataException;
56
import org.gvsig.fmap.dal.exception.InitializeException;
57
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
58
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
59
import org.gvsig.i18n.Messages;
60
import org.gvsig.raster.roi.ROI;
61
import org.slf4j.Logger;
62
import org.slf4j.LoggerFactory;
63
/**
64
 * Clase base de todos los procesos raster. En ella se genstionan todas las
65
 * funciones comunes como incremento de la tarea, gesti?n de eventos a la tarea, 
66
 * par?metros de la tarea, etc ...
67
 * 
68
 * @author Nacho Brodin nachobrodin@gmail.com
69
 */
70
public abstract class ProcessUtils {
71
        private Logger          log          = LoggerFactory.getLogger(ProcessUtils.class);
72
        protected NoData        doubleNODATA = RasterLocator.getManager().getDataStructFactory().createDefaultNoData(1, Buffer.TYPE_DOUBLE);
73
        
74
        /**
75
         * Registra un mensaje de error en el log de gvSIG
76
         * @param msg Mensaje a guardar en el log
77
         * @param parent Objeto que hizo disparar el mensaje
78
         * @param exception Excepcion que ha sido recogida
79
         */
80
        public void debug(String msg, Object parent, Exception exception) {
81
                if(parent != null)
82
                    LoggerFactory
83
            .getLogger(parent.getClass()).debug(Messages.getText(msg), exception);
84
        }
85
        
86
        /**
87
         * Shows a error dialog with a text and a accept button 
88
         * @param msg Message to show in the dialog
89
         * @param parentWindow Parent window
90
         */
91
        public void messageBoxError(String msg, Object parentWindow){
92
                String string = Messages.getText("accept");
93
                Object[] options = {string};
94
                JOptionPane.showOptionDialog((Component)parentWindow,
95
                                        "<html>" + Messages.getText(msg).replaceAll("\n", "<br>") + "</html>",
96
                                        Messages.getText("confirmacion"),
97
                                        JOptionPane.OK_OPTION,
98
                                        JOptionPane.ERROR_MESSAGE,
99
                                        null,
100
                                        options,
101
                                        string);
102
        }
103
        
104
        /**
105
         * Muestra un dialogo de error con un texto y un bot?n de aceptar. El error es
106
         * registrado en el log de gvSIG con la excepcion que se le pase por parametro
107
         * @param msg Mensaje a mostrar en el dialogo.
108
         * @param parentWindow Ventana desde la que se lanza el dialogo
109
         * @param exception Excepcion que ha sido recogida
110
         */
111
        public void messageBoxError(String msg, Object parentWindow, Exception exception) {
112
                debug(msg, parentWindow, exception);
113
                messageBoxError(msg, parentWindow);
114
        }
115
        
116
        /**
117
         * Muestra un dialogo de error con un texto y un bot?n de aceptar. Se le pasa como ?ltimo par?metros
118
         * una lista de excepciones que ser?n guardadas en el log
119
         * @param msg Mensaje a mostrar en el dialogo.
120
         * @param parentWindow Ventana desde la que se lanza el dialogo
121
         * @param exception Excepcion que ha sido recogida
122
         */
123
        public void messageBoxError(String msg, Object parentWindow, ArrayList<Exception> exception) {
124
                for (int i = 0; i < exception.size(); i++) 
125
                        debug(msg, parentWindow, exception.get(i));
126
                messageBoxError(msg, parentWindow);
127
        }
128
        
129
        /**
130
         * Exports a raster buffer to disk
131
         * @param sFilename
132
         * @param buf
133
         * @param cellsize
134
         * @param minX
135
         * @param minY
136
         * @return
137
         * @throws ProviderNotRegisteredException 
138
         * @throws InitializeException 
139
         */
140
        public void exportRaster(final String sFilename, 
141
                        Buffer buf, 
142
                        ColorInterpretation ci,
143
                        Extent windowExtent,
144
                        NoData nodata,
145
                        IProjection proj) {
146
                nodata.setFileName(sFilename);
147
                nodata.save();
148
                
149
                buf.setDataExtent(windowExtent.toRectangle2D());
150
                
151
                DataManager manager = DALLocator.getDataManager();
152
                String provider = "Gdal Store";
153
                try {
154
                        DataServerExplorerParameters eparams = manager.createServerExplorerParameters("FilesystemExplorer");
155
                        DataServerExplorer serverExplorer = manager.openServerExplorer(eparams.getExplorerName(), eparams);
156

    
157
                        NewRasterStoreParameters sparams = (NewRasterStoreParameters)serverExplorer.getAddParameters(provider);
158
                        sparams.setBuffer(buf);
159
                        sparams.setColorInterpretation(ci.getValues());
160
                        sparams.setProjection(proj);
161
                        sparams.setDestination(sFilename);
162
                        
163
                        serverExplorer.add("Gdal Store", sparams, true);
164
                } catch (InitializeException e) {
165
                        log.debug("Error saving the file of the process", e);
166
                } catch (ProviderNotRegisteredException e) {
167
                        log.debug("Error saving the file of the process", e);
168
                } catch (ValidateDataParametersException e) {
169
                        log.debug("Error saving the file of the process", e);
170
                } catch (DataException e) {
171
                        log.debug("Error saving the file of the process", e);
172
                }
173
        }
174
        
175
        /**
176
         * Exports a raster buffer to disk
177
         * @param sFilename
178
         * @param buf
179
         * @param cellsize
180
         * @param minX
181
         * @param minY
182
         * @return
183
         * @throws ProviderNotRegisteredException 
184
         * @throws InitializeException 
185
         */
186
    public boolean exportRaster(final String sFilename, Buffer buf, double cellsize, double minX,
187
        double minY, NoData nodata) {
188
        return exportRaster(sFilename, buf, cellsize, minX, minY);
189
    }
190
        
191
    /**
192
     * Exports buffer to disk
193
     * 
194
     * @param sFilename
195
     *            Name of file to write data buffer
196
     * @param buf
197
     *            data buffer
198
     * @param cellsize
199
     *            Cell size of new raster
200
     * @param minX
201
     * @param minY
202
     * @param nodata
203
     *            No data value of new raster
204
     * @param proj
205
     *            Projection of new raster
206
     * @return
207
     */
208
    public boolean exportRaster(final String sFilename, Buffer buf, double cellsize, double minX,
209
        double minY, NoData nodata, IProjection proj) {
210
        boolean result = exportRaster(sFilename, buf, cellsize, minX, minY, proj);
211
        nodata.setFileName(sFilename);
212
        nodata.save();
213
        return result;
214
    }
215
        
216
    /**
217
     * Export buffer to disk
218
     * 
219
     * @param sFilename
220
     *            Name of raster file
221
     * @param buf
222
     *            Buffer data with new data
223
     * @param alphaBuffer
224
     *            Buffer with alpha data
225
     * @param cellsize
226
     *            Cell size of new raster
227
     * @param ulx
228
     *            X coordinate of upper left corner
229
     * @param uly
230
     *            Y coordinate of upper left corner
231
     * @param proj
232
     *            Projection of new raster
233
     * @return
234
     */
235
    @SuppressWarnings("deprecation")
236
    public boolean exportRaster(final String sFilename, Buffer buf, Buffer alphaBuffer,
237
        double cellsize, double ulx, double uly, IProjection proj) {
238
                try {
239
                        RasterManager manager = RasterLocator.getManager();
240
                        final DataServerWriter writerBufferServer = manager.createDataServerWriter();
241
                        writerBufferServer.setBuffer(buf, -1);
242
                        int nBands = buf.getBandCount();
243
                        ColorInterpretation colorInterpretation = null;
244
                        if(alphaBuffer != null) {
245
                                colorInterpretation = RasterLocator.getManager().getDataStructFactory().createColorInterpretation(
246
                                                new String[] { 
247
                                                                ColorInterpretation.RED_BAND, 
248
                                                                ColorInterpretation.GREEN_BAND, 
249
                                                                ColorInterpretation.BLUE_BAND,
250
                                                                ColorInterpretation.ALPHA_BAND});
251
                        } else {
252
                                if(nBands == 1)
253
                                        colorInterpretation = RasterLocator.getManager().getDataStructFactory().createColorInterpretation(
254
                                                        new String[] { ColorInterpretation.GRAY_BAND });
255
                        }
256
                        final Params params = manager.createWriterParams(sFilename);
257
                        final AffineTransform affineTransform =
258
                                new AffineTransform(cellsize, 0, 0,
259
                                                -cellsize, ulx, uly);
260

    
261
                        final RasterWriter writer = manager.createWriter(
262
                                                writerBufferServer, 
263
                                                sFilename,
264
                                                nBands, 
265
                                                affineTransform, 
266
                                                buf.getWidth(),
267
                                                buf.getHeight(), 
268
                                                buf.getDataType(), 
269
                                                params, 
270
                                                proj);
271
                        if(colorInterpretation != null)
272
                                writer.setColorBandsInterpretation(colorInterpretation.getValues());
273
                        writer.dataWrite();
274
                        writer.writeClose();
275
                } catch (final Exception e) {
276
                        e.printStackTrace();
277
                        return false;
278
                }
279
                return true;
280
        }
281
        
282
    /**
283
     * Export buffer to disk
284
     * 
285
     * @param sFilename
286
     *            Name of raster file
287
     * @param buf
288
     *            Buffer data with new data
289
     * @param alphaBuffer
290
     *            Buffer with alpha data
291
     * @param cellsize
292
     *            Cell size of new raster
293
     * @param ulx
294
     *            X coordinate of upper left corner
295
     * @param uly
296
     *            Y coordinate of upper left corner
297
     * @return
298
     */
299
    public boolean exportRaster(final String sFilename, Buffer buf, Buffer alphaBuffer,
300
        double cellsize, double ulx, double uly) {
301
        return exportRaster(sFilename, buf, alphaBuffer, cellsize, ulx, uly, null);
302
    }
303
        
304
    /**
305
     * Exports raster buffer to disk
306
     * 
307
     * @param sFilename
308
     *            Name of raster file
309
     * @param buf
310
     *            Buffer data with new data
311
     * @param cellsize
312
     *            Cell size of new raster
313
     * @param ulx
314
     *            X coordinate of upper left corner
315
     * @param uly
316
     *            Y coordinate of upper left corner
317
     * @return
318
     */
319
    public boolean exportRaster(final String sFilename, Buffer buf, double cellsize, double ulx,
320
        double uly) {
321
        return exportRaster(sFilename, buf, null, cellsize, ulx, uly);
322
    }
323
        
324
    /**
325
     * Exports raster buffer to disk
326
     * 
327
     * @param sFilename
328
     *            Name of raster file
329
     * @param buf
330
     *            Buffer data with new data
331
     * @param cellsize
332
     *            Cell size of new raster
333
     * @param ulx
334
     *            X coordinate of upper left corner
335
     * @param uly
336
     *            Y coordinate of upper left corner
337
     * @param proj
338
     *            Projection of new raster
339
     * @return
340
     */
341
    public boolean exportRaster(final String sFilename, Buffer buf, double cellsize, double ulx,
342
        double uly, IProjection proj) {
343
        return exportRaster(sFilename, buf, null, cellsize, ulx, uly, proj);
344
    }
345
        
346
        /**
347
         * Gets a list of rectangles which represents the pixel coordinates of each DataStore.
348
         * This rectangle is the area that intersects with the other DataStores in the         list.
349
         * @param dataStoreList
350
         * @return
351
         */
352
        protected Rectangle2D[] getIntersectionInPxCoords(RasterDataStore[] dataStoreList) {
353
                Extent extentIntersect = null;
354
                int nRectangles = 0;
355
                for (int i = 0; i < dataStoreList.length; i++) {
356
                        if(dataStoreList[i] != null) {
357
                                if(extentIntersect == null)
358
                                        extentIntersect = dataStoreList[i].getExtent();
359
                                else
360
                                        extentIntersect = extentIntersect.intersection(dataStoreList[i].getExtent());
361
                                nRectangles ++;
362
                        }
363
                }
364
                Rectangle2D[] result = new Rectangle2D[nRectangles];
365
                
366
                Point2D p1 = new Point2D.Double(extentIntersect.getULX(), extentIntersect.getULY());
367
                Point2D p2 = new Point2D.Double(extentIntersect.getLRX(), extentIntersect.getLRY());
368
                
369
                int cont = 0;
370
                for (int i = 0; i < dataStoreList.length; i++) {
371
                        if(dataStoreList[i] != null) {
372
                                Point2D init = dataStoreList[i].worldToRaster(p1);
373
                                Point2D end = dataStoreList[i].worldToRaster(p2);
374
                                result[cont] = new Rectangle2D.Double(
375
                                                init.getX(), 
376
                                                init.getY(), 
377
                                                Math.abs(end.getX() - init.getX()), 
378
                                                Math.abs(end.getY() - init.getY()));
379
                                cont++;
380
                        }
381
                }
382
                return result;
383
        }
384
        
385
        /**
386
         * Checks if the point in pixel coordinates is inside the region of 
387
         * interest or not. The point will be
388
         * @param x 
389
         * @param y
390
         * @param rois
391
         * @param extentResult
392
         *       Bounding box of the area to which belongs the point defined in pixel coordinates (x, y)
393
         * @return
394
         */
395
        public boolean isInsideOfROI(int x, int y, List<ROI> rois, Extent extentResult) {
396
                if(rois == null || rois.size() == 0)
397
                        return true;
398
                
399
                ROI roi = rois.get(0);
400
                int[] shift = getROIAnalysisShift(extentResult, roi.getStore().getExtent(), roi.getStore().getCellSize());
401
                
402
                for (int i = 0; i < rois.size(); i++) {
403
                        if(rois.get(i).isInsideOfPolygon(x + shift[0], y + shift[1]))
404
                                return true;
405
                }
406
                return false;
407
        }
408
        
409
        /**
410
         * Gets the shift in pixels between the source bounding box and the result bounding box.
411
         * This is useful to get if a pixel is inside a region of interest because the ROI has 
412
         * associate the source. 
413
         * @param extentResult
414
         * @param sourceExtent
415
         * @return
416
         */
417
        private int[] getROIAnalysisShift(Extent extentResult, Extent sourceExtent, double cellsize) {
418
                double xDistance = Math.abs(extentResult.getULX() - sourceExtent.getULX());
419
                double yDistance = Math.abs(extentResult.getULY() - sourceExtent.getULY());
420
                return new int[]{(int)(xDistance / cellsize), (int)(yDistance / cellsize)};
421
        }
422
        
423
        /**
424
         * Gets the bounding box taking into account whether there are ROIs or not
425
         * @return
426
         */
427
        public Extent getExtentResult(Extent window, List<ROI> rois, RasterDataStore store) {
428
                if(window != null)
429
                        return window.intersection(store.getExtent());
430
                if(rois == null)
431
                        return store.getExtent();
432
                else {
433
                        Extent maxExtent = null;
434
                        for (int i = 0; i < rois.size(); i++) {
435
                                if(i == 0)
436
                                        maxExtent = rois.get(i).getROIExtent();
437
                                else
438
                                        maxExtent = maxExtent.encloseBoundinBoxes(rois.get(i).getROIExtent());
439
                        }
440
                        return maxExtent.intersection(store.getExtent());
441
                }
442
        }
443
        
444
        /**
445
         * Returns true if the algorithm is applied to the entire layer
446
         * @param extent
447
         * @param rois
448
         * @param store
449
         * @return
450
         */
451
        public boolean isAnalizedEntireLayer(Extent window, List<ROI> rois, RasterDataStore store) {
452
                if(window == null) {
453
                        if(rois == null || rois.size() == 0)
454
                                return true;
455
                }
456
                return false;
457
        }
458
        
459
        /**
460
         * Gets the bounding box of the source in pixel coordinates
461
         * @param resultExtent
462
         * @return
463
         */
464
        public Rectangle2D getSourcePxBox(Extent resultExtent, RasterDataStore store) {
465
                if(resultExtent == null || resultExtent.equals(store.getExtent()))
466
                        return new Rectangle2D.Double(0, 0, store.getWidth(), store.getHeight());
467
                Point2D p1 = store.worldToRaster(new Point2D.Double(resultExtent.getULX(), resultExtent.getULY()));
468
                Point2D p2 = store.worldToRaster(new Point2D.Double(resultExtent.getLRX(), resultExtent.getLRY()));
469
                return new Rectangle2D.Double(p1.getX(), p1.getY(), Math.abs(p2.getX() - p1.getX()), Math.abs(p2.getY() - p1.getY()));
470
        }
471
        
472
        /**
473
         * Builds the output buffer
474
         * @param sourcePxBBox
475
         * @param bandCount
476
         * @return
477
         */
478
        public Buffer createOutputBuffer(int w, int h, int bandCount) {
479
                return createOutputBuffer(w, h, bandCount, Buffer.TYPE_DOUBLE);
480
        }
481
        
482
        public Buffer createOutputBuffer(int w, int h, int bandCount, int datatype) {
483
                RasterManager rManager = RasterLocator.getManager();
484
                BufferParam bParams = rManager.getBufferFactory().createBufferParams(
485
                                w, 
486
                                h, 
487
                                bandCount, 
488
                                datatype, 
489
                                true);
490
                Buffer resultBuffer = null;
491
                try {
492
                        resultBuffer = rManager.getBufferFactory().createBuffer(bParams);
493
                } catch (BufferCreationException e) {
494
                        new ProcessException("Error creating the output buffer", e);
495
                }
496
                return resultBuffer;
497
        }
498
        
499
        /**
500
         * Gets a data buffer from a <code>RasterDataStore</code> 
501
     */
502
    public Buffer createSourceBuffer(RasterDataStore store, Rectangle2D sourcePxBBox, boolean[] bands) throws ProcessException {
503
        RasterManager rManager = RasterLocator.getManager();
504
        RasterQuery query = rManager.createQuery();
505
        query.setReadOnly(true);
506
        
507
        int nBands = getNumberOfSelectedBands(bands);
508
        int count = 0;
509
        int[] drawableBands = new int[nBands];
510
        for (int i = 0; i < bands.length; i++) {
511
                        if(bands[i]) {
512
                                drawableBands[count] = i;
513
                                count ++;
514
                        }
515
                }
516
        
517
        query.setDrawableBands(drawableBands);
518
        query.setAreaOfInterest(
519
                        new Rectangle(
520
                        (int)sourcePxBBox.getX(), 
521
                        (int)sourcePxBBox.getY(), 
522
                        (int)sourcePxBBox.getWidth(), 
523
                        (int)sourcePxBBox.getHeight()));
524

    
525
        try {
526
                Buffer buffer = null;
527
                try {
528
                        buffer = store.query(query);
529
                } catch (QueryException e) {
530
                        new ProcessException("Error creating the input buffer", e);
531
                }  
532
                return buffer;
533
        } catch (ProcessInterruptedException e) {
534
        }
535
        return null;
536
    } 
537
    
538
        /**
539
         * Gets the number of the selected bands from a list of boolean values.
540
         * Each element in this list represents a band and true or false if the band
541
         * will be used in the task.
542
         * @param bandsPCs
543
         * @return
544
         */
545
        private int getNumberOfSelectedBands(boolean[] b) {
546
                int bandCount = 0;
547
        for (int i = 0; i < b.length; i++) {
548
                        if(b[i])
549
                                bandCount++;
550
                }
551
        return bandCount;
552
        }
553
        
554
        /**
555
         * Gets a value of the buffer in double format
556
         * @param b
557
         * @param row
558
         * @param col
559
         * @param band
560
         * @return
561
         */
562
        protected double getData(Buffer b, int row, int col, int band) {
563
                if(b.getDataType() == Buffer.TYPE_BYTE) {
564
                        return (double)b.getElemByte(row, col, band);
565
                }
566
                if(b.getDataType() == Buffer.TYPE_DOUBLE) {
567
                        return b.getElemDouble(row, col, band);
568
                }
569
                if(b.getDataType() == Buffer.TYPE_FLOAT) {
570
                        return (double)b.getElemFloat(row, col, band);
571
                }
572
                if(b.getDataType() == Buffer.TYPE_INT) {
573
                        return (double)b.getElemInt(row, col, band);
574
                }
575
                if(b.getDataType() == Buffer.TYPE_SHORT) {
576
                        return (double)b.getElemShort(row, col, band);
577
                }
578
                
579
                return doubleNODATA.getValue().doubleValue();
580
        }
581
}