Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libRaster / src / org / gvsig / raster / dataset / RasterDataset.java @ 26939

History | View | Annotate | Download (33.6 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

    
30
import org.cresques.cts.ICoordTrans;
31
import org.cresques.cts.IProjection;
32
import org.gvsig.raster.RasterLibrary;
33
import org.gvsig.raster.dataset.io.GdalDriver;
34
import org.gvsig.raster.dataset.io.IRegistrableRasterFormat;
35
import org.gvsig.raster.dataset.io.MemoryRasterDriver;
36
import org.gvsig.raster.dataset.io.MemoryRasterDriverParam;
37
import org.gvsig.raster.dataset.io.RasterDriverException;
38
import org.gvsig.raster.dataset.io.rmf.ClassSerializer;
39
import org.gvsig.raster.dataset.io.rmf.ParsingException;
40
import org.gvsig.raster.dataset.io.rmf.RmfBlocksManager;
41
import org.gvsig.raster.dataset.properties.DatasetColorInterpretation;
42
import org.gvsig.raster.dataset.properties.DatasetHistogram;
43
import org.gvsig.raster.dataset.properties.DatasetMetadata;
44
import org.gvsig.raster.dataset.properties.DatasetStatistics;
45
import org.gvsig.raster.dataset.serializer.ColorInterpretationRmfSerializer;
46
import org.gvsig.raster.dataset.serializer.GeoInfoRmfSerializer;
47
import org.gvsig.raster.dataset.serializer.ProjectionRmfSerializer;
48
import org.gvsig.raster.dataset.serializer.RmfSerializerException;
49
import org.gvsig.raster.datastruct.ColorTable;
50
import org.gvsig.raster.datastruct.Extent;
51
import org.gvsig.raster.datastruct.NoData;
52
import org.gvsig.raster.datastruct.Transparency;
53
import org.gvsig.raster.datastruct.serializer.ColorTableRmfSerializer;
54
import org.gvsig.raster.datastruct.serializer.NoDataRmfSerializer;
55
import org.gvsig.raster.projection.CRS;
56
import org.gvsig.raster.util.RasterUtilities;
57
import org.gvsig.tools.ToolsLocator;
58
import org.gvsig.tools.extensionpoint.ExtensionPoint;
59
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
60
import org.gvsig.tools.extensionpoint.ExtensionPoint.Extension;
61

    
62
/**
63
 * Manejador de ficheros raster georeferenciados.
64
 *
65
 * Esta clase abstracta es el ancestro de todas las clases que proporcionan
66
 * soporte para ficheros raster georeferenciados.<br>
67
 * Actua tambien como una 'Fabrica', ocultando al cliente la manera en que
68
 * se ha implementado ese manejo. Una clase nueva que soportara un nuevo
69
 * tipo de raster tendr?a que registrar su extensi?n o extensiones usando
70
 * el m?todo @see registerExtension.<br>
71
 */
72
public abstract class RasterDataset extends GeoInfo {
73
        /**
74
         * Flags que representan a las bandas visualizables
75
         */
76
        public static final int              RED_BAND            = 0x01;
77
        public static final int              GREEN_BAND          = 0x02;
78
        public static final int              BLUE_BAND           = 0x04;
79
        public static final int              ALPHA_BAND          = 0x08;
80

    
81
        /**
82
         * N?mero de bandas de la imagen
83
         */
84
        protected int                        bandCount           = 1;
85
        private int[]                        dataType            = null;
86

    
87
        protected DatasetStatistics          stats               = new DatasetStatistics(this);
88
        protected DatasetHistogram           histogram           = null;
89
        protected Object                     param               = null;
90
        protected RmfBlocksManager           rmfBlocksManager    = null;
91

    
92
        protected ColorTable                 colorTable          = null;
93
        protected DatasetColorInterpretation colorInterpretation = null;
94

    
95
        /**
96
         * Valor del NoData
97
         */
98
        protected double                     noData              = 0;
99

    
100
        protected String                     wktProjection       = "";
101

    
102
        /**
103
         * Indica si el valor NoData esta activo
104
         */
105
        protected boolean                    noDataEnabled       = false;
106

    
107
        /*
108
         * (non-Javadoc)
109
         * @see java.lang.Object#clone()
110
         */
111
        public Object clone() {
112
                try {
113
                        RasterDataset dataset = RasterDataset.open(proj, param);
114
                        // Estas van por referencia
115
                        dataset.histogram = histogram;
116
                        dataset.stats = stats;
117
                        return dataset;
118
                } catch (NotSupportedExtensionException e) {
119
                        e.printStackTrace();
120
                } catch (RasterDriverException e) {
121
                        e.printStackTrace();
122
                }
123
                return null;
124
        }
125

    
126
        /**
127
         * Constructor
128
         */
129
        public RasterDataset() {
130
        }
131

    
132
        /**
133
         * Factoria para abrir distintos tipos de raster.
134
         *
135
         * @param proj Proyecci?n en la que est? el raster.
136
         * @param fName Nombre del fichero.
137
         * @return GeoRasterFile, o null si hay problemas.
138
         */
139
        public static RasterDataset open(IProjection proj, Object param) throws NotSupportedExtensionException, RasterDriverException {
140
                String idFormat = null;
141

    
142
                if (param instanceof String)
143
                        idFormat = RasterUtilities.getExtensionFromFileName(((String) param));
144
                if (param instanceof IRegistrableRasterFormat)
145
                        idFormat = ((IRegistrableRasterFormat) param).getFormatID();
146

    
147
                RasterDataset grf = null;
148

    
149
                Class clase = null;
150
                if (param instanceof MemoryRasterDriverParam)
151
                        clase = MemoryRasterDriver.class;
152
                else if (idFormat != null) {
153
                        ExtensionPointManager extensionPoints =ToolsLocator.getExtensionPointManager();
154
                        ExtensionPoint point=extensionPoints.get("RasterReader");
155
//                                ExtensionPoint extensionPoint = ExtensionPoint.getExtensionPoint("RasterReader");
156
                        Extension ext = point.get(idFormat);
157
                        if (ext != null)
158
                                clase = ext.getExtension();
159
                }
160

    
161
                if (clase == null)
162
                        clase = GdalDriver.class;
163

    
164
                Class [] args = {IProjection.class, Object.class};
165
                try {
166
                        Constructor hazNuevo = clase.getConstructor(args);
167
                        Object [] args2 = {proj, param};
168
                        grf = (RasterDataset) hazNuevo.newInstance(args2);
169
                } catch (SecurityException e) {
170
                        throw new RasterDriverException("Error SecurityException in open");
171
                } catch (NoSuchMethodException e) {
172
                        throw new RasterDriverException("Error NoSuchMethodException in open");
173
                } catch (IllegalArgumentException e) {
174
                        throw new RasterDriverException("Error IllegalArgumentException in open");
175
                } catch (InstantiationException e) {
176
                        throw new RasterDriverException("Error InstantiationException in open");
177
                } catch (IllegalAccessException e) {
178
                        throw new RasterDriverException("Error IllegalAccessException in open");
179
                } catch (InvocationTargetException e) {
180
                        throw new NotSupportedExtensionException("Error in open. Problemas con las librer?as.");
181
                }
182
                return grf;
183
        }
184

    
185
        /**
186
         * Acciones de inicilizaci?n comunes a todos los drivers.
187
         * Este m?todo debe ser llamado explicitamente por el constructor de cada driver.
188
         * Estas son acciones de inicializaci?n que se ejecutan despu?s del constructor de cada driver.
189
         * Las acciones que hayan de ser realizadas antes se definen en el constructor de RasterDataset.
190
         */
191
        protected void init() {
192
        }
193

    
194
        /**
195
         * Tipo de fichero soportado.
196
         * Devuelve true si el tipo de fichero (extension) est? soportado, si no
197
         * devuelve false.
198
         *
199
         * @param fName Fichero raster
200
         * @return  true si est? soportado, si no false.
201
                */
202
        public static boolean fileIsSupported(String fName) {
203
                ExtensionPointManager extensionPoints =ToolsLocator.getExtensionPointManager();
204
                ExtensionPoint point=extensionPoints.get("RasterReader");
205
//                ExtensionPoint extensionPoint = ExtensionPoint.getExtensionPoint("RasterReader");
206
                return point.has(RasterUtilities.getExtensionFromFileName(fName));
207
        }
208

    
209
        /**
210
         * Obtiene la lista de extensiones de ficheros soportadas
211
         * @return Lista de extensiones registradas
212
         */
213
        public static String[] getExtensionsSupported() {
214
                ExtensionPointManager extensionPoints =ToolsLocator.getExtensionPointManager();
215
                ExtensionPoint point=extensionPoints.get("RasterReader");
216
                return (String[])point.getNames().toArray(new String[0]);
217
        }
218

    
219
        /**
220
         * Constructor
221
         * @param proj        Proyecci?n
222
         * @param name        Nombre del fichero de imagen.
223
         */
224
        public RasterDataset(IProjection proj, Object param) {
225
                super(proj, param);
226
                if(param instanceof String)
227
                        setFileSize(new File(getFName()).length());
228
        }
229

    
230

    
231
        /**
232
         * Carga un fichero raster. Puede usarse para calcular el extent e instanciar
233
         * un objeto de este tipo.
234
         */
235
        abstract public GeoInfo load();
236

    
237
        /**
238
         * Cierra el fichero y libera los recursos.
239
         */
240
        abstract public void close();
241

    
242
        /**
243
         * Carga metadatos desde el fichero Rmf si estos existen
244
         * @param fName Nombre del fichero
245
         * @throws ParsingException
246
         */
247
        protected void loadFromRmf(RmfBlocksManager manager) throws ParsingException {
248
                if (!manager.checkRmf())
249
                        return;
250

    
251
                if (!new File(manager.getPath()).exists())
252
                        return;
253

    
254
                GeoInfoRmfSerializer geoInfoSerializer = new GeoInfoRmfSerializer(this);
255
                ColorTableRmfSerializer colorTableSerializer = new ColorTableRmfSerializer();
256
                NoDataRmfSerializer noDataSerializer = new NoDataRmfSerializer(new NoData(noData, RasterLibrary.NODATATYPE_LAYER));
257
                ColorInterpretationRmfSerializer colorInterpSerializer = new ColorInterpretationRmfSerializer();
258
                ProjectionRmfSerializer projectionRmfSerializer = new ProjectionRmfSerializer();
259

    
260
                manager.addClient(geoInfoSerializer);
261
                manager.addClient(colorTableSerializer);
262
                manager.addClient(noDataSerializer);
263
                manager.addClient(colorInterpSerializer);
264
                manager.addClient(projectionRmfSerializer);
265

    
266
                manager.read(null);
267

    
268
                manager.removeAllClients();
269

    
270
                if (colorTableSerializer.getResult() != null)
271
                        setColorTable((ColorTable) colorTableSerializer.getResult());
272

    
273
                if (noDataSerializer.getResult() != null) {
274
                        noData = ((org.gvsig.raster.datastruct.NoData) noDataSerializer.getResult()).getValue();
275
                        noDataEnabled = (((NoData) noDataSerializer.getResult()).getType() != RasterLibrary.NODATATYPE_DISABLED);
276
                }
277

    
278
                if (colorInterpSerializer.getResult() != null) {
279
                        DatasetColorInterpretation ci = (DatasetColorInterpretation) colorInterpSerializer.getResult();
280
                        setColorInterpretation(ci);
281
                        if (ci.getBand(DatasetColorInterpretation.ALPHA_BAND) != -1)
282
                                getTransparencyDatasetStatus().setTransparencyBand(ci.getBand(DatasetColorInterpretation.ALPHA_BAND));
283
                }
284

    
285
                if (projectionRmfSerializer.getResult() != null)
286
                        wktProjection = CRS.convertIProjectionToWkt((IProjection) projectionRmfSerializer.getResult());
287
        }
288

    
289
        /**
290
         * Obtiene el ancho de la imagen
291
         * @return Ancho de la imagen
292
         */
293
        abstract public int getWidth();
294

    
295
        /**
296
         * Obtiene el ancho de la imagen
297
         * @return Ancho de la imagen
298
         */
299
        abstract public int getHeight();
300

    
301
        /**
302
         * Reproyecci?n.
303
         * @param rp        Coordenadas de la transformaci?n
304
         */
305
        abstract public void reProject(ICoordTrans rp);
306

    
307
        /**
308
         * Asigna un nuevo Extent
309
         * @param e        Extent
310
         */
311
        abstract public void setView(Extent e);
312

    
313
        /**
314
         * Obtiene el extent asignado
315
         * @return        Extent
316
         */
317
        abstract public Extent getView();
318

    
319
        /**
320
         * Obtiene el valor del raster en la coordenada que se le pasa.
321
         * El valor ser? Double, Int, Byte, etc. dependiendo del tipo de
322
         * raster.
323
         * @param x        coordenada X
324
         * @param y coordenada Y
325
         * @return
326
         */
327
        abstract public Object getData(int x, int y, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
328

    
329
        /**
330
         * Obtiene el n?nero de bandas del fichero
331
         * @return Entero que representa el n?mero de bandas
332
         */
333
        public int getBandCount() {
334
                return bandCount;
335
        }
336

    
337
        /**
338
         * @return Returns the dataType.
339
         */
340
        public int[] getDataType() {
341
                return dataType;
342
        }
343

    
344
        /**
345
         * @param dataType The dataType to set.
346
         */
347
        public void setDataType(int[] dataType) {
348
                this.dataType = dataType;
349
        }
350

    
351
        /**
352
         * Obtiene el tama?o de pixel en X
353
         * @return tama?o de pixel en X
354
         */
355
        public double getPixelSizeX() {
356
                return externalTransformation.getScaleX();
357
        }
358

    
359
        /**
360
         * Obtiene el tama?o de pixel en Y
361
         * @return tama?o de pixel en Y
362
         */
363
        public double getPixelSizeY() {
364
                return externalTransformation.getScaleY();
365
        }
366

    
367
        /**
368
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales.
369
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
370
         * pixeles de disco.
371
         * @param ulx Posici?n X superior izquierda
372
         * @param uly Posici?n Y superior izquierda
373
         * @param lrx Posici?n X inferior derecha
374
         * @param lry Posici?n Y inferior derecha
375
         * @param rasterBuf        Buffer de datos
376
         * @param bandList
377
         * @return Buffer de datos
378
         */
379
        abstract public IBuffer getWindowRaster(double ulx, double uly, double lrx, double lry, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
380

    
381
        /**
382
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales.
383
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
384
         * pixeles de disco.
385
         * @param x Posici?n X superior izquierda
386
         * @param y Posici?n Y superior izquierda
387
         * @param w Ancho en coordenadas reales
388
         * @param h Alto en coordenadas reales
389
         * @param rasterBuf        Buffer de datos
390
         * @param bandList
391
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
392
         * @return Buffer de datos
393
         */
394
        abstract public IBuffer getWindowRaster(double x, double y, double w, double h, BandList bandList, IBuffer rasterBuf, boolean adjustToExtent)throws InterruptedException, RasterDriverException;
395

    
396
        /**
397
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales.
398
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
399
         *
400
         * @param minX Posici?n m?nima X superior izquierda
401
         * @param minY Posici?n m?nima Y superior izquierda
402
         * @param maxX Posici?n m?xima X inferior derecha
403
         * @param maxY Posici?n m?xima Y inferior derecha
404
         * @param bufWidth Ancho del buffer de datos
405
         * @param bufHeight Alto del buffer de datos
406
         * @param rasterBuf        Buffer de datos
407
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
408
         * @param bandList
409
         * @return Buffer de datos
410
         */
411
        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;
412

    
413
        /**
414
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel.
415
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
416
         * pixeles de disco.
417
         * @param x Posici?n X superior izquierda
418
         * @param y Posici?n Y superior izquierda
419
         * @param w Ancho en coordenadas reales
420
         * @param h Alto en coordenadas reales
421
         * @param rasterBuf        Buffer de datos
422
         * @param bandList
423
         * @return Buffer de datos
424
         */
425
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
426

    
427
        /**
428
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel.
429
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
430
         *
431
         * @param x Posici?n X superior izquierda
432
         * @param y Posici?n Y superior izquierda
433
         * @param w Ancho en coordenadas reales
434
         * @param h Alto en coordenadas reales
435
         * @param bufWidth Ancho del buffer de datos
436
         * @param bufHeight Alto del buffer de datos
437
         * @param rasterBuf        Buffer de datos
438
         * @param bandList
439
         * @return Buffer de datos
440
         */
441
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, int bufWidth, int bufHeight, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
442

    
443
        abstract public int getBlockSize();
444

    
445
        /**
446
         * Obtiene el objeto que contiene los metadatos. Este m?todo debe ser redefinido por los
447
         * drivers si necesitan devolver metadatos.
448
         * @return
449
         */
450
        public DatasetMetadata getMetadata(){
451
                return null;
452
        }
453

    
454
        /**
455
         * Obtiene el valor NoData asociado al raster. Si hay un valor en el fichero
456
         * RMF se devuelve este, sino se buscar? en la cabecera del raster o metadatos de
457
         * este. Si finalmente no encuentra ninguno se devuelve el valor por defecto
458
         * definido en la libreria.
459
         * @return
460
         */
461
        public double getNoDataValue() {
462
                return noData;
463
        }
464

    
465
        /**
466
         * Pone el valor original de noData. Primero lo consulta del valor del metadata
467
         * y luego del RMF.
468
         */
469
        public void resetNoDataValue() {
470
                /**
471
                 * Intentamos recuperar el valor del metadatas, en caso de no encontrarlo le
472
                 * asignamos el noData por defecto
473
                 */
474
                noDataEnabled = false;
475
                do {
476
                        if (getMetadata() == null) {
477
                                noData = RasterLibrary.defaultNoDataValue;
478
                                break;
479
                        }
480

    
481
                        if (getMetadata().getNoDataValue().length == 0) {
482
                                noData = RasterLibrary.defaultNoDataValue;
483
                                break;
484
                        }
485

    
486
                        noData = getMetadata().getNoDataValue()[0];
487
                        noDataEnabled = getMetadata().isNoDataEnabled();
488
                } while (false);
489

    
490
                try {
491
                        NoData noDataObject = (NoData) loadObjectFromRmf(NoData.class, null);
492
                        if (noDataObject != null) {
493
                                if (noDataObject.getType() > 0)
494
                                        noData = noDataObject.getValue();
495
                                noDataEnabled = (noDataObject.getType() > 0);
496
                        }
497
                } catch (RmfSerializerException e) {
498
                }
499
        }
500

    
501
        /**
502
         * Establece el valor del NoData
503
         * @param value
504
         */
505
        public void setNoDataValue(double value) {
506
                noData = value;
507
                noDataEnabled = true;
508
        }
509

    
510
        /**
511
         * Obtiene el objeto que contiene que contiene la interpretaci?n de
512
         * color por banda
513
         * @return
514
         */
515
        public DatasetColorInterpretation getColorInterpretation(){
516
                return colorInterpretation;
517
        }
518

    
519
        /**
520
         * Asigna el objeto que contiene que contiene la interpretaci?n de
521
         * color por banda
522
         * @param DatasetColorInterpretation
523
         */
524
        public void setColorInterpretation(DatasetColorInterpretation colorInterpretation){
525
                this.colorInterpretation = colorInterpretation;
526
        }
527

    
528
        /**
529
         * Dice si el fichero tiene georreferenciaci?n o no.
530
         * @return true si tiene georreferenciaci?n y false si no la tiene
531
         */
532
        public boolean isGeoreferenced(){
533
                return true;
534
        }
535

    
536
        /**
537
         * Obtiene el objeto paleta. Esta paleta es la que tiene adjunta el fichero de disco. Si es
538
         * null este objeto quiere decir que no tiene paleta para su visualizaci?n.
539
         * @return Palette
540
         */
541
        public ColorTable getColorTable() {
542
                return colorTable;
543
        }
544

    
545
        /**
546
         * Define el objeto paleta. Si se define null quiere decir que no tiene paleta
547
         * para su visualizaci?n.
548
         * @param value
549
         */
550
        public void setColorTable(ColorTable value) {
551
                colorTable = value;
552
        }
553

    
554
        /**
555
         * Obtiene el estado de transparencia de un GeoRasterFile.
556
         * @return Objeto TransparencyFileStatus
557
         */
558
        public Transparency getTransparencyDatasetStatus() {
559
                return null;
560
        }
561

    
562
        /**
563
         * Dado unas coordenadas reales, un tama?o de buffer y un tama?o de raster.
564
         * Si el buffer es de mayor tama?o que el raster (supersampleo) quiere decir que
565
         * por cada pixel de buffer se repiten varios del raster. Esta funci?n calcula el
566
         * n?mero de pixels de desplazamiento en X e Y que corresponden al primer pixel del
567
         * buffer en la esquina superior izquierda. Esto es necesario porque la coordenada
568
         * solicitada es real y puede no caer sobre un pixel completo. Este calculo es
569
         * util cuando un cliente quiere supersamplear sobre un buffer y que no se lo haga
570
         * el driver autom?ticamente.
571
         * @param dWorldTLX Coordenada real X superior izquierda
572
         * @param dWorldTLY Coordenada real Y superior izquierda
573
         * @param dWorldBRX Coordenada real X inferior derecha
574
         * @param dWorldBRY Coordenada real Y inferior derecha
575
         * @param nWidth Ancho del raster
576
         * @param nHeight Alto del raster
577
         * @param bufWidth Ancho del buffer
578
         * @param bufHeight Alto del buffer
579
         * @return Array de dos elementos con el desplazamiento en X e Y.
580
         */
581
        public double[] calcSteps(double dWorldTLX, double dWorldTLY, double dWorldBRX, double dWorldBRY,
582
                        double nWidth, double nHeight, int bufWidth, int bufHeight) {
583

    
584
                Point2D p1 = new Point2D.Double(dWorldTLX, dWorldTLY);
585
                Point2D p2 = new Point2D.Double(dWorldBRX, dWorldBRY);
586

    
587
                Point2D tl = worldToRaster(new Point2D.Double(p1.getX(), p1.getY()));
588
                Point2D br = worldToRaster(new Point2D.Double(p2.getX(), p2.getY()));
589

    
590
                double wPx = (bufWidth / Math.abs(br.getX() - tl.getX()));
591
                double hPx = (bufHeight / Math.abs(br.getY() - tl.getY()));
592

    
593
                int x = (int)((tl.getX() > br.getX()) ? Math.floor(br.getX()) : Math.floor(tl.getX()));
594
                int y = (int)((tl.getY() > br.getY()) ? Math.floor(br.getY()) : Math.floor(tl.getY()));
595

    
596
                double a = (tl.getX() > br.getX()) ? (Math.abs(br.getX() - x)) : (Math.abs(tl.getX() - x));
597
                double b = (tl.getY() > br.getY()) ? (Math.abs(br.getY() - y)) : (Math.abs(tl.getY() - y));
598

    
599
                                double stpX = (int)((a * bufWidth) / Math.abs(br.getX() - tl.getX()));
600
                double stpY = (int)((b * bufHeight) / Math.abs(br.getY() - tl.getY()));
601

    
602
                return new double[]{stpX, stpY, wPx, hPx};
603
        }
604

    
605
        /**
606
         * Lee una l?nea completa del raster y devuelve un array del tipo correcto. Esta funci?n es util
607
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista.
608
         * @param nLine N?mero de l?nea a leer
609
         * @param band Banda requerida
610
         * @return Object que es un array unidimendional del tipo de datos del raster
611
         * @throws InvalidSetViewException
612
         * @throws FileNotOpenException
613
         * @throws RasterDriverException
614
         */
615
        abstract public Object readCompleteLine(int line, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
616

    
617
        /**
618
         * Lee un bloque completo de datos del raster y devuelve un array tridimensional del tipo correcto. Esta funci?n es util
619
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista.
620
         * @param pos Posici?n donde se empieza  a leer
621
         * @param blockHeight Altura m?xima del bloque leido
622
         * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
623
         * @throws InvalidSetViewException
624
         * @throws FileNotOpenException
625
         * @throws RasterDriverException
626
         */
627
        abstract public Object readBlock(int pos, int blockHeight)
628
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException, InterruptedException;
629

    
630
        /**
631
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
632
         * @param pt Punto a transformar
633
         * @return punto transformado en coordenadas del mundo
634
         */
635
        public Point2D rasterToWorld(Point2D pt) {
636
                Point2D p = new Point2D.Double();
637
                externalTransformation.transform(pt, p);
638
                return p;
639
        }
640

    
641
        /**
642
         * Convierte un punto desde del mundo a coordenadas pixel.
643
         * @param pt Punto a transformar
644
         * @return punto transformado en coordenadas pixel
645
         */
646
        public Point2D worldToRaster(Point2D pt) {
647
                Point2D p = new Point2D.Double();
648
                try {
649
                        externalTransformation.inverseTransform(pt, p);
650
                } catch (NoninvertibleTransformException e) {
651
                        return pt;
652
                }
653
                return p;
654
        }
655

    
656
        /**
657
         * Calcula el extent en coordenadas del mundo real
658
         * @return Extent
659
         */
660
        public Extent getExtent() {
661
                return new Extent(        rasterToWorld(new Point2D.Double(0, 0)),
662
                                                        rasterToWorld(new Point2D.Double(getWidth(), getHeight())),
663
                                                        rasterToWorld(new Point2D.Double(getWidth(), 0)),
664
                                                        rasterToWorld(new Point2D.Double(0, getHeight())));
665
        }
666

    
667
        /**
668
         * Calcula el extent en coordenadas del mundo real sin rotaci?n. Solo coordenadas y tama?o de pixel
669
         * @return Extent
670
         */
671
        public Extent getExtentWithoutRot() {
672
                AffineTransform at = new AffineTransform(        externalTransformation.getScaleX(), 0,
673
                                                                                                        0, externalTransformation.getScaleY(),
674
                                                                                                        externalTransformation.getTranslateX(), externalTransformation.getTranslateY());
675
                Point2D p1 = new Point2D.Double(0, 0);
676
                Point2D p2 = new Point2D.Double(getWidth(), getHeight());
677
                at.transform(p1, p1);
678
                at.transform(p2, p2);
679
                return new Extent(p1, p2);
680
        }
681

    
682
        /**
683
         * ASigna el par?metro de inicializaci?n del driver.
684
         */
685
        public void setParam(Object param) {
686
                this.param = param;
687
        }
688

    
689
        /**
690
         * Obtiene las estadisticas asociadas al fichero
691
         * @return Objeto con las estadisticas
692
         */
693
        public DatasetStatistics getStatistics() {
694
                return stats;
695
        }
696

    
697
        /**
698
         * Obtiene el n?mero de overviews de una banda
699
         * @return
700
         */
701
        abstract public int getOverviewCount(int band) throws BandAccessException, RasterDriverException;
702

    
703
        /**
704
         * Obtiene el ancho de una overview de una banda
705
         * @return
706
         */
707
        abstract public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException;
708

    
709
        /**
710
         * Obtiene el alto de una overview de una banda
711
         * @return
712
         */
713
        abstract public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException;
714

    
715
        /**
716
         * Informa de si el dataset soporta overviews o no.
717
         * @return true si soporta overviews y false si no las soporta.
718
         */
719
        abstract public boolean overviewsSupport();
720

    
721
        /**
722
         * Obtiene el histograma asociado al dataset. Este puede ser obtenido
723
         * completo o seg?n una lista de clases pasada.
724
         *
725
         * @return Histograma asociado al dataset.
726
         */
727
        public DatasetHistogram getHistogram() {
728
                if (histogram == null)
729
                        histogram = new DatasetHistogram(this);
730
                return histogram;
731
        }
732

    
733
        /**
734
         * Pone a cero el porcentaje de progreso del proceso de calculo de histograma
735
         */
736
        public void resetPercent() {
737
                if (histogram != null)
738
                        histogram.resetPercent();
739
        }
740

    
741
        /**
742
         * Obtiene el porcentaje de proceso en la construcci?n del histograma,
743
         * @return porcentaje de progreso
744
         */
745
        public int getPercent() {
746
                if (histogram != null)
747
                        return histogram.getPercent();
748
                return 0;
749
        }
750

    
751
        /**
752
         * Obtiene el gestor de ficheros RMF
753
         * @return RmfBloksManager
754
         */
755
        public RmfBlocksManager getRmfBlocksManager() {
756
                if (rmfBlocksManager == null) {
757
                        String fileRMF = RasterUtilities.getNameWithoutExtension(getFName()) + ".rmf";
758
                        rmfBlocksManager = new RmfBlocksManager(fileRMF);
759
                }
760
                return rmfBlocksManager;
761
        }
762

    
763
        /**
764
         * Informa de si el punto en coordenadas del mundo real pasado por par?metro cae dentro del
765
         * raster o fuera. Para este calculo cogeremos el punto a averiguar si est? dentro del raster
766
         * y le aplicaremos la transformaci?n inversa de la transformaci?n af?n aplicada. Una vez hecho
767
         * esto ya se puede comprobar si est? dentro de los l?mites del extent del raster.
768
         * @param p Punto a comprobar en coordenadas reales
769
         * @return true si el punto est? dentro y false si est? fuera.
770
         */
771
        public boolean isInside(Point2D p){
772
                //Realizamos los calculos solo si el punto est? dentro del extent de la imagen rotada, as? nos ahorramos los calculos
773
                //cuando el puntero est? fuera
774

    
775
                Point2D pt = new Point2D.Double();
776
                try {
777

    
778
                        getAffineTransform().inverseTransform(p, pt);
779
                        if(        pt.getX() >= 0 && pt.getX() < getWidth() &&
780
                                        pt.getY() >= 0 && pt.getY() < getHeight())
781
                                return true;
782
                } catch (NoninvertibleTransformException e) {
783
                        return false;
784
                }
785

    
786
                return false;
787
        }
788

    
789
        /**
790
         * Consulta de si un raster tiene rotaci?n o no.
791
         * @return true si tiene rotaci?n y false si no la tiene.
792
         */
793
        public boolean isRotated() {
794
                if(externalTransformation.getShearX() != 0 || externalTransformation.getShearY() != 0)
795
                        return true;
796
                return false;
797
        }
798

    
799
        /**
800
         * Devuelve si el RasterDataSet tiene el valor noData activo
801
         * @return the noDataEnabled
802
         */
803
        public boolean isNoDataEnabled() {
804
                return noDataEnabled;
805
        }
806

    
807
        /**
808
         * Define si el RasterDataSet tiene el valor noData activo
809
         * @param noDataEnabled the noDataEnabled to set
810
         */
811
        public void setNoDataEnabled(boolean noDataEnabled) {
812
                this.noDataEnabled = noDataEnabled;
813
        }
814

    
815
        /**
816
         * Devuelve si el Dataset es reproyectable
817
         * @return
818
         */
819
        public boolean isReproyectable() {
820
                return false;
821
        }
822

    
823
        public String getWktProjection() {
824
                return wktProjection;
825
        }
826

    
827
        /**
828
         * Devuelve un serializador que tenga un constructor con la clase pasada por parametro
829
         * @throws RmfSerializerException
830
         */
831
        static private Class getSerializerClass(Class class1) throws RmfSerializerException {
832
                ExtensionPointManager extensionPoints =ToolsLocator.getExtensionPointManager();
833
                ExtensionPoint point=extensionPoints.get("Serializer");
834
//                ExtensionPoint extensionPoint = ExtensionPoint.getExtensionPoint("Serializer");
835
                Iterator iterator = point.iterator();
836
                while (iterator.hasNext()) {
837
                        ExtensionPoint.Extension extension = (ExtensionPoint.Extension) iterator
838
                                        .next();
839
                        if (extension != null) {
840
                                Class[] args = { class1 };
841
                                Class clase = extension.getExtension();
842
                                try {
843
                                        clase.getConstructor(args);
844
                                        return clase;
845
                                } catch (Exception e) {
846
                                        // Si no encuentra un constructor para esta clase, seguir? buscando en los dem?s elementos
847
                                }
848
                        }
849
                }
850
                throw new RmfSerializerException("No se ha encontrado la clase para el serializador");
851
        }
852

    
853
        /**
854
         * Construye un serializador que soporte la clase class1. El constructor se invoca
855
         * con el parametro value.
856
         *
857
         * @param class1
858
         * @param value
859
         * @return
860
         * @throws RmfSerializerException
861
         */
862
        static private ClassSerializer getSerializerObject(Class class1, Object value) throws RmfSerializerException {
863
                try {
864
                        Class[] args = { class1 };
865
                        Constructor constructor = getSerializerClass(class1).getConstructor(args);
866
                        Object[] args2 = { value };
867
                        return (ClassSerializer) constructor.newInstance(args2);
868
                } catch (Exception e) {
869
                        throw new RmfSerializerException("No se ha podido crear el serializador para el Rmf", e);
870
                }
871
        }
872

    
873
        /**
874
         * Guarda en el RMF que trata el BlocksManager el valor value usando el serializador que soporta
875
         * la clase class1.
876
         *
877
         * @param blocksManager
878
         * @param class1
879
         * @param value
880
         * @throws RmfSerializerException
881
         */
882
        static private void saveObjectToRmfFile(RmfBlocksManager blocksManager, Class class1, Object value) throws RmfSerializerException {
883
                ClassSerializer serializerObject = getSerializerObject(class1, value);
884

    
885
                if (serializerObject == null)
886
                        throw new RmfSerializerException("No se ha podido encontrar el serializador para el Rmf");
887

    
888
                if (!blocksManager.checkRmf())
889
                        throw new RmfSerializerException("Error al comprobar el fichero Rmf");
890

    
891
                blocksManager.addClient(serializerObject);
892
                try {
893
                        blocksManager.write(true);
894
                } catch (IOException e) {
895
                        throw new RmfSerializerException("Error al escribir el fichero Rmf", e);
896
                }
897
                blocksManager.removeAllClients();
898
        }
899

    
900
        /**
901
         * Guarda en el fichero file (en formato RMF) el objecto value usando el serializador que trata
902
         * las clases class1.
903
         *
904
         * Si el fichero RMF no existe se crea. Ha de ser un RMF de formato valido.
905
         *
906
         * @param file
907
         * @param class1
908
         * @param value
909
         * @throws RmfSerializerException
910
         */
911
        static public void saveObjectToRmfFile(String file, Class class1, Object value) throws RmfSerializerException {
912
                String fileRMF = RasterUtilities.getNameWithoutExtension(file) + ".rmf";
913
                RmfBlocksManager blocksManager = new RmfBlocksManager(fileRMF);
914
                saveObjectToRmfFile(blocksManager, class1, value);
915
        }
916

    
917
        /**
918
         * Guarda en el fichero file (en formato RMF) el objecto value usando el serializador que trata
919
         * la misma clase que el objeto value.
920
         *
921
         * Si el fichero RMF no existe se crea. Ha de ser un RMF de formato valido.
922
         *
923
         * @param file
924
         * @param value
925
         * @throws RmfSerializerException
926
         */
927
        static public void saveObjectToRmfFile(String file, Object value) throws RmfSerializerException {
928
                saveObjectToRmfFile(file, value.getClass(), value);
929
        }
930

    
931
        /**
932
         * Guarda en el RMF el objecto actual en caso de que exista un serializador para el.
933
         * El tipo del objeto se especifica en el parametro class1.
934
         * Esto nos puede permitir poder poner a null un valor y encontrar su serializador.
935
         * @param value
936
         * @throws RmfSerializerException
937
         */
938
        public void saveObjectToRmf(Class class1, Object value) throws RmfSerializerException {
939
                saveObjectToRmfFile(getRmfBlocksManager(), class1, value);
940
        }
941

    
942
        /**
943
         * Carga un objecto desde un serializador del tipo class1. Usa value para iniciar dicho
944
         * serializador
945
         *
946
         * @param class1
947
         * @param value
948
         * @return
949
         * @throws RmfSerializerException
950
         */
951
        static private Object loadObjectFromRmfFile(RmfBlocksManager blocksManager, Class class1, Object value) throws RmfSerializerException {
952
                ClassSerializer serializerObject = getSerializerObject(class1, value);
953

    
954
                if (serializerObject == null)
955
                        throw new RmfSerializerException("No se ha podido encontrar el serializador para el Rmf");
956

    
957
                if (!blocksManager.checkRmf())
958
                        throw new RmfSerializerException("Error al comprobar el fichero Rmf");
959

    
960
                blocksManager.addClient(serializerObject);
961
                try {
962
                        blocksManager.read(null);
963
                } catch (ParsingException e) {
964
                        throw new RmfSerializerException("Error al leer el fichero Rmf", e);
965
                }
966
                blocksManager.removeAllClients();
967

    
968
                return serializerObject.getResult();
969
        }
970

    
971
        /**
972
         * Carga un objecto del fichero RMF del dataset
973
         * @param class1
974
         * @param value
975
         * @return
976
         * @throws RmfSerializerException
977
         */
978
        public Object loadObjectFromRmf(Class class1, Object value) throws RmfSerializerException {
979
                return loadObjectFromRmfFile(getRmfBlocksManager(), class1, value);
980
        }
981

    
982
        /**
983
         * Carga un objeto del fichero RMF especificado por parametro
984
         * @param file
985
         * @param class1
986
         * @param value
987
         * @return
988
         * @throws RmfSerializerException
989
         */
990
        static public Object loadObjectFromRmfFile(String file, Class class1, Object value) throws RmfSerializerException {
991
                String fileRMF = RasterUtilities.getNameWithoutExtension(file) + ".rmf";
992
                RmfBlocksManager blocksManager = new RmfBlocksManager(fileRMF);
993
                return loadObjectFromRmfFile(blocksManager, class1, value);
994
        }
995

    
996
        /**
997
         * Guarda en el RMF el objecto actual en caso de que exista un serializador para el
998
         * @param value
999
         * @throws RmfSerializerException
1000
         */
1001
        public void saveObjectToRmf(Object value) throws RmfSerializerException {
1002
                saveObjectToRmf(value.getClass(), value);
1003
        }
1004

    
1005
        /**
1006
         * Carga un objecto desde un serializador usando el tipo del mismo objeto pasado por parametro.
1007
         * Usa value para iniciar dicho serializador
1008
         * @param value
1009
         * @return
1010
         * @throws RmfSerializerException
1011
         */
1012
        public Object loadObjectFromRmf(Object value) throws RmfSerializerException {
1013
                return loadObjectFromRmf(value.getClass(), value);
1014
        }
1015
}