Statistics
| Revision:

gvsig-raster / org.gvsig.raster.tools / trunk / org.gvsig.raster.tools / org.gvsig.raster.tools.algorithm / org.gvsig.raster.tools.algorithm.base / src / main / java / org / gvsig / raster / tools / algorithm / base / process / RasterProcess.java @ 1864

History | View | Annotate | Download (19.1 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.tools.algorithm.base.process;
23

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

    
31
import javax.swing.JOptionPane;
32

    
33
import org.gvsig.fmap.dal.coverage.RasterLocator;
34
import org.gvsig.fmap.dal.coverage.RasterManager;
35
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
36
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
37
import org.gvsig.fmap.dal.coverage.datastruct.Params;
38
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
39
import org.gvsig.fmap.dal.coverage.process.CancelEvent;
40
import org.gvsig.fmap.dal.coverage.process.TaskEventManager;
41
import org.gvsig.fmap.dal.coverage.store.DataServerWriter;
42
import org.gvsig.fmap.dal.coverage.store.RasterDataStore;
43
import org.gvsig.fmap.dal.coverage.store.RasterWriter;
44
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
45
import org.gvsig.gui.beans.buttonspanel.ButtonsPanel;
46
import org.gvsig.gui.beans.incrementabletask.IIncrementable;
47
import org.gvsig.gui.beans.incrementabletask.IncrementableEvent;
48
import org.gvsig.gui.beans.incrementabletask.IncrementableListener;
49
import org.gvsig.gui.beans.incrementabletask.IncrementableTask;
50
import org.gvsig.i18n.Messages;
51
import org.gvsig.tools.dispose.Disposable;
52
import org.slf4j.Logger;
53
import org.slf4j.LoggerFactory;
54
/**
55
 * Clase base de todos los procesos raster. En ella se genstionan todas las
56
 * funciones comunes como incremento de la tarea, gesti?n de eventos a la tarea, 
57
 * par?metros de la tarea, etc ...
58
 * 
59
 * 18/12/2007
60
 * @author Nacho Brodin nachobrodin@gmail.com
61
 */
62
public abstract class RasterProcess implements IIncrementable, IncrementableListener, Runnable, Disposable {
63
        protected IncrementableTask incrementableTask = null;
64
        protected volatile Thread   blinker           = null;
65
        protected TaskEventManager  taskEventManager  = null;
66
        protected IProcessActions   externalActions   = null;
67
        protected Hashtable<String, Object>
68
                                    taskParams        = new Hashtable<String, Object>();
69

    
70
        private String              log               = "";
71
        private String              lastLine          = "";
72
        private long                time              = 0;
73
        private boolean             progressActive    = true;
74
        private IProcessActions     queueActions      = null;
75
        private Logger              logger            = LoggerFactory.getLogger(RasterProcess.class.toString());
76
        protected int               percent           = 0;
77
        
78
        /**
79
         * Crea la ventana de IncrementableTask
80
         */
81
        public IncrementableTask getIncrementableTask() {
82
                if (incrementableTask == null) {
83
                        incrementableTask = new IncrementableTask(this);
84
                        incrementableTask.addIncrementableListener(this);
85
                }
86
                return incrementableTask;
87
        }
88
        
89
        /**
90
         * Define si se puede cancelar el proceso. Por defecto es true.
91
         * @param enabled
92
         */
93
        public void setCancelable(boolean enabled) {
94
                getIncrementableTask().getButtonsPanel().setEnabled(ButtonsPanel.BUTTON_CANCEL, enabled);
95
        }
96
        
97
        /**
98
         * Muestra la ventana de IncrementableTask
99
         */
100
        public void showIncrementableWindow() {
101
                if (progressActive) {
102
                        getIncrementableTask().showWindow();
103
                        getIncrementableTask().start();
104
                }
105
        }
106

    
107
        /**
108
         * Arranca el proceso de recorte de un layer
109
         */
110
        public void start() {
111
                showIncrementableWindow();
112
                if(blinker == null)
113
                        blinker = new Thread(this);
114
                blinker.start();
115
        }
116
                
117
        /**
118
         * Proceso de carga de par?metros. Puede no hacerse una carga de par?metros 
119
         * explicita y obtenerlos directamente de la tabla Hash cuando vayan a usarse. 
120
         * Esto queda a elecci?n del programador. En caso de hacerse una carga de par?metros
121
         * explicita esta llamada deber?a hacerse justo despues del constructor de la clase
122
         * que contendr? el proceso.
123
         */
124
        public abstract void init();
125
        
126
        /**
127
         * Proceso
128
         * @throws InterruptedException
129
         */
130
        public abstract void process() throws ProcessInterruptedException, ProcessException;
131
        
132
        /**
133
         * Obtenci?n de un objeto de resultado. Este objeto deber? ser el mismo que el que se
134
         * pasa por par?metro en el "end" de IProcessActions. Este m?todo es util cuando la tarea no se
135
         * lanza en un Thread (ejecutamos process directamente) y queremos recoger el resultado
136
         * sin registrarnos al evento de finalizaci?n de tarea.
137
         * @return objeto resultado de la tarea
138
         */
139
        public Object getResult() {
140
                return null;
141
        }
142
        
143
        /**
144
         * Proceso
145
         * @throws ProcessException 
146
         */
147
        public void execute() throws ProcessInterruptedException, ProcessException {
148
                init();
149
                process();
150
        }
151
        
152
        /**
153
         * M?todo donde se ejecutar? el Thread. Este har? las acciones globales para 
154
         * cualquier tarea y llamar? al m?todo execute especifico de una tarea.
155
         */
156
        public void run() {
157
                long t1 = new java.util.Date().getTime();
158

    
159
                try {
160
                        taskEventManager = RasterLocator.getManager().createRasterTask(this);
161
                        execute();
162
                } catch (ProcessInterruptedException e) {
163
                        if (externalActions != null)
164
                                externalActions.interrupted();
165
                        Thread.currentThread().interrupt();
166
                } catch (ProcessException e) {
167
                        if (progressActive) {
168
                                if (incrementableTask != null) {
169
                                        getIncrementableTask().processFinalize();
170
                                        incrementableTask = null;
171
                                }
172
                        }
173
                        logger.warn(RasterLocator.getManager().getRasterUtils().getTrace(e));
174
                        if(e.getMessage() != null && e.getMessage().compareTo("") != 0)
175
                                messageBoxError(e.getMessage(), this);
176
                        else
177
                                messageBoxError("error_processing", this);
178
                        queueActions = null;
179

    
180
                } catch (Exception e) {
181
                        if (progressActive) {
182
                                if (incrementableTask != null) {
183
                                        getIncrementableTask().processFinalize();
184
                                        incrementableTask = null;
185
                                }
186
                        }
187
                        logger.warn(RasterLocator.getManager().getRasterUtils().getTrace(e));
188
                        if(e.getMessage() != null && e.getMessage().compareTo("") != 0)
189
                                messageBoxError(e.getMessage(), null);
190
                        else
191
                                messageBoxError("error_processing", null);
192
                        queueActions = null;
193
                } finally {
194
                        taskEventManager.removeTask();
195
                        if (progressActive) {
196
                                if (incrementableTask != null)
197
                                        getIncrementableTask().processFinalize();
198
                        }
199
                        if (queueActions != null)
200
                                queueActions.end(this);
201
                        time = new java.util.Date().getTime() - t1;
202
                        blinker = null;
203
                }
204
        }
205
        
206
        /**
207
         * Activa o desactiva el interfaz de progreso en el lanzamiento de la tarea como un thread.
208
         * @param active true para activarlo o false para desactivarlo
209
         */
210
        public void setProgressActive(boolean active) {
211
                this.progressActive = active;
212
        }
213
        
214
        /**
215
         * Obtiene el tiempo que tard? en ejecutarse la tarea 
216
         * la ?ltima vez que se proces?
217
         */
218
        public long getTime() {
219
                return time;
220
        }
221
        
222
        /**
223
         * Obtiene el objeto para ejecutar acciones externar.
224
         * @param IProcessActions
225
         */
226
        public IProcessActions getActions() {
227
                return externalActions;
228
        }
229

    
230
        /**
231
         * Asigna el objeto para ejecutar acciones externar.
232
         * @param IProcessActions
233
         */
234
        public void setActions(IProcessActions actions) {
235
                this.externalActions = actions;
236
        }
237
        
238
        /**
239
         * Obtiene el objeto para ejecutar acciones de la cola de procesos de ejecuci?n exclusiva.
240
         * @param IProcessActions
241
         */
242
        public IProcessActions getUniqueProcessActions() {
243
                return queueActions;
244
        }
245

    
246
        /**
247
         * Asigna el objeto para ejecutar acciones externar.
248
         * @param IProcessActions
249
         */
250
        public void setUniqueProcessActions(IProcessActions actions) {
251
                this.queueActions = actions;
252
        }
253
        
254
        /**
255
         * Inserta una nueva l?nea en el log del cuadro de incremento de tarea
256
         * @param line
257
         */
258
        protected void insertLineLog(String line) {
259
                lastLine = line;
260
                log = log + line + "\n";
261
        }
262
        
263
        /**
264
         * Obtiene la ?ltima l?nea introducida en el log del cuadro de incremento.
265
         */
266
        public String getLabel() {
267
                return lastLine;
268
        }
269
        
270
        /**
271
         * Obtiene el texto de log del cuadro de incremento completo.
272
         */
273
        public String getLog() {
274
                return log;
275
        }
276
        
277
        /**
278
         * Un evento de cancelado es enviado a la tarea cuando actionCanceled es activado. Para
279
         * ello se crear? un objeto CancelEvent y se asignar? a la tarea en ejecuci?n. Esta lo
280
         * procesar? cuando pueda e interrumpir? el proceso.
281
         */
282
        public void actionCanceled(IncrementableEvent e) {
283
                taskEventManager.setEvent(new CancelEvent(this));
284
        }
285
        
286
        /**
287
         * A?ade un par?metro a la tarea
288
         * @param name Clave del par?metro
289
         * @param param Objeto pasado como par?metro
290
         */
291
        public void addParam(String name, Object param) {
292
                if (param != null)
293
                        taskParams.put(name, param);
294
                else
295
                        taskParams.remove(name);
296
        }
297

    
298
        /**
299
         * Elimina un par?metro de la tarea
300
         * @param name Clave del par?metro a eliminar
301
         */
302
        public void removeParam(String name) {
303
                taskParams.remove(name);
304
        }
305

    
306
        /**
307
         * Obtiene un par?metro a partir de la clave
308
         * @param name Par?metro
309
         * @return Par?metro
310
         */
311
        public Object getParam(String name) {
312
                return taskParams.get(name);
313
        }
314
        
315
        /**
316
         * Obtiene un par?metro String a partir de la clave
317
         * @param name Par?metro
318
         * @return Par?metro
319
         */
320
        public String getStringParam(String name) {
321
                Object value = taskParams.get(name);
322
                return (value != null && value instanceof String) ? (String)value : null;
323
        }
324
        
325
        /**
326
         * Obtiene un par?metro byte a partir de la clave
327
         * @param name Par?metro
328
         * @return Par?metro
329
         */
330
        public byte getByteParam(String name) {
331
                Object value = taskParams.get(name);
332
                return (value != null && value instanceof Byte) ? ((Byte)value).byteValue() : 0;
333
        }
334
        
335
        /**
336
         * Obtiene un par?metro float a partir de la clave
337
         * @param name Par?metro
338
         * @return Par?metro
339
         */
340
        public float getFloatParam(String name) {
341
                Object value = taskParams.get(name);
342
                return (value != null && value instanceof Float) ? ((Float)value).floatValue() : 0F;
343
        }
344
        
345
        /**
346
         * Obtiene un par?metro double a partir de la clave
347
         * @param name Par?metro
348
         * @return Par?metro
349
         */
350
        public double getDoubleParam(String name) {
351
                Object value = taskParams.get(name);
352
                return (value != null && value instanceof Double) ? ((Double)value).doubleValue() : 0D;
353
        }
354
        
355
        /**
356
         * Obtiene un par?metro entero a partir de la clave
357
         * @param name Par?metro
358
         * @return Par?metro
359
         */
360
        public int getIntParam(String name) {
361
                Object value = taskParams.get(name);
362
                return (value != null && value instanceof Integer) ? ((Integer)value).intValue() : 0;
363
        }
364
        
365
        /**
366
         * Obtiene un par?metro boolean a partir de la clave
367
         * @param name Par?metro
368
         * @return Par?metro
369
         */
370
        public boolean getBooleanParam(String name) {
371
                Object value = taskParams.get(name);
372
                return (value != null && value instanceof Boolean) ? ((Boolean)value).booleanValue() : false;
373
        }
374
        
375
        /**
376
         * Obtiene un par?metro int[] a partir de la clave
377
         * @param name Par?metro
378
         * @return Par?metro
379
         */
380
        public int[] getIntArrayParam(String name) {
381
                Object value = taskParams.get(name);
382
                return (value != null && value instanceof int[]) ? ((int[])value) : null;
383
        }
384
        
385
        /**
386
         * Obtiene un par?metro double[] a partir de la clave
387
         * @param name Par?metro
388
         * @return Par?metro
389
         */
390
        public double[] getDoubleArrayParam(String name) {
391
                Object value = taskParams.get(name);
392
                return (value != null && value instanceof double[]) ? ((double[])value) : null;
393
        }
394
        
395
        /**
396
         * Obtiene un par?metro extent a partir de la clave
397
         * @param name Par?metro
398
         * @return Par?metro
399
         */
400
        public Extent getExtentParam(String name) {
401
                Object value = taskParams.get(name);
402
                return (value != null && value instanceof Extent) ? ((Extent)value) : null;
403
        }
404
        
405
        /**
406
         * Updates the percentaje of progress and manages the cancelation
407
         * @param parcial
408
         * @param total
409
         * @throws ProcessInterruptedException
410
         */
411
        public void updatePercent(int parcial, int total) throws ProcessInterruptedException {
412
                if (taskEventManager != null && taskEventManager.getEvent() != null)
413
                        taskEventManager.manageEvent(taskEventManager.getEvent());
414
                percent = (int)((parcial * 100) / total);
415
        }
416
        
417
        /*
418
         * (non-Javadoc)
419
         * @see org.gvsig.gui.beans.incrementabletask.IncrementableListener#actionResumed(org.gvsig.gui.beans.incrementabletask.IncrementableEvent)
420
         */
421
        public void actionResumed(IncrementableEvent e) {        
422
        }
423
        
424
        /*
425
         * (non-Javadoc)
426
         * @see org.gvsig.gui.beans.incrementabletask.IncrementableListener#actionSuspended(org.gvsig.gui.beans.incrementabletask.IncrementableEvent)
427
         */
428
        public void actionSuspended(IncrementableEvent e) {
429
        }
430
        
431
        /*
432
         * (non-Javadoc)
433
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#isCancelable()
434
         */
435
        public boolean isCancelable() {
436
                return true;
437
        }
438

    
439
        /*
440
         * (non-Javadoc)
441
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#isPausable()
442
         */
443
        public boolean isPausable() {
444
                return false;
445
        }
446
        
447
        /**
448
         * Registra un mensaje de error en el log de gvSIG
449
         * @param msg Mensaje a guardar en el log
450
         * @param parent Objeto que hizo disparar el mensaje
451
         * @param exception Excepcion que ha sido recogida
452
         */
453
        public static void debug(String msg, Object parent, Exception exception) {
454
                if(parent != null)
455
                    LoggerFactory
456
            .getLogger(parent.getClass()).debug(Messages.getText(msg), exception);
457
        }
458
        
459
        public void dispose() {
460
                try {
461
                        finalize();
462
                } catch (Throwable e) {
463
                }
464
        }
465
        
466
        /*
467
         * (non-Javadoc)
468
         * @see java.lang.Object#finalize()
469
         */
470
        @Override
471
        protected void finalize() throws Throwable {
472
                incrementableTask           = null;
473
                blinker                     = null;
474
                externalActions             = null;
475
                if(taskParams != null) {
476
                        taskParams.clear();
477
                        taskParams = null;
478
                }
479
                log                         = null;
480
                lastLine                    = null;
481
                queueActions                = null;
482
                logger                      = null;
483
                super.finalize();
484
        }
485
        
486
        /**
487
         * Shows a error dialog with a text and a accept button 
488
         * @param msg Message to show in the dialog
489
         * @param parentWindow Parent window
490
         */
491
        public static void messageBoxError(String msg, Object parentWindow){
492
                String string = Messages.getText("accept");
493
                Object[] options = {string};
494
                JOptionPane.showOptionDialog((Component)parentWindow,
495
                                        "<html>" + Messages.getText(msg).replaceAll("\n", "<br>") + "</html>",
496
                                        Messages.getText("confirmacion"),
497
                                        JOptionPane.OK_OPTION,
498
                                        JOptionPane.ERROR_MESSAGE,
499
                                        null,
500
                                        options,
501
                                        string);
502
        }
503
        
504
        /**
505
         * Muestra un dialogo de error con un texto y un bot?n de aceptar. El error es
506
         * registrado en el log de gvSIG con la excepcion que se le pase por parametro
507
         * @param msg Mensaje a mostrar en el dialogo.
508
         * @param parentWindow Ventana desde la que se lanza el dialogo
509
         * @param exception Excepcion que ha sido recogida
510
         */
511
        public static void messageBoxError(String msg, Object parentWindow, Exception exception) {
512
                debug(msg, parentWindow, exception);
513
                messageBoxError(msg, parentWindow);
514
        }
515
        
516
        /**
517
         * Muestra un dialogo de error con un texto y un bot?n de aceptar. Se le pasa como ?ltimo par?metros
518
         * una lista de excepciones que ser?n guardadas en el log
519
         * @param msg Mensaje a mostrar en el dialogo.
520
         * @param parentWindow Ventana desde la que se lanza el dialogo
521
         * @param exception Excepcion que ha sido recogida
522
         */
523
        public static void messageBoxError(String msg, Object parentWindow, ArrayList<Exception> exception) {
524
                for (int i = 0; i < exception.size(); i++) 
525
                        debug(msg, parentWindow, exception.get(i));
526
                messageBoxError(msg, parentWindow);
527
        }
528
        
529
        /**
530
         * Exports a raster buffer to disk
531
         * @param sFilename
532
         * @param buf
533
         * @param cellsize
534
         * @param minX
535
         * @param minY
536
         * @return
537
         */
538
        public boolean exportRaster(final String sFilename, 
539
                        Buffer buf, 
540
                        Buffer alphaBuffer, 
541
                        double cellsize, 
542
                        double minX, 
543
                        double minY) {
544
                try {
545
                        RasterManager manager = RasterLocator.getManager();
546
                        final DataServerWriter writerBufferServer = manager.createDataServerWriter();
547
                        writerBufferServer.setBuffer(buf, -1);
548
                        int nBands = buf.getBandCount();
549
                        ColorInterpretation colorInterpretation = null;
550
                        if(alphaBuffer != null) {
551
                                writerBufferServer.setAlphaBuffer(alphaBuffer);
552
                                nBands ++;
553
                                colorInterpretation = RasterLocator.getManager().getDataStructFactory().createColorInterpretation(
554
                                                new String[] { 
555
                                                                ColorInterpretation.RED_BAND, 
556
                                                                ColorInterpretation.GREEN_BAND, 
557
                                                                ColorInterpretation.BLUE_BAND,
558
                                                                ColorInterpretation.ALPHA_BAND});
559
                        } else {
560
                                if(nBands == 1)
561
                                        colorInterpretation = RasterLocator.getManager().getDataStructFactory().createColorInterpretation(
562
                                                        new String[] { ColorInterpretation.GRAY_BAND });
563
                        }
564
                        final Params params = manager.createWriterParams(sFilename);
565
                        final AffineTransform affineTransform =
566
                                new AffineTransform(cellsize, 0, 0,
567
                                                -cellsize, minX, minY);
568

    
569
                        final RasterWriter writer = manager.createWriter(
570
                                                writerBufferServer, 
571
                                                sFilename,
572
                                                nBands, 
573
                                                affineTransform, 
574
                                                buf.getWidth(),
575
                                                buf.getHeight(), 
576
                                                buf.getDataType(), 
577
                                                params, 
578
                                                null);
579
                        if(colorInterpretation != null)
580
                                writer.setColorBandsInterpretation(colorInterpretation.getValues());
581
                        writer.dataWrite();
582
                        writer.writeClose();
583
                } catch (final Exception e) {
584
                        e.printStackTrace();
585
                        return false;
586
                }
587
                return true;
588
        }
589
        
590
        /**
591
         * Exports a raster buffer to disk
592
         * @param sFilename
593
         * @param buf
594
         * @param cellsize
595
         * @param minX
596
         * @param minY
597
         * @return
598
         */
599
        public boolean exportRaster(final String sFilename, 
600
                        Buffer buf, 
601
                        double cellsize, 
602
                        double minX, 
603
                        double minY) {
604
        return exportRaster(sFilename, buf, null, cellsize, minX, minY);
605
    }
606
        
607
        /**
608
         * Gets a list of rectangles which represents the pixel coordinates of each DataStore.
609
         * This rectangle is the area that intersects with the other DataStores in the         list.
610
         * @param dataStoreList
611
         * @return
612
         */
613
        protected Rectangle2D[] getIntersectionInPxCoords(RasterDataStore[] dataStoreList) {
614
                Extent extentIntersect = null;
615
                int nRectangles = 0;
616
                for (int i = 0; i < dataStoreList.length; i++) {
617
                        if(dataStoreList[i] != null) {
618
                                if(extentIntersect == null)
619
                                        extentIntersect = dataStoreList[i].getExtent();
620
                                else
621
                                        extentIntersect = extentIntersect.intersection(dataStoreList[i].getExtent());
622
                                nRectangles ++;
623
                        }
624
                }
625
                Rectangle2D[] result = new Rectangle2D[nRectangles];
626
                
627
                Point2D p1 = new Point2D.Double(extentIntersect.getULX(), extentIntersect.getULY());
628
                Point2D p2 = new Point2D.Double(extentIntersect.getLRX(), extentIntersect.getLRY());
629
                
630
                int cont = 0;
631
                for (int i = 0; i < dataStoreList.length; i++) {
632
                        if(dataStoreList[i] != null) {
633
                                Point2D init = dataStoreList[i].worldToRaster(p1);
634
                                Point2D end = dataStoreList[i].worldToRaster(p2);
635
                                result[cont] = new Rectangle2D.Double(
636
                                                init.getX(), 
637
                                                init.getY(), 
638
                                                Math.abs(end.getX() - init.getX()), 
639
                                                Math.abs(end.getY() - init.getY()));
640
                                cont++;
641
                        }
642
                }
643
                return result;
644
        }
645
}