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 |
} |