Statistics
| Revision:

gvsig-raster / org.gvsig.raster.cache / trunk / org.gvsig.raster.cache / org.gvsig.raster.cache.lib.impl / src / main / java / org / gvsig / raster / cache / tile / impl / provider / DefaultCacheStruct.java @ 952

History | View | Annotate | Download (16.1 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.cache.tile.impl.provider;
23

    
24
import java.awt.geom.Point2D;
25
import java.awt.geom.Rectangle2D;
26
import java.util.ArrayList;
27

    
28
import org.gvsig.raster.cache.tile.Tile;
29
import org.gvsig.raster.cache.tile.TileCacheLocator;
30
import org.gvsig.raster.cache.tile.disk.ITileFileSystemStrategy;
31
import org.gvsig.raster.cache.tile.exception.TileBuildException;
32
import org.gvsig.raster.cache.tile.impl.TileImpl;
33
import org.gvsig.raster.cache.tile.provider.CacheStruct;
34

    
35
/**
36
 * Implementation for a structure of a cache
37
 * @author Nacho Brodin (nachobrodin@gmail.com)
38
 */
39
public class DefaultCacheStruct implements CacheStruct {
40
    private TileMatrixSet                 tileMatrixSet  = null;
41
    private ArrayList<TileMatrixLimits>   limits         = null;
42
    private String                        layerName      = null;
43
    private String                        uri            = null;
44
        private Rectangle2D                   worldExtent    = null;
45
        private String                        fileSuffix     = null;
46
        private String                        epsg           = null;
47
        private long                          fileSize       = 0;
48
        private double                        realPixelSize  = 0;
49
        private Rectangle2D                   layerExtent    = null;
50
    
51
    public DefaultCacheStruct(int typeOfCoords, 
52
                    int levels, 
53
                    Rectangle2D layerExtent, 
54
                    double pixelSize,
55
                    int tilePxWidth,
56
                    int tilePxHeight,
57
                    String uri,
58
                    String layerName,
59
                    ITileFileSystemStrategy strategy,
60
                    String baseDir,
61
                    String fileSuffix,
62
                    String epsg,
63
                    long size) {
64
            this.uri = uri;
65
            this.layerName = layerName;
66
            this.fileSuffix = fileSuffix;
67
            this.fileSize = size;
68
            this.realPixelSize = pixelSize;
69
            this.layerExtent = layerExtent;
70
            if(epsg != null && epsg.startsWith("EPSG:"))
71
                    this.epsg = epsg;
72
            
73
            //Coordenadas del mundo en geogr?ficas y planas
74
            
75
            if(typeOfCoords == CacheStruct.GEOGRAFIC) {
76
                    worldExtent = new Rectangle2D.Double(-180, -90, 360, 180);
77
            } 
78
            if(typeOfCoords == CacheStruct.FLAT) {
79
                    worldExtent = new Rectangle2D.Double(-20037508, -20037508, 40075016, 40075016);
80
            }
81
            
82
            double[] pixelSizeList = buildWorldMatrix(typeOfCoords, levels, tilePxWidth, tilePxHeight, worldExtent);
83
        buildLayerMatrix(levels, tilePxWidth, tilePxHeight, worldExtent, layerExtent, pixelSizeList, pixelSize);
84
    }
85
    
86
    private void buildLayerMatrix(int levels, 
87
                    int tilePxWidth, 
88
                    int tilePxHeight,
89
                    Rectangle2D worldExtent,
90
                    Rectangle2D layerExtent,
91
                    double[] pixelSizeList,
92
                    double maxPixelSize) {
93
            limits = new ArrayList<TileMatrixLimits>();
94

    
95
            for (int i = 0; i < levels; i++) {
96
                    //Calculo de tiles para ese nivel en la capa actual
97
                    int minTileCol = (int)(Math.abs(layerExtent.getMinX() - worldExtent.getMinX()) / pixelSizeList[i]) / tilePxWidth;
98
                    int minTileRow = (int)(Math.abs(layerExtent.getMaxY() - worldExtent.getMaxY()) / pixelSizeList[i]) / tilePxHeight;
99
                    int maxTileCol = (int)(Math.abs(layerExtent.getMaxX() - worldExtent.getMinX()) / pixelSizeList[i]) / tilePxWidth;
100
                    int maxTileRow = (int)(Math.abs(layerExtent.getMinY() - worldExtent.getMaxY()) / pixelSizeList[i]) / tilePxHeight;
101
                    
102
                    //int imageTileWidth = (int)Math.ceil((layerExtent.getWidth() / pixelSizeList[i]) / tilePxWidth);
103
                    //int imageTileHeight = (int)Math.ceil((layerExtent.getHeight() / pixelSizeList[i]) / tilePxHeight);
104
                    TileMatrixLimits limit = new TileMatrixLimits();
105
                    limit.setMinTileRow(minTileRow);
106
                    limit.setMinTileCol(minTileCol);
107
                    limit.setMaxTileRow(maxTileRow);
108
                    limit.setMaxTileCol(maxTileCol);
109
                    
110
                    //Calcula las coordenadas de la esquina superior izquierda del TileMatrixLimits
111
                    double ulx = worldExtent.getMinX() + (minTileCol * tilePxWidth * pixelSizeList[i]);
112
                    double uly = worldExtent.getMaxY() - (minTileRow * tilePxHeight * pixelSizeList[i]);
113
                    limit.getTileMatrix().setTopLeftCorner(new double[]{ulx, uly});
114
                    limit.getTileMatrix().setScaleDenominator(pixelSizeList[i]);
115
                    limit.getTileMatrix().setTileWidth(tilePxWidth);
116
                    limit.getTileMatrix().setTileHeight(tilePxHeight);
117
                    
118
                    limits.add(limit);
119
                    if(i == (levels - 1) || (maxPixelSize != Double.POSITIVE_INFINITY && maxPixelSize != Double.NEGATIVE_INFINITY && pixelSizeList[i] < maxPixelSize)) {
120
                            //System.out.println("Image res:" + maxPixelSize + " Real res:" + pixelSizeList[i]);
121
                            break;
122
                    }
123
            }
124
    }
125
    
126
    private double[] buildWorldMatrix(int typeOfCoords,
127
                    int levels, 
128
                    int tilePxWidth, 
129
                    int tilePxHeight,
130
                    Rectangle2D worldExtent) {
131
            double[] pixelSizeList = new double[levels];
132
            
133
            limits = new ArrayList<TileMatrixLimits>();
134
            tileMatrixSet = new TileMatrixSet();
135
            tileMatrixSet.setBbox(worldExtent);
136
            
137
            int nTilesWidth = 0;
138
            int nTilesHeight = 0;
139
                    
140
            for (int i = 0; i < levels; i++) {
141
                    TileMatrix tm = new TileMatrix();
142
                    tm.setTileWidth(tilePxWidth);
143
                    tm.setTileHeight(tilePxHeight);
144
                    if(i == 0) {
145
                            nTilesWidth = (typeOfCoords == CacheStruct.FLAT) ? 1 : 2;
146
                            nTilesHeight = 1;
147
                    } else {
148
                            nTilesWidth *= 2;
149
                            nTilesHeight *= 2;
150
                    }
151
                    
152
                    tm.setMatrixWidth(nTilesWidth);
153
                    tm.setMatrixHeight(nTilesHeight);
154
                    if((tilePxWidth * nTilesWidth) != 0)
155
                            pixelSizeList[i] = worldExtent.getWidth() / ((long)tilePxWidth * (long)nTilesWidth);
156
                    else
157
                            pixelSizeList[i] = 0;
158
                    //System.out.println("-Level:" + i + " " + nTilesWidth + " " + nTilesHeight + " " + pixelSizeList[i]);
159
                    tm.setScaleDenominator(pixelSizeList[i]);
160
                    tileMatrixSet.getTileMatrix().add(tm);
161
            }
162
            return pixelSizeList;
163
    }
164

    
165
    /*
166
     * (non-Javadoc)
167
     * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getNumberOfLevels()
168
     */
169
        public int getNumberOfLevels() {
170
                return tileMatrixSet.getTileMatrix().size();
171
        }
172

    
173
        /*
174
         * (non-Javadoc)
175
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getLayerName()
176
         */
177
        public String getLayerName() {
178
                return layerName;
179
        }
180

    
181
        /*
182
         * (non-Javadoc)
183
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getServerURL()
184
         */
185
        public String getServerURL() {
186
                return uri;
187
        }
188
        
189
        /*
190
         * (non-Javadoc)
191
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getFileSuffix()
192
         */
193
        public String getFileSuffix() {
194
                return fileSuffix;
195
        }
196

    
197
        /*
198
         * (non-Javadoc)
199
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getTileSizeByLevel(int)
200
         */
201
        public int[] getTileSizeByLevel(int level) {
202
                return new int[] {
203
                        tileMatrixSet.getTileMatrix().get(level).getTileWidth(),
204
                        tileMatrixSet.getTileMatrix().get(level).getTileHeight()
205
                };
206
        }
207
        
208
        /*
209
         * (non-Javadoc)
210
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getTileSizeInRealCoordsByLevel(int)
211
         */
212
        public double[] getTileSizeInRealCoordsByLevel(int level) {
213
                return new double[] {
214
                                getPixelSizeByLevel(level) * tileMatrixSet.getTileMatrix().get(level).getTileWidth(),
215
                                getPixelSizeByLevel(level) *  tileMatrixSet.getTileMatrix().get(level).getTileHeight()
216
                        };
217
        }
218

    
219
        /*
220
         * (non-Javadoc)
221
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getLayerWidthOfTileMatrixByLevel(int)
222
         */
223
        public int getLayerWidthOfTileMatrixByLevel(int level) {
224
                TileMatrixLimits l = limits.get(level);
225
                return l.getMaxTileRow() - l.getMinTileRow();
226
        }
227
        
228
        /*
229
         * (non-Javadoc)
230
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getLayerHeightOfTileMatrixByLevel(int)
231
         */
232
        public int getLayerHeightOfTileMatrixByLevel(int level) {
233
                TileMatrixLimits l = limits.get(level);
234
                return l.getMaxTileCol() - l.getMinTileCol();
235
        }
236

    
237
        /*
238
         * (non-Javadoc)
239
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getLayerInitXTilePositionByLevel(int)
240
         */
241
        public int getLayerInitXTilePositionByLevel(int level) {
242
                TileMatrixLimits l = limits.get(level);
243
                return l.getMinTileCol();
244
        }
245

    
246
        /*
247
         * (non-Javadoc)
248
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getLayerInitYTilePositionByLevel(int)
249
         */
250
        public int getLayerInitYTilePositionByLevel(int level) {
251
                TileMatrixLimits l = limits.get(level);
252
                return l.getMinTileRow();
253
        }
254

    
255
        /*
256
         * (non-Javadoc)
257
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getWorldHeightOfTileMatrixByLevel(int)
258
         */
259
        public long getWorldHeightOfTileMatrixByLevel(int level) {
260
                return tileMatrixSet.getTileMatrix().get(level).getMatrixWidth();
261
        }
262

    
263
        /*
264
         * (non-Javadoc)
265
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getWorldWidthOfTileMatrixByLevel(int)
266
         */
267
        public long getWorldWidthOfTileMatrixByLevel(int level) {
268
                return tileMatrixSet.getTileMatrix().get(level).getMatrixHeight();
269
        }
270
        
271
        /*
272
         * (non-Javadoc)
273
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getPixelSizeByLevel(int)
274
         */
275
        public double getPixelSizeByLevel(int level) {
276
                if(level < 0)
277
                        return realPixelSize;
278
                return tileMatrixSet.getTileMatrix().get(level).getScaleDenominator();
279
        }
280
        
281
        /*
282
         * (non-Javadoc)
283
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getTileExtent(org.gvsig.raster.cache.tile.Tile)
284
         */
285
        public Point2D[] getTileExtent(Tile tile) {
286
                return limits.get(tile.getLevel()).getTileExtent(tile.getRow(), tile.getCol());
287
        }
288
        
289
        /*
290
         * (non-Javadoc)
291
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getTileExtent(int, int, int)
292
         */
293
        public Point2D[] getTileExtent(int level, int col, int row) {
294
                return limits.get(level).getTileExtent(row, col);
295
        }
296
        
297
        /*
298
         * (non-Javadoc)
299
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getTileStructure(int, int, int, java.awt.geom.Point2D, java.awt.geom.Point2D)
300
         */
301
        public Tile getTileStructure(int level, int tileCol, int tileRow, Point2D ul, Point2D lr) throws TileBuildException  {
302
                int[] size = getTileSizeByLevel(level);
303
                Tile tile = TileCacheLocator.getManager().createTile(level, tileRow, tileCol);
304
                tile.setUl(ul);
305
                tile.setLr(lr);
306
                tile.setWidthPx(size[0]);
307
                tile.setHeightPx(size[1]);
308
                
309
                return tile;
310
        }
311
        
312
        /*
313
         * (non-Javadoc)
314
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getTileList(java.awt.geom.Rectangle2D)
315
         */
316
        public ArrayList<Tile> getTileList(Rectangle2D r) {
317
                int tilePxWidth = tileMatrixSet.getTileMatrix().get(0).getTileWidth();
318
                int tilePxHeight = tileMatrixSet.getTileMatrix().get(0).getTileHeight();
319
                int minTileCol = (int)(r.getX() / tilePxWidth);
320
                int minTileRow = (int)(r.getY() / tilePxHeight);
321
                int maxTileCol = (int)((r.getX() + r.getWidth()) / tilePxWidth);
322
                int maxTileRow = (int)((r.getY() + r.getHeight()) / tilePxHeight);
323
                double tileWCWidth = tilePxWidth * realPixelSize;
324
                double tileWCHeight = tilePxHeight * realPixelSize;
325
                
326
                //Calculo de tiles con sus coordenadas
327
                ArrayList<Tile> tileList = new ArrayList<Tile>();
328
                for (int i = minTileRow; i <= maxTileRow; i++) {
329
                        for (int j = minTileCol; j <= maxTileCol; j++) {
330
                                Point2D ulTile = new Point2D.Double(
331
                                                layerExtent.getMinX() + (tileWCWidth * j),
332
                                                layerExtent.getMaxY() - (tileWCHeight * i));
333
                                Point2D lrTile = new Point2D.Double(ulTile.getX() + tileWCWidth, ulTile.getY() - tileWCHeight);
334
                                Tile t = new TileImpl(tilePxWidth, tilePxHeight, i, j, ulTile, lrTile);
335
                                t.setLevel(-1);
336
                                int initTileX = tilePxWidth * j;
337
                                int initTileY = tilePxHeight * i;
338
                                Rectangle2D rTile = new Rectangle2D.Double(initTileX, initTileY, tilePxWidth, tilePxHeight);
339
                                t.setCoordsPx(rTile);
340
                                tileList.add(t);
341
                        }
342
                }
343
                return tileList;
344
        }
345
        
346
        /*
347
         * (non-Javadoc)
348
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getTileList(java.awt.geom.Point2D, java.awt.geom.Point2D)
349
         */
350
        public ArrayList<Tile> getTileList(Point2D ul, Point2D lr, double mtsPixelRequest) {
351
                //Selecci?n de nivel de resoluci?n
352
                int tilePxWidth = 0;
353
                int tilePxHeight = 0;
354
                double tileWCWidth = 0;
355
                double tileWCHeight = 0;
356
                int level = 0;
357
                double mtsPixelLevel = 0;
358
                for (int i = 0; i < tileMatrixSet.getTileMatrix().size(); i++) {
359
                        mtsPixelLevel = tileMatrixSet.getTileMatrix().get(i).getScaleDenominator();
360
                        if(mtsPixelRequest > mtsPixelLevel) {
361
                                level = Math.max(i, 0);
362
                                //Se ajusta al m?ximo nivel disponible para esa capa
363
                                if(level > (limits.size() - 1)) {
364
                                        level = limits.size() - 1;
365
                                        mtsPixelLevel = tileMatrixSet.getTileMatrix().get(level).getScaleDenominator();
366
                                }
367
                                
368
                                tilePxWidth = tileMatrixSet.getTileMatrix().get(level).getTileWidth();
369
                                tilePxHeight = tileMatrixSet.getTileMatrix().get(level).getTileHeight();
370
                                
371
                                //mtsPixelLevel = tileMatrixSet.getTileMatrix().get(i - 1).getScaleDenominator();
372
                                tileWCWidth = tilePxWidth * mtsPixelLevel;
373
                                tileWCHeight = tilePxHeight * mtsPixelLevel;
374
                                break;
375
                        }
376
                }
377
                
378
                //Calculo del rectangulo de tiles
379
                int minTileCol = (int)((Math.abs(ul.getX() - worldExtent.getMinX()) / mtsPixelLevel) / tilePxWidth);
380
                int minTileRow = (int)((Math.abs(ul.getY() - worldExtent.getMaxY()) / mtsPixelLevel) / tilePxHeight);
381
                double maxTC = ((Math.abs(lr.getX() - worldExtent.getMinX()) / mtsPixelLevel) / tilePxWidth);
382
                double maxTR = ((Math.abs(lr.getY() - worldExtent.getMaxY()) / mtsPixelLevel) / tilePxHeight);
383
                int maxTileCol = ((maxTC - ((int)maxTC)) == 0) ? (int)(maxTC - 1) : (int)maxTC;
384
                int maxTileRow = ((maxTR - ((int)maxTR)) == 0) ? (int)(maxTR - 1) : (int)maxTR;
385
                
386
                //Calculo de tiles con sus coordenadas
387
                ArrayList<Tile> tileList = new ArrayList<Tile>();
388
                for (int i = minTileRow; i <= maxTileRow; i++) {
389
                        for (int j = minTileCol; j <= maxTileCol; j++) {
390
                                Point2D ulTile = new Point2D.Double(
391
                                                worldExtent.getMinX() + (tileWCWidth * j),
392
                                                worldExtent.getMaxY() - (tileWCHeight * i));
393
                                Point2D lrTile = new Point2D.Double(ulTile.getX() + tileWCWidth, ulTile.getY() - tileWCHeight);
394
                                Tile t = new TileImpl(tilePxWidth, tilePxHeight, i, j, ulTile, lrTile);
395
                                t.setLevel(level);
396
                                tileList.add(t);
397
                        }
398
                }
399
                return tileList;
400
        }
401
        
402
        /*
403
         * (non-Javadoc)
404
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#compare(org.gvsig.raster.cache.tile.provider.CacheStruct)
405
         */
406
        public boolean compare(CacheStruct struct) {
407
                //Compara: n?mero de niveles, tama?o de tile, 
408
                //anchoXalto de la matriz, tama?o de pixel por nivel, 
409
                //coordenadas de al menos un tile de la matriz
410
                if(struct.getNumberOfLevels() == getNumberOfLevels()) {
411
                        for (int i = 0; i < getNumberOfLevels(); i++) {
412
                                if(        struct.getTileSizeByLevel(i)[0] == getTileSizeByLevel(i)[0] && 
413
                                        struct.getTileSizeByLevel(i)[1] == getTileSizeByLevel(i)[1] &&
414
                                        struct.getWorldHeightOfTileMatrixByLevel(i) == getWorldHeightOfTileMatrixByLevel(i) &&
415
                                        struct.getWorldWidthOfTileMatrixByLevel(i) == getWorldWidthOfTileMatrixByLevel(i) &&
416
                                        clipDecimals(struct.getPixelSizeByLevel(i), 2) == clipDecimals(getPixelSizeByLevel(i), 2) &&
417
                                        compareExtents(struct.getTileExtent(i, 0, 0), getTileExtent(i, 0, 0))) {
418
                                        return true;
419
                                }
420
                        }
421
                }
422
                return false;
423
        }
424
        
425
        /*
426
         * (non-Javadoc)
427
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getEPSG()
428
         */
429
        public String getEPSG() {
430
                return epsg;
431
        }
432

    
433
        /*
434
         * (non-Javadoc)
435
         * @see org.gvsig.raster.cache.tile.provider.CacheStruct#getFileSize()
436
         */
437
        public String getFileSize() {
438
                return fileSize + "";
439
        }
440
        
441
        private boolean compareExtents(Point2D[] p, Point2D[] p1) {
442
                return (p[0].getX() == p1[0].getX() && p[0].getY() == p1[0].getY() &&
443
                                p[1].getX() == p1[1].getX() && p[1].getY() == p1[1].getY());
444
        }
445
        
446
        public double clipDecimals(double num, int n) {
447
                long m = (long) Math.pow(10, n);
448
                long aux = Math.round(num * m);
449
                return (double) aux / (double) m;
450
        }
451

    
452
}