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 @ 1747

History | View | Annotate | Download (18 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.gui.beans.buttonspanel.ButtonsPanel;
45
import org.gvsig.gui.beans.incrementabletask.IIncrementable;
46
import org.gvsig.gui.beans.incrementabletask.IncrementableEvent;
47
import org.gvsig.gui.beans.incrementabletask.IncrementableListener;
48
import org.gvsig.gui.beans.incrementabletask.IncrementableTask;
49
import org.gvsig.i18n.Messages;
50
import org.gvsig.tools.dispose.Disposable;
51
import org.slf4j.Logger;
52
import org.slf4j.LoggerFactory;
53
/**
54
 * Clase base de todos los procesos raster. En ella se genstionan todas las
55
 * funciones comunes como incremento de la tarea, gesti?n de eventos a la tarea, 
56
 * par?metros de la tarea, etc ...
57
 * 
58
 * 18/12/2007
59
 * @author Nacho Brodin nachobrodin@gmail.com
60
 */
61
public abstract class RasterProcess implements IIncrementable, IncrementableListener, Runnable, Disposable {
62
        protected IncrementableTask incrementableTask = null;
63
        protected volatile Thread   blinker           = null;
64
        protected TaskEventManager  taskEventManager  = null;
65
        protected IProcessActions   externalActions   = null;
66
        protected Hashtable<String, Object>
67
                                    taskParams        = new Hashtable<String, Object>();
68

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

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

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

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

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

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

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

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

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

    
539
        try {
540
            RasterManager manager = RasterLocator.getManager();
541
            final DataServerWriter writerBufferServer =
542
                manager.createDataServerWriter();
543
            writerBufferServer.setBuffer(buf, -1);
544
            final Params params = manager.createWriterParams(sFilename);
545
            final AffineTransform affineTransform =
546
                new AffineTransform(cellsize, 0, 0,
547
                    -cellsize, minX, minY);
548

    
549
            final RasterWriter writer =
550
                manager.createWriter(writerBufferServer, sFilename,
551
                    buf.getBandCount(), affineTransform, buf.getWidth(),
552
                    buf.getHeight(), buf.getDataType(), params, null);
553
            writer.dataWrite();
554
            writer.writeClose();
555

    
556
        } catch (final Exception e) {
557
                e.printStackTrace();
558
            return false;
559
        }
560

    
561
        return true;
562

    
563
    }
564
        
565
        /**
566
         * Gets a list of rectangles which represents the pixel coordinates of each DataStore.
567
         * This rectangle is the area that intersects with the other DataStores in the         list.
568
         * @param dataStoreList
569
         * @return
570
         */
571
        protected Rectangle2D[] getIntersectionInPxCoords(RasterDataStore[] dataStoreList) {
572
                Extent extentIntersect = null;
573
                int nRectangles = 0;
574
                for (int i = 0; i < dataStoreList.length; i++) {
575
                        if(dataStoreList[i] != null) {
576
                                if(extentIntersect == null)
577
                                        extentIntersect = dataStoreList[i].getExtent();
578
                                else
579
                                        extentIntersect = extentIntersect.intersection(dataStoreList[i].getExtent());
580
                                nRectangles ++;
581
                        }
582
                }
583
                Rectangle2D[] result = new Rectangle2D[nRectangles];
584
                
585
                Point2D p1 = new Point2D.Double(extentIntersect.getULX(), extentIntersect.getULY());
586
                Point2D p2 = new Point2D.Double(extentIntersect.getLRX(), extentIntersect.getLRY());
587
                
588
                int cont = 0;
589
                for (int i = 0; i < dataStoreList.length; i++) {
590
                        if(dataStoreList[i] != null) {
591
                                Point2D init = dataStoreList[i].worldToRaster(p1);
592
                                Point2D end = dataStoreList[i].worldToRaster(p2);
593
                                result[cont] = new Rectangle2D.Double(
594
                                                init.getX(), 
595
                                                init.getY(), 
596
                                                Math.abs(end.getX() - init.getX()), 
597
                                                Math.abs(end.getY() - init.getY()));
598
                                cont++;
599
                        }
600
                }
601
                return result;
602
        }
603
}