Statistics
| Revision:

gvsig-osm / org.gvsig.raster.osm / trunk / org.gvsig.raster.osm / org.gvsig.raster.osm.io / src / main / java / org / gvsig / raster / osm / cachestruct / OSMCacheStruct.java @ 85

History | View | Annotate | Download (12.1 KB)

1
/* OSM layers for gvSIG. 
2
 * Geographic Information System of the Valencian Government
3
*
4
* Copyright (C) 2012 Nacho Brodin
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.osm.cachestruct;
23

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

    
29
import org.gvsig.fmap.dal.coverage.RasterLocator;
30
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
31
import org.gvsig.raster.cache.tile.Tile;
32
import org.gvsig.raster.cache.tile.TileCacheLocator;
33
import org.gvsig.raster.cache.tile.exception.TileBuildException;
34
import org.gvsig.raster.cache.tile.provider.CacheStruct;
35

    
36
/**
37
 * Implementation for a structure of a cache
38
 * @author Nacho Brodin (nachobrodin@gmail.com)
39
 */
40
public class OSMCacheStruct implements CacheStruct {
41
    private TileMatrixSet                 tileMatrixSet  = null;
42
    private ArrayList<TileMatrixLimits>   limits         = null;
43
    private String                        layerName      = 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
    
50
    public OSMCacheStruct(int levels, 
51
                    int tilePxWidth,
52
                    int tilePxHeight,
53
                    String layerName,
54
                    String baseDir,
55
                    String fileSuffix,
56
                    long size) {
57
            this.layerName = layerName;
58
            this.fileSuffix = fileSuffix;
59
            this.fileSize = size;
60
            this.epsg = "EPSG:3857"; //WGS87 Pseudomercator
61
            
62
            //Coordenadas del mundo en geogr?ficas y planas
63
            
64
            //worldExtent = new Rectangle2D.Double(-180, -85.0511, 360, 170.1022); // arctan(sin(PI)) = 85.0511
65
            //worldExtent = new Rectangle2D.Double(-180, -180, 360, 360);
66
            worldExtent = new Rectangle2D.Double(-20037508, -20037508, 40075016, 40075016);
67
            double[][] pixelSizeList = buildWorldMatrix(levels, tilePxWidth, tilePxHeight, worldExtent);
68
        buildLayerMatrix(levels, tilePxWidth, tilePxHeight, worldExtent, pixelSizeList);
69
        
70
    }
71
    
72
    private void buildLayerMatrix(int levels, 
73
                    int tilePxWidth, 
74
                    int tilePxHeight,
75
                    Rectangle2D worldExtent,
76
                    double[][] pixelSizeList) {
77
            limits = new ArrayList<TileMatrixLimits>();
78

    
79
            for (int i = 0; i < levels; i++) {
80
                    //Calculo de tiles para ese nivel en la capa actual
81
                    int minTileCol = 0;
82
                    int minTileRow = 0;
83
                    int maxTileCol = (i == 0) ? 0 : (int)Math.pow(2, i) - 1;
84
                    int maxTileRow = (i == 0) ? 0 : (int)Math.pow(2, i) - 1;
85
                    
86
                    TileMatrixLimits limit = new TileMatrixLimits();
87
                    limit.setMinTileRow(minTileRow);
88
                    limit.setMinTileCol(minTileCol);
89
                    limit.setMaxTileRow(maxTileRow);
90
                    limit.setMaxTileCol(maxTileCol);
91
                    
92
                    //Calcula las coordenadas de la esquina superior izquierda del TileMatrixLimits
93
                    double ulx = worldExtent.getMinX() + (minTileCol * tilePxWidth * pixelSizeList[0][i]);
94
                    double uly = worldExtent.getMaxY() - (minTileRow * tilePxHeight * pixelSizeList[1][i]);
95
                    limit.getTileMatrix().setTopLeftCorner(new double[]{ulx, uly});
96
                    limit.getTileMatrix().setScaleXDenominator(pixelSizeList[0][i]);
97
                    limit.getTileMatrix().setScaleYDenominator(pixelSizeList[1][i]);
98
                    limit.getTileMatrix().setTileWidth(tilePxWidth);
99
                    limit.getTileMatrix().setTileHeight(tilePxHeight);
100
                    
101
                    limits.add(limit);
102
            }
103
    }
104
    
105
    private double[][] buildWorldMatrix(int levels, 
106
                    int tilePxWidth, 
107
                    int tilePxHeight,
108
                    Rectangle2D worldExtent) {
109
            double[] pixelSizeXList = new double[levels];
110
            double[] pixelSizeYList = new double[levels];
111
            
112
            limits = new ArrayList<TileMatrixLimits>();
113
            tileMatrixSet = new TileMatrixSet();
114
            tileMatrixSet.setBbox(worldExtent);
115
            
116
            int nTilesWidth = 0;
117
            int nTilesHeight = 0;
118
                    
119
            for (int i = 0; i < levels; i++) {
120
                    TileMatrix tm = new TileMatrix();
121
                    tm.setTileWidth(tilePxWidth);
122
                    tm.setTileHeight(tilePxHeight);
123
            
124
                    nTilesWidth = (i == 0) ? 1 : nTilesWidth * 2;
125
                    nTilesHeight = (i == 0) ? 1 : nTilesHeight * 2;
126
                    
127
                    tm.setMatrixWidth(nTilesWidth);
128
                    tm.setMatrixHeight(nTilesHeight);
129
                    if((tilePxWidth * nTilesWidth) != 0)
130
                            pixelSizeXList[i] = worldExtent.getWidth() / ((long)tilePxWidth * (long)nTilesWidth);
131
                    else
132
                            pixelSizeXList[i] = 0;
133
                    
134
                    if((tilePxHeight * nTilesHeight) != 0)
135
                            pixelSizeYList[i] = worldExtent.getHeight() / ((long)tilePxHeight * (long)nTilesHeight);
136
                    else
137
                            pixelSizeYList[i] = 0;
138
                    //System.out.println("-Level:" + i + " " + nTilesWidth + " " + nTilesHeight + " " + pixelSizeList[i]);
139
                    tm.setScaleXDenominator(pixelSizeXList[i]);
140
                    tm.setScaleYDenominator(pixelSizeYList[i]);
141
                    tileMatrixSet.getTileMatrix().add(tm);
142
            }
143
            
144
            double[][] r = new double [2][];
145
            r[0] = pixelSizeXList;
146
            r[1] = pixelSizeYList;
147
            return r;
148
    }
149
    
150
    public Extent getWorldExtent() {
151
            return RasterLocator.getManager().getDataStructFactory().createExtent(worldExtent);
152
    }
153

    
154
        public int getNumberOfLevels() {
155
                return tileMatrixSet.getTileMatrix().size();
156
        }
157

    
158
        public String getLayerName() {
159
                return layerName;
160
        }
161

    
162
        public String getServerURL() {
163
                return layerName;
164
        }
165
        
166
        public String getFileSuffix() {
167
                return fileSuffix;
168
        }
169

    
170
        public int[] getTileSizeByLevel(int level) {
171
                return new int[] {
172
                        tileMatrixSet.getTileMatrix().get(level).getTileWidth(),
173
                        tileMatrixSet.getTileMatrix().get(level).getTileHeight()
174
                };
175
        }
176
        
177
        public double[] getTileSizeInRealCoordsByLevel(int level) {
178
                return new double[] {
179
                                tileMatrixSet.getTileMatrix().get(level).getScaleXDenominator() * tileMatrixSet.getTileMatrix().get(level).getTileWidth(),
180
                                tileMatrixSet.getTileMatrix().get(level).getScaleYDenominator() *  tileMatrixSet.getTileMatrix().get(level).getTileHeight()
181
                        };
182
        }
183

    
184
        public int getLayerWidthOfTileMatrixByLevel(int level) {
185
                TileMatrixLimits l = limits.get(level);
186
                return l.getMaxTileRow() - l.getMinTileRow();
187
        }
188
        
189
        public int getLayerHeightOfTileMatrixByLevel(int level) {
190
                TileMatrixLimits l = limits.get(level);
191
                return l.getMaxTileCol() - l.getMinTileCol();
192
        }
193

    
194
        public int getLayerInitXTilePositionByLevel(int level) {
195
                TileMatrixLimits l = limits.get(level);
196
                return l.getMinTileCol();
197
        }
198

    
199
        public int getLayerInitYTilePositionByLevel(int level) {
200
                TileMatrixLimits l = limits.get(level);
201
                return l.getMinTileRow();
202
        }
203

    
204
        public long getWorldHeightOfTileMatrixByLevel(int level) {
205
                return tileMatrixSet.getTileMatrix().get(level).getMatrixWidth();
206
        }
207

    
208
        public long getWorldWidthOfTileMatrixByLevel(int level) {
209
                return tileMatrixSet.getTileMatrix().get(level).getMatrixHeight();
210
        }
211
        
212
        public double getPixelSizeByLevel(int level) {
213
                if(level < 0)
214
                        return realPixelSize;
215
                return tileMatrixSet.getTileMatrix().get(level).getScaleXDenominator();
216
        }
217
        
218
        public Point2D[] getTileExtent(Tile tile) {
219
                return limits.get(tile.getLevel()).getTileExtent(tile.getRow(), tile.getCol());
220
        }
221
        
222
        public Point2D[] getTileExtent(int level, int col, int row) {
223
                return limits.get(level).getTileExtent(row, col);
224
        }
225
        
226
        public List<Tile> getTileList(Rectangle2D r) {
227
                //No se necesita el nivel de resoluci?n real ya que es solo para dibujado
228
                return null;
229
        }
230
        
231
        public List<Tile> getTileList(Point2D ul, Point2D lr, double mtsPixelXRequest) {
232
                //Selecci?n de nivel de resoluci?n
233
                int tilePxWidth = 0;
234
                int tilePxHeight = 0;
235
                double tileWCWidth = 0;
236
                double tileWCHeight = 0;
237
                int level = 0;
238
                double mtsPixelXLevel = 0;
239
                double mtsPixelYLevel = 0;
240
                for (int i = 0; i < tileMatrixSet.getTileMatrix().size(); i++) {
241
                        mtsPixelXLevel = tileMatrixSet.getTileMatrix().get(i).getScaleXDenominator();
242
                        mtsPixelYLevel = tileMatrixSet.getTileMatrix().get(i).getScaleYDenominator();
243
                        if(clipDecimals(mtsPixelXRequest, 6) >= clipDecimals(mtsPixelXLevel, 6) 
244
                                || i == (tileMatrixSet.getTileMatrix().size() - 1)) {
245
                                level = Math.max(i, 0);
246
                                //Se ajusta al m?ximo nivel disponible para esa capa
247
                                if(level > (limits.size() - 1)) {
248
                                        level = limits.size() - 1;
249
                                        mtsPixelXLevel = tileMatrixSet.getTileMatrix().get(level).getScaleXDenominator();
250
                                        mtsPixelYLevel = tileMatrixSet.getTileMatrix().get(level).getScaleYDenominator();
251
                                }
252
                                
253
                                tilePxWidth = tileMatrixSet.getTileMatrix().get(level).getTileWidth();
254
                                tilePxHeight = tileMatrixSet.getTileMatrix().get(level).getTileHeight();
255
                                
256
                                //mtsPixelLevel = tileMatrixSet.getTileMatrix().get(i - 1).getScaleDenominator();
257
                                tileWCWidth = tilePxWidth * mtsPixelXLevel;
258
                                tileWCHeight = tilePxHeight * mtsPixelYLevel;
259
                                break;
260
                        }
261
                }
262
                
263
                //Calculo del rectangulo de tiles
264
                int minTileCol = (int)((Math.abs(ul.getX() - worldExtent.getMinX()) / mtsPixelXLevel) / tilePxWidth);
265
                int minTileRow = (int)((Math.abs(ul.getY() - worldExtent.getMaxY()) / mtsPixelYLevel) / tilePxHeight);
266
                double maxTC = ((Math.abs(lr.getX() - worldExtent.getMinX()) / mtsPixelXLevel) / tilePxWidth);
267
                double maxTR = ((Math.abs(lr.getY() - worldExtent.getMaxY()) / mtsPixelYLevel) / tilePxHeight);
268
                int maxTileCol = ((maxTC - ((int)maxTC)) == 0) ? (int)(maxTC - 1) : (int)maxTC;
269
                int maxTileRow = ((maxTR - ((int)maxTR)) == 0) ? (int)(maxTR - 1) : (int)maxTR;
270
                
271
                //Calculo de tiles con sus coordenadas
272
                List<Tile> tileList = new ArrayList<Tile>();
273
                for (int i = minTileRow; i <= maxTileRow; i++) {
274
                        for (int j = minTileCol; j <= maxTileCol; j++) {
275
                                Point2D ulTile = new Point2D.Double(
276
                                                worldExtent.getMinX() + (tileWCWidth * j),
277
                                                worldExtent.getMaxY() - (tileWCHeight * i));
278
                                Point2D lrTile = new Point2D.Double(ulTile.getX() + tileWCWidth, ulTile.getY() - tileWCHeight);
279
                                Tile t = TileCacheLocator.getManager().createTile(tilePxWidth, tilePxHeight, i, j, ulTile, lrTile);
280
                                t.setLevel(level);
281
                                tileList.add(t);
282
                        }
283
                }
284
                return tileList;
285
        }
286
        
287
        public boolean compare(CacheStruct struct) {
288
                //Compara: n?mero de niveles, tama?o de tile, 
289
                //anchoXalto de la matriz, tama?o de pixel por nivel, 
290
                //coordenadas de al menos un tile de la matriz
291
                if(struct.getNumberOfLevels() == getNumberOfLevels()) {
292
                        for (int i = 0; i < getNumberOfLevels(); i++) {
293
                                if(        struct.getTileSizeByLevel(i)[0] == getTileSizeByLevel(i)[0] && 
294
                                        struct.getTileSizeByLevel(i)[1] == getTileSizeByLevel(i)[1] &&
295
                                        struct.getWorldHeightOfTileMatrixByLevel(i) == getWorldHeightOfTileMatrixByLevel(i) &&
296
                                        struct.getWorldWidthOfTileMatrixByLevel(i) == getWorldWidthOfTileMatrixByLevel(i) &&
297
                                        clipDecimals(struct.getPixelSizeByLevel(i), 2) == clipDecimals(getPixelSizeByLevel(i), 2) &&
298
                                        compareExtents(struct.getTileExtent(i, 0, 0), getTileExtent(i, 0, 0))) {
299
                                        return true;
300
                                }
301
                        }
302
                }
303
                return false;
304
        }
305
        
306
        public String getEPSG() {
307
                return epsg;
308
        }
309

    
310
        public String getFileSize() {
311
                return fileSize + "";
312
        }
313
        
314
        private boolean compareExtents(Point2D[] p, Point2D[] p1) {
315
                return (p[0].getX() == p1[0].getX() && p[0].getY() == p1[0].getY() &&
316
                                p[1].getX() == p1[1].getX() && p[1].getY() == p1[1].getY());
317
        }
318
        
319
        public double clipDecimals(double num, int n) {
320
                long m = (long) Math.pow(10, n);
321
                long aux = Math.round(num * m);
322
                return (double) aux / (double) m;
323
        }
324

    
325
        public Tile getTileStructure(int level, int tileCol, int tileRow,
326
                        Point2D ul, Point2D lr) throws TileBuildException {
327
                int[] size = getTileSizeByLevel(level);
328
                Tile tile = TileCacheLocator.getManager().createTile(level, tileRow, tileCol);
329
                tile.setUl(ul);
330
                tile.setLr(lr);
331
                tile.setWidthPx(size[0]);
332
                tile.setHeightPx(size[1]);
333
                        
334
                return tile;
335
        }
336

    
337
}