Statistics
| Revision:

gvsig-raster / org.gvsig.raster.wmts / trunk / org.gvsig.raster.wmts / org.gvsig.raster.wmts.io / src / main / java / org / gvsig / raster / wmts / io / WMTSProvider.java @ 1367

History | View | Annotate | Download (51.4 KB)

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

    
24
import java.awt.geom.AffineTransform;
25
import java.awt.geom.NoninvertibleTransformException;
26
import java.awt.geom.Point2D;
27
import java.awt.geom.Rectangle2D;
28
import java.io.File;
29
import java.io.IOException;
30
import java.net.ConnectException;
31
import java.net.MalformedURLException;
32
import java.net.URL;
33
import java.util.ArrayList;
34

    
35
import org.gvsig.compat.net.ICancellable;
36
import org.gvsig.fmap.dal.DALLocator;
37
import org.gvsig.fmap.dal.DataStore;
38
import org.gvsig.fmap.dal.DataStoreParameters;
39
import org.gvsig.fmap.dal.coverage.RasterLocator;
40
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
41
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
42
import org.gvsig.fmap.dal.coverage.datastruct.DatasetBand;
43
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
44
import org.gvsig.fmap.dal.coverage.exception.BandAccessException;
45
import org.gvsig.fmap.dal.coverage.exception.BandNotFoundInListException;
46
import org.gvsig.fmap.dal.coverage.exception.FileNotOpenException;
47
import org.gvsig.fmap.dal.coverage.exception.InfoByPointException;
48
import org.gvsig.fmap.dal.coverage.exception.InvalidSetViewException;
49
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
50
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
51
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
52
import org.gvsig.fmap.dal.coverage.exception.RemoteServiceException;
53
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
54
import org.gvsig.fmap.dal.coverage.store.props.HistogramComputer;
55
import org.gvsig.fmap.dal.coverage.store.props.Transparency;
56
import org.gvsig.fmap.dal.coverage.util.MathUtils;
57
import org.gvsig.fmap.dal.exception.InitializeException;
58
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
59
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
60
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
61
import org.gvsig.metadata.MetadataLocator;
62
import org.gvsig.raster.cache.tile.TileCacheLocator;
63
import org.gvsig.raster.cache.tile.TileCacheManager;
64
import org.gvsig.raster.cache.tile.exception.TileGettingException;
65
import org.gvsig.raster.cache.tile.provider.CacheStruct;
66
import org.gvsig.raster.cache.tile.provider.TileListener;
67
import org.gvsig.raster.cache.tile.provider.TileServer;
68
import org.gvsig.raster.impl.DefaultRasterManager;
69
import org.gvsig.raster.impl.buffer.DefaultRasterQuery;
70
import org.gvsig.raster.impl.datastruct.BandListImpl;
71
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
72
import org.gvsig.raster.impl.datastruct.ExtentImpl;
73
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
74
import org.gvsig.raster.impl.provider.MemoryMatrixBuffer;
75
import org.gvsig.raster.impl.provider.RasterProvider;
76
import org.gvsig.raster.impl.provider.RemoteRasterProvider;
77
import org.gvsig.raster.impl.provider.TiledRasterProvider;
78
import org.gvsig.raster.impl.store.DefaultStoreFactory;
79
import org.gvsig.raster.impl.store.properties.DataStoreColorInterpretation;
80
import org.gvsig.raster.impl.store.properties.DataStoreTransparency;
81
import org.gvsig.raster.impl.store.properties.RemoteStoreHistogram;
82
import org.gvsig.raster.util.DefaultProviderServices;
83
import org.gvsig.raster.wmts.io.downloader.WMTSTileServer;
84
import org.gvsig.remoteclient.exceptions.ServerErrorException;
85
import org.gvsig.remoteclient.wmts.WMTSStatus;
86
import org.gvsig.remoteclient.wmts.exception.DownloadException;
87
import org.gvsig.remoteclient.wmts.exception.WMTSException;
88
import org.gvsig.remoteclient.wmts.struct.WMTSBoundingBox;
89
import org.gvsig.remoteclient.wmts.struct.WMTSLayer;
90
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrix;
91
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixLimits;
92
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixSet;
93
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixSetLink;
94
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrix.Tile;
95
import org.gvsig.tools.ToolsLocator;
96
import org.gvsig.tools.task.TaskStatus;
97
import org.slf4j.Logger;
98
import org.slf4j.LoggerFactory;
99
/**
100
 * Provider for WMTS service
101
 *
102
 * @author Nacho Brodin (nachobrodin@gmail.com)
103
 */
104
public class WMTSProvider extends DefaultRasterProvider implements RemoteRasterProvider, TiledRasterProvider {
105
        public static String                NAME                     = "Wmts Store";
106
        public static String                DESCRIPTION              = "Wmts Raster file";
107
        public static final String          METADATA_DEFINITION_NAME = "WmtsStore";
108
        private static Logger               logger                   = LoggerFactory.getLogger(WMTSProvider.class);
109
        public static boolean               TILED                    = true;
110
        
111
        //Los tiles se piden de forma secuencial y sin lanzar threads para ello (+Lento)
112
        public static int                   SEQUENTIAL               = 0;
113
        //Los tiles se piden en threads y hay un thread manager para gestionar que no se pidan m?s de cierto n?mero
114
        public static int                   LIMITED_THREADS          = 1;
115
        //Los tiles se piden en threads y se lanzan tantos threads como tiles haya
116
        public static int                   UNLIMITED_THREADS        = 2;
117
        private int                         requestType              = LIMITED_THREADS;
118
        
119
        private static final double         MTS_X_GRADO              = 111319.490793274;
120
        
121
        private Extent                      viewRequest              = null;
122
        private WMTSConnector               connector                = null;
123
        //private static Hashtable<URL, WMTSConnector>    
124
        //                                    drivers                  = new Hashtable<URL, WMTSConnector> ();
125
        private boolean                     open                     = false;
126
        private File                        lastRequest              = null;
127
        private DataStoreTransparency       lastFileTransparency     = null;
128
        private int                         lastWidthRequest         = 0;
129
        private int                         lastHeightRequest        = 0;
130
        private WMTSStatus                  lastStatus               = null;
131
        private boolean                     gridSubsets              = true;
132
        private Extent[]                    extentByLevel            = null; //Only for layers without gridSubsets
133
        private MathUtils                   math                     = RasterLocator.getManager().getMathUtils();
134
        
135
        /**
136
         * This thread manages the number of tiles that have been thrown.
137
         * This number is controlled by the NTHREADS_QUEUE variable.
138
         * 
139
         * @author Nacho Brodin (nachobrodin@gmail.com)
140
         */
141
        public class RequestThreadManager extends Thread {
142
                private TilePipe           pipe           = null;
143
                private ArrayList<Tile>    tiles          = null;
144
                private WMTSStatus         status         = null;
145
                
146
                public RequestThreadManager(TilePipe pipe, ArrayList<Tile> tiles, WMTSStatus status) {
147
                        this.pipe = pipe;
148
                        this.tiles = tiles;
149
                        this.status = status;
150
                }
151
                
152
                public void run() {
153
                        for (int i = 0; i < tiles.size(); i++) {
154
                                Tile tile = tiles.get(i);
155
                                WMTSStatus statusCopy = status.cloneStatus();
156
                                statusCopy.setTileRow(tile.row);
157
                                statusCopy.setTileCol(tile.col);
158
                                if (pipe.getSize() > TilePipe.NTHREADS_QUEUE) {
159
                                        try {
160
                                                synchronized (this) {
161
                                                        wait();                                                        
162
                                                }
163
                                        } catch( InterruptedException e ) {
164
                                        }
165
                                }
166
                                new RequestTileLauncher(pipe, statusCopy, tile).start();
167
                        }
168
                }
169
        }
170
        
171
        /**
172
         * Thread to download a tile
173
         * @author Nacho Brodin (nachobrodin@gmail.com)
174
         */
175
        class RequestTileLauncher extends Thread {
176
                private TilePipe      pipe    = null;
177
                private WMTSStatus    status  = null;
178
                private Tile          tile    = null;
179

    
180
                public RequestTileLauncher(TilePipe pipe, WMTSStatus status, Tile tile) {
181
                        this.pipe = pipe;
182
                        this.status = status;
183
                        this.tile = tile;
184
                }
185

    
186
                public void run() {
187
                        try {
188
                                //File file = getConnector().getTile(status, null);
189
                                URL url = getConnector().getTileURL(status);
190
                                tile.file = getConnector().downloadFile(url, null);
191
                                pipe.setTile(tile);
192
                        } catch (DownloadException e) {
193
                                logger.info("Error downloading files", e);
194
                        } catch (MalformedURLException e) {
195
                                logger.info("Malformed URL", e);
196
                        } catch (WMTSException e) {
197
                                logger.info("", e);
198
                        }
199
                }
200
        }
201
        
202
        /**
203
         * Point information 
204
         * @author Nacho Brodin (nachobrodin@gmail.com)
205
         */
206
        public class PointInfo {
207
                public Point2D worldCoord;
208
                public Point2D tile;
209
                public Point2D pixelInTile;
210
                public int     level;
211
                
212
                public PointInfo(Point2D worldCoord) {
213
                        this.worldCoord = worldCoord;
214
                }
215
        }
216

    
217
        public static void register() {
218
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
219
                if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
220
                        dataman.registerStoreProvider(NAME,
221
                                        WMTSProvider.class, WMTSDataParametersImpl.class);
222
                }
223

    
224
                if (!dataman.getExplorerProviders().contains(WMTSServerExplorer.NAME)) {
225
                        dataman.registerExplorerProvider(WMTSServerExplorer.NAME, WMTSServerExplorer.class, WMTSServerExplorerParameters.class);
226
                }
227
                dataman.registerStoreFactory(NAME, DefaultStoreFactory.class);
228
        }
229
        
230
        public WMTSProvider() throws NotSupportedExtensionException {
231
                super();
232
        }
233
        
234
        /**
235
         * Constructor. Abre el dataset.
236
         * @param proj Proyecci?n
237
         * @param fName Nombre del fichero
238
         * @throws NotSupportedExtensionException
239
         */
240
        public WMTSProvider(String params) throws NotSupportedExtensionException {
241
                super(params);
242
                if(params instanceof String) {
243
                        WMTSDataParameters p = new WMTSDataParametersImpl();
244
                        p.setURI((String)params);
245
                        super.init(p, null, ToolsLocator.getDynObjectManager()
246
                                        .createDynObject(
247
                                                        MetadataLocator.getMetadataManager().getDefinition(
248
                                                                        DataStore.METADATA_DEFINITION_NAME)));
249
                        init(p, null);
250
                }
251
        }
252
        
253
        public WMTSProvider(WMTSDataParameters params,
254
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
255
                super(params, storeServices, ToolsLocator.getDynObjectManager()
256
                                .createDynObject(
257
                                                MetadataLocator.getMetadataManager().getDefinition(
258
                                                                DataStore.METADATA_DEFINITION_NAME)));
259
                init(params, storeServices);
260
        }
261
        
262
        /**
263
         * Gets the connector from the URL
264
         * @return
265
         * @throws RemoteServiceException
266
         */
267
        public WMTSConnector getConnector() throws WMTSException {
268
                if(connector == null) {
269
                        WMTSDataParameters p = (WMTSDataParameters)parameters;
270
                        URL url = null;
271
                        try {
272
                                url = new URL(p.getURI());
273
                        } catch (Exception e) {
274
                                throw new WMTSException("Malformed URL",e);
275
                        }
276
                        try {
277
                                connector = new WMTSConnector(url);
278
                        } catch (ConnectException e) {
279
                                throw new WMTSException("Connect exception",e);
280
                        } catch (IOException e) {
281
                                throw new WMTSException("Connect exception",e);
282
                        }
283
                }
284
                return connector;
285
        }
286

    
287
        /**
288
         * Crea las referencias al fichero y carga
289
         * las estructuras con la informaci?n y los metadatos.
290
         * @param proj Proyecci?n
291
         * @param param Parametros de carga
292
         * @throws NotSupportedExtensionException
293
         */
294
        public void init (DataStoreParameters params,
295
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
296
                setParam(storeServices, params);
297
                if(((WMTSDataParameters)params).getImageFormat().compareTo("image/gif") == 0) {
298
                        setDataType(new int[]{Buffer.TYPE_BYTE});
299
                        bandCount = 1;
300
                } else {
301
                        setDataType(new int[]{Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE});
302
                        bandCount = 4;
303
                }
304
                
305
                if(!(param instanceof WMTSDataParameters))
306
                        return;
307
                
308
                gridSubsets = hasGridSubsets((WMTSDataParameters)param);
309
                open = true;
310
        }
311
        
312
        /**
313
         * Returns true if this layer has grid subsets
314
         * @return
315
         */
316
        public boolean hasGridSubsets() {
317
                return gridSubsets;
318
        }
319
        
320
        /**
321
         * Checks if this layer has grid subsets or doesn't
322
         * @param p
323
         * @return
324
         */
325
        @SuppressWarnings("unchecked")
326
        private boolean hasGridSubsets(WMTSDataParameters p) {
327
                ArrayList tileMatrixSetLimits = null;
328
                ArrayList<?> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
329
                String srs = p.getSRSCode();
330
                for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
331
                        WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
332
                        WMTSTileMatrixSet tms = tileMatrixSetLink.getTileMatrixSet();
333
                        ArrayList tmsl = tileMatrixSetLink.getTileMatrixLimits();
334
                        String srsTileSet = tms.getSupportedCRS();
335
                        if(srsTileSet.compareTo(srs) == 0) {
336
                                tileMatrixSetLimits = tmsl;
337
                        }
338
                }
339
                
340
                return tileMatrixSetLimits.size() <= 0 ? false : true; 
341
        }
342
        
343
        /*public static final WMTSConnector getConnectorFromURL(URL url) throws IOException {
344
                WMTSConnector drv = (WMTSConnector) drivers.get(url);
345
                if (drv == null) {
346
                        drv = new WMTSConnector(url);
347
                        drivers.put(url, drv);
348
                }
349
                return drv;
350
        }*/
351
        
352
        /**
353
         * Obtiene el objeto que contiene que contiene la interpretaci?n de
354
         * color por banda
355
         * @return
356
         */
357
        public ColorInterpretation getColorInterpretation() {
358
                if(super.getColorInterpretation() == null) {
359
                        ColorInterpretation colorInterpretation = new DataStoreColorInterpretation();
360
                        colorInterpretation.initColorInterpretation(getBandCount());
361
                        if(getBandCount() >= 3) {
362
                                colorInterpretation.setColorInterpValue(0, DataStoreColorInterpretation.RED_BAND);
363
                                colorInterpretation.setColorInterpValue(1, DataStoreColorInterpretation.GREEN_BAND);
364
                                colorInterpretation.setColorInterpValue(2, DataStoreColorInterpretation.BLUE_BAND);
365
                        }
366
                        if(getBandCount() == 4)
367
                                colorInterpretation.setColorInterpValue(3, DataStoreColorInterpretation.ALPHA_BAND);
368
                        if(getBandCount() > 4 || getBandCount() < 3) {
369
                                for (int i = 0; i < getBandCount(); i++) {
370
                                        colorInterpretation.setColorInterpValue(i, DataStoreColorInterpretation.UNDEF_BAND);
371
                                }
372
                        }
373
                        setColorInterpretation(colorInterpretation);
374
                }
375
                return super.getColorInterpretation();
376
        }
377
        
378
        /*
379
         * (non-Javadoc)
380
         * @see org.gvsig.raster.impl.provider.RasterProvider#isTiled()
381
         */
382
        public boolean isTiled() {
383
                return true;
384
        }
385
        
386
        /*
387
         * (non-Javadoc)
388
         * @see org.gvsig.fmap.dal.coverage.dataset.RasterDataSet#getAffineTransform()
389
         */
390
        public AffineTransform getAffineTransform() {
391
                WMTSDataParameters p = (WMTSDataParameters)parameters;
392
                Extent e = getExtent();
393
                double psX = e.width() / (lastWidthRequest <= 0 ? p.getWidth() : lastWidthRequest);
394
                double psY = -(e.height() / (lastHeightRequest <= 0 ? p.getHeight() : lastHeightRequest));
395
                ownTransformation = new AffineTransform(
396
                                psX, 
397
                                0, 
398
                                0, 
399
                                psY, 
400
                                e.getULX() - (psX / 2),
401
                                e.getULY() - (psY / 2));
402
                externalTransformation = (AffineTransform) ownTransformation.clone();
403
                return ownTransformation;
404
        }
405
        
406
        /**
407
         * Gets the bounding box in world coordinates. If the layer has grid subsets (TileMatrixLimits) then
408
         * this will have a only extent but if the layer doesn't have grid subsets then this will have a different
409
         * extent in each level resolution. In this case we need to know the extent for each level.
410
         * @return Extent
411
         */
412
        public Extent getExtent() {
413
                WMTSDataParameters p = (WMTSDataParameters)parameters;
414
                if(gridSubsets) {
415
                        WMTSLayer layer = p.getLayer();
416
                        WMTSBoundingBox bbox = layer.getWGS84BBox();
417
                        return new ExtentImpl(bbox.toRectangle2D());
418
                } else {
419
                        WMTSTileMatrixSet tileMatrixSet = getTileMatrixSetLink().getTileMatrixSet();
420
                        
421
                        //Si ya se han calculado los niveles es q el extent es v?lido sino el nivel ser? el 0
422
                        double scale = 0D;
423
                        int level = 0;
424
                        if(extentByLevel != null && p.getExtent() != null) {
425
                                scale = getScale(p.getExtent(), p.getWidth());
426
                                try {
427
                                        level = getLevelFromScale(scale, tileMatrixSet);
428
                                } catch (RasterDriverException e) {
429
                                        e.printStackTrace();
430
                                }                                
431
                        }
432
                        
433
                        Extent[] ext = getExtentByResolutionLevel();
434
                        
435
                        if(ext != null && level >= 0 && level < ext.length)
436
                                return ext[level];
437
                }
438
                return null;
439
        }
440
        
441
        /**
442
         * Gets the suffix of the downloaded image
443
         * @return
444
         */
445
        public String getFileSuffix() {
446
                WMTSDataParameters p = (WMTSDataParameters)parameters;
447
                String format = p.getImageFormat();
448
                if (format == null){
449
                        return "xml";
450
                }
451
                if (format.indexOf("png") >= 0){
452
                return "png";
453
                }        
454
            if (format.indexOf("xml") >= 0){
455
                return "xml";
456
            }        
457
            if (format.indexOf("gif") >= 0){
458
                return "gif";
459
            }
460
            if (format.indexOf("tif") >= 0){
461
                return "tif";
462
            }
463
            if (format.indexOf("bmp") >= 0){
464
                return "bmp";
465
            }
466
            if (format.indexOf("jpg") >= 0
467
                || format.indexOf("jpeg") >= 0){
468
                return "jpg";                         
469
            }
470
                return "xml";
471
        }
472

    
473
        /**
474
         * When a layer doesn't have grid subsets this will have a different bounding
475
         * box by resolution level. This function calculates and returns the array of
476
         * extents, one by resolution level.
477
         * @return
478
         */
479
        public Extent[] getExtentByResolutionLevel() {
480
                if(extentByLevel == null) {
481
                        WMTSDataParameters p = (WMTSDataParameters)parameters;
482
                        WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
483
                        WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
484
                        
485
                    double widthMtsTile = 0;
486
                    double heightMtsTile = 0;
487
                        ArrayList<?> tileMatrixList = tileMatrixSet.getTileMatrix();
488
                        extentByLevel = new ExtentImpl[tileMatrixList.size()];
489
                        for (int i = 0; i < tileMatrixList.size(); i++) {
490
                                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixList.get(i);
491
                            if(!p.isProjected()) {
492
                                    widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
493
                                    heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
494
                            } else {
495
                                    widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
496
                                    heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
497
                            }
498
                            
499
                            double h = Math.abs(tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getMatrixHeight() * heightMtsTile)));
500
                            Rectangle2D r = new Rectangle2D.Double(
501
                                            tileMatrix.getTopLeftCorner()[1], 
502
                                            tileMatrix.getTopLeftCorner()[0] - h,
503
                                            Math.abs(tileMatrix.getTopLeftCorner()[1] - (tileMatrix.getTopLeftCorner()[1] + (tileMatrix.getMatrixWidth() * widthMtsTile))),
504
                                            h);
505
                            extentByLevel[i] = new ExtentImpl(r);
506
                        }
507
                        
508
                }
509
                return extentByLevel;
510
        }
511
        
512
        /*
513
         * (non-Javadoc)
514
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLayerExtent(java.lang.String, java.lang.String)
515
         */
516
        public Rectangle2D getLayerExtent(String layerName, String srs) throws RemoteServiceException {
517
                return null;
518
        }
519

    
520
        /*
521
         * (non-Javadoc)
522
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#load()
523
         */
524
        public RasterProvider load() {
525
                return this;
526
        }
527
        
528
        /*
529
         * (non-Javadoc)
530
         * @see org.gvsig.raster.impl.provider.RasterProvider#isOpen()
531
         */
532
        public boolean isOpen() {
533
                return open;
534
        }
535

    
536
        /*
537
         * (non-Javadoc)
538
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#close()
539
         */
540
        public void close() {
541
                open = false;
542
        }
543
        
544
        /*
545
         * (non-Javadoc)
546
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTransparency()
547
         */
548
        public Transparency getTransparency() {
549
                if(lastFileTransparency == null) {
550
                        lastFileTransparency = new DataStoreTransparency();
551
                        lastFileTransparency.setTransparencyBand(3);
552
                }
553
                return lastFileTransparency;
554
        }
555

    
556
        /*
557
         * (non-Javadoc)
558
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#translateFileName(java.lang.String)
559
         */
560
        public String translateFileName(String fileName) {
561
                return fileName;
562
        }
563

    
564
        /*
565
         * (non-Javadoc)
566
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setView(org.gvsig.fmap.dal.coverage.datastruct.Extent)
567
         */
568
        public void setView(Extent e) {
569
                viewRequest = e;
570
        }
571

    
572
        /*
573
         * (non-Javadoc)
574
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getView()
575
         */
576
        public Extent getView() {
577
                return viewRequest;
578
        }
579

    
580
        /*
581
         * (non-Javadoc)
582
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWidth()
583
         */
584
        public double getWidth() {
585
                WMTSDataParameters p = (WMTSDataParameters)parameters;
586
                if (lastWidthRequest <= 0) 
587
                        return p.getWidth();
588
                return lastWidthRequest;
589
        }
590

    
591
        /*
592
         * (non-Javadoc)
593
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getHeight()
594
         */
595
        public double getHeight() {
596
                WMTSDataParameters p = (WMTSDataParameters)parameters;
597
                if (lastHeightRequest <= 0) 
598
                        return p.getHeight();
599
                return lastHeightRequest;
600
        }
601

    
602
        /*
603
         * (non-Javadoc)
604
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#readCompleteLine(int, int)
605
         */
606
        public Object readCompleteLine(int line, int band)
607
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
608
                return null;
609
        }
610
        
611
        /**
612
         * When the remote layer has fixed size this method downloads the file and return its reference. 
613
         * File layer has in the long side FIXED_SIZE pixels and the bounding box is complete. This file could be
614
         * useful to build an histogram or calculate statistics. This represents a sample of data.
615
         * @return
616
         * @throws RasterDriverException
617
         */
618
        public File getFileLayer() throws RasterDriverException {
619
                return null;
620
        }
621

    
622
        /**
623
         * Reads a complete block of data and returns an tridimensional array of the right type. This function is useful
624
         * to read a file very fast without setting a view. In a WMTS service when the size is fixed then it will read the
625
         * entire image but when the source hasn't pixel size it will read a sample of data. This set of data will have
626
         * the size defined in FIXED_SIZE. 
627
         * 
628
         * @param pos Posici?n donde se empieza  a leer
629
         * @param blockHeight Altura m?xima del bloque leido
630
         * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
631
         * @throws InvalidSetViewException
632
         * @throws FileNotOpenException
633
         * @throws RasterDriverException
634
         */
635
        public Object readBlock(int pos, int blockHeight, double scale) 
636
        throws InvalidSetViewException, FileNotOpenException, RasterDriverException, ProcessInterruptedException {
637
                return null;
638
        }
639
        
640
        /*
641
         * (non-Javadoc)
642
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLastRequestHeight()
643
         */
644
        public double getLastRequestHeight() throws RasterDriverException {
645
                return 0;
646
        }
647
        
648
        /*
649
         * (non-Javadoc)
650
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLastRequestWidth()
651
         */
652
        public double getLastRequestWidth() throws RasterDriverException {
653
                return 0;
654
        }
655

    
656
        /*
657
         * (non-Javadoc)
658
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getData(int, int, int)
659
         */
660
        public Object getData(int x, int y, int band)
661
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
662
                return null;
663
        }
664
        
665
        /**
666
         * Assigns the list of bands RGB and read a window of data
667
         * @param rasterBuf
668
         * @param bandList
669
         * @param lastFile
670
         * @param ulx
671
         * @param uly
672
         * @param lrx
673
         * @param lry
674
         * @return
675
         * @throws RasterDriverException
676
         * @throws ProcessInterruptedException
677
         */
678
        public Buffer getBuffer(Buffer rasterBuf, BandList bandList, File lastFile, 
679
                        double ulx, double uly, double lrx, double lry) throws RasterDriverException, ProcessInterruptedException {
680
                return null;
681
        }
682
        
683
        /**
684
         * Gets the tile matrix from the selected level
685
         * @param level
686
         * @return
687
         */
688
        @SuppressWarnings("unchecked")
689
        private WMTSTileMatrix getTileMatrixByLevel(int level) {
690
                level = adjustLevel(level);
691
                
692
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
693
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
694
                ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
695
                
696
                WMTSTileMatrixLimits tileMatrixLimits = null;
697
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(level);
698
                if(hasGridSubsets()) {
699
                        tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(level);
700
                        tileMatrix = tileMatrixLimits.getTileMatrix();
701
                }
702
                return tileMatrix;
703
        }
704
        
705
        /**
706
         * Returns the number of levels
707
         * @return
708
         */
709
        @SuppressWarnings("unchecked")
710
        public int getZoomLevels() {
711
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
712
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
713
                if(hasGridSubsets()) {
714
                        ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
715
                        return Math.min(tileMatrixSet.getTileMatrix().size(), tileMatrixSetLimits.size());
716
                }
717
                return tileMatrixSet.getTileMatrix().size();
718
                
719
        }
720
        
721
        /*
722
         * (non-Javadoc)
723
         * @see org.gvsig.raster.impl.provider.RasterProvider#getCoordsInTheNearestLevel(org.gvsig.fmap.dal.coverage.datastruct.Extent, int, int)
724
         */
725
        public Extent getCoordsInTheNearestLevel(Extent extent, int w, int h) {
726
                double[] pixelSizes = getPixelSizeByLevel();
727
                double currentPixelSize = extent.width() / (double)w;
728
                
729
                int level = 0;
730
                for (int i = 0; i < (pixelSizes.length - 1); i++) {
731
                        if(currentPixelSize < pixelSizes[i] && currentPixelSize >= pixelSizes[i + 1]) {
732
                                level = i + 1;
733
                                break;
734
                        }
735
                }
736
                
737
                return getZoomLevelCoordinates(level, extent, w, h);
738
        }
739
        
740
        /*
741
         * (non-Javadoc)
742
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getCoordsInLevel(java.awt.geom.Point2D, int, int, int)
743
         */
744
        public Extent getCoordsInLevel(Point2D viewCenter, int level, int w, int h) {
745
                WMTSDataParameters p = (WMTSDataParameters)param;
746
                level = adjustLevel(level);
747
                WMTSTileMatrix tileMatrix = getTileMatrixByLevel(level);
748
                
749
                boolean proj = p.isProjected();
750
                
751
                double psX = tileMatrix.getWidthMtsTile(proj) / tileMatrix.getTileWidth();
752
                double psY = tileMatrix.getHeightMtsTile(proj) / tileMatrix.getTileHeight();
753
                
754
                double ulx = viewCenter.getX() - ((w / 2) * psX);
755
                double uly = viewCenter.getY() - ((h / 2) * psY);
756
                double lrx = ulx + (w * psX);
757
                double lry = uly + (h * psY);
758
                return new ExtentImpl(ulx, uly, lrx, lry);
759
        }
760
        
761
        /**
762
         * Calculates the extent of a zoom level using other extent as a reference. The new extent is 
763
         * calculated with the same coordinate at the center. 
764
         * @param level
765
         * @param extent
766
         * @param w
767
         * @param h
768
         * @return
769
         */
770
        public Extent getZoomLevelCoordinates(int level, Extent extent, int w, int h) {
771
                double centerX = extent.getCenterX();
772
                double centerY = extent.getCenterY();
773
                return getCoordsInLevel(new Point2D.Double(centerX, centerY), level, w, h);
774
        }
775
        
776
        /**
777
         * Returns a list of pixel sizes by level
778
         * @return
779
         */
780
        public double[] getPixelSizeByLevel() {
781
                WMTSDataParameters p = (WMTSDataParameters)param;
782
                double[] list = new double[getZoomLevels()];
783
                
784
                for (int i = 0; i < getZoomLevels(); i++) {
785
                        WMTSTileMatrix tileMatrix = getTileMatrixByLevel(i);
786
                        list[i] = math.adjustDouble(tileMatrix.getWidthMtsTile(p.isProjected()) / tileMatrix.getTileWidth());
787
                }
788
                return list;
789
        }
790
        
791
        /**
792
         * Adjust de level to the range
793
         * @param level
794
         * @return
795
         */
796
        private int adjustLevel(int level) {
797
                if(level < 0)
798
                        level = 0;
799
                if(level > getZoomLevels())
800
                        level = getZoomLevels();
801
                return level;
802
        }
803
        
804
        /*
805
         * (non-Javadoc)
806
         * @see org.gvsig.raster.impl.provider.TiledRasterProvider#getTile(int, int, int, org.gvsig.fmap.dal.coverage.datastruct.Extent)
807
         */
808
        public org.gvsig.raster.cache.tile.Tile getTile(DefaultRasterQuery q) throws TileGettingException {
809
                //q.getResolutionLevel(), q.getTileCol(), q.getTileRow(), q.getBBox(), q.getCacheStruct()!
810
                
811
                CacheStruct str = getTileServer().getStruct();
812
                
813
                //1-Selecci?n de WMTSTileMatrixSet por srs
814
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
815
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
816
                ArrayList<?> tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
817
                
818
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(q.getResolutionLevel());
819
                if(gridSubsets) {
820
                        WMTSTileMatrixLimits tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(q.getResolutionLevel());
821
                        tileMatrix = tileMatrixLimits.getTileMatrix();
822
                }
823
                int bufWidth = tileMatrix.getTileWidth();
824
                int bufHeight = tileMatrix.getTileHeight();
825
                
826
                try {
827
                        Rectangle2D r = q.getBBox().toRectangle2D();//new Rectangle2D.Double(Math.min(minX, maxX), Math.min(minY, maxY), Math.abs(maxX - minX), Math.abs(maxY - minY));
828
                        WMTSStatus status = buildWMTSStatus(r, bufWidth , bufHeight);
829
                        
830
                        int[] size = str.getTileSizeByLevel(q.getResolutionLevel());
831
                        Tile tile = tileMatrix.new Tile(size[0], size[1], 
832
                                        q.getTileRow(), q.getTileCol(), 
833
                                        q.getBBox().getULX(), q.getBBox().getULY(), q.getBBox().getLRX(), q.getBBox().getLRY());
834
                        
835
                        File file = getConnector().getTile(status, null);
836
                        tile.file = file;
837
                        //Creamos un BandList con todas las bandas del fichero
838
                        BandList bandList = new BandListImpl();
839
                        for(int i = 0; i < getBandCount(); i++) {
840
                                try {
841
                                        DatasetBand band = new DatasetBandImpl(getURIOfFirstProvider(), i, getDataType()[i], getBandCount());
842
                                        bandList.addBand(band, i);
843
                                } catch(BandNotFoundInListException e) {
844
                                        //No a?adimos la banda
845
                                }
846
                        }
847
                        return drawTile(tile, null, bandList);
848
                } catch (WMTSException e) {
849
                        throw new TileGettingException("Error getting tiles", e);
850
                } catch (ServerErrorException e) {
851
                        throw new TileGettingException("Error getting tiles", e);
852
                } catch (RasterDriverException e) {
853
                        throw new TileGettingException("Error getting tiles", e);
854
                }
855
        }
856
        
857
        /*
858
         * (non-Javadoc)
859
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer, org.gvsig.fmap.dal.coverage.grid.render.TileListener, int)
860
         */
861
        public void getWindow(Extent ex, int bufWidth, int bufHeight, 
862
                        BandList bandList, TileListener listener, TaskStatus taskStatus) throws ProcessInterruptedException, RasterDriverException {
863
                Rectangle2D r = ex.toRectangle2D();//new Rectangle2D.Double(Math.min(minX, maxX), Math.min(minY, maxY), Math.abs(maxX - minX), Math.abs(maxY - minY));
864
                WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
865
                request(status, bandList, listener, requestType);
866
        }
867
        
868
        /*
869
         * (non-Javadoc)
870
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer, boolean)
871
         */
872
        public Buffer getWindow(Extent extent, int bufWidth, int bufHeight, 
873
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus taskStatus) throws ProcessInterruptedException, RasterDriverException {
874
                Rectangle2D r = extent.toRectangle2D();//new Rectangle2D.Double(Math.min(ulx, lrx), Math.min(lry, uly), Math.abs(lrx - ulx), Math.abs(uly - lry));
875
                WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
876
                org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null, requestType);
877
                MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
878
                return matrixBuffer.getWindow(extent, rasterBuf);
879
        }
880
        
881
        /*
882
         * (non-Javadoc)
883
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(org.gvsig.fmap.dal.coverage.datastruct.Extent, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
884
         */
885
        public Buffer getWindow(Extent extent, BandList bandList, Buffer rasterBuf, TaskStatus taskStatus) 
886
                throws ProcessInterruptedException, RasterDriverException {
887
                lastWidthRequest = rasterBuf.getWidth();
888
                lastHeightRequest = rasterBuf.getHeight();
889
                Rectangle2D r = extent.toRectangle2D();//new Rectangle2D.Double(Math.min(ulx, lrx), Math.min(lry, uly), Math.abs(lrx - ulx), Math.abs(uly - lry));
890
                WMTSStatus status = buildWMTSStatus(r, lastWidthRequest, lastHeightRequest);
891
                org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null, requestType);
892
                MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
893
                return matrixBuffer.getWindow(extent, rasterBuf);
894
        }
895

    
896
        /*
897
         * (non-Javadoc)
898
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer, boolean)
899
         */
900
        public Buffer getWindow(double ulx, double uly, double w, double h, 
901
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus taskStatus) throws ProcessInterruptedException, RasterDriverException {
902
                lastWidthRequest = rasterBuf.getWidth();
903
                lastHeightRequest = rasterBuf.getHeight();
904
                Rectangle2D r = new Rectangle2D.Double(ulx, uly - h, w, h);
905
                WMTSStatus status = buildWMTSStatus(r, lastWidthRequest, lastHeightRequest);
906
                org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null, requestType);
907
                MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
908
                return matrixBuffer.getWindow(new ExtentImpl(ulx, uly, ulx + w, uly - h), rasterBuf);
909
        }
910

    
911
        /*
912
         * (non-Javadoc)
913
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(int, int, int, int, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
914
         */
915
        public Buffer getWindow(int x, int y, int w, int h, BandList bandList, Buffer rasterBuf, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
916
                lastWidthRequest = rasterBuf.getWidth();
917
                lastHeightRequest = rasterBuf.getHeight();
918
                return null;
919
        }
920
        
921
        /**
922
         * Gets the information from a point 
923
         * @param wcx
924
         * @param wcy
925
         * @param level
926
         * @return
927
         * @throws RasterDriverException
928
         */
929
        public String getFeatureInfo(double wcx, double wcy, int level) throws RasterDriverException {
930
                PointInfo pointInfo = new PointInfo(new Point2D.Double(wcx, wcy));
931
                pointInfo.level = level;
932
                getTileInfo(pointInfo);
933
                
934
                WMTSConnector connector = null;
935
                try {
936
                        connector = getConnector();
937
                        lastStatus.setTileRow((int)pointInfo.tile.getX());
938
                        lastStatus.setTileCol((int)pointInfo.tile.getY());
939
                        
940
                        String fi = connector.getFeatureInfo(lastStatus, (int)pointInfo.pixelInTile.getX(), (int)pointInfo.pixelInTile.getY(), null);
941
                        return fi;
942
                } catch (WMTSException e) {
943
                        throw new RasterDriverException("Error getting the connector object", e);
944
                } catch (ServerErrorException e) {
945
                        throw new RasterDriverException("Error getting the connector object", e);
946
                }
947
        }
948
        
949
        /**
950
         * Gets a tile position from a world coordinates point and a resolution level
951
         * @param point
952
         * @param level
953
         * @return An array with two elements. The first is the row and the second the column
954
         * of the tile in the tile matrix
955
         */
956
        @SuppressWarnings({ "unchecked"})
957
        private void getTileInfo(PointInfo pointInfo) {
958
                WMTSDataParameters p = (WMTSDataParameters)param;
959
                
960
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
961
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
962
                ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
963
                
964
                WMTSTileMatrixLimits tileMatrixLimits = null;
965
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(pointInfo.level);
966
                if(hasGridSubsets()) {
967
                        tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(pointInfo.level);
968
                        tileMatrix = tileMatrixLimits.getTileMatrix();
969
                }
970
                
971
                ArrayList<Tile> tiles = null;
972
                if(hasGridSubsets())
973
                        tiles = tileMatrix.contains(p.isProjected(), tileMatrixLimits, pointInfo.worldCoord, getExtent().toRectangle2D());
974
                else
975
                        tiles = tileMatrix.contains(p.isProjected(), pointInfo.worldCoord, getExtent().toRectangle2D());
976
                
977
                //Tile row and column
978
                pointInfo.tile = new Point2D.Double(tiles.get(0).row, tiles.get(0).col);
979
                
980
                //Desplazamiento en pixels dentro del tile
981
                Point2D rasterPoint = tiles.get(0).worldToRaster(pointInfo.worldCoord);
982
                pointInfo.pixelInTile = new Point2D.Double(rasterPoint.getX(), rasterPoint.getY());
983
        }
984
        
985
        /**
986
         * Builds the WMTSStatus object using the parameters and the request bounding box. 
987
         * @param r
988
         * @param bufWidth
989
         * @return
990
         * @throws RasterDriverException
991
         */
992
        @SuppressWarnings("unchecked")
993
        public WMTSStatus buildWMTSStatus(Rectangle2D r, int bufWidth, int bufHeight) throws RasterDriverException {
994
                WMTSDataParameters p = (WMTSDataParameters)param;
995
                
996
                //Mantiene actualizados los par?metros del WMTSStoreParameters con la ?ltima petici?n hecha
997
                p.setExtent(r);
998
                p.setWidth(bufWidth);
999
                p.setHeight(bufHeight);
1000
                
1001
                lastWidthRequest = bufWidth;
1002
                lastHeightRequest = bufHeight;
1003
                
1004
                //1-Selecci?n de WMTSTileMatrixSet por srs
1005
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
1006
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
1007
                ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
1008
                int initialLevel = p.getLayer().getInitialLevel(tileMatrixSet.getIdentifier());
1009
                
1010
                //Esto hace lo mismo que getScale y getLevelFromScale
1011
                /*int level = 0;
1012
                double[] pixelSizes = getPixelSizeByLevel();
1013
                double psViewPort = math.adjustDouble(r.getWidth() / (double)bufWidth);
1014
                for (int i = 0; i < pixelSizes.length - 1; i++) {
1015
                        if(psViewPort <= pixelSizes[i] && psViewPort > pixelSizes[i + 1]) {
1016
                                level = i;
1017
                                break;
1018
                        }
1019
                }*/
1020
                
1021
                //2-Calculo de la escala
1022
                double scale = getScale(r, bufWidth);
1023
                
1024
                //3-Selecci?n del nivel a partir de la escala
1025
                int level = getLevelFromScale(scale, tileMatrixSet);
1026
                
1027
                //Para evitar que se salga del array si la capa tiene menos niveles que el tilematrixset
1028
                int dif = 0;
1029
                if(gridSubsets)
1030
                        dif = (level - initialLevel) >= tileMatrixSetLimits.size() ?  (level - initialLevel) - tileMatrixSetLimits.size() + 1 : 0;
1031
                
1032
                //4-Obtenemos la matriz de tiles y los l?mites si tiene subsets
1033
                @SuppressWarnings("unused")
1034
                WMTSTileMatrixLimits tileMatrixLimits = null;
1035
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(level - dif);
1036
                if(gridSubsets)
1037
                        tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(level - initialLevel - dif);
1038
                
1039
                //5-Selecci?n de tiles que entran en esta bounding box
1040
                ArrayList<Tile> tiles = null;
1041
                /*if(gridSubsets)
1042
                        tiles = tileMatrix.intersects(p.isProjected(), tileMatrixLimits, r, getExtent().toRectangle2D());
1043
                else*/
1044
                tiles = tileMatrix.intersects(p.isProjected(), r, getExtent().toRectangle2D());
1045
                
1046
                //6-Petici?n
1047
                WMTSStatus status = new WMTSStatus();
1048
                status.setTileList(tiles);
1049
                status.setLayer(p.getLayer().getIdentifier());//.substring(p.getLayer().getIdentifier().indexOf("_") + 1));
1050
                status.setFormat(p.getImageFormat());
1051
                status.setInfoFormat(p.getInfoFormat());
1052
                status.setStyle(p.getStyle() != null ? p.getStyle().getIdentifier() : "");
1053
                status.setTileMatrixSet(tileMatrixSet.getIdentifier());
1054
                status.setTileMatrix(tileMatrix.getIdentifier());
1055
                status.setLevel(level - dif);
1056
                this.lastStatus = status;
1057
                
1058
                return status;
1059
        }
1060
        
1061
        /**
1062
         * Gets the resolution level from the real coordinates
1063
         * @param r
1064
         * @param 
1065
         * @return
1066
         * @throws RasterDriverException
1067
         */
1068
        public int getLevelFromRealCoords(Rectangle2D r, int width) throws RasterDriverException {
1069
                double scale = getScale(r, width);
1070
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
1071
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
1072
                return getLevelFromScale(scale, tileMatrixSet);
1073
        }
1074
        
1075
        /**
1076
         * Gets the resolution level from the scale
1077
         * @param scale
1078
         * @param tileMatrixSet
1079
         * @return
1080
         * @throws RasterDriverException
1081
         */
1082
        public int getLevelFromScale(double scale, WMTSTileMatrixSet tileMatrixSet) throws RasterDriverException {
1083
                //Recorremos los tileMatrix para obtener la escala m?s aproximada
1084
                int levelModifier = 0;
1085
                scale = math.adjustDouble(scale);
1086
                try {
1087
                        for (int resolutionLevel = 0; resolutionLevel < tileMatrixSet.getTileMatrix().size(); resolutionLevel++) {
1088
                                WMTSTileMatrix tm = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(resolutionLevel);
1089
                                double scaleDenominator = math.adjustDouble(tm.getScaleDenominator());
1090
                                if(scale >= scaleDenominator) {
1091
                                        return Math.max(resolutionLevel + levelModifier, 0);
1092
                                }
1093
                        }
1094
                } catch (IndexOutOfBoundsException e) {
1095
                        throw new RasterDriverException("Error in this resolution level", e);
1096
                }
1097
                return 0;
1098
        }
1099
        
1100
        /**
1101
         * Get the tile matrix set using the crs
1102
         * @param srs
1103
         * @return
1104
         */
1105
        public WMTSTileMatrixSetLink getTileMatrixSetLink() {
1106
                WMTSDataParameters p = (WMTSDataParameters)param;
1107
                ArrayList<?> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
1108
                for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
1109
                        WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
1110
                        String srsTileSet = tileMatrixSetLink.getTileMatrixSet().getSupportedCRS();
1111
                        if(srsTileSet.compareTo(p.getSRSCode()) == 0) {
1112
                                return tileMatrixSetLink;
1113
                        }
1114
                }
1115
                if(tileMatrixSetLinkList != null && tileMatrixSetLinkList.size() > 0)
1116
                        return (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(0);
1117
                return null;
1118
        }
1119
        
1120
        /**
1121
         * Gets the scale using the extent and the width in pixels.
1122
         * @param r
1123
         * @param width
1124
         * @return
1125
         */
1126
        private double getScale(Rectangle2D r, int width) {
1127
                WMTSDataParameters p = (WMTSDataParameters)param;
1128
                if(!p.isProjected()) {
1129
                        return (1000 * r.getWidth() * MTS_X_GRADO) / (width * 0.28);
1130
                } else
1131
                        return (1000 * r.getWidth()) / (width * 0.28);
1132
        }
1133
        
1134
        /**
1135
         * Throw a request
1136
         * @param status
1137
         * @param bandList
1138
         * @param listener
1139
         * @param alphaBandNumber 
1140
         * @return returns a buffer if the listener is null. In any other case it return null.
1141
         * @throws RasterDriverException 
1142
         * @throws ProcessInterruptedException 
1143
         */
1144
        @SuppressWarnings("unchecked")
1145
        private synchronized org.gvsig.raster.cache.tile.Tile[] request(
1146
                        WMTSStatus status, BandList bandList, TileListener listener, int requestType) throws RasterDriverException, ProcessInterruptedException {
1147
                //WMTSDataParameters p = (WMTSDataParameters)param;
1148
                WMTSConnector connector = null;
1149
                try {
1150
                        connector = getConnector();
1151
                } catch (WMTSException e) {
1152
                        throw new RasterDriverException("Error getting the connector object", e);
1153
                }
1154
                
1155
                if(connector == null)
1156
                        throw new RasterDriverException("Error getting the connector object");
1157
                
1158
                ArrayList<Tile> tiles = status.getTileList();
1159
                
1160
                TilePipe pipe = new TilePipe();
1161
                //TilePipe2 pipe = new TilePipe2();
1162
                //TileThreadPool pool = null;
1163
                
1164
                //Caso 1: Lanza un thread que gestiona que no se lancen muchos threads a la vez
1165
                if(requestType == LIMITED_THREADS) {
1166
                        RequestThreadManager threadManager = new RequestThreadManager(pipe, tiles, status);
1167
                        pipe.setRequestManager(threadManager);
1168
                        threadManager.start();
1169
                //Caso 2: Lanza todos los threads
1170
                } else if(requestType == UNLIMITED_THREADS) {
1171
                        for (int i = 0; i < tiles.size(); i++) {
1172
                                Tile tile = tiles.get(i);
1173
                                WMTSStatus statusCopy = status.cloneStatus();
1174
                                statusCopy.setTileRow(tile.row);
1175
                                statusCopy.setTileCol(tile.col);
1176
                                new RequestTileLauncher(pipe, statusCopy, tile).start();
1177
                        }
1178
                }
1179
                
1180
                org.gvsig.raster.cache.tile.Tile[] tileList = new org.gvsig.raster.cache.tile.Tile[tiles.size()]; 
1181
                
1182
                if(requestType == LIMITED_THREADS || requestType == UNLIMITED_THREADS) {
1183
                        int nCollected = 0;
1184
                        while (nCollected < tiles.size()) {
1185
                                Tile tile = pipe.getTile();
1186
                                tileList[nCollected] = drawTile(tile, listener, bandList);
1187
                                nCollected ++;
1188
                        }
1189
                }
1190
                
1191
                if(requestType == SEQUENTIAL) {
1192
                        for (int i = 0; i < tiles.size(); i++) {
1193
                                Tile tile = tiles.get(i);
1194
                                status.setTileRow(tile.row);
1195
                                status.setTileCol(tile.col);
1196
                                //TODO:Cancelaci?n
1197
                                try {
1198
                                        File file = connector.getTile(status, null);
1199
                                        tile.file = file;
1200
                                        tileList[i] = drawTile(tile, listener, bandList);
1201
                                } catch (WMTSException e) {
1202
                                        throw new RasterDriverException("Error getting tiles", e);
1203
                                } catch (ServerErrorException e) {
1204
                                        throw new RasterDriverException("Error getting tiles", e);
1205
                                }
1206
                        }
1207
                }
1208
                if(listener != null) 
1209
                        listener.endReading();
1210
                
1211
                return tileList;
1212
        }
1213
        
1214
        /**
1215
         * Reads a tile with gdal and calls the method nextBuffer
1216
         * @param tile
1217
         * @param listener
1218
         * @param bandList
1219
         * @return
1220
         * @throws RasterDriverException
1221
         */
1222
        private synchronized org.gvsig.raster.cache.tile.Tile drawTile(Tile tile, TileListener listener, BandList bandList) throws RasterDriverException {
1223
                WMTSDataParameters p = (WMTSDataParameters)param;
1224
                try {
1225
                        String serverName = bandList.getBand(0).getFileName();
1226
                        for (int j = 0; j < bandList.getBandCount(); j++) {
1227
                                bandList.getBand(j).setFileName(tile.file.getPath());
1228
                        }
1229
                        
1230
                        DefaultRasterProvider driver = DefaultProviderServices.loadProvider(tile.file);
1231
                        colorTable = driver.getColorTable();
1232
                        bandCount = driver.getBandCount();
1233
                        lastFileTransparency = (DataStoreTransparency)driver.getTransparency();
1234
                        Buffer rasterBuf = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], tile.wPx, tile.hPx, 3, true);
1235
                        
1236
                        DefaultRasterQuery q = (DefaultRasterQuery)RasterLocator.getManager().createQuery();
1237
                        q.setAreaOfInterest(0, 0, tile.wPx, tile.hPx);
1238
                        q.setBandList(bandList);
1239
                        q.setBuffer(rasterBuf);
1240
                        Buffer buf = driver.getDataSet(q);
1241
                        
1242
                        buf.setDataExtent(new Rectangle2D.Double(Math.min(tile.ulx, tile.lrx), Math.min(tile.uly, tile.lry), Math.abs(tile.ulx - tile.lrx), Math.abs(tile.uly - tile.lry)));
1243
                        
1244
                        Buffer alphaBand = null;
1245
                        if(p.getAlphaBand() != -1 && listener != null && p.getAlphaBand() < bandCount) {
1246
                                alphaBand = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], tile.wPx, tile.hPx, 1, true);
1247
                                int[] oldDB = bandList.getDrawableBands();
1248
                                bandList.setDrawableBands(new int[]{p.getAlphaBand()});
1249
                                q.setBandList(bandList);
1250
                                q.setBuffer(alphaBand);
1251
                                alphaBand = driver.getDataSet(q);
1252
                                bandList.setDrawableBands(oldDB);
1253
                        }
1254

    
1255
                        for (int j = 0; j < bandList.getBandCount(); j++) {
1256
                                bandList.getBand(j).setFileName(serverName);
1257
                        }
1258

    
1259
                        driver.close();
1260

    
1261

    
1262
                        TileCacheManager m = TileCacheLocator.getManager();
1263
                        org.gvsig.raster.cache.tile.Tile t = m.createTile(-1, tile.row, tile.col);
1264
                        t.setData(new Object[]{buf, alphaBand});
1265
                        t.setUl(new Point2D.Double(tile.ulx, tile.uly));
1266
                        t.setLr(new Point2D.Double(tile.lrx, tile.lry));
1267
                        t.setDownloaderParams("AffineTransform", getAffineTransform());
1268
                        t.setDownloaderParams("Tiling", new Boolean(true));
1269
                        if(listener != null) 
1270
                                listener.tileReady(t);
1271
                        else 
1272
                                return t;
1273

    
1274
                } catch (ProcessInterruptedException e) {
1275
                } catch (TileGettingException e) {
1276
                        throw new RasterDriverException("Error throwing a tile", e);
1277
                } catch (ProviderNotRegisteredException e) {
1278
                        throw new RasterDriverException("Error throwing a tile", e);
1279
                } catch (InitializeException e) {
1280
                        throw new RasterDriverException("Error throwing a tile", e);
1281
                }
1282
                return null;
1283
        }
1284

    
1285
        /*
1286
         * (non-Javadoc)
1287
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getBlockSize()
1288
         */
1289
        public int getBlockSize() {
1290
                return 0;
1291
        }
1292

    
1293
        /*
1294
         * (non-Javadoc)
1295
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setAffineTransform(java.awt.geom.AffineTransform)
1296
         */
1297
        public void setAffineTransform(AffineTransform t){
1298
                
1299
        }
1300

    
1301
        /*
1302
         * (non-Javadoc)
1303
         * @see org.gvsig.raster.impl.provider.RasterProvider#getOverviewCount(int)
1304
         */
1305
        public int getOverviewCount(int band) throws BandAccessException, RasterDriverException {
1306
                return 0;
1307
        }
1308

    
1309
        /*
1310
         * (non-Javadoc)
1311
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewWidth(int, int)
1312
         */
1313
        public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException {
1314
                return 0;
1315
        }
1316

    
1317
        /*
1318
         * (non-Javadoc)
1319
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewHeight(int, int)
1320
         */
1321
        public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException {
1322
                return 0;
1323
        }
1324

    
1325
        /*
1326
         * (non-Javadoc)
1327
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isOverviewsSupported()
1328
         */
1329
        public boolean isOverviewsSupported() {
1330
                return false;
1331
        }
1332

    
1333
        /*
1334
         * (non-Javadoc)
1335
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isReproyectable()
1336
         */
1337
        public boolean isReproyectable() {
1338
                return false;
1339
        }
1340

    
1341
        /*
1342
         * (non-Javadoc)
1343
         * @see org.gvsig.fmap.dal.raster.spi.CoverageStoreProvider#getName()
1344
         */
1345
        public String getName() {
1346
                return NAME;
1347
        }
1348
        
1349
        /**
1350
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
1351
         * @param pt Punto a transformar
1352
         * @return punto transformado en coordenadas del mundo
1353
         */
1354
        public Point2D rasterToWorld(Point2D pt) {
1355
                Point2D p = new Point2D.Double();
1356
                getAffineTransform().transform(pt, p);
1357
                return p;
1358
        }
1359

    
1360
        /**
1361
         * Convierte un punto desde del mundo a coordenadas pixel.
1362
         * @param pt Punto a transformar
1363
         * @return punto transformado en coordenadas pixel
1364
         */
1365
        public Point2D worldToRaster(Point2D pt) {
1366
                Point2D p = new Point2D.Double();
1367
                try {
1368
                        getAffineTransform().inverseTransform(pt, p);
1369
                } catch (NoninvertibleTransformException e) {
1370
                        return pt;
1371
                }
1372
                return p;
1373
        }
1374
        
1375
        /*
1376
         * (non-Javadoc)
1377
         * @see org.gvsig.raster.impl.provider.RasterProvider#setStatus(org.gvsig.raster.impl.provider.RasterProvider)
1378
         */
1379
        public void setStatus(RasterProvider provider) {
1380
                if(provider instanceof WMTSProvider) {
1381
                }
1382
        }
1383
        
1384
        /*
1385
         * (non-Javadoc)
1386
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLastRequest()
1387
         */
1388
        public File getLastRequest() {
1389
                return lastRequest;
1390
        }
1391
        
1392
        /**
1393
         * ASigna el par?metro de inicializaci?n del driver.
1394
         */
1395
        @Override
1396
        public void setParam(DataStoreProviderServices storeServices, DataStoreParameters param) {
1397
                if(param instanceof WMTSDataParameters)
1398
                        this.uri = ((WMTSDataParameters)param).getURI();
1399
                this.param = param;
1400
                this.storeServices = storeServices;
1401
        }
1402
        
1403
        public String getInfoByPoint(int x, int y, Extent bbox, int w, int h, ICancellable cancellable) throws InfoByPointException {
1404
                int level;
1405
                try {
1406
                        level = getLevelFromRealCoords(bbox.toRectangle2D(), w);
1407
                        return getFeatureInfo(x, y, level);
1408
                } catch (RasterDriverException e) {
1409
                        throw new InfoByPointException("Error in getFeatureInfo", e);
1410
                }
1411
        }
1412
        
1413
        /*
1414
         * (non-Javadoc)
1415
         * @see org.gvsig.raster.impl.provider.RasterProvider#getNearestLevel(double)
1416
         */
1417
        public int getNearestLevel(double pixelSize) {
1418
                double[] pixelSizes = getPixelSizeByLevel();
1419
                for (int i = 0; i < pixelSizes.length - 1; i++) {
1420
                        if(pixelSize <= pixelSizes[i] && pixelSize > pixelSizes[i + 1]) {
1421
                                return i;
1422
                        }
1423
                }
1424
                if(pixelSize < pixelSizes[getZoomLevels() - 1])
1425
                        return getZoomLevels() - 1;
1426
                return 0;
1427
        }
1428
        
1429
        /*
1430
         * (non-Javadoc)
1431
         * @see org.gvsig.raster.impl.provider.RasterProvider#getTileServer()
1432
         */
1433
        public TileServer getTileServer() {
1434
                if(tileServer == null) {
1435
                        tileServer = new WMTSTileServer(this, getTileMatrixSetLink());
1436
                }
1437
                return tileServer;
1438
        }
1439
        
1440
        /*
1441
         * (non-Javadoc)
1442
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTileSize(int)
1443
         */
1444
        public int[] getTileSize(int level) {
1445
                return getTileServer().getStruct().getTileSizeByLevel(level);
1446
        }
1447

    
1448
        /*
1449
         * (non-Javadoc)
1450
         * @see org.gvsig.raster.impl.provider.RasterProvider#isRasterEnclosed()
1451
         */
1452
        public boolean isRasterEnclosed() {
1453
                return true;
1454
        }
1455
        
1456
        /*
1457
         * (non-Javadoc)
1458
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getBufferLastRequest()
1459
         */
1460
        public Buffer getBufferLastRequest() throws ProcessInterruptedException, RasterDriverException {
1461
                return null;
1462
        }
1463
        
1464
        /**
1465
         * Gets the srs code
1466
         * @return
1467
         */
1468
        public String getSRSCode() {
1469
                WMTSDataParameters p = (WMTSDataParameters)param;
1470
                return p.getSRSCode();
1471
        }
1472

    
1473
        /*
1474
         * (non-Javadoc)
1475
         * @see org.gvsig.raster.impl.provider.TiledRasterProvider#getInternalProvider()
1476
         */
1477
        public RasterProvider getInternalProvider() {
1478
                return this;
1479
        }
1480
        
1481
        /*
1482
         * (non-Javadoc)
1483
         * @see org.gvsig.fmap.dal.coverage.store.props.Histogramable#getHistogramComputer()
1484
         */
1485
        public HistogramComputer getHistogramComputer() {
1486
                if (histogram == null)
1487
                        histogram = new RemoteStoreHistogram(this);
1488
                return histogram;
1489
        }
1490
}