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

History | View | Annotate | Download (51.3 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.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.HistogramException;
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.datastruct.BandListImpl;
70
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
71
import org.gvsig.raster.impl.datastruct.ExtentImpl;
72
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
73
import org.gvsig.raster.impl.provider.MemoryMatrixBuffer;
74
import org.gvsig.raster.impl.provider.RasterProvider;
75
import org.gvsig.raster.impl.provider.RemoteRasterProvider;
76
import org.gvsig.raster.impl.provider.TiledRasterProvider;
77
import org.gvsig.raster.impl.store.DefaultStoreFactory;
78
import org.gvsig.raster.impl.store.properties.DataStoreColorInterpretation;
79
import org.gvsig.raster.impl.store.properties.DataStoreTransparency;
80
import org.gvsig.raster.impl.store.properties.RemoteStoreHistogram;
81
import org.gvsig.raster.util.DefaultProviderServices;
82
import org.gvsig.raster.wmts.io.downloader.WMTSTileServer;
83
import org.gvsig.remoteclient.exceptions.ServerErrorException;
84
import org.gvsig.remoteclient.wmts.WMTSStatus;
85
import org.gvsig.remoteclient.wmts.exception.DownloadException;
86
import org.gvsig.remoteclient.wmts.exception.WMTSException;
87
import org.gvsig.remoteclient.wmts.struct.WMTSBoundingBox;
88
import org.gvsig.remoteclient.wmts.struct.WMTSLayer;
89
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrix;
90
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixLimits;
91
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixSet;
92
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixSetLink;
93
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrix.Tile;
94
import org.gvsig.tools.ToolsLocator;
95
import org.slf4j.Logger;
96
import org.slf4j.LoggerFactory;
97
/**
98
 * Provider for WMTS service
99
 *
100
 * @author Nacho Brodin (nachobrodin@gmail.com)
101
 */
102
public class WMTSProvider extends DefaultRasterProvider implements RemoteRasterProvider, TiledRasterProvider {
103
        public static String                NAME                     = "Wmts Store";
104
        public static String                DESCRIPTION              = "Wmts Raster file";
105
        public static final String          METADATA_DEFINITION_NAME = "WmtsStore";
106
        private static Logger               logger                   = LoggerFactory.getLogger(WMTSProvider.class);
107
        public static boolean               TILED                    = true;
108
        
109
        //Los tiles se piden de forma secuencial y sin lanzar threads para ello (+Lento)
110
        public static int                   SEQUENTIAL               = 0;
111
        //Los tiles se piden en threads y hay un thread manager para gestionar que no se pidan m?s de cierto n?mero
112
        public static int                   LIMITED_THREADS          = 1;
113
        //Los tiles se piden en threads y se lanzan tantos threads como tiles haya
114
        public static int                   UNLIMITED_THREADS        = 2;
115
        private int                         requestType              = LIMITED_THREADS;
116
        
117
        private static final double         MTS_X_GRADO              = 111319.490793274;
118
        
119
        private Extent                      viewRequest              = null;
120
        private static Hashtable<URL, WMTSConnector>    
121
                                            drivers                  = new Hashtable<URL, WMTSConnector> ();
122
        private boolean                     open                     = false;
123
        private File                        lastRequest              = null;
124
        private DataStoreTransparency       lastFileTransparency     = null;
125
        private int                         lastWidthRequest         = 0;
126
        private int                         lastHeightRequest        = 0;
127
        private WMTSStatus                  lastStatus               = null;
128
        private boolean                     gridSubsets              = true;
129
        private Extent[]                    extentByLevel            = null; //Only for layers without gridSubsets
130
        private MathUtils                   math                     = RasterLocator.getManager().getMathUtils();
131
        
132
        /**
133
         * This thread manages the number of tiles that have been thrown.
134
         * This number is controlled by the NTHREADS_QUEUE variable.
135
         * 
136
         * @author Nacho Brodin (nachobrodin@gmail.com)
137
         */
138
        public class RequestThreadManager extends Thread {
139
                private TilePipe           pipe           = null;
140
                private ArrayList<Tile>    tiles          = null;
141
                private WMTSStatus         status         = null;
142
                
143
                public RequestThreadManager(TilePipe pipe, ArrayList<Tile> tiles, WMTSStatus status) {
144
                        this.pipe = pipe;
145
                        this.tiles = tiles;
146
                        this.status = status;
147
                }
148
                
149
                public void run() {
150
                        for (int i = 0; i < tiles.size(); i++) {
151
                                Tile tile = tiles.get(i);
152
                                WMTSStatus statusCopy = status.cloneStatus();
153
                                statusCopy.setTileRow(tile.row);
154
                                statusCopy.setTileCol(tile.col);
155
                                if (pipe.getSize() > TilePipe.NTHREADS_QUEUE) {
156
                                        try {
157
                                                synchronized (this) {
158
                                                        wait();                                                        
159
                                                }
160
                                        } catch( InterruptedException e ) {
161
                                        }
162
                                }
163
                                new RequestTileLauncher(pipe, statusCopy, tile).start();
164
                        }
165
                }
166
        }
167
        
168
        /**
169
         * Thread to download a tile
170
         * @author Nacho Brodin (nachobrodin@gmail.com)
171
         */
172
        class RequestTileLauncher extends Thread {
173
                private TilePipe      pipe    = null;
174
                private WMTSStatus    status  = null;
175
                private Tile          tile    = null;
176

    
177
                public RequestTileLauncher(TilePipe pipe, WMTSStatus status, Tile tile) {
178
                        this.pipe = pipe;
179
                        this.status = status;
180
                        this.tile = tile;
181
                }
182

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

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

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

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

    
513
        /*
514
         * (non-Javadoc)
515
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#load()
516
         */
517
        public RasterProvider load() {
518
                return this;
519
        }
520
        
521
        /*
522
         * (non-Javadoc)
523
         * @see org.gvsig.raster.impl.provider.RasterProvider#isOpen()
524
         */
525
        public boolean isOpen() {
526
                return open;
527
        }
528

    
529
        /*
530
         * (non-Javadoc)
531
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#close()
532
         */
533
        public void close() {
534
                open = false;
535
        }
536
        
537
        /*
538
         * (non-Javadoc)
539
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTransparency()
540
         */
541
        public Transparency getTransparency() {
542
                if(lastFileTransparency == null) {
543
                        lastFileTransparency = new DataStoreTransparency();
544
                        lastFileTransparency.setTransparencyBand(3);
545
                }
546
                return lastFileTransparency;
547
        }
548

    
549
        /*
550
         * (non-Javadoc)
551
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#translateFileName(java.lang.String)
552
         */
553
        public String translateFileName(String fileName) {
554
                return fileName;
555
        }
556

    
557
        /*
558
         * (non-Javadoc)
559
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setView(org.gvsig.fmap.dal.coverage.datastruct.Extent)
560
         */
561
        public void setView(Extent e) {
562
                viewRequest = e;
563
        }
564

    
565
        /*
566
         * (non-Javadoc)
567
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getView()
568
         */
569
        public Extent getView() {
570
                return viewRequest;
571
        }
572

    
573
        /*
574
         * (non-Javadoc)
575
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWidth()
576
         */
577
        public double getWidth() {
578
                WMTSDataParameters p = (WMTSDataParameters)parameters;
579
                if (lastWidthRequest <= 0) 
580
                        return p.getWidth();
581
                return lastWidthRequest;
582
        }
583

    
584
        /*
585
         * (non-Javadoc)
586
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getHeight()
587
         */
588
        public double getHeight() {
589
                WMTSDataParameters p = (WMTSDataParameters)parameters;
590
                if (lastHeightRequest <= 0) 
591
                        return p.getHeight();
592
                return lastHeightRequest;
593
        }
594

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

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

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

    
889
        /*
890
         * (non-Javadoc)
891
         * @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)
892
         */
893
        public Buffer getWindow(double ulx, double uly, double w, double h, 
894
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
895
                lastWidthRequest = rasterBuf.getWidth();
896
                lastHeightRequest = rasterBuf.getHeight();
897
                Rectangle2D r = new Rectangle2D.Double(ulx, uly - h, w, h);
898
                WMTSStatus status = buildWMTSStatus(r, lastWidthRequest, lastHeightRequest);
899
                org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null, requestType);
900
                MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
901
                return matrixBuffer.getWindow(new ExtentImpl(ulx, uly, ulx + w, uly - h), rasterBuf);
902
        }
903

    
904
        /*
905
         * (non-Javadoc)
906
         * @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)
907
         */
908
        public Buffer getWindow(int x, int y, BandList bandList, Buffer rasterBuf) throws ProcessInterruptedException, RasterDriverException {
909
                lastWidthRequest = rasterBuf.getWidth();
910
                lastHeightRequest = rasterBuf.getHeight();
911
                return null;
912
        }
913

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

    
1247
                        for (int j = 0; j < bandList.getBandCount(); j++) {
1248
                                bandList.getBand(j).setFileName(serverName);
1249
                        }
1250

    
1251
                        driver.close();
1252

    
1253

    
1254
                        TileCacheManager m = TileCacheLocator.getManager();
1255
                        org.gvsig.raster.cache.tile.Tile t = m.createTile(-1, tile.row, tile.col);
1256
                        t.setData(new Object[]{buf, alphaBand});
1257
                        t.setUl(new Point2D.Double(tile.ulx, tile.uly));
1258
                        t.setLr(new Point2D.Double(tile.lrx, tile.lry));
1259
                        t.setDownloaderParams("AffineTransform", getAffineTransform());
1260
                        t.setDownloaderParams("Tiling", new Boolean(true));
1261
                        if(listener != null) 
1262
                                listener.tileReady(t);
1263
                        else 
1264
                                return t;
1265

    
1266
                } catch (ProcessInterruptedException e) {
1267
                } catch (TileGettingException e) {
1268
                        throw new RasterDriverException("Error throwing a tile", e);
1269
                } catch (ProviderNotRegisteredException e) {
1270
                        throw new RasterDriverException("Error throwing a tile", e);
1271
                } catch (InitializeException e) {
1272
                        throw new RasterDriverException("Error throwing a tile", e);
1273
                }
1274
                return null;
1275
        }
1276

    
1277
        /*
1278
         * (non-Javadoc)
1279
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getBlockSize()
1280
         */
1281
        public int getBlockSize() {
1282
                return 0;
1283
        }
1284

    
1285
        /*
1286
         * (non-Javadoc)
1287
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setAffineTransform(java.awt.geom.AffineTransform)
1288
         */
1289
        public void setAffineTransform(AffineTransform t){
1290
                
1291
        }
1292

    
1293
        /*
1294
         * (non-Javadoc)
1295
         * @see org.gvsig.raster.impl.provider.RasterProvider#getOverviewCount(int)
1296
         */
1297
        public int getOverviewCount(int band) throws BandAccessException, RasterDriverException {
1298
                return 0;
1299
        }
1300

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

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

    
1317
        /*
1318
         * (non-Javadoc)
1319
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isOverviewsSupported()
1320
         */
1321
        public boolean isOverviewsSupported() {
1322
                return false;
1323
        }
1324

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

    
1333
        /*
1334
         * (non-Javadoc)
1335
         * @see org.gvsig.fmap.dal.raster.spi.CoverageStoreProvider#getName()
1336
         */
1337
        public String getName() {
1338
                return NAME;
1339
        }
1340
        
1341
        /**
1342
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
1343
         * @param pt Punto a transformar
1344
         * @return punto transformado en coordenadas del mundo
1345
         */
1346
        public Point2D rasterToWorld(Point2D pt) {
1347
                Point2D p = new Point2D.Double();
1348
                getAffineTransform().transform(pt, p);
1349
                return p;
1350
        }
1351

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

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

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