Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / dataset / RasterDataset.java @ 22484

History | View | Annotate | Download (33.1 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.raster.dataset;
20

    
21
import java.awt.geom.AffineTransform;
22
import java.awt.geom.NoninvertibleTransformException;
23
import java.awt.geom.Point2D;
24
import java.io.File;
25
import java.io.IOException;
26
import java.lang.reflect.Constructor;
27
import java.lang.reflect.InvocationTargetException;
28
import java.util.Iterator;
29
import java.util.Map.Entry;
30

    
31
import org.cresques.cts.ICoordTrans;
32
import org.cresques.cts.IProjection;
33
import org.gvsig.raster.RasterLibrary;
34
import org.gvsig.raster.dataset.io.GdalDriver;
35
import org.gvsig.raster.dataset.io.IRegistrableRasterFormat;
36
import org.gvsig.raster.dataset.io.MemoryRasterDriver;
37
import org.gvsig.raster.dataset.io.MemoryRasterDriverParam;
38
import org.gvsig.raster.dataset.io.RasterDriverException;
39
import org.gvsig.raster.dataset.io.rmf.ClassSerializer;
40
import org.gvsig.raster.dataset.io.rmf.ParsingException;
41
import org.gvsig.raster.dataset.io.rmf.RmfBlocksManager;
42
import org.gvsig.raster.dataset.properties.DatasetColorInterpretation;
43
import org.gvsig.raster.dataset.properties.DatasetHistogram;
44
import org.gvsig.raster.dataset.properties.DatasetMetadata;
45
import org.gvsig.raster.dataset.properties.DatasetStatistics;
46
import org.gvsig.raster.dataset.serializer.ColorInterpretationRmfSerializer;
47
import org.gvsig.raster.dataset.serializer.GeoInfoRmfSerializer;
48
import org.gvsig.raster.dataset.serializer.ProjectionRmfSerializer;
49
import org.gvsig.raster.dataset.serializer.RmfSerializerException;
50
import org.gvsig.raster.datastruct.ColorTable;
51
import org.gvsig.raster.datastruct.Extent;
52
import org.gvsig.raster.datastruct.NoData;
53
import org.gvsig.raster.datastruct.Transparency;
54
import org.gvsig.raster.datastruct.serializer.ColorTableRmfSerializer;
55
import org.gvsig.raster.datastruct.serializer.NoDataRmfSerializer;
56
import org.gvsig.raster.projection.CRS;
57
import org.gvsig.raster.util.RasterUtilities;
58
import org.gvsig.raster.util.extensionPoints.ExtensionPoint;
59
/**
60
 * Manejador de ficheros raster georeferenciados.
61
 * 
62
 * Esta clase abstracta es el ancestro de todas las clases que proporcionan
63
 * soporte para ficheros raster georeferenciados.<br>
64
 * Actua tambien como una 'Fabrica', ocultando al cliente la manera en que
65
 * se ha implementado ese manejo. Una clase nueva que soportara un nuevo
66
 * tipo de raster tendr?a que registrar su extensi?n o extensiones usando
67
 * el m?todo @see registerExtension.<br> 
68
 */
69
public abstract class RasterDataset extends GeoInfo {
70
        /**
71
         * Flags que representan a las bandas visualizables
72
         */
73
        public static final int              RED_BAND            = 0x01;
74
        public static final int              GREEN_BAND          = 0x02;
75
        public static final int              BLUE_BAND           = 0x04;
76
        public static final int              ALPHA_BAND          = 0x08;
77

    
78
        /**
79
         * N?mero de bandas de la imagen
80
         */
81
        protected int                        bandCount           = 1;
82
        private int[]                        dataType            = null;
83

    
84
        protected DatasetStatistics          stats               = new DatasetStatistics(this);
85
        protected DatasetHistogram           histogram           = null;
86
        protected Object                     param               = null;
87
        protected RmfBlocksManager           rmfBlocksManager    = null;
88

    
89
        protected ColorTable                 colorTable          = null;
90
        protected DatasetColorInterpretation colorInterpretation = null;
91

    
92
        /**
93
         * Valor del NoData
94
         */
95
        protected double                     noData              = 0;
96

    
97
        protected String                     wktProjection       = "";
98

    
99
        /**
100
         * Indica si el valor NoData esta activo
101
         */
102
        protected boolean                    noDataEnabled       = false;
103
        
104
        /*
105
         * (non-Javadoc)
106
         * @see java.lang.Object#clone()
107
         */
108
        public Object clone() {
109
                try {
110
                        RasterDataset dataset = RasterDataset.open(proj, param);
111
                        // Estas van por referencia
112
                        dataset.histogram = histogram;
113
                        dataset.stats = stats;
114
                        return dataset;
115
                } catch (NotSupportedExtensionException e) {
116
                        e.printStackTrace();
117
                } catch (RasterDriverException e) {
118
                        e.printStackTrace();
119
                }
120
                return null;
121
        }
122
        
123
        /**
124
         * Constructor
125
         */
126
        public RasterDataset() {
127
        }
128
        
129
        /**
130
         * Factoria para abrir distintos tipos de raster.
131
         * 
132
         * @param proj Proyecci?n en la que est? el raster.
133
         * @param fName Nombre del fichero.
134
         * @return GeoRasterFile, o null si hay problemas.
135
         */
136
        public static RasterDataset open(IProjection proj, Object param) throws NotSupportedExtensionException, RasterDriverException {
137
                String idFormat = null;
138

    
139
                if (param instanceof String)
140
                        idFormat = RasterUtilities.getExtensionFromFileName(((String) param));
141
                if (param instanceof IRegistrableRasterFormat)
142
                        idFormat = ((IRegistrableRasterFormat) param).getFormatID();
143

    
144
                RasterDataset grf = null;
145

    
146
                Class clase = null;
147
                if (param instanceof MemoryRasterDriverParam) {
148
                        clase = MemoryRasterDriver.class;
149
                } else {
150
                        if (idFormat != null) {
151
                                ExtensionPoint extensionPoint = ExtensionPoint.getExtensionPoint("RasterReader");
152
                                clase = (Class) extensionPoint.getValue(idFormat);
153
                        }
154
                }
155

    
156
                if (clase == null)
157
                        clase = GdalDriver.class;
158
                
159
                Class [] args = {IProjection.class, Object.class};
160
                try {
161
                        Constructor hazNuevo = clase.getConstructor(args);
162
                        Object [] args2 = {proj, param};
163
                        grf = (RasterDataset) hazNuevo.newInstance(args2);
164
                } catch (SecurityException e) {
165
                        throw new RasterDriverException("Error SecurityException in open");
166
                } catch (NoSuchMethodException e) {
167
                        throw new RasterDriverException("Error NoSuchMethodException in open");
168
                } catch (IllegalArgumentException e) {
169
                        throw new RasterDriverException("Error IllegalArgumentException in open");
170
                } catch (InstantiationException e) {
171
                        throw new RasterDriverException("Error InstantiationException in open");
172
                } catch (IllegalAccessException e) {
173
                        throw new RasterDriverException("Error IllegalAccessException in open");
174
                } catch (InvocationTargetException e) {
175
                        throw new NotSupportedExtensionException("Error in open. Problemas con las librer?as.");
176
                }
177
                return grf;
178
        }
179
                
180
        /**
181
         * Acciones de inicilizaci?n comunes a todos los drivers.
182
         * Este m?todo debe ser llamado explicitamente por el constructor de cada driver.
183
         * Estas son acciones de inicializaci?n que se ejecutan despu?s del constructor de cada driver.
184
         * Las acciones que hayan de ser realizadas antes se definen en el constructor de RasterDataset.
185
         */
186
        protected void init() {
187
        }
188
        
189
        /**
190
         * Tipo de fichero soportado.
191
         * Devuelve true si el tipo de fichero (extension) est? soportado, si no
192
         * devuelve false.
193
         * 
194
         * @param fName Fichero raster
195
         * @return  true si est? soportado, si no false.
196
                */
197
        public static boolean fileIsSupported(String fName) {
198
                ExtensionPoint extensionPoint = ExtensionPoint.getExtensionPoint("RasterReader");
199
                return extensionPoint.existKey(RasterUtilities.getExtensionFromFileName(fName));
200
        }
201

    
202
        /**
203
         * Obtiene la lista de extensiones de ficheros soportadas
204
         * @return Lista de extensiones registradas
205
         */
206
        public static String[] getExtensionsSupported() {
207
                return ExtensionPoint.getExtensionPoint("RasterReader").getKeys();
208
        }
209
        
210
        /**
211
         * Constructor
212
         * @param proj        Proyecci?n
213
         * @param name        Nombre del fichero de imagen.
214
         */
215
        public RasterDataset(IProjection proj, Object param) {
216
                super(proj, param);
217
                if(param instanceof String)
218
                        setFileSize(new File(getFName()).length());
219
        }
220

    
221
        
222
        /**
223
         * Carga un fichero raster. Puede usarse para calcular el extent e instanciar 
224
         * un objeto de este tipo.
225
         */
226
        abstract public GeoInfo load();
227
        
228
        /**
229
         * Cierra el fichero y libera los recursos.
230
         */
231
        abstract public void close();
232
                
233
        /**
234
         * Carga metadatos desde el fichero Rmf si estos existen
235
         * @param fName Nombre del fichero
236
         * @throws ParsingException 
237
         */
238
        protected void loadFromRmf(RmfBlocksManager manager) throws ParsingException {
239
                if (!manager.checkRmf())
240
                        return;
241

    
242
                if (!new File(manager.getPath()).exists())
243
                        return;
244

    
245
                GeoInfoRmfSerializer geoInfoSerializer = new GeoInfoRmfSerializer(this);
246
                ColorTableRmfSerializer colorTableSerializer = new ColorTableRmfSerializer();
247
                NoDataRmfSerializer noDataSerializer = new NoDataRmfSerializer(new NoData(noData, RasterLibrary.NODATATYPE_LAYER));
248
                ColorInterpretationRmfSerializer colorInterpSerializer = new ColorInterpretationRmfSerializer();
249
                ProjectionRmfSerializer projectionRmfSerializer = new ProjectionRmfSerializer();
250

    
251
                manager.addClient(geoInfoSerializer);
252
                manager.addClient(colorTableSerializer);
253
                manager.addClient(noDataSerializer);
254
                manager.addClient(colorInterpSerializer);
255
                manager.addClient(projectionRmfSerializer);
256

    
257
                manager.read(null);
258

    
259
                manager.removeAllClients();
260

    
261
                if (colorTableSerializer.getResult() != null)
262
                        setColorTable((ColorTable) colorTableSerializer.getResult());
263

    
264
                if (noDataSerializer.getResult() != null) {
265
                        noData = ((org.gvsig.raster.datastruct.NoData) noDataSerializer.getResult()).getValue();
266
                        noDataEnabled = (((NoData) noDataSerializer.getResult()).getType() != RasterLibrary.NODATATYPE_DISABLED);
267
                }
268

    
269
                if (colorInterpSerializer.getResult() != null) {
270
                        DatasetColorInterpretation ci = (DatasetColorInterpretation) colorInterpSerializer.getResult();
271
                        setColorInterpretation(ci);
272
                        if (ci.getBand(DatasetColorInterpretation.ALPHA_BAND) != -1)
273
                                getTransparencyDatasetStatus().setTransparencyBand(ci.getBand(DatasetColorInterpretation.ALPHA_BAND));
274
                }
275

    
276
                if (projectionRmfSerializer.getResult() != null) {
277
                        wktProjection = CRS.convertIProjectionToWkt((IProjection) projectionRmfSerializer.getResult());
278
                }
279
        }
280

    
281
        /**
282
         * Obtiene el ancho de la imagen
283
         * @return Ancho de la imagen
284
         */
285
        abstract public int getWidth();
286
        
287
        /**
288
         * Obtiene el ancho de la imagen
289
         * @return Ancho de la imagen
290
         */
291
        abstract public int getHeight();
292

    
293
        /**
294
         * Reproyecci?n.
295
         * @param rp        Coordenadas de la transformaci?n
296
         */
297
        abstract public void reProject(ICoordTrans rp);
298

    
299
        /**
300
         * Asigna un nuevo Extent 
301
         * @param e        Extent
302
         */
303
        abstract public void setView(Extent e);
304
        
305
        /**
306
         * Obtiene el extent asignado
307
         * @return        Extent
308
         */
309
        abstract public Extent getView();
310
                                
311
        /**
312
         * Obtiene el valor del raster en la coordenada que se le pasa.
313
         * El valor ser? Double, Int, Byte, etc. dependiendo del tipo de
314
         * raster.
315
         * @param x        coordenada X
316
         * @param y coordenada Y
317
         * @return
318
         */
319
        abstract public Object getData(int x, int y, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
320

    
321
        /**
322
         * Obtiene el n?nero de bandas del fichero
323
         * @return Entero que representa el n?mero de bandas
324
         */
325
        public int getBandCount() { 
326
                return bandCount; 
327
        }
328
                
329
        /**
330
         * @return Returns the dataType.
331
         */
332
        public int[] getDataType() {
333
                return dataType;
334
        }
335
        
336
        /**
337
         * @param dataType The dataType to set.
338
         */
339
        public void setDataType(int[] dataType) {
340
                this.dataType = dataType;
341
        }
342
         
343
        /**
344
         * Obtiene el tama?o de pixel en X
345
         * @return tama?o de pixel en X
346
         */
347
        public double getPixelSizeX() {
348
                return externalTransformation.getScaleX();
349
        }
350
        
351
        /**
352
         * Obtiene el tama?o de pixel en Y
353
         * @return tama?o de pixel en Y
354
         */
355
        public double getPixelSizeY() {
356
                return externalTransformation.getScaleY();
357
        }
358

    
359
        /**
360
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
361
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
362
         * pixeles de disco. 
363
         * @param ulx Posici?n X superior izquierda
364
         * @param uly Posici?n Y superior izquierda
365
         * @param lrx Posici?n X inferior derecha
366
         * @param lry Posici?n Y inferior derecha
367
         * @param rasterBuf        Buffer de datos
368
         * @param bandList
369
         * @return Buffer de datos
370
         */
371
        abstract public IBuffer getWindowRaster(double ulx, double uly, double lrx, double lry, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
372
        
373
        /**
374
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
375
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
376
         * pixeles de disco. 
377
         * @param x Posici?n X superior izquierda
378
         * @param y Posici?n Y superior izquierda
379
         * @param w Ancho en coordenadas reales
380
         * @param h Alto en coordenadas reales
381
         * @param rasterBuf        Buffer de datos
382
         * @param bandList
383
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
384
         * @return Buffer de datos
385
         */
386
        abstract public IBuffer getWindowRaster(double x, double y, double w, double h, BandList bandList, IBuffer rasterBuf, boolean adjustToExtent)throws InterruptedException, RasterDriverException;
387
        
388
        /**
389
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
390
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
391
         * 
392
         * @param minX Posici?n m?nima X superior izquierda
393
         * @param minY Posici?n m?nima Y superior izquierda
394
         * @param maxX Posici?n m?xima X inferior derecha
395
         * @param maxY Posici?n m?xima Y inferior derecha
396
         * @param bufWidth Ancho del buffer de datos
397
         * @param bufHeight Alto del buffer de datos
398
         * @param rasterBuf        Buffer de datos
399
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
400
         * @param bandList
401
         * @return Buffer de datos
402
         */
403
        abstract public IBuffer getWindowRaster(double minX, double minY, double maxX, double maxY, int bufWidth, int bufHeight, BandList bandList, IBuffer rasterBuf, boolean adjustToExtent)throws InterruptedException, RasterDriverException;
404
        
405
        /**
406
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
407
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
408
         * pixeles de disco. 
409
         * @param x Posici?n X superior izquierda
410
         * @param y Posici?n Y superior izquierda
411
         * @param w Ancho en coordenadas reales
412
         * @param h Alto en coordenadas reales
413
         * @param rasterBuf        Buffer de datos
414
         * @param bandList
415
         * @return Buffer de datos
416
         */
417
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
418
        
419
        /**
420
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
421
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
422
         * 
423
         * @param x Posici?n X superior izquierda
424
         * @param y Posici?n Y superior izquierda
425
         * @param w Ancho en coordenadas reales
426
         * @param h Alto en coordenadas reales
427
         * @param bufWidth Ancho del buffer de datos
428
         * @param bufHeight Alto del buffer de datos
429
         * @param rasterBuf        Buffer de datos
430
         * @param bandList
431
         * @return Buffer de datos
432
         */
433
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, int bufWidth, int bufHeight, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
434
        
435
        abstract public int getBlockSize();
436
        
437
        /**
438
         * Obtiene el objeto que contiene los metadatos. Este m?todo debe ser redefinido por los
439
         * drivers si necesitan devolver metadatos. 
440
         * @return
441
         */
442
        public DatasetMetadata getMetadata(){
443
                return null;
444
        }
445

    
446
        /**
447
         * Obtiene el valor NoData asociado al raster. Si hay un valor en el fichero
448
         * RMF se devuelve este, sino se buscar? en la cabecera del raster o metadatos de
449
         * este. Si finalmente no encuentra ninguno se devuelve el valor por defecto
450
         * definido en la libreria.
451
         * @return
452
         */
453
        public double getNoDataValue() {
454
                return noData;
455
        }
456

    
457
        /**
458
         * Pone el valor original de noData. Primero lo consulta del valor del metadata
459
         * y luego del RMF.
460
         */
461
        public void resetNoDataValue() {
462
                /**
463
                 * Intentamos recuperar el valor del metadatas, en caso de no encontrarlo le
464
                 * asignamos el noData por defecto
465
                 */
466
                noDataEnabled = false;
467
                do {
468
                        if (getMetadata() == null) {
469
                                noData = RasterLibrary.defaultNoDataValue;
470
                                break;
471
                        }
472

    
473
                        if (getMetadata().getNoDataValue().length == 0) {
474
                                noData = RasterLibrary.defaultNoDataValue;
475
                                break;
476
                        }
477

    
478
                        noData = getMetadata().getNoDataValue()[0];
479
                        noDataEnabled = getMetadata().isNoDataEnabled();
480
                } while (false);
481

    
482
                try {
483
                        NoData noDataObject = (NoData) loadObjectFromRmf(NoData.class, null);
484
                        if (noDataObject != null) {
485
                                if (noDataObject.getType() > 0)
486
                                        noData = noDataObject.getValue();
487
                                noDataEnabled = (noDataObject.getType() > 0);
488
                        }
489
                } catch (RmfSerializerException e) {
490
                }
491
        }
492
        
493
        /**
494
         * Establece el valor del NoData
495
         * @param value
496
         */
497
        public void setNoDataValue(double value) {
498
                noData = value;
499
                noDataEnabled = true;
500
        }
501
                
502
        /**
503
         * Obtiene el objeto que contiene que contiene la interpretaci?n de 
504
         * color por banda
505
         * @return
506
         */
507
        public DatasetColorInterpretation getColorInterpretation(){
508
                return colorInterpretation;
509
        }
510
                
511
        /**
512
         * Asigna el objeto que contiene que contiene la interpretaci?n de 
513
         * color por banda
514
         * @param DatasetColorInterpretation
515
         */
516
        public void setColorInterpretation(DatasetColorInterpretation colorInterpretation){
517
                this.colorInterpretation = colorInterpretation;
518
        }
519
        
520
        /**
521
         * Dice si el fichero tiene georreferenciaci?n o no.
522
         * @return true si tiene georreferenciaci?n y false si no la tiene
523
         */
524
        public boolean isGeoreferenced(){
525
                return true;
526
        }
527

    
528
        /**
529
         * Obtiene el objeto paleta. Esta paleta es la que tiene adjunta el fichero de disco. Si es
530
         * null este objeto quiere decir que no tiene paleta para su visualizaci?n. 
531
         * @return Palette
532
         */
533
        public ColorTable getColorTable() {
534
                return colorTable;
535
        }
536

    
537
        /**
538
         * Define el objeto paleta. Si se define null quiere decir que no tiene paleta
539
         * para su visualizaci?n. 
540
         * @param value
541
         */
542
        public void setColorTable(ColorTable value) {
543
                colorTable = value;
544
        }
545
        
546
        /**
547
         * Obtiene el estado de transparencia de un GeoRasterFile. 
548
         * @return Objeto TransparencyFileStatus
549
         */
550
        public Transparency getTransparencyDatasetStatus() {
551
                return null;
552
        }
553
        
554
        /**
555
         * Dado unas coordenadas reales, un tama?o de buffer y un tama?o de raster. 
556
         * Si el buffer es de mayor tama?o que el raster (supersampleo) quiere decir que 
557
         * por cada pixel de buffer se repiten varios del raster. Esta funci?n calcula el 
558
         * n?mero de pixels de desplazamiento en X e Y que corresponden al primer pixel del
559
         * buffer en la esquina superior izquierda. Esto es necesario porque la coordenada
560
         * solicitada es real y puede no caer sobre un pixel completo. Este calculo es
561
         * util cuando un cliente quiere supersamplear sobre un buffer y que no se lo haga
562
         * el driver autom?ticamente.
563
         * @param dWorldTLX Coordenada real X superior izquierda
564
         * @param dWorldTLY Coordenada real Y superior izquierda
565
         * @param dWorldBRX Coordenada real X inferior derecha
566
         * @param dWorldBRY Coordenada real Y inferior derecha
567
         * @param nWidth Ancho del raster
568
         * @param nHeight Alto del raster
569
         * @param bufWidth Ancho del buffer
570
         * @param bufHeight Alto del buffer
571
         * @return Array de dos elementos con el desplazamiento en X e Y. 
572
         */
573
        public double[] calcSteps(double dWorldTLX, double dWorldTLY, double dWorldBRX, double dWorldBRY, 
574
                        double nWidth, double nHeight, int bufWidth, int bufHeight) {
575

    
576
                Point2D p1 = new Point2D.Double(dWorldTLX, dWorldTLY);
577
                Point2D p2 = new Point2D.Double(dWorldBRX, dWorldBRY);
578

    
579
                Point2D tl = worldToRaster(new Point2D.Double(p1.getX(), p1.getY()));
580
                Point2D br = worldToRaster(new Point2D.Double(p2.getX(), p2.getY()));
581
                
582
                double wPx = (bufWidth / Math.abs(br.getX() - tl.getX()));
583
                double hPx = (bufHeight / Math.abs(br.getY() - tl.getY()));
584
                
585
                int x = (int)((tl.getX() > br.getX()) ? Math.floor(br.getX()) : Math.floor(tl.getX()));
586
                int y = (int)((tl.getY() > br.getY()) ? Math.floor(br.getY()) : Math.floor(tl.getY()));
587
                
588
                double a = (tl.getX() > br.getX()) ? (Math.abs(br.getX() - x)) : (Math.abs(tl.getX() - x));
589
                double b = (tl.getY() > br.getY()) ? (Math.abs(br.getY() - y)) : (Math.abs(tl.getY() - y)); 
590

    
591
                                double stpX = (int)((a * bufWidth) / Math.abs(br.getX() - tl.getX()));
592
                double stpY = (int)((b * bufHeight) / Math.abs(br.getY() - tl.getY()));
593
                
594
                return new double[]{stpX, stpY, wPx, hPx};
595
        }
596
        
597
        /**
598
         * Lee una l?nea completa del raster y devuelve un array del tipo correcto. Esta funci?n es util
599
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista. 
600
         * @param nLine N?mero de l?nea a leer
601
         * @param band Banda requerida
602
         * @return Object que es un array unidimendional del tipo de datos del raster
603
         * @throws InvalidSetViewException
604
         * @throws FileNotOpenException
605
         * @throws RasterDriverException
606
         */
607
        abstract public Object readCompleteLine(int line, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
608
        
609
        /**
610
         * Lee un bloque completo de datos del raster y devuelve un array tridimensional del tipo correcto. Esta funci?n es util
611
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista. 
612
         * @param pos Posici?n donde se empieza  a leer
613
         * @param blockHeight Altura m?xima del bloque leido
614
         * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
615
         * @throws InvalidSetViewException
616
         * @throws FileNotOpenException
617
         * @throws RasterDriverException
618
         */
619
        abstract public Object readBlock(int pos, int blockHeight)
620
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException, InterruptedException;
621
        
622
        /**
623
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
624
         * @param pt Punto a transformar
625
         * @return punto transformado en coordenadas del mundo
626
         */
627
        public Point2D rasterToWorld(Point2D pt) {
628
                Point2D p = new Point2D.Double();
629
                externalTransformation.transform(pt, p);
630
                return p;
631
        }
632
        
633
        /**
634
         * Convierte un punto desde del mundo a coordenadas pixel.
635
         * @param pt Punto a transformar
636
         * @return punto transformado en coordenadas pixel
637
         */
638
        public Point2D worldToRaster(Point2D pt) {
639
                Point2D p = new Point2D.Double();
640
                try {
641
                        externalTransformation.inverseTransform(pt, p);
642
                } catch (NoninvertibleTransformException e) {
643
                        return pt;
644
                }
645
                return p;
646
        }
647
        
648
        /**
649
         * Calcula el extent en coordenadas del mundo real
650
         * @return Extent
651
         */
652
        public Extent getExtent() {
653
                return new Extent(        rasterToWorld(new Point2D.Double(0, 0)), 
654
                                                        rasterToWorld(new Point2D.Double(getWidth(), getHeight())),
655
                                                        rasterToWorld(new Point2D.Double(getWidth(), 0)),
656
                                                        rasterToWorld(new Point2D.Double(0, getHeight())));
657
        }
658
        
659
        /**
660
         * Calcula el extent en coordenadas del mundo real sin rotaci?n. Solo coordenadas y tama?o de pixel
661
         * @return Extent
662
         */
663
        public Extent getExtentWithoutRot() {
664
                AffineTransform at = new AffineTransform(        externalTransformation.getScaleX(), 0, 
665
                                                                                                        0, externalTransformation.getScaleY(), 
666
                                                                                                        externalTransformation.getTranslateX(), externalTransformation.getTranslateY());
667
                Point2D p1 = new Point2D.Double(0, 0);
668
                Point2D p2 = new Point2D.Double(getWidth(), getHeight());
669
                at.transform(p1, p1);
670
                at.transform(p2, p2);
671
                return new Extent(p1, p2);
672
        }
673
        
674
        /**
675
         * ASigna el par?metro de inicializaci?n del driver.
676
         */
677
        public void setParam(Object param) {
678
                this.param = param;
679
        }
680
        
681
        /**
682
         * Obtiene las estadisticas asociadas al fichero
683
         * @return Objeto con las estadisticas
684
         */
685
        public DatasetStatistics getStatistics() {
686
                return stats;
687
        }
688
        
689
        /**
690
         * Obtiene el n?mero de overviews de una banda
691
         * @return
692
         */
693
        abstract public int getOverviewCount(int band) throws BandAccessException, RasterDriverException;
694

    
695
        /**
696
         * Obtiene el ancho de una overview de una banda
697
         * @return
698
         */
699
        abstract public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException;
700

    
701
        /**
702
         * Obtiene el alto de una overview de una banda
703
         * @return
704
         */
705
        abstract public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException;
706
        
707
        /**
708
         * Informa de si el dataset soporta overviews o no.
709
         * @return true si soporta overviews y false si no las soporta.
710
         */
711
        abstract public boolean overviewsSupport();
712
        
713
        /**
714
         * Obtiene el histograma asociado al dataset. Este puede ser obtenido 
715
         * completo o seg?n una lista de clases pasada.
716
         * 
717
         * @return Histograma asociado al dataset.
718
         */
719
        public DatasetHistogram getHistogram() {
720
                if (histogram == null)
721
                        histogram = new DatasetHistogram(this);
722
                return histogram;
723
        }
724
        
725
        /**
726
         * Pone a cero el porcentaje de progreso del proceso de calculo de histograma
727
         */
728
        public void resetPercent() {
729
                if (histogram != null)
730
                        histogram.resetPercent();
731
        }
732

    
733
        /**
734
         * Obtiene el porcentaje de proceso en la construcci?n del histograma,
735
         * @return porcentaje de progreso
736
         */
737
        public int getPercent() {
738
                if (histogram != null) 
739
                        return histogram.getPercent();
740
                return 0;
741
        }
742

    
743
        /**
744
         * Obtiene el gestor de ficheros RMF
745
         * @return RmfBloksManager
746
         */
747
        public RmfBlocksManager getRmfBlocksManager() {
748
                if (rmfBlocksManager == null) {
749
                        String fileRMF = RasterUtilities.getNameWithoutExtension(getFName()) + ".rmf";
750
                        rmfBlocksManager = new RmfBlocksManager(fileRMF);
751
                }
752
                return rmfBlocksManager;
753
        }
754
                
755
        /**
756
         * Informa de si el punto en coordenadas del mundo real pasado por par?metro cae dentro del 
757
         * raster o fuera. Para este calculo cogeremos el punto a averiguar si est? dentro del raster 
758
         * y le aplicaremos la transformaci?n inversa de la transformaci?n af?n aplicada. Una vez hecho 
759
         * esto ya se puede comprobar si est? dentro de los l?mites del extent del raster.
760
         * @param p Punto a comprobar en coordenadas reales
761
         * @return true si el punto est? dentro y false si est? fuera.
762
         */
763
        public boolean isInside(Point2D p){
764
                //Realizamos los calculos solo si el punto est? dentro del extent de la imagen rotada, as? nos ahorramos los calculos
765
                //cuando el puntero est? fuera
766
                
767
                Point2D pt = new Point2D.Double();
768
                try {
769
                        
770
                        getAffineTransform().inverseTransform(p, pt);
771
                        if(        pt.getX() >= 0 && pt.getX() < getWidth() &&
772
                                        pt.getY() >= 0 && pt.getY() < getHeight())
773
                                return true;
774
                } catch (NoninvertibleTransformException e) {
775
                        return false;
776
                }
777
                
778
                return false;
779
        }
780
        
781
        /**
782
         * Consulta de si un raster tiene rotaci?n o no.
783
         * @return true si tiene rotaci?n y false si no la tiene.
784
         */
785
        public boolean isRotated() {
786
                if(externalTransformation.getShearX() != 0 || externalTransformation.getShearY() != 0)
787
                        return true;
788
                return false;
789
        }
790

    
791
        /**
792
         * Devuelve si el RasterDataSet tiene el valor noData activo
793
         * @return the noDataEnabled
794
         */
795
        public boolean isNoDataEnabled() {
796
                return noDataEnabled;
797
        }
798

    
799
        /**
800
         * Define si el RasterDataSet tiene el valor noData activo 
801
         * @param noDataEnabled the noDataEnabled to set
802
         */
803
        public void setNoDataEnabled(boolean noDataEnabled) {
804
                this.noDataEnabled = noDataEnabled;
805
        }
806

    
807
        /**
808
         * Devuelve si el Dataset es reproyectable 
809
         * @return
810
         */
811
        public boolean isReproyectable() {
812
                return false;
813
        }
814
        
815
        public String getWktProjection() {
816
                return wktProjection;
817
        }
818

    
819
        /**
820
         * Devuelve un serializador que tenga un constructor con la clase pasada por parametro
821
         * @throws RmfSerializerException 
822
         */
823
        static private Class getSerializerClass(Class class1) throws RmfSerializerException {
824
                ExtensionPoint extensionPoint = ExtensionPoint.getExtensionPoint("Serializer");
825
                Iterator iterator = extensionPoint.getIterator();
826
                while (iterator.hasNext()) {
827
                        Entry entry = (Entry) iterator.next();
828
                        if (entry != null) {
829
                                Class[] args = { class1 };
830
                                Class clase = (Class) entry.getValue();
831
                                try {
832
                                        clase.getConstructor(args);
833
                                        return clase;
834
                                } catch (Exception e) {
835
                                        // Si no encuentra un constructor para esta clase, seguir? buscando en los dem?s elementos
836
                                }
837
                        }
838
                }
839
                throw new RmfSerializerException("No se ha encontrado la clase para el serializador");
840
        }
841
        
842
        /**
843
         * Construye un serializador que soporte la clase class1. El constructor se invoca
844
         * con el parametro value.
845
         * 
846
         * @param class1
847
         * @param value
848
         * @return
849
         * @throws RmfSerializerException 
850
         */
851
        static private ClassSerializer getSerializerObject(Class class1, Object value) throws RmfSerializerException {
852
                ClassSerializer serializerObject = null;
853
                try {
854
                        Class[] args = { class1 };
855
                        Constructor constructor = getSerializerClass(class1).getConstructor(args);
856
                        Object[] args2 = { value };
857
                        serializerObject = (ClassSerializer) constructor.newInstance(args2);
858
                } catch (Exception e) {
859
                        throw new RmfSerializerException("No se ha podido crear el serializador para el Rmf", e);
860
                }
861
                return serializerObject;
862
        }
863

    
864
        /**
865
         * Guarda en el RMF que trata el BlocksManager el valor value usando el serializador que soporta
866
         * la clase class1.
867
         *  
868
         * @param blocksManager
869
         * @param class1
870
         * @param value
871
         * @throws RmfSerializerException 
872
         */
873
        static private void saveObjectToRmfFile(RmfBlocksManager blocksManager, Class class1, Object value) throws RmfSerializerException {
874
                ClassSerializer serializerObject = getSerializerObject(class1, value);
875

    
876
                if (serializerObject == null) 
877
                        throw new RmfSerializerException("No se ha podido encontrar el serializador para el Rmf");
878

    
879
                if (!blocksManager.checkRmf())
880
                        throw new RmfSerializerException("Error al comprobar el fichero Rmf");
881
                        
882
                blocksManager.addClient(serializerObject);
883
                try {
884
                        blocksManager.write(true);
885
                } catch (IOException e) {
886
                        throw new RmfSerializerException("Error al escribir el fichero Rmf", e);
887
                }
888
                blocksManager.removeAllClients();
889
        }
890

    
891
        /**
892
         * Guarda en el fichero file (en formato RMF) el objecto value usando el serializador que trata
893
         * las clases class1.
894
         * 
895
         * Si el fichero RMF no existe se crea. Ha de ser un RMF de formato valido.
896
         * 
897
         * @param file
898
         * @param class1
899
         * @param value
900
         * @throws RmfSerializerException 
901
         */
902
        static public void saveObjectToRmfFile(String file, Class class1, Object value) throws RmfSerializerException {
903
                String fileRMF = RasterUtilities.getNameWithoutExtension(file) + ".rmf";
904
                RmfBlocksManager blocksManager = new RmfBlocksManager(fileRMF);
905
                saveObjectToRmfFile(blocksManager, class1, value);
906
        }
907

    
908
        /**
909
         * Guarda en el fichero file (en formato RMF) el objecto value usando el serializador que trata
910
         * la misma clase que el objeto value.
911
         * 
912
         * Si el fichero RMF no existe se crea. Ha de ser un RMF de formato valido.
913
         * 
914
         * @param file
915
         * @param value
916
         * @throws RmfSerializerException 
917
         */
918
        static public void saveObjectToRmfFile(String file, Object value) throws RmfSerializerException {
919
                saveObjectToRmfFile(file, value.getClass(), value);
920
        }
921
        
922
        /**
923
         * Guarda en el RMF el objecto actual en caso de que exista un serializador para el.
924
         * El tipo del objeto se especifica en el parametro class1.
925
         * Esto nos puede permitir poder poner a null un valor y encontrar su serializador.
926
         * @param value
927
         * @throws RmfSerializerException 
928
         */
929
        public void saveObjectToRmf(Class class1, Object value) throws RmfSerializerException {
930
                saveObjectToRmfFile(getRmfBlocksManager(), class1, value);
931
        }
932
        
933
        /**
934
         * Carga un objecto desde un serializador del tipo class1. Usa value para iniciar dicho
935
         * serializador
936
         *  
937
         * @param class1
938
         * @param value
939
         * @return
940
         * @throws RmfSerializerException 
941
         */
942
        static private Object loadObjectFromRmfFile(RmfBlocksManager blocksManager, Class class1, Object value) throws RmfSerializerException {
943
                ClassSerializer serializerObject = getSerializerObject(class1, value);
944

    
945
                if (serializerObject == null) 
946
                        throw new RmfSerializerException("No se ha podido encontrar el serializador para el Rmf");
947

    
948
                if (!blocksManager.checkRmf())
949
                        throw new RmfSerializerException("Error al comprobar el fichero Rmf");
950

    
951
                blocksManager.addClient(serializerObject);
952
                try {
953
                        blocksManager.read(null);
954
                } catch (ParsingException e) {
955
                        throw new RmfSerializerException("Error al leer el fichero Rmf", e);
956
                }
957
                blocksManager.removeAllClients();
958

    
959
                return serializerObject.getResult();
960
        }
961

    
962
        /**
963
         * Carga un objecto del fichero RMF del dataset
964
         * @param class1
965
         * @param value
966
         * @return
967
         * @throws RmfSerializerException 
968
         */
969
        public Object loadObjectFromRmf(Class class1, Object value) throws RmfSerializerException {
970
                return loadObjectFromRmfFile(getRmfBlocksManager(), class1, value);
971
        }
972
        
973
        /**
974
         * Carga un objeto del fichero RMF especificado por parametro
975
         * @param file
976
         * @param class1
977
         * @param value
978
         * @return
979
         * @throws RmfSerializerException 
980
         */
981
        static public Object loadObjectFromRmfFile(String file, Class class1, Object value) throws RmfSerializerException {
982
                String fileRMF = RasterUtilities.getNameWithoutExtension(file) + ".rmf";
983
                RmfBlocksManager blocksManager = new RmfBlocksManager(fileRMF);
984
                return loadObjectFromRmfFile(blocksManager, class1, value);
985
        }
986
        
987
        /**
988
         * Guarda en el RMF el objecto actual en caso de que exista un serializador para el
989
         * @param value
990
         * @throws RmfSerializerException 
991
         */
992
        public void saveObjectToRmf(Object value) throws RmfSerializerException {
993
                saveObjectToRmf(value.getClass(), value);
994
        }
995

    
996
        /**
997
         * Carga un objecto desde un serializador usando el tipo del mismo objeto pasado por parametro.
998
         * Usa value para iniciar dicho serializador
999
         * @param value
1000
         * @return
1001
         * @throws RmfSerializerException 
1002
         */
1003
        public Object loadObjectFromRmf(Object value) throws RmfSerializerException {
1004
                return loadObjectFromRmf(value.getClass(), value);
1005
        }
1006
}