Statistics
| Revision:

gvsig-raster / org.gvsig.raster / trunk / org.gvsig.raster / org.gvsig.raster.io / org.gvsig.raster.io.base / src / main / java / org / gvsig / fmap / dal / coverage / dataset / io / wmts / WMTSProvider.java @ 234

History | View | Annotate | Download (30.8 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.fmap.dal.coverage.dataset.io.wmts;
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.URL;
31
import java.util.ArrayList;
32
import java.util.Hashtable;
33

    
34
import org.gvsig.fmap.dal.DALLocator;
35
import org.gvsig.fmap.dal.DataStore;
36
import org.gvsig.fmap.dal.DataStoreParameters;
37
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
38
import org.gvsig.fmap.dal.coverage.dataset.io.GdalProvider;
39
import org.gvsig.fmap.dal.coverage.dataset.io.param.WMTSDataParametersImpl;
40
import org.gvsig.fmap.dal.coverage.dataset.io.server.DefaultWMTSServerExplorerParameters;
41
import org.gvsig.fmap.dal.coverage.dataset.io.server.WMTSServerExplorerImpl;
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.WMSException;
51
import org.gvsig.fmap.dal.coverage.explorer.WMTSServerExplorer;
52
import org.gvsig.fmap.dal.coverage.grid.render.TileListener;
53
import org.gvsig.fmap.dal.coverage.store.parameter.WMTSDataParameters;
54
import org.gvsig.fmap.dal.coverage.store.props.Transparency;
55
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
56
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
57
import org.gvsig.metadata.MetadataLocator;
58
import org.gvsig.raster.impl.DefaultRasterManager;
59
import org.gvsig.raster.impl.datastruct.ExtentImpl;
60
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
61
import org.gvsig.raster.impl.provider.RasterProvider;
62
import org.gvsig.raster.impl.provider.RemoteRasterProvider;
63
import org.gvsig.raster.impl.store.AbstractRasterDataStore;
64
import org.gvsig.raster.impl.store.DefaultStoreFactory;
65
import org.gvsig.raster.impl.store.properties.DataStoreColorInterpretation;
66
import org.gvsig.raster.impl.store.properties.DataStoreTransparency;
67
import org.gvsig.remoteclient.exceptions.ServerErrorException;
68
import org.gvsig.remoteclient.wmts.WMTSStatus;
69
import org.gvsig.remoteclient.wmts.exception.WMTSException;
70
import org.gvsig.remoteclient.wmts.struct.WMTSBoundingBox;
71
import org.gvsig.remoteclient.wmts.struct.WMTSLayer;
72
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrix;
73
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixLimits;
74
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixSet;
75
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrixSetLink;
76
import org.gvsig.remoteclient.wmts.struct.WMTSTileMatrix.Tile;
77
import org.gvsig.tools.ToolsLocator;
78
import org.gvsig.tools.extensionpoint.ExtensionPoint;
79
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
80
/**
81
 * Clase que representa al driver de acceso a datos de wmts.
82
 *
83
 * @author Nacho Brodin (nachobrodin@gmail.com)
84
 */
85
public class WMTSProvider extends DefaultRasterProvider implements RemoteRasterProvider {
86
        public static String                NAME                     = "Wmts Store";
87
        public static String                DESCRIPTION              = "Wmts Raster file";
88
        public static final String          METADATA_DEFINITION_NAME = "WmtsStore";
89
        private static final double         MTS_X_GRADO              = 111319.490793274;
90
        
91
        private Extent                      viewRequest              = null;
92
        private static Hashtable<URL, WMTSConnector>    
93
                                            drivers                  = new Hashtable<URL, WMTSConnector> ();
94
        private boolean                     open                     = false;
95
        //Only for fixed size. Complete extent and FIXED_SIZE in long side
96
        private File                        lastRequest              = null;
97
        private DataStoreTransparency       lastFileTransparency     = null;
98
        private int                         lastWidthRequest         = 0;
99
        private int                         lastHeightRequest        = 0;
100
        private boolean                     gridSubsets              = true;
101
        private Extent[]                    extentByLevel            = null; //Only for layers without gridSubsets
102
        
103
        public static void register() {
104
                ExtensionPointManager extensionPoints = ToolsLocator.getExtensionPointManager();
105
                ExtensionPoint point = extensionPoints.get("RasterReader");
106
                point.append("wmts", "", WMTSProvider.class);
107
                
108
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
109
                if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
110
                        dataman.registerStoreProvider(NAME,
111
                                        WMTSProvider.class, WMTSDataParametersImpl.class);
112
                }
113

    
114
                if (!dataman.getExplorerProviders().contains(WMTSServerExplorerImpl.NAME)) {
115
                        dataman.registerExplorerProvider(WMTSServerExplorer.NAME, WMTSServerExplorerImpl.class, DefaultWMTSServerExplorerParameters.class);
116
                }
117
                dataman.registerStoreFactory(NAME, DefaultStoreFactory.class);
118
        }
119
        
120
        public WMTSProvider() throws NotSupportedExtensionException {
121
                super();
122
        }
123
        
124
        /**
125
         * Constructor. Abre el dataset.
126
         * @param proj Proyecci?n
127
         * @param fName Nombre del fichero
128
         * @throws NotSupportedExtensionException
129
         */
130
        public WMTSProvider(String params) throws NotSupportedExtensionException {
131
                super(params);
132
                if(params instanceof String) {
133
                        WMTSDataParametersImpl p = new WMTSDataParametersImpl();
134
                        p.setHost((String)params);
135
                        super.init(p, null, ToolsLocator.getDynObjectManager()
136
                                        .createDynObject(
137
                                                        MetadataLocator.getMetadataManager().getDefinition(
138
                                                                        DataStore.METADATA_DEFINITION_NAME)));
139
                        init(p, null);
140
                }
141
        }
142
        
143
        public WMTSProvider(WMTSDataParametersImpl params,
144
                        AbstractRasterDataStore storeServices) throws NotSupportedExtensionException {
145
                super(params, storeServices, ToolsLocator.getDynObjectManager()
146
                                .createDynObject(
147
                                                MetadataLocator.getMetadataManager().getDefinition(
148
                                                                DataStore.METADATA_DEFINITION_NAME)));
149
                init(params, storeServices);
150
        }
151
        
152
        /**
153
         * Gets the connector from the URL
154
         * @return
155
         * @throws WMSException
156
         */
157
        private WMTSConnector getConnector() throws WMSException {
158
                WMTSDataParametersImpl p = (WMTSDataParametersImpl)parameters;
159
                URL url = null;
160
                try {
161
                        url = new URL(p.getHost());
162
                } catch (Exception e) {
163
                        throw new WMSException("Malformed URL",e);
164
                }
165
                try {
166
                        return WMTSProvider.getConnectorFromURL(url);
167
                } catch (IOException e) {
168
                        throw new WMSException("Error getting the connector",e);
169
                }
170
        }
171
        
172
        /**
173
         * Crea las referencias al fichero y carga
174
         * las estructuras con la informaci?n y los metadatos.
175
         * @param proj Proyecci?n
176
         * @param param Parametros de carga
177
         * @throws NotSupportedExtensionException
178
         */
179
        public void init (DataStoreParameters params,
180
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
181
                setParam(params);
182
                setDataType(new int[]{Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE});
183
                bandCount = 4;
184
                
185
                if(!(param instanceof WMTSDataParameters))
186
                        return;
187
                
188
                gridSubsets = hasGridSubsets((WMTSDataParameters)param);
189
        }
190
        
191
        /**
192
         * Checks if this layer has grid subsets or doesn't
193
         * @param p
194
         * @return
195
         */
196
        @SuppressWarnings("unchecked")
197
        private boolean hasGridSubsets(WMTSDataParameters p) {
198
                ArrayList tileMatrixSetLimits = null;
199
                ArrayList<?> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
200
                String srs = p.getSRSCode();
201
                for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
202
                        WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
203
                        WMTSTileMatrixSet tms = tileMatrixSetLink.getTileMatrixSet();
204
                        ArrayList tmsl = tileMatrixSetLink.getTileMatrixLimits();
205
                        String srsTileSet = tms.getSupportedCRS();
206
                        if(srsTileSet.compareTo(srs) == 0) {
207
                                tileMatrixSetLimits = tmsl;
208
                        }
209
                }
210
                
211
                return tileMatrixSetLimits.size() <= 0 ? false : true; 
212
        }
213
        
214
        public static final WMTSConnector getConnectorFromURL(URL url) throws IOException {
215
                WMTSConnector drv = (WMTSConnector) drivers.get(url);
216
                if (drv == null) {
217
                        drv = new WMTSConnector(url);
218
                        drivers.put(url, drv);
219
                }
220
                return drv;
221
        }
222
        
223
        /**
224
         * Obtiene el objeto que contiene que contiene la interpretaci?n de
225
         * color por banda
226
         * @return
227
         */
228
        public DataStoreColorInterpretation getColorInterpretation() {
229
                if(colorInterpretation == null) {
230
                        colorInterpretation = new DataStoreColorInterpretation();
231
                        colorInterpretation.initColorInterpretation(getBandCount());
232
                        colorInterpretation.setColorInterpValue(0, DataStoreColorInterpretation.RED_BAND);
233
                        colorInterpretation.setColorInterpValue(1, DataStoreColorInterpretation.GREEN_BAND);
234
                        colorInterpretation.setColorInterpValue(2, DataStoreColorInterpretation.BLUE_BAND);
235
                }
236
                return colorInterpretation;
237
        }
238
        
239
        /*
240
         * (non-Javadoc)
241
         * @see org.gvsig.raster.impl.provider.RasterProvider#isTiled()
242
         */
243
        public boolean isTiled() {
244
                return true;
245
        }
246
        
247
        /*
248
         * (non-Javadoc)
249
         * @see org.gvsig.fmap.dal.coverage.dataset.RasterDataSet#getAffineTransform()
250
         */
251
        public AffineTransform getAffineTransform() {
252
                WMTSDataParametersImpl p = (WMTSDataParametersImpl)parameters;
253
                Extent e = getExtent();
254
                double psX = e.width() / (lastWidthRequest <= 0 ? p.getWidth() : lastWidthRequest);
255
                double psY = -(e.height() / (lastHeightRequest <= 0 ? p.getHeight() : lastHeightRequest));
256
                ownTransformation = new AffineTransform(
257
                                psX, 
258
                                0, 
259
                                0, 
260
                                psY, 
261
                                e.getULX() - (psX / 2),
262
                                e.getULY() - (psY / 2));
263
                externalTransformation = (AffineTransform) ownTransformation.clone();
264
                return ownTransformation;
265
        }
266
        
267
        /**
268
         * Gets the bounding box in world coordinates. If the layer has grid subsets (TileMatrixLimits) then
269
         * this will have a only extent but if the layer doesn't have grid subsets then this will have a different
270
         * extent in each level resolution. In this case we need to know the extent for each level.
271
         * @return Extent
272
         */
273
        public Extent getExtent() {
274
                WMTSDataParametersImpl p = (WMTSDataParametersImpl)parameters;
275
                if(gridSubsets) {
276
                        WMTSLayer layer = p.getLayer();
277
                        WMTSBoundingBox bbox = layer.getWGS84BBox();
278
                        return new ExtentImpl(bbox.toRectangle2D());
279
                } else {
280
                        WMTSTileMatrixSet tileMatrixSet = getTileMatrixSetLink().getTileMatrixSet();
281
                        
282
                        //Si ya se han calculado los niveles es q el extent es v?lido sino el nivel ser? el 0
283
                        double scale = 0D;
284
                        int level = 0;
285
                        if(extentByLevel != null && p.getExtent() != null) {
286
                                scale = getScale(p.getExtent(), p.getWidth());
287
                                try {
288
                                        level = getLevelFromScale(scale, tileMatrixSet);
289
                                } catch (RasterDriverException e) {
290
                                        e.printStackTrace();
291
                                }                                
292
                        }
293
                        
294
                        Extent[] ext = getExtentByResolutionLevel();
295
                        
296
                        if(ext != null && level >= 0 && level < ext.length)
297
                                return ext[level];
298
                }
299
                return null;
300
        }
301

    
302
        /**
303
         * When a layer doesn't have grid subsets this will have a different bounding
304
         * box by resolution level. This function calculates and returns the array of
305
         * extents, one by resolution level.
306
         * @return
307
         */
308
        private Extent[] getExtentByResolutionLevel() {
309
                if(extentByLevel == null) {
310
                        WMTSDataParametersImpl p = (WMTSDataParametersImpl)parameters;
311
                        WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
312
                        WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
313
                        
314
                    double widthMtsTile = 0;
315
                    double heightMtsTile = 0;
316
                        ArrayList<?> tileMatrixList = tileMatrixSet.getTileMatrix();
317
                        extentByLevel = new ExtentImpl[tileMatrixList.size()];
318
                        for (int i = 0; i < tileMatrixList.size(); i++) {
319
                                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixList.get(i);
320
                            if(!p.getSRS().isProjected()) {
321
                                    widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
322
                                    heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
323
                            } else {
324
                                    widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
325
                                    heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
326
                            }
327
                            
328
                            double h = Math.abs(tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getMatrixHeight() * heightMtsTile)));
329
                            Rectangle2D r = new Rectangle2D.Double(
330
                                            tileMatrix.getTopLeftCorner()[1], 
331
                                            tileMatrix.getTopLeftCorner()[0] - h,
332
                                            Math.abs(tileMatrix.getTopLeftCorner()[1] - (tileMatrix.getTopLeftCorner()[1] + (tileMatrix.getMatrixWidth() * widthMtsTile))),
333
                                            h);
334
                            extentByLevel[i] = new ExtentImpl(r);
335
                        }
336
                        
337
                }
338
                return extentByLevel;
339
        }
340
        
341
        /*
342
         * (non-Javadoc)
343
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLayerExtent(java.lang.String, java.lang.String)
344
         */
345
        public Rectangle2D getLayerExtent(String layerName, String srs) throws WMSException {
346
                return null;
347
        }
348

    
349
        /*
350
         * (non-Javadoc)
351
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#load()
352
         */
353
        public RasterProvider load() {
354
                return this;
355
        }
356
        
357
        /*
358
         * (non-Javadoc)
359
         * @see org.gvsig.raster.impl.provider.RasterProvider#isOpen()
360
         */
361
        public boolean isOpen() {
362
                return open;
363
        }
364

    
365
        /*
366
         * (non-Javadoc)
367
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#close()
368
         */
369
        public void close() {
370
                open = false;
371
        }
372
        
373
        /*
374
         * (non-Javadoc)
375
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTransparency()
376
         */
377
        public Transparency getTransparency() {
378
                if(lastFileTransparency == null)
379
                        lastFileTransparency = new DataStoreTransparency();
380
                return lastFileTransparency;
381
        }
382

    
383
        /*
384
         * (non-Javadoc)
385
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#translateFileName(java.lang.String)
386
         */
387
        public String translateFileName(String fileName) {
388
                return fileName;
389
        }
390

    
391
        /*
392
         * (non-Javadoc)
393
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setView(org.gvsig.fmap.dal.coverage.datastruct.Extent)
394
         */
395
        public void setView(Extent e) {
396
                viewRequest = e;
397
        }
398

    
399
        /*
400
         * (non-Javadoc)
401
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getView()
402
         */
403
        public Extent getView() {
404
                return viewRequest;
405
        }
406

    
407
        /*
408
         * (non-Javadoc)
409
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWidth()
410
         */
411
        public double getWidth() {
412
                WMTSDataParametersImpl p = (WMTSDataParametersImpl)parameters;
413
                if (lastWidthRequest <= 0) 
414
                        return p.getWidth();
415
                return lastWidthRequest;
416
        }
417

    
418
        /*
419
         * (non-Javadoc)
420
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getHeight()
421
         */
422
        public double getHeight() {
423
                WMTSDataParametersImpl p = (WMTSDataParametersImpl)parameters;
424
                if (lastHeightRequest <= 0) 
425
                        return p.getHeight();
426
                return lastHeightRequest;
427
        }
428

    
429
        /*
430
         * (non-Javadoc)
431
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#readCompleteLine(int, int)
432
         */
433
        public Object readCompleteLine(int line, int band)
434
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
435
                return null;
436
        }
437
        
438
        /**
439
         * When the remote layer has fixed size this method downloads the file and return its reference. 
440
         * File layer has in the long side FIXED_SIZE pixels and the bounding box is complete. This file could be
441
         * useful to build an histogram or calculate statistics. This represents a sample of data.
442
         * @return
443
         * @throws RasterDriverException
444
         */
445
        public File getFileLayer() throws RasterDriverException {
446
                return null;
447
        }
448

    
449
        /**
450
         * Reads a complete block of data and returns an tridimensional array of the right type. This function is useful
451
         * to read a file very fast without setting a view. In a WMS service when the size is fixed then it will read the
452
         * entire image but when the source hasn't pixel size it will read a sample of data. This set of data will have
453
         * the size defined in FIXED_SIZE. 
454
         * 
455
         * @param pos Posici?n donde se empieza  a leer
456
         * @param blockHeight Altura m?xima del bloque leido
457
         * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
458
         * @throws InvalidSetViewException
459
         * @throws FileNotOpenException
460
         * @throws RasterDriverException
461
         */
462
        public Object readBlock(int pos, int blockHeight) 
463
        throws InvalidSetViewException, FileNotOpenException, RasterDriverException, ProcessInterruptedException {
464
                return null;
465
        }
466

    
467
        /*
468
         * (non-Javadoc)
469
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getData(int, int, int)
470
         */
471
        public Object getData(int x, int y, int band)
472
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
473
                return null;
474
        }
475
        
476
        /**
477
         * Assigns the list of bands RGB and read a window of data
478
         * @param rasterBuf
479
         * @param bandList
480
         * @param lastFile
481
         * @param ulx
482
         * @param uly
483
         * @param lrx
484
         * @param lry
485
         * @return
486
         * @throws RasterDriverException
487
         * @throws ProcessInterruptedException
488
         */
489
        public Buffer getBuffer(Buffer rasterBuf, BandList bandList, File lastFile, 
490
                        double ulx, double uly, double lrx, double lry) throws RasterDriverException, ProcessInterruptedException {
491
                return null;
492
        }
493
        
494
        /*
495
         * (non-Javadoc)
496
         * @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)
497
         */
498
        public void getWindowRaster(double minX, double minY, double maxX, double maxY, 
499
                        int bufWidth, int bufHeight, BandList bandList, TileListener listener)throws ProcessInterruptedException, RasterDriverException {
500
                Rectangle2D r = new Rectangle2D.Double(Math.min(minX, maxX), Math.min(minY, maxY), Math.abs(maxX - minX), Math.abs(maxY - minY));
501
                WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
502
                request(status, bandList, listener);
503
        }
504
        
505
        /**
506
         * Builds the WMTSStatus object using the parameters and the request bounding box. 
507
         * @param r
508
         * @param bufWidth
509
         * @return
510
         * @throws RasterDriverException
511
         */
512
        @SuppressWarnings("unchecked")
513
        private WMTSStatus buildWMTSStatus(Rectangle2D r, int bufWidth, int bufHeight) throws RasterDriverException {
514
                WMTSDataParameters p = (WMTSDataParameters)param;
515
                
516
                //Mantiene actualizados los par?metros del WMTSStoreParameters con la ?ltima petici?n hecha
517
                p.setExtent(r);
518
                p.setWidth(bufWidth);
519
                p.setHeight(bufHeight);
520
                
521
                lastWidthRequest = bufWidth;
522
                lastHeightRequest = bufHeight;
523
                
524
                //1-Selecci?n de WMTSTileMatrixSet por srs
525
                WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
526
                WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
527
                ArrayList tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
528
                
529
                //2-Calculo de la escala
530
                double scale = getScale(r, bufWidth);
531
                
532
                //3-Selecci?n del nivel a partir de la escala
533
                int level = getLevelFromScale(scale, tileMatrixSet);
534

    
535
                //4-Obtenemos la matriz de tiles y los l?mites si tiene subsets
536
                WMTSTileMatrixLimits tileMatrixLimits = null;
537
                WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(level);
538
                if(gridSubsets)
539
                        tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(level);
540
                
541
                //5-Selecci?n de tiles que entran en esta bounding box
542
                ArrayList<Tile> tiles = null;
543
                if(gridSubsets)
544
                        tiles = tileMatrix.intersects(p.getSRS().isProjected(), tileMatrixLimits, r, getExtent().toRectangle2D());
545
                else
546
                        tiles = tileMatrix.intersects(p.getSRS().isProjected(), r, getExtent().toRectangle2D());
547
                
548
                //6-Petici?n
549
                WMTSStatus status = new WMTSStatus();
550
                status.setTileList(tiles);
551
                status.setLayer(p.getLayer().getIdentifier());
552
                status.setFormat(p.getImageFormat());
553
                status.setStyle(p.getStyle() != null ? p.getStyle().getIdentifier() : "");
554
                status.setTileMatrixSet(tileMatrixSet.getIdentifier());
555
                status.setTileMatrix(tileMatrix.getIdentifier());
556
                return status;
557
        }
558
        
559
        /**
560
         * Gets the resolution level from the scale
561
         * @param scale
562
         * @param tileMatrixSet
563
         * @return
564
         * @throws RasterDriverException
565
         */
566
        public int getLevelFromScale(double scale, WMTSTileMatrixSet tileMatrixSet) throws RasterDriverException {
567
                //Recorremos los tileMatrix para obtener la escala m?s aproximada
568
                int levelModifier = 0;
569
                try {
570
                        for (int resolutionLevel = 0; resolutionLevel < tileMatrixSet.getTileMatrix().size(); resolutionLevel++) {
571
                                WMTSTileMatrix tm = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(resolutionLevel);
572
                                double scaleDenominator = tm.getScaleDenominator();
573
                                if(scale >= scaleDenominator) {
574
                                        return Math.max(resolutionLevel + levelModifier, 0);
575
                                }
576
                        }
577
                } catch (IndexOutOfBoundsException e) {
578
                        throw new RasterDriverException("Error in this resolution level", e);
579
                }
580
                return 0;
581
        }
582
        
583
        /**
584
         * Get the tile matrix set using the crs
585
         * @param srs
586
         * @return
587
         */
588
        private WMTSTileMatrixSetLink getTileMatrixSetLink() {
589
                WMTSDataParameters p = (WMTSDataParameters)param;
590
                ArrayList<?> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
591
                for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
592
                        WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
593
                        String srsTileSet = tileMatrixSetLink.getTileMatrixSet().getSupportedCRS();
594
                        if(srsTileSet.compareTo(p.getSRSCode()) == 0) {
595
                                return tileMatrixSetLink;
596
                        }
597
                }
598
                if(tileMatrixSetLinkList != null && tileMatrixSetLinkList.size() > 0)
599
                        return (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(0);
600
                return null;
601
        }
602
        
603
        /**
604
         * Gets the scale using the extent and the width in pixels.
605
         * @param r
606
         * @param width
607
         * @return
608
         */
609
        private double getScale(Rectangle2D r, int width) {
610
                WMTSDataParameters p = (WMTSDataParameters)param;
611
                if(!p.getSRS().isProjected()) {
612
                        return (1000 * r.getWidth() * MTS_X_GRADO) / (width * 0.28);
613
                } else
614
                        return (1000 * r.getWidth()) / (width * 0.28);
615
        }
616
        
617
        /**
618
         * Throw a request
619
         * @param status
620
         * @param bandList
621
         * @param listener
622
         * @param alphaBandNumber 
623
         * @return returns a buffer if the listener is null. In any other case it return null.
624
         * @throws RasterDriverException 
625
         * @throws ProcessInterruptedException 
626
         */
627
        @SuppressWarnings("unchecked")
628
        private Buffer request(WMTSStatus status, BandList bandList, TileListener listener) throws RasterDriverException, ProcessInterruptedException {
629
                WMTSDataParameters p = (WMTSDataParameters)param;
630
                WMTSConnector connector = null;
631
                try {
632
                        connector = getConnector();
633
                } catch (WMSException e) {
634
                        throw new RasterDriverException("Error getting the connector object", e);
635
                }
636
                
637
                if(connector == null)
638
                        throw new RasterDriverException("Error getting the connector object");
639
                
640
                ArrayList<Tile> tiles = status.getTileList();
641
                
642
                for (int i = 0; i < tiles.size(); i++) {
643
                        Tile tile = tiles.get(i);
644
                        status.setTileRow(tile.row);
645
                        status.setTileCol(tile.col);
646
                        //TODO:Cancelaci?n
647
                        try {
648
                                File file = connector.getTile(status, null);
649
                                
650
                                String serverName = bandList.getBand(0).getFileName();
651
                                for (int j = 0; j < bandList.getBandCount(); j++) {
652
                                        bandList.getBand(j).setFileName(file.getPath());
653
                                }
654
                                
655
                                GdalProvider driver = new GdalProvider(file.getPath());
656
                                bandCount = driver.getBandCount();
657
                                lastFileTransparency = driver.getTransparency();
658
                                Buffer rasterBuf = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], tile.wPx, tile.hPx, 3, true);
659
                                Buffer buf = driver.getWindowRaster(0, 0, tile.wPx, tile.hPx, bandList, rasterBuf);
660
                                
661
                                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)));
662
                                
663
                                Buffer alphaBand = null;
664
                                if(p.getAlphaBand() != -1 && listener != null) {
665
                                        alphaBand = DefaultRasterManager.getInstance().createBuffer(getDataType()[0], tile.wPx, tile.hPx, 1, true);
666
                                        int[] oldDB = bandList.getDrawableBands();
667
                                        bandList.setDrawableBands(new int[]{p.getAlphaBand()});
668
                                        alphaBand = driver.getWindowRaster(0, 0, tile.wPx, tile.hPx, bandList, alphaBand);
669
                                        bandList.setDrawableBands(oldDB);
670
                                }
671
                                
672
                                for (int j = 0; j < bandList.getBandCount(); j++) {
673
                                        bandList.getBand(j).setFileName(serverName);
674
                                }
675
                                
676
                                driver.close();
677
                                
678
                                if(listener != null)
679
                                        listener.nextBuffer(buf, alphaBand, new ExtentImpl(tile.ulx, tile.uly, tile.lrx, tile.lry), getAffineTransform(), null, true);
680
                                else
681
                                        return buf;
682
                                
683
                        } catch (WMTSException e) {
684
                                throw new RasterDriverException("Error getting tiles", e);
685
                        } catch (ServerErrorException e) {
686
                                throw new RasterDriverException("Error getting tiles", e);
687
                        } catch (NotSupportedExtensionException e) {
688
                                throw new RasterDriverException("Error getting tiles", e);
689
                        }
690
                }
691
                if(listener != null)
692
                        listener.endReading();
693
                return null;
694
        }
695

    
696
        /*
697
         * (non-Javadoc)
698
         * @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)
699
         */
700
        public Buffer getWindowRaster(double ulx, double uly, double lrx, double lry, 
701
                        BandList bandList, Buffer rasterBuf) throws ProcessInterruptedException, RasterDriverException {
702
                lastWidthRequest = rasterBuf.getWidth();
703
                lastHeightRequest = rasterBuf.getHeight();
704
                return null;
705
        }
706

    
707
        /*
708
         * (non-Javadoc)
709
         * @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)
710
         */
711
        public Buffer getWindowRaster(double ulx, double uly, double w, double h, 
712
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
713
                lastWidthRequest = rasterBuf.getWidth();
714
                lastHeightRequest = rasterBuf.getHeight();
715
                return null;
716
        }
717

    
718
        /*
719
         * (non-Javadoc)
720
         * @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)
721
         */
722
        public Buffer getWindowRaster(double ulx, double uly, double lrx, double lry, 
723
                        int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
724
                Rectangle2D r = new Rectangle2D.Double(Math.min(ulx, lrx), Math.min(lry, uly), Math.abs(lrx - ulx), Math.abs(uly - lry));
725
                WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
726
                return request(status, bandList, null);
727
        }
728

    
729
        /*
730
         * (non-Javadoc)
731
         * @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)
732
         */
733
        public Buffer getWindowRaster(int x, int y, int w, int h, BandList bandList, Buffer rasterBuf) throws ProcessInterruptedException, RasterDriverException {
734
                lastWidthRequest = rasterBuf.getWidth();
735
                lastHeightRequest = rasterBuf.getHeight();
736
                return null;
737
        }
738

    
739
        /*
740
         * (non-Javadoc)
741
         * @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)
742
         */
743
        public Buffer getWindowRaster(int x, int y, int w, int h, int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf) throws ProcessInterruptedException, RasterDriverException {
744
                lastWidthRequest = rasterBuf.getWidth();
745
                lastHeightRequest = rasterBuf.getHeight();
746
                return null;
747
        }
748

    
749
        /*
750
         * (non-Javadoc)
751
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getBlockSize()
752
         */
753
        public int getBlockSize() {
754
                return 0;
755
        }
756

    
757
        /*
758
         * (non-Javadoc)
759
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setAffineTransform(java.awt.geom.AffineTransform)
760
         */
761
        public void setAffineTransform(AffineTransform t){
762
                
763
        }
764

    
765
        /*
766
         * (non-Javadoc)
767
         * @see org.gvsig.raster.impl.provider.RasterProvider#getOverviewCount(int)
768
         */
769
        public int getOverviewCount(int band) throws BandAccessException, RasterDriverException {
770
                return 0;
771
        }
772

    
773
        /*
774
         * (non-Javadoc)
775
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewWidth(int, int)
776
         */
777
        public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException {
778
                return 0;
779
        }
780

    
781
        /*
782
         * (non-Javadoc)
783
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewHeight(int, int)
784
         */
785
        public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException {
786
                return 0;
787
        }
788

    
789
        /*
790
         * (non-Javadoc)
791
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#overviewsSupport()
792
         */
793
        public boolean overviewsSupport() {
794
                return false;
795
        }
796

    
797
        /*
798
         * (non-Javadoc)
799
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isReproyectable()
800
         */
801
        public boolean isReproyectable() {
802
                return false;
803
        }
804

    
805
        /*
806
         * (non-Javadoc)
807
         * @see org.gvsig.fmap.dal.raster.spi.CoverageStoreProvider#getName()
808
         */
809
        public String getName() {
810
                return NAME;
811
        }
812
        
813
        /**
814
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
815
         * @param pt Punto a transformar
816
         * @return punto transformado en coordenadas del mundo
817
         */
818
        public Point2D rasterToWorld(Point2D pt) {
819
                Point2D p = new Point2D.Double();
820
                getAffineTransform().transform(pt, p);
821
                return p;
822
        }
823

    
824
        /**
825
         * Convierte un punto desde del mundo a coordenadas pixel.
826
         * @param pt Punto a transformar
827
         * @return punto transformado en coordenadas pixel
828
         */
829
        public Point2D worldToRaster(Point2D pt) {
830
                Point2D p = new Point2D.Double();
831
                try {
832
                        getAffineTransform().inverseTransform(pt, p);
833
                } catch (NoninvertibleTransformException e) {
834
                        return pt;
835
                }
836
                return p;
837
        }
838
        
839
        /*
840
         * (non-Javadoc)
841
         * @see org.gvsig.raster.impl.provider.RasterProvider#setStatus(org.gvsig.raster.impl.provider.RasterProvider)
842
         */
843
        public void setStatus(RasterProvider provider) {
844
                if(provider instanceof WMTSProvider) {
845
                }
846
        }
847
        
848
        /*
849
         * (non-Javadoc)
850
         * @see org.gvsig.raster.impl.provider.RemoteRasterProvider#getLastRequest()
851
         */
852
        public File getLastRequest() {
853
                return lastRequest;
854
        }
855
        
856
        /**
857
         * ASigna el par?metro de inicializaci?n del driver.
858
         */
859
        @Override
860
        public void setParam(DataStoreParameters param) {
861
                if(param instanceof WMTSDataParameters)
862
                        this.name = ((WMTSDataParameters)param).getHost();
863
                this.param = param;
864
        }
865

    
866
}