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

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

    
166
                public RequestTileLauncher(TilePipe pipe, WMTSStatus status, Tile tile) {
167
                        this.pipe = pipe;
168
                        this.status = status;
169
                        this.tile = tile;
170
                }
171

    
172
                public void run() {
173
                        try {
174
                                //File file = getConnector().getTile(status, null);
175
                                URL url = getConnector().getTileURL(status);
176
                                tile.file = getConnector().downloadFile(url, null);
177
                                pipe.setTile(tile);
178
                        } catch (DownloadException e) {
179
                        //} catch (ServerErrorException e) {
180
                        } catch (MalformedURLException e) {
181
                                // TODO Auto-generated catch block
182
                                e.printStackTrace();
183
                        } catch (WMTSException e) {
184
                                // TODO Auto-generated catch block
185
                                e.printStackTrace();
186
                        }
187
                }
188
        }
189
        
190
        /**
191
         * Point information 
192
         * @author Nacho Brodin (nachobrodin@gmail.com)
193
         */
194
        public class PointInfo {
195
                public Point2D worldCoord;
196
                public Point2D tile;
197
                public Point2D pixelInTile;
198
                public int     level;
199
                
200
                public PointInfo(Point2D worldCoord) {
201
                        this.worldCoord = worldCoord;
202
                }
203
        }
204

    
205
        public static void register() {
206
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
207
                if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
208
                        dataman.registerStoreProvider(NAME,
209
                                        WMTSProvider.class, WMTSDataParameters.class);
210
                }
211

    
212
                if (!dataman.getExplorerProviders().contains(WMTSServerExplorer.NAME)) {
213
                        dataman.registerExplorerProvider(WMTSServerExplorer.NAME, WMTSServerExplorer.class, WMTSServerExplorerParameters.class);
214
                }
215
                dataman.registerStoreFactory(NAME, DefaultStoreFactory.class);
216
        }
217
        
218
        public WMTSProvider() throws NotSupportedExtensionException {
219
                super();
220
        }
221
        
222
        /**
223
         * Constructor. Abre el dataset.
224
         * @param proj Proyecci?n
225
         * @param fName Nombre del fichero
226
         * @throws NotSupportedExtensionException
227
         */
228
        public WMTSProvider(String params) throws NotSupportedExtensionException {
229
                super(params);
230
                if(params instanceof String) {
231
                        WMTSDataParameters p = new WMTSDataParameters();
232
                        p.setURI((String)params);
233
                        super.init(p, null, ToolsLocator.getDynObjectManager()
234
                                        .createDynObject(
235
                                                        MetadataLocator.getMetadataManager().getDefinition(
236
                                                                        DataStore.METADATA_DEFINITION_NAME)));
237
                        init(p, null);
238
                }
239
        }
240
        
241
        public WMTSProvider(WMTSDataParameters params,
242
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
243
                super(params, storeServices, ToolsLocator.getDynObjectManager()
244
                                .createDynObject(
245
                                                MetadataLocator.getMetadataManager().getDefinition(
246
                                                                DataStore.METADATA_DEFINITION_NAME)));
247
                init(params, storeServices);
248
        }
249
        
250
        /**
251
         * Gets the connector from the URL
252
         * @return
253
         * @throws RemoteServiceException
254
         */
255
        public WMTSConnector getConnector() throws WMTSException {
256
                WMTSDataParameters p = (WMTSDataParameters)parameters;
257
                URL url = null;
258
                try {
259
                        url = new URL(p.getURI());
260
                } catch (Exception e) {
261
                        throw new WMTSException("Malformed URL",e);
262
                }
263
                try {
264
                        return WMTSProvider.getConnectorFromURL(url);
265
                } catch (IOException e) {
266
                        throw new WMTSException("Error getting the connector",e);
267
                }
268
        }
269
        
270
        /**
271
         * Crea las referencias al fichero y carga
272
         * las estructuras con la informaci?n y los metadatos.
273
         * @param proj Proyecci?n
274
         * @param param Parametros de carga
275
         * @throws NotSupportedExtensionException
276
         */
277
        public void init (DataStoreParameters params,
278
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
279
                setParam(storeServices, params);
280
                if(((WMTSDataParameters)params).getImageFormat().compareTo("image/gif") == 0) {
281
                        setDataType(new int[]{Buffer.TYPE_BYTE});
282
                        bandCount = 1;
283
                } else {
284
                        setDataType(new int[]{Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE});
285
                        bandCount = 4;
286
                }
287
                
288
                if(!(param instanceof WMTSDataParameters))
289
                        return;
290
                
291
                gridSubsets = hasGridSubsets((WMTSDataParameters)param);
292
        }
293
        
294
        /**
295
         * Returns true if this layer has grid subsets
296
         * @return
297
         */
298
        public boolean hasGridSubsets() {
299
                return gridSubsets;
300
        }
301
        
302
        /**
303
         * Checks if this layer has grid subsets or doesn't
304
         * @param p
305
         * @return
306
         */
307
        @SuppressWarnings("unchecked")
308
        private boolean hasGridSubsets(WMTSDataParameters p) {
309
                ArrayList tileMatrixSetLimits = null;
310
                ArrayList<?> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
311
                String srs = p.getSRSCode();
312
                for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
313
                        WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
314
                        WMTSTileMatrixSet tms = tileMatrixSetLink.getTileMatrixSet();
315
                        ArrayList tmsl = tileMatrixSetLink.getTileMatrixLimits();
316
                        String srsTileSet = tms.getSupportedCRS();
317
                        if(srsTileSet.compareTo(srs) == 0) {
318
                                tileMatrixSetLimits = tmsl;
319
                        }
320
                }
321
                
322
                return tileMatrixSetLimits.size() <= 0 ? false : true; 
323
        }
324
        
325
        public static final WMTSConnector getConnectorFromURL(URL url) throws IOException {
326
                WMTSConnector drv = (WMTSConnector) drivers.get(url);
327
                if (drv == null) {
328
                        drv = new WMTSConnector(url);
329
                        drivers.put(url, drv);
330
                }
331
                return drv;
332
        }
333
        
334
        /**
335
         * Obtiene el objeto que contiene que contiene la interpretaci?n de
336
         * color por banda
337
         * @return
338
         */
339
        public DataStoreColorInterpretation getColorInterpretation() {
340
                if(colorInterpretation == null) {
341
                        colorInterpretation = new DataStoreColorInterpretation();
342
                        colorInterpretation.initColorInterpretation(getBandCount());
343
                        colorInterpretation.setColorInterpValue(0, DataStoreColorInterpretation.RED_BAND);
344
                        colorInterpretation.setColorInterpValue(1, DataStoreColorInterpretation.GREEN_BAND);
345
                        colorInterpretation.setColorInterpValue(2, DataStoreColorInterpretation.BLUE_BAND);
346
                }
347
                return colorInterpretation;
348
        }
349
        
350
        /*
351
         * (non-Javadoc)
352
         * @see org.gvsig.raster.impl.provider.RasterProvider#isTiled()
353
         */
354
        public boolean isTiled() {
355
                return true;
356
        }
357
        
358
        /*
359
         * (non-Javadoc)
360
         * @see org.gvsig.fmap.dal.coverage.dataset.RasterDataSet#getAffineTransform()
361
         */
362
        public AffineTransform getAffineTransform() {
363
                WMTSDataParameters p = (WMTSDataParameters)parameters;
364
                Extent e = getExtent();
365
                double psX = e.width() / (lastWidthRequest <= 0 ? p.getWidth() : lastWidthRequest);
366
                double psY = -(e.height() / (lastHeightRequest <= 0 ? p.getHeight() : lastHeightRequest));
367
                ownTransformation = new AffineTransform(
368
                                psX, 
369
                                0, 
370
                                0, 
371
                                psY, 
372
                                e.getULX() - (psX / 2),
373
                                e.getULY() - (psY / 2));
374
                externalTransformation = (AffineTransform) ownTransformation.clone();
375
                return ownTransformation;
376
        }
377
        
378
        /**
379
         * Gets the bounding box in world coordinates. If the layer has grid subsets (TileMatrixLimits) then
380
         * this will have a only extent but if the layer doesn't have grid subsets then this will have a different
381
         * extent in each level resolution. In this case we need to know the extent for each level.
382
         * @return Extent
383
         */
384
        public Extent getExtent() {
385
                WMTSDataParameters p = (WMTSDataParameters)parameters;
386
                if(gridSubsets) {
387
                        WMTSLayer layer = p.getLayer();
388
                        WMTSBoundingBox bbox = layer.getWGS84BBox();
389
                        return new ExtentImpl(bbox.toRectangle2D());
390
                } else {
391
                        WMTSTileMatrixSet tileMatrixSet = getTileMatrixSetLink().getTileMatrixSet();
392
                        
393
                        //Si ya se han calculado los niveles es q el extent es v?lido sino el nivel ser? el 0
394
                        double scale = 0D;
395
                        int level = 0;
396
                        if(extentByLevel != null && p.getExtent() != null) {
397
                                scale = getScale(p.getExtent(), p.getWidth());
398
                                try {
399
                                        level = getLevelFromScale(scale, tileMatrixSet);
400
                                } catch (RasterDriverException e) {
401
                                        e.printStackTrace();
402
                                }                                
403
                        }
404
                        
405
                        Extent[] ext = getExtentByResolutionLevel();
406
                        
407
                        if(ext != null && level >= 0 && level < ext.length)
408
                                return ext[level];
409
                }
410
                return null;
411
        }
412
        
413
        /**
414
         * Gets the suffix of the downloaded image
415
         * @return
416
         */
417
        public String getFileSuffix() {
418
                WMTSDataParameters p = (WMTSDataParameters)parameters;
419
                String format = p.getImageFormat();
420
                if (format == null){
421
                        return "xml";
422
                }
423
                if (format.indexOf("png") >= 0){
424
                return "png";
425
                }        
426
            if (format.indexOf("xml") >= 0){
427
                return "xml";
428
            }        
429
            if (format.indexOf("gif") >= 0){
430
                return "gif";
431
            }
432
            if (format.indexOf("tif") >= 0){
433
                return "tif";
434
            }
435
            if (format.indexOf("bmp") >= 0){
436
                return "bmp";
437
            }
438
            if (format.indexOf("jpg") >= 0
439
                || format.indexOf("jpeg") >= 0){
440
                return "jpg";                         
441
            }
442
                return "xml";
443
        }
444

    
445
        /**
446
         * When a layer doesn't have grid subsets this will have a different bounding
447
         * box by resolution level. This function calculates and returns the array of
448
         * extents, one by resolution level.
449
         * @return
450
         */
451
        public Extent[] getExtentByResolutionLevel() {
452
                if(extentByLevel == null) {
453
                        WMTSDataParameters p = (WMTSDataParameters)parameters;
454
                        WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
455
                        WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
456
                        
457
                    double widthMtsTile = 0;
458
                    double heightMtsTile = 0;
459
                        ArrayList<?> tileMatrixList = tileMatrixSet.getTileMatrix();
460
                        extentByLevel = new ExtentImpl[tileMatrixList.size()];
461
                        for (int i = 0; i < tileMatrixList.size(); i++) {
462
                                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixList.get(i);
463
                            if(!p.isProjected()) {
464
                                    widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
465
                                    heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
466
                            } else {
467
                                    widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
468
                                    heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
469
                            }
470
                            
471
                            double h = Math.abs(tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getMatrixHeight() * heightMtsTile)));
472
                            Rectangle2D r = new Rectangle2D.Double(
473
                                            tileMatrix.getTopLeftCorner()[1], 
474
                                            tileMatrix.getTopLeftCorner()[0] - h,
475
                                            Math.abs(tileMatrix.getTopLeftCorner()[1] - (tileMatrix.getTopLeftCorner()[1] + (tileMatrix.getMatrixWidth() * widthMtsTile))),
476
                                            h);
477
                            extentByLevel[i] = new ExtentImpl(r);
478
                        }
479
                        
480
                }
481
                return extentByLevel;
482
        }
483
        
484
        /*
485
         * (non-Javadoc)
486
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLayerExtent(java.lang.String, java.lang.String)
487
         */
488
        public Rectangle2D getLayerExtent(String layerName, String srs) throws RemoteServiceException {
489
                return null;
490
        }
491

    
492
        /*
493
         * (non-Javadoc)
494
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#load()
495
         */
496
        public RasterProvider load() {
497
                return this;
498
        }
499
        
500
        /*
501
         * (non-Javadoc)
502
         * @see org.gvsig.raster.impl.provider.RasterProvider#isOpen()
503
         */
504
        public boolean isOpen() {
505
                return open;
506
        }
507

    
508
        /*
509
         * (non-Javadoc)
510
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#close()
511
         */
512
        public void close() {
513
                open = false;
514
        }
515
        
516
        /*
517
         * (non-Javadoc)
518
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTransparency()
519
         */
520
        public Transparency getTransparency() {
521
                if(lastFileTransparency == null) {
522
                        lastFileTransparency = new DataStoreTransparency();
523
                        lastFileTransparency.setTransparencyBand(3);
524
                }
525
                return lastFileTransparency;
526
        }
527

    
528
        /*
529
         * (non-Javadoc)
530
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#translateFileName(java.lang.String)
531
         */
532
        public String translateFileName(String fileName) {
533
                return fileName;
534
        }
535

    
536
        /*
537
         * (non-Javadoc)
538
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setView(org.gvsig.fmap.dal.coverage.datastruct.Extent)
539
         */
540
        public void setView(Extent e) {
541
                viewRequest = e;
542
        }
543

    
544
        /*
545
         * (non-Javadoc)
546
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getView()
547
         */
548
        public Extent getView() {
549
                return viewRequest;
550
        }
551

    
552
        /*
553
         * (non-Javadoc)
554
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWidth()
555
         */
556
        public double getWidth() {
557
                WMTSDataParameters p = (WMTSDataParameters)parameters;
558
                if (lastWidthRequest <= 0) 
559
                        return p.getWidth();
560
                return lastWidthRequest;
561
        }
562

    
563
        /*
564
         * (non-Javadoc)
565
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getHeight()
566
         */
567
        public double getHeight() {
568
                WMTSDataParameters p = (WMTSDataParameters)parameters;
569
                if (lastHeightRequest <= 0) 
570
                        return p.getHeight();
571
                return lastHeightRequest;
572
        }
573

    
574
        /*
575
         * (non-Javadoc)
576
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#readCompleteLine(int, int)
577
         */
578
        public Object readCompleteLine(int line, int band)
579
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
580
                return null;
581
        }
582
        
583
        /**
584
         * When the remote layer has fixed size this method downloads the file and return its reference. 
585
         * File layer has in the long side FIXED_SIZE pixels and the bounding box is complete. This file could be
586
         * useful to build an histogram or calculate statistics. This represents a sample of data.
587
         * @return
588
         * @throws RasterDriverException
589
         */
590
        public File getFileLayer() throws RasterDriverException {
591
                return null;
592
        }
593

    
594
        /**
595
         * Reads a complete block of data and returns an tridimensional array of the right type. This function is useful
596
         * to read a file very fast without setting a view. In a WMS service when the size is fixed then it will read the
597
         * entire image but when the source hasn't pixel size it will read a sample of data. This set of data will have
598
         * the size defined in FIXED_SIZE. 
599
         * 
600
         * @param pos Posici?n donde se empieza  a leer
601
         * @param blockHeight Altura m?xima del bloque leido
602
         * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
603
         * @throws InvalidSetViewException
604
         * @throws FileNotOpenException
605
         * @throws RasterDriverException
606
         */
607
        public Object readBlock(int pos, int blockHeight) 
608
        throws InvalidSetViewException, FileNotOpenException, RasterDriverException, ProcessInterruptedException {
609
                return null;
610
        }
611

    
612
        /*
613
         * (non-Javadoc)
614
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getData(int, int, int)
615
         */
616
        public Object getData(int x, int y, int band)
617
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
618
                return null;
619
        }
620
        
621
        /**
622
         * Assigns the list of bands RGB and read a window of data
623
         * @param rasterBuf
624
         * @param bandList
625
         * @param lastFile
626
         * @param ulx
627
         * @param uly
628
         * @param lrx
629
         * @param lry
630
         * @return
631
         * @throws RasterDriverException
632
         * @throws ProcessInterruptedException
633
         */
634
        public Buffer getBuffer(Buffer rasterBuf, BandList bandList, File lastFile, 
635
                        double ulx, double uly, double lrx, double lry) throws RasterDriverException, ProcessInterruptedException {
636
                return null;
637
        }
638
        
639
        /**
640
         * Gets the tile matrix from the selected level
641
         * @param level
642
         * @return
643
         */
644
        @SuppressWarnings("unchecked")
645
        private WMTSTileMatrix getTileMatrixByLevel(int level) {
646
                level = adjustLevel(level);
647
                
648
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
649
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
650
                ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
651
                
652
                WMTSTileMatrixLimits tileMatrixLimits = null;
653
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(level);
654
                if(hasGridSubsets()) {
655
                        tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(level);
656
                        tileMatrix = tileMatrixLimits.getTileMatrix();
657
                }
658
                return tileMatrix;
659
        }
660
        
661
        /**
662
         * Returns the number of levels
663
         * @return
664
         */
665
        @SuppressWarnings("unchecked")
666
        public int getZoomLevels() {
667
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
668
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
669
                if(hasGridSubsets()) {
670
                        ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
671
                        return Math.min(tileMatrixSet.getTileMatrix().size(), tileMatrixSetLimits.size());
672
                }
673
                return tileMatrixSet.getTileMatrix().size();
674
                
675
        }
676
        
677
        /*
678
         * (non-Javadoc)
679
         * @see org.gvsig.raster.impl.provider.RasterProvider#getCoordsInTheNearestLevel(org.gvsig.fmap.dal.coverage.datastruct.Extent, int, int)
680
         */
681
        public Extent getCoordsInTheNearestLevel(Extent extent, int w, int h) {
682
                double[] pixelSizes = getPixelSizeByLevel();
683
                double currentPixelSize = extent.width() / (double)w;
684
                
685
                int level = 0;
686
                for (int i = 0; i < (pixelSizes.length - 1); i++) {
687
                        if(currentPixelSize < pixelSizes[i] && currentPixelSize >= pixelSizes[i + 1]) {
688
                                level = i + 1;
689
                                break;
690
                        }
691
                }
692
                
693
                return getZoomLevelCoordinates(level, extent, w, h);
694
        }
695
        
696
        /*
697
         * (non-Javadoc)
698
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getCoordsInLevel(java.awt.geom.Point2D, int, int, int)
699
         */
700
        public Extent getCoordsInLevel(Point2D viewCenter, int level, int w, int h) {
701
                WMTSDataParameters p = (WMTSDataParameters)param;
702
                level = adjustLevel(level);
703
                WMTSTileMatrix tileMatrix = getTileMatrixByLevel(level);
704
                
705
                boolean proj = p.isProjected();
706
                
707
                double psX = tileMatrix.getWidthMtsTile(proj) / tileMatrix.getTileWidth();
708
                double psY = tileMatrix.getHeightMtsTile(proj) / tileMatrix.getTileHeight();
709
                
710
                double ulx = viewCenter.getX() - ((w / 2) * psX);
711
                double uly = viewCenter.getY() - ((h / 2) * psY);
712
                double lrx = ulx + (w * psX);
713
                double lry = uly + (h * psY);
714
                return new ExtentImpl(ulx, uly, lrx, lry);
715
        }
716
        
717
        /**
718
         * Calculates the extent of a zoom level using other extent as a reference. The new extent is 
719
         * calculated with the same coordinate at the center. 
720
         * @param level
721
         * @param extent
722
         * @param w
723
         * @param h
724
         * @return
725
         */
726
        public Extent getZoomLevelCoordinates(int level, Extent extent, int w, int h) {
727
                double centerX = extent.getCenterX();
728
                double centerY = extent.getCenterY();
729
                return getCoordsInLevel(new Point2D.Double(centerX, centerY), level, w, h);
730
        }
731
        
732
        /**
733
         * Returns a list of pixel sizes by level
734
         * @return
735
         */
736
        public double[] getPixelSizeByLevel() {
737
                WMTSDataParameters p = (WMTSDataParameters)param;
738
                double[] list = new double[getZoomLevels()];
739
                
740
                for (int i = 0; i < getZoomLevels(); i++) {
741
                        WMTSTileMatrix tileMatrix = getTileMatrixByLevel(i);
742
                        list[i] = math.adjustDouble(tileMatrix.getWidthMtsTile(p.isProjected()) / tileMatrix.getTileWidth());
743
                }
744
                return list;
745
        }
746
        
747
        /**
748
         * Adjust de level to the range
749
         * @param level
750
         * @return
751
         */
752
        private int adjustLevel(int level) {
753
                if(level < 0)
754
                        level = 0;
755
                if(level > getZoomLevels())
756
                        level = getZoomLevels();
757
                return level;
758
        }
759
        
760
        /*
761
         * (non-Javadoc)
762
         * @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)
763
         */
764
        public void getWindow(Extent ex, int bufWidth, int bufHeight, 
765
                        BandList bandList, TileListener listener) throws ProcessInterruptedException, RasterDriverException {
766
                Rectangle2D r = ex.toRectangle2D();//new Rectangle2D.Double(Math.min(minX, maxX), Math.min(minY, maxY), Math.abs(maxX - minX), Math.abs(maxY - minY));
767
                WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
768
                request(status, bandList, listener);
769
        }
770
        
771
        /*
772
         * (non-Javadoc)
773
         * @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)
774
         */
775
        public Buffer getWindow(Extent extent, 
776
                        int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
777
                Rectangle2D r = extent.toRectangle2D();//new Rectangle2D.Double(Math.min(ulx, lrx), Math.min(lry, uly), Math.abs(lrx - ulx), Math.abs(uly - lry));
778
                WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
779
                org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null);
780
                MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
781
                return matrixBuffer.getWindow(extent, rasterBuf);
782
        }
783
        
784
        /*
785
         * (non-Javadoc)
786
         * @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)
787
         */
788
        public Buffer getWindow(Extent extent, BandList bandList, Buffer rasterBuf) 
789
                throws ProcessInterruptedException, RasterDriverException {
790
                lastWidthRequest = rasterBuf.getWidth();
791
                lastHeightRequest = rasterBuf.getHeight();
792
                Rectangle2D r = extent.toRectangle2D();//new Rectangle2D.Double(Math.min(ulx, lrx), Math.min(lry, uly), Math.abs(lrx - ulx), Math.abs(uly - lry));
793
                WMTSStatus status = buildWMTSStatus(r, lastWidthRequest, lastHeightRequest);
794
                org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null);
795
                MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
796
                return matrixBuffer.getWindow(extent, rasterBuf);
797
        }
798

    
799
        /*
800
         * (non-Javadoc)
801
         * @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)
802
         */
803
        public Buffer getWindow(double ulx, double uly, double w, double h, 
804
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
805
                lastWidthRequest = rasterBuf.getWidth();
806
                lastHeightRequest = rasterBuf.getHeight();
807
                Rectangle2D r = new Rectangle2D.Double(ulx, uly - h, w, h);
808
                WMTSStatus status = buildWMTSStatus(r, lastWidthRequest, lastHeightRequest);
809
                org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null);
810
                MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
811
                return matrixBuffer.getWindow(new ExtentImpl(ulx, uly, ulx + w, uly - h), rasterBuf);
812
        }
813

    
814
        /*
815
         * (non-Javadoc)
816
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(int, int, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
817
         */
818
        public Buffer getWindow(int x, int y, BandList bandList, Buffer rasterBuf) throws ProcessInterruptedException, RasterDriverException {
819
                lastWidthRequest = rasterBuf.getWidth();
820
                lastHeightRequest = rasterBuf.getHeight();
821
                return null;
822
        }
823

    
824
        /*
825
         * (non-Javadoc)
826
         * @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)
827
         */
828
        public Buffer getWindow(int x, int y, int w, int h, int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf) throws ProcessInterruptedException, RasterDriverException {
829
                lastWidthRequest = rasterBuf.getWidth();
830
                lastHeightRequest = rasterBuf.getHeight();
831
                return null;
832
        }
833
        
834
        /**
835
         * Gets the information from a point 
836
         * @param wcx
837
         * @param wcy
838
         * @param level
839
         * @return
840
         * @throws RasterDriverException
841
         */
842
        public String getFeatureInfo(double wcx, double wcy, int level) throws RasterDriverException {
843
                PointInfo pointInfo = new PointInfo(new Point2D.Double(wcx, wcy));
844
                pointInfo.level = level;
845
                getTileInfo(pointInfo);
846
                
847
                WMTSConnector connector = null;
848
                try {
849
                        connector = getConnector();
850
                        lastStatus.setTileRow((int)pointInfo.tile.getX());
851
                        lastStatus.setTileCol((int)pointInfo.tile.getY());
852
                        
853
                        String fi = connector.getFeatureInfo(lastStatus, (int)pointInfo.pixelInTile.getX(), (int)pointInfo.pixelInTile.getY(), null);
854
                        return fi;
855
                } catch (WMTSException e) {
856
                        throw new RasterDriverException("Error getting the connector object", e);
857
                } catch (ServerErrorException e) {
858
                        throw new RasterDriverException("Error getting the connector object", e);
859
                }
860
        }
861
        
862
        /**
863
         * Gets a tile position from a world coordinates point and a resolution level
864
         * @param point
865
         * @param level
866
         * @return An array with two elements. The first is the row and the second the column
867
         * of the tile in the tile matrix
868
         */
869
        @SuppressWarnings({ "unchecked"})
870
        private void getTileInfo(PointInfo pointInfo) {
871
                WMTSDataParameters p = (WMTSDataParameters)param;
872
                
873
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
874
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
875
                ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
876
                
877
                WMTSTileMatrixLimits tileMatrixLimits = null;
878
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(pointInfo.level);
879
                if(hasGridSubsets()) {
880
                        tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(pointInfo.level);
881
                        tileMatrix = tileMatrixLimits.getTileMatrix();
882
                }
883
                
884
                ArrayList<Tile> tiles = null;
885
                if(hasGridSubsets())
886
                        tiles = tileMatrix.contains(p.isProjected(), tileMatrixLimits, pointInfo.worldCoord, getExtent().toRectangle2D());
887
                else
888
                        tiles = tileMatrix.contains(p.isProjected(), pointInfo.worldCoord, getExtent().toRectangle2D());
889
                
890
                //Tile row and column
891
                pointInfo.tile = new Point2D.Double(tiles.get(0).row, tiles.get(0).col);
892
                
893
                //Desplazamiento en pixels dentro del tile
894
                Point2D rasterPoint = tiles.get(0).worldToRaster(pointInfo.worldCoord);
895
                pointInfo.pixelInTile = new Point2D.Double(rasterPoint.getX(), rasterPoint.getY());
896
        }
897
        
898
        /**
899
         * Builds the WMTSStatus object using the parameters and the request bounding box. 
900
         * @param r
901
         * @param bufWidth
902
         * @return
903
         * @throws RasterDriverException
904
         */
905
        @SuppressWarnings("unchecked")
906
        public WMTSStatus buildWMTSStatus(Rectangle2D r, int bufWidth, int bufHeight) throws RasterDriverException {
907
                WMTSDataParameters p = (WMTSDataParameters)param;
908
                
909
                //Mantiene actualizados los par?metros del WMTSStoreParameters con la ?ltima petici?n hecha
910
                p.setExtent(r);
911
                p.setWidth(bufWidth);
912
                p.setHeight(bufHeight);
913
                
914
                lastWidthRequest = bufWidth;
915
                lastHeightRequest = bufHeight;
916
                
917
                //1-Selecci?n de WMTSTileMatrixSet por srs
918
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
919
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
920
                ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
921
                
922
                
923
                //Esto hace lo mismo que getScale y getLevelFromScale
924
                /*int level = 0;
925
                double[] pixelSizes = getPixelSizeByLevel();
926
                double psViewPort = math.adjustDouble(r.getWidth() / (double)bufWidth);
927
                for (int i = 0; i < pixelSizes.length - 1; i++) {
928
                        if(psViewPort <= pixelSizes[i] && psViewPort > pixelSizes[i + 1]) {
929
                                level = i;
930
                                break;
931
                        }
932
                }*/
933
                
934
                //2-Calculo de la escala
935
                double scale = getScale(r, bufWidth);
936
                
937
                //3-Selecci?n del nivel a partir de la escala
938
                int level = getLevelFromScale(scale, tileMatrixSet);
939

    
940
                //4-Obtenemos la matriz de tiles y los l?mites si tiene subsets
941
                WMTSTileMatrixLimits tileMatrixLimits = null;
942
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(level);
943
                if(gridSubsets)
944
                        tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(level);
945
                
946
                //5-Selecci?n de tiles que entran en esta bounding box
947
                ArrayList<Tile> tiles = null;
948
                if(gridSubsets)
949
                        tiles = tileMatrix.intersects(p.isProjected(), tileMatrixLimits, r, getExtent().toRectangle2D());
950
                else
951
                        tiles = tileMatrix.intersects(p.isProjected(), r, getExtent().toRectangle2D());
952
                
953
                //6-Petici?n
954
                WMTSStatus status = new WMTSStatus();
955
                status.setTileList(tiles);
956
                status.setLayer(p.getLayer().getIdentifier());
957
                status.setFormat(p.getImageFormat());
958
                status.setInfoFormat(p.getInfoFormat());
959
                status.setStyle(p.getStyle() != null ? p.getStyle().getIdentifier() : "");
960
                status.setTileMatrixSet(tileMatrixSet.getIdentifier());
961
                status.setTileMatrix(tileMatrix.getIdentifier());
962
                status.setLevel(level);
963
                this.lastStatus = status;
964
                return status;
965
        }
966
        
967
        /**
968
         * Gets the resolution level from the real coordinates
969
         * @param r
970
         * @param 
971
         * @return
972
         * @throws RasterDriverException
973
         */
974
        public int getLevelFromRealCoords(Rectangle2D r, int width) throws RasterDriverException {
975
                double scale = getScale(r, width);
976
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
977
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
978
                return getLevelFromScale(scale, tileMatrixSet);
979
        }
980
        
981
        /**
982
         * Gets the resolution level from the scale
983
         * @param scale
984
         * @param tileMatrixSet
985
         * @return
986
         * @throws RasterDriverException
987
         */
988
        public int getLevelFromScale(double scale, WMTSTileMatrixSet tileMatrixSet) throws RasterDriverException {
989
                //Recorremos los tileMatrix para obtener la escala m?s aproximada
990
                int levelModifier = 0;
991
                scale = math.adjustDouble(scale);
992
                try {
993
                        for (int resolutionLevel = 0; resolutionLevel < tileMatrixSet.getTileMatrix().size(); resolutionLevel++) {
994
                                WMTSTileMatrix tm = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(resolutionLevel);
995
                                double scaleDenominator = math.adjustDouble(tm.getScaleDenominator());
996
                                if(scale >= scaleDenominator) {
997
                                        return Math.max(resolutionLevel + levelModifier, 0);
998
                                }
999
                        }
1000
                } catch (IndexOutOfBoundsException e) {
1001
                        throw new RasterDriverException("Error in this resolution level", e);
1002
                }
1003
                return 0;
1004
        }
1005
        
1006
        /**
1007
         * Get the tile matrix set using the crs
1008
         * @param srs
1009
         * @return
1010
         */
1011
        public WMTSTileMatrixSetLink getTileMatrixSetLink() {
1012
                WMTSDataParameters p = (WMTSDataParameters)param;
1013
                ArrayList<?> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
1014
                for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
1015
                        WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
1016
                        String srsTileSet = tileMatrixSetLink.getTileMatrixSet().getSupportedCRS();
1017
                        if(srsTileSet.compareTo(p.getSRSCode()) == 0) {
1018
                                return tileMatrixSetLink;
1019
                        }
1020
                }
1021
                if(tileMatrixSetLinkList != null && tileMatrixSetLinkList.size() > 0)
1022
                        return (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(0);
1023
                return null;
1024
        }
1025
        
1026
        /**
1027
         * Gets the scale using the extent and the width in pixels.
1028
         * @param r
1029
         * @param width
1030
         * @return
1031
         */
1032
        private double getScale(Rectangle2D r, int width) {
1033
                WMTSDataParameters p = (WMTSDataParameters)param;
1034
                if(!p.isProjected()) {
1035
                        return (1000 * r.getWidth() * MTS_X_GRADO) / (width * 0.28);
1036
                } else
1037
                        return (1000 * r.getWidth()) / (width * 0.28);
1038
        }
1039
        
1040
        /**
1041
         * Throw a request
1042
         * @param status
1043
         * @param bandList
1044
         * @param listener
1045
         * @param alphaBandNumber 
1046
         * @return returns a buffer if the listener is null. In any other case it return null.
1047
         * @throws RasterDriverException 
1048
         * @throws ProcessInterruptedException 
1049
         */
1050
        @SuppressWarnings("unchecked")
1051
        private synchronized org.gvsig.raster.cache.tile.Tile[] request(WMTSStatus status, BandList bandList, TileListener listener) throws RasterDriverException, ProcessInterruptedException {
1052
                //WMTSDataParameters p = (WMTSDataParameters)param;
1053
                WMTSConnector connector = null;
1054
                try {
1055
                        connector = getConnector();
1056
                } catch (WMTSException e) {
1057
                        throw new RasterDriverException("Error getting the connector object", e);
1058
                }
1059
                
1060
                if(connector == null)
1061
                        throw new RasterDriverException("Error getting the connector object");
1062
                
1063
                ArrayList<Tile> tiles = status.getTileList();
1064
                
1065
                TilePipe pipe = new TilePipe();
1066
                //TilePipe2 pipe = new TilePipe2();
1067
                //TileThreadPool pool = null;
1068
                
1069
                //Caso 1: Lanza un thread que gestiona que no se lancen muchos threads a la vez
1070
                if(requestType == LIMITED_THREADS) {
1071
                        RequestThreadManager threadManager = new RequestThreadManager(pipe, tiles, status);
1072
                        pipe.setRequestManager(threadManager);
1073
                        threadManager.start();
1074
                //Caso 2: Lanza todos los threads
1075
                } else if(requestType == UNLIMITED_THREADS) {
1076
                        for (int i = 0; i < tiles.size(); i++) {
1077
                                Tile tile = tiles.get(i);
1078
                                WMTSStatus statusCopy = status.cloneStatus();
1079
                                statusCopy.setTileRow(tile.row);
1080
                                statusCopy.setTileCol(tile.col);
1081
                                new RequestTileLauncher(pipe, statusCopy, tile).start();
1082
                        }
1083
                }
1084
                
1085
                org.gvsig.raster.cache.tile.Tile[] tileList = new org.gvsig.raster.cache.tile.Tile[tiles.size()]; 
1086
                
1087
                if(requestType == LIMITED_THREADS || requestType == UNLIMITED_THREADS) {
1088
                        int nCollected = 0;
1089
                        while (nCollected < tiles.size()) {
1090
                                Tile tile = pipe.getTile();
1091
                                tileList[nCollected] = drawTile(tile, listener, bandList);
1092
                                nCollected ++;
1093
                        }
1094
                }
1095
                
1096
                if(requestType == SEQUENTIAL) {
1097
                        for (int i = 0; i < tiles.size(); i++) {
1098
                                Tile tile = tiles.get(i);
1099
                                status.setTileRow(tile.row);
1100
                                status.setTileCol(tile.col);
1101
                                //TODO:Cancelaci?n
1102
                                try {
1103
                                        File file = connector.getTile(status, null);
1104
                                        tile.file = file;
1105
                                        tileList[i] = drawTile(tile, listener, bandList);
1106
                                } catch (WMTSException e) {
1107
                                        throw new RasterDriverException("Error getting tiles", e);
1108
                                } catch (ServerErrorException e) {
1109
                                        throw new RasterDriverException("Error getting tiles", e);
1110
                                }
1111
                        }
1112
                }
1113
                if(listener != null) 
1114
                        listener.endReading();
1115
                
1116
                return tileList;
1117
        }
1118
        
1119
        /**
1120
         * Reads a tile with gdal and calls the method nextBuffer
1121
         * @param tile
1122
         * @param listener
1123
         * @param bandList
1124
         * @return
1125
         * @throws RasterDriverException
1126
         */
1127
        private synchronized org.gvsig.raster.cache.tile.Tile drawTile(Tile tile, TileListener listener, BandList bandList) throws RasterDriverException {
1128
                WMTSDataParameters p = (WMTSDataParameters)param;
1129
                try {
1130
                        String serverName = bandList.getBand(0).getFileName();
1131
                        for (int j = 0; j < bandList.getBandCount(); j++) {
1132
                                bandList.getBand(j).setFileName(tile.file.getPath());
1133
                        }
1134
                        
1135
                        GdalProvider driver = new GdalProvider(tile.file.getPath());
1136
                        colorTable = driver.getColorTable();
1137
                        bandCount = driver.getBandCount();
1138
                        lastFileTransparency = driver.getTransparency();
1139
                        Buffer rasterBuf = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], tile.wPx, tile.hPx, 3, true);
1140
                        Buffer buf = driver.getWindow(0, 0, bandList, rasterBuf);
1141
                        
1142
                        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)));
1143
                        
1144
                        Buffer alphaBand = null;
1145
                        if(p.getAlphaBand() != -1 && listener != null && p.getAlphaBand() < bandCount) {
1146
                                alphaBand = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], tile.wPx, tile.hPx, 1, true);
1147
                                int[] oldDB = bandList.getDrawableBands();
1148
                                bandList.setDrawableBands(new int[]{p.getAlphaBand()});
1149
                                alphaBand = driver.getWindow(0, 0, bandList, alphaBand);
1150
                                bandList.setDrawableBands(oldDB);
1151
                        }
1152

    
1153
                        for (int j = 0; j < bandList.getBandCount(); j++) {
1154
                                bandList.getBand(j).setFileName(serverName);
1155
                        }
1156

    
1157
                        driver.close();
1158

    
1159

    
1160
                        TileCacheManager m = TileCacheLocator.getManager();
1161
                        org.gvsig.raster.cache.tile.Tile t = m.createTile(-1, tile.row, tile.col);
1162
                        t.setData(new Object[]{buf, alphaBand});
1163
                        t.setUl(new Point2D.Double(tile.ulx, tile.uly));
1164
                        t.setLr(new Point2D.Double(tile.lrx, tile.lry));
1165
                        t.setDownloaderParams("AffineTransform", getAffineTransform());
1166
                        t.setDownloaderParams("Tiling", new Boolean(true));
1167
                        if(listener != null) 
1168
                                listener.tileReady(t);
1169
                        else 
1170
                                return t;
1171

    
1172
                } catch (NotSupportedExtensionException e) {
1173
                        throw new RasterDriverException("Error getting tiles", e);
1174
                } catch (ProcessInterruptedException e) {
1175
                } catch (TileGettingException e) {
1176
                        throw new RasterDriverException("Error throwing a tile", e);
1177
                }
1178
                return null;
1179
        }
1180

    
1181
        /*
1182
         * (non-Javadoc)
1183
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getBlockSize()
1184
         */
1185
        public int getBlockSize() {
1186
                return 0;
1187
        }
1188

    
1189
        /*
1190
         * (non-Javadoc)
1191
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setAffineTransform(java.awt.geom.AffineTransform)
1192
         */
1193
        public void setAffineTransform(AffineTransform t){
1194
                
1195
        }
1196

    
1197
        /*
1198
         * (non-Javadoc)
1199
         * @see org.gvsig.raster.impl.provider.RasterProvider#getOverviewCount(int)
1200
         */
1201
        public int getOverviewCount(int band) throws BandAccessException, RasterDriverException {
1202
                return 0;
1203
        }
1204

    
1205
        /*
1206
         * (non-Javadoc)
1207
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewWidth(int, int)
1208
         */
1209
        public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException {
1210
                return 0;
1211
        }
1212

    
1213
        /*
1214
         * (non-Javadoc)
1215
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewHeight(int, int)
1216
         */
1217
        public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException {
1218
                return 0;
1219
        }
1220

    
1221
        /*
1222
         * (non-Javadoc)
1223
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#overviewsSupport()
1224
         */
1225
        public boolean overviewsSupport() {
1226
                return false;
1227
        }
1228

    
1229
        /*
1230
         * (non-Javadoc)
1231
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isReproyectable()
1232
         */
1233
        public boolean isReproyectable() {
1234
                return false;
1235
        }
1236

    
1237
        /*
1238
         * (non-Javadoc)
1239
         * @see org.gvsig.fmap.dal.raster.spi.CoverageStoreProvider#getName()
1240
         */
1241
        public String getName() {
1242
                return NAME;
1243
        }
1244
        
1245
        /**
1246
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
1247
         * @param pt Punto a transformar
1248
         * @return punto transformado en coordenadas del mundo
1249
         */
1250
        public Point2D rasterToWorld(Point2D pt) {
1251
                Point2D p = new Point2D.Double();
1252
                getAffineTransform().transform(pt, p);
1253
                return p;
1254
        }
1255

    
1256
        /**
1257
         * Convierte un punto desde del mundo a coordenadas pixel.
1258
         * @param pt Punto a transformar
1259
         * @return punto transformado en coordenadas pixel
1260
         */
1261
        public Point2D worldToRaster(Point2D pt) {
1262
                Point2D p = new Point2D.Double();
1263
                try {
1264
                        getAffineTransform().inverseTransform(pt, p);
1265
                } catch (NoninvertibleTransformException e) {
1266
                        return pt;
1267
                }
1268
                return p;
1269
        }
1270
        
1271
        /*
1272
         * (non-Javadoc)
1273
         * @see org.gvsig.raster.impl.provider.RasterProvider#setStatus(org.gvsig.raster.impl.provider.RasterProvider)
1274
         */
1275
        public void setStatus(RasterProvider provider) {
1276
                if(provider instanceof WMTSProvider) {
1277
                }
1278
        }
1279
        
1280
        /*
1281
         * (non-Javadoc)
1282
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLastRequest()
1283
         */
1284
        public File getLastRequest() {
1285
                return lastRequest;
1286
        }
1287
        
1288
        /**
1289
         * ASigna el par?metro de inicializaci?n del driver.
1290
         */
1291
        @Override
1292
        public void setParam(DataStoreProviderServices storeServices, DataStoreParameters param) {
1293
                if(param instanceof WMTSDataParameters)
1294
                        this.name = ((WMTSDataParameters)param).getURI();
1295
                this.param = param;
1296
                this.storeServices = storeServices;
1297
        }
1298
        
1299
        /*
1300
         * (non-Javadoc)
1301
         * @see org.gvsig.raster.impl.provider.RasterProvider#getInfoByPoint(double, double)
1302
         */
1303
        public String getInfoByPoint(double x, double y, ICancellable cancellable) throws RemoteServiceException {
1304
                WMTSDataParameters p = (WMTSDataParameters)param;
1305
                int level;
1306
                try {
1307
                        level = getLevelFromRealCoords(p.getExtent(), lastWidthRequest);
1308
                        return getFeatureInfo(x, y, level);
1309
                } catch (RasterDriverException e) {
1310
                        throw new RemoteServiceException(e);
1311
                }
1312
        }
1313
        
1314
        /*
1315
         * (non-Javadoc)
1316
         * @see org.gvsig.raster.impl.provider.RasterProvider#getNearestLevel(double)
1317
         */
1318
        public int getNearestLevel(double pixelSize) {
1319
                double[] pixelSizes = getPixelSizeByLevel();
1320
                for (int i = 0; i < pixelSizes.length - 1; i++) {
1321
                        if(pixelSize <= pixelSizes[i] && pixelSize > pixelSizes[i + 1]) {
1322
                                return i;
1323
                        }
1324
                }
1325
                if(pixelSize < pixelSizes[getZoomLevels() - 1])
1326
                        return getZoomLevels() - 1;
1327
                return 0;
1328
        }
1329
        
1330
        /*
1331
         * (non-Javadoc)
1332
         * @see org.gvsig.raster.impl.provider.RasterProvider#getTileServer()
1333
         */
1334
        public TileServer getTileServer() {
1335
                if(tileServer == null) {
1336
                        tileServer = new WMTSTileServer(this, getTileMatrixSetLink());
1337
                }
1338
                return tileServer;
1339
        }
1340
        
1341
        /*
1342
         * (non-Javadoc)
1343
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTileSize(int)
1344
         */
1345
        public int[] getTileSize(int level) {
1346
                return getTileServer().getStruct().getTileSizeByLevel(level);
1347
        }
1348

    
1349
        /*
1350
         * (non-Javadoc)
1351
         * @see org.gvsig.raster.impl.provider.RasterProvider#isRasterEnclosed()
1352
         */
1353
        public boolean isRasterEnclosed() {
1354
                return true;
1355
        }
1356
        
1357
        /*
1358
         * (non-Javadoc)
1359
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getBufferLastRequest()
1360
         */
1361
        public Buffer getBufferLastRequest() throws ProcessInterruptedException, RasterDriverException {
1362
                return null;
1363
        }
1364
}