| | 169 | * Routines to convert back and forth from lon/lat to Integer |
|---|
| | 170 | * representation of tiles |
|---|
| | 171 | */ |
|---|
| | 172 | |
|---|
| | 173 | /** |
|---|
| | 174 | * @private |
|---|
| | 175 | * |
|---|
| | 176 | * @param {float} lon |
|---|
| | 177 | * @param {Integer} tilesAtThisZoom |
|---|
| | 178 | * |
|---|
| | 179 | * @returns A integer representing the lon at a particular Zoom |
|---|
| | 180 | * @type Integer |
|---|
| | 181 | */ |
|---|
| | 182 | _lon2Gx:function(lon,tilesAtThisZoom) { |
|---|
| | 183 | var x = Math.floor((180+lon) * tilesAtThisZoom / 360); |
|---|
| | 184 | return x; |
|---|
| | 185 | }, |
|---|
| | 186 | |
|---|
| | 187 | /** |
|---|
| | 188 | * @private |
|---|
| | 189 | * @param {float} lat |
|---|
| | 190 | * @param {Integer} tilesAtThisZoom |
|---|
| | 191 | * |
|---|
| | 192 | * @returns A integer representing the lat at a particular Zoom |
|---|
| | 193 | * @type Integer |
|---|
| | 194 | */ |
|---|
| | 195 | _lat2Gy:function(lat,tilesAtThisZoom) { |
|---|
| | 196 | var srlat = Math.sin( lat * Math.PI / 180); |
|---|
| | 197 | var y = Math.floor(((1 - (0.5 * Math.log((1 + srlat) / (1 - srlat))) / Math.PI) / 2.0) * tilesAtThisZoom); |
|---|
| | 198 | return y; |
|---|
| | 199 | }, |
|---|
| | 200 | |
|---|
| | 201 | /** |
|---|
| | 202 | * @private |
|---|
| | 203 | * @param {Integer} x |
|---|
| | 204 | * @param {Integer} tilesAtThisZoom |
|---|
| | 205 | * |
|---|
| | 206 | * @returns A float (lon) representing the integer tile at a particular Zoom |
|---|
| | 207 | * @type float |
|---|
| | 208 | */ |
|---|
| | 209 | _Gx2lon:function(x, tilesAtThisZoom) { |
|---|
| | 210 | var lonWidth = 360.0 / tilesAtThisZoom; |
|---|
| | 211 | var lon = -180 + (x * lonWidth); |
|---|
| | 212 | return lon; |
|---|
| | 213 | }, |
|---|
| | 214 | |
|---|
| | 215 | /** |
|---|
| | 216 | * @private |
|---|
| | 217 | * @param {Integer} y |
|---|
| | 218 | * @param {Integer} tilesAtThisZoom |
|---|
| | 219 | * |
|---|
| | 220 | * @returns A float (lat) representing the integer tile at a particular Zoom |
|---|
| | 221 | * @type float |
|---|
| | 222 | */ |
|---|
| | 223 | _Gy2lat:function(y, tilesAtThisZoom) { |
|---|
| | 224 | var latHeight = 2.0 / tilesAtThisZoom; |
|---|
| | 225 | var lat = ((tilesAtThisZoom / 2 - y - 1) * latHeight); |
|---|
| | 226 | latHeight += lat; |
|---|
| | 227 | latHeight = (2.0 * Math.atan(Math.exp(Math.PI * latHeight))) |
|---|
| | 228 | - (Math.PI/2); |
|---|
| | 229 | latHeight *= (180/Math.PI); |
|---|
| | 230 | lat = (2.0 * Math.atan(Math.exp(Math.PI * lat))) - (Math.PI/2); |
|---|
| | 231 | lat *= (180/Math.PI); |
|---|
| | 232 | latHeight -= lat; |
|---|
| | 233 | if (latHeight < 0.0) { |
|---|
| | 234 | lat = lat + latHeight; |
|---|
| | 235 | latHeight = -latHeight; |
|---|
| | 236 | } |
|---|
| | 237 | return lat; |
|---|
| | 238 | }, |
|---|
| | 239 | |
|---|
| | 240 | /** |
|---|
| 178 | | var tilelon = resolution * this.tileSize.w; |
|---|
| 179 | | var tilelat = resolution * this.tileSize.h; |
|---|
| 180 | | |
|---|
| 181 | | var offsetlon = bounds.left - extent.left; |
|---|
| 182 | | var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; |
|---|
| 183 | | var tilecolremain = offsetlon/tilelon - tilecol; |
|---|
| 184 | | var tileoffsetx = -tilecolremain * this.tileSize.w; |
|---|
| 185 | | var tileoffsetlon = extent.left + tilecol * tilelon; |
|---|
| 186 | | |
|---|
| 187 | | var offsetlat = bounds.top - (extent.bottom + tilelat); |
|---|
| 188 | | var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer; |
|---|
| 189 | | var tilerowremain = tilerow - offsetlat/tilelat; |
|---|
| 190 | | var tileoffsety = -tilerowremain * this.tileSize.h; |
|---|
| 191 | | var tileoffsetlat = extent.bottom + tilerow * tilelat; |
|---|
| 192 | | |
|---|
| 193 | | tileoffsetx = Math.round(tileoffsetx); // heaven help us |
|---|
| 194 | | tileoffsety = Math.round(tileoffsety); |
|---|
| 195 | | |
|---|
| 196 | | this.origin = new OpenLayers.Pixel(tileoffsetx, tileoffsety); |
|---|
| 197 | | |
|---|
| 198 | | var startX = tileoffsetx; |
|---|
| 199 | | var startLon = tileoffsetlon; |
|---|
| 200 | | |
|---|
| 201 | | var rowidx = 0; |
|---|
| 202 | | |
|---|
| 203 | | do { |
|---|
| 204 | | var row = this.grid[rowidx++]; |
|---|
| 205 | | if (!row) { |
|---|
| 206 | | row = new Array(); |
|---|
| 207 | | this.grid.push(row); |
|---|
| 208 | | } |
|---|
| 209 | | |
|---|
| 210 | | tileoffsetlon = startLon; |
|---|
| 211 | | tileoffsetx = startX; |
|---|
| 212 | | var colidx = 0; |
|---|
| | 254 | |
|---|
| | 255 | var layContainerDivleft = parseInt(this.map.layerContainerDiv.style.left); |
|---|
| | 256 | var layContainerDivtop = parseInt(this.map.layerContainerDiv.style.top); |
|---|
| | 257 | |
|---|
| | 258 | if (this.newTile) { |
|---|
| | 259 | var zoom = this.map.getZoom(); |
|---|
| | 260 | |
|---|
| | 261 | var tilesAtThisZoom = 1 << zoom; |
|---|
| | 262 | |
|---|
| | 263 | // find the closest tiles for reference |
|---|
| | 264 | var xleft = this._lon2Gx(bounds.left, tilesAtThisZoom); |
|---|
| | 265 | var xright = this._lon2Gx(bounds.right, tilesAtThisZoom); |
|---|
| | 266 | var ybottom = this._lat2Gy(bounds.bottom, tilesAtThisZoom); |
|---|
| | 267 | var ytop = this._lat2Gy(bounds.top, tilesAtThisZoom); |
|---|
| | 268 | |
|---|
| | 269 | // add in buffer |
|---|
| | 270 | xleft -= this.buffer; |
|---|
| | 271 | xright += this.buffer; |
|---|
| | 272 | ybottom += this.buffer; |
|---|
| | 273 | ytop -= this.buffer; |
|---|
| | 274 | |
|---|
| | 275 | var tilecol = xright-xleft; |
|---|
| | 276 | var tilerow = ybottom-ytop; |
|---|
| | 277 | var x = xleft; |
|---|
| | 278 | var y = ytop; |
|---|
| | 279 | |
|---|
| | 280 | var rowidx = 0; |
|---|
| | 281 | do { |
|---|
| | 282 | var row = this.grid[rowidx++]; |
|---|
| | 283 | if (!row) { |
|---|
| | 284 | row = new Array(); |
|---|
| | 285 | this.grid.push(row); |
|---|
| | 286 | } |
|---|
| | 287 | |
|---|
| | 288 | x = xleft; |
|---|
| | 289 | |
|---|
| | 290 | var colidx = 0; |
|---|
| | 291 | do { |
|---|
| | 292 | |
|---|
| | 293 | var pix = this.map.getLayerPxFromLonLat( |
|---|
| | 294 | new OpenLayers.LonLat(this._Gx2lon(x,tilesAtThisZoom), |
|---|
| | 295 | this._Gy2lat(y,tilesAtThisZoom))); |
|---|
| | 296 | |
|---|
| | 297 | var bottomLeft = this.map.getLonLatFromLayerPx(pix); |
|---|
| | 298 | var topRightPx = pix.clone(); |
|---|
| | 299 | topRightPx.x += this.tileSize.w; |
|---|
| | 300 | topRightPx.y -= this.tileSize.h; |
|---|
| | 301 | var topRight = this.map.getLonLatFromLayerPx(topRightPx); |
|---|
| | 302 | |
|---|
| | 303 | var tileBounds = new OpenLayers.Bounds( |
|---|
| | 304 | bottomLeft.lon, |
|---|
| | 305 | bottomLeft.lat, |
|---|
| | 306 | topRight.lon, |
|---|
| | 307 | topRight.lat); |
|---|
| | 308 | |
|---|
| | 309 | // shift pix from lower left to the upper left |
|---|
| | 310 | //pix.y -= this.tileSize.h; |
|---|
| | 311 | |
|---|
| | 312 | pix.x -= layContainerDivleft; |
|---|
| | 313 | pix.y -= layContainerDivtop; |
|---|
| | 314 | |
|---|
| | 315 | var tile = row[colidx++]; |
|---|
| | 316 | if (!tile) { |
|---|
| | 317 | tile = this.addTile(tileBounds, pix); |
|---|
| | 318 | row.push(tile); |
|---|
| | 319 | } else { |
|---|
| | 320 | tile.moveTo(tileBounds, pix, false); |
|---|
| | 321 | } |
|---|
| | 322 | x++; |
|---|
| | 323 | } while (colidx <= tilecol) |
|---|
| | 324 | y++; |
|---|
| | 325 | } while (rowidx <= tilerow ) |
|---|
| | 326 | } else { |
|---|
| | 327 | var tilelon = resolution * this.tileSize.w; |
|---|
| | 328 | var tilelat = resolution * this.tileSize.h; |
|---|
| | 329 | |
|---|
| | 330 | var offsetlon = bounds.left - extent.left; |
|---|
| | 331 | var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; |
|---|
| | 332 | var tilecolremain = offsetlon/tilelon - tilecol; |
|---|
| | 333 | var tileoffsetx = -tilecolremain * this.tileSize.w; |
|---|
| | 334 | var tileoffsetlon = extent.left + tilecol * tilelon; |
|---|
| | 335 | |
|---|
| | 336 | var offsetlat = bounds.top - (extent.bottom + tilelat); |
|---|
| | 337 | var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer; |
|---|
| | 338 | var tilerowremain = tilerow - offsetlat/tilelat; |
|---|
| | 339 | var tileoffsety = -tilerowremain * this.tileSize.h; |
|---|
| | 340 | var tileoffsetlat = extent.bottom + tilerow * tilelat; |
|---|
| | 341 | |
|---|
| | 342 | tileoffsetx = Math.round(tileoffsetx); // heaven help us |
|---|
| | 343 | tileoffsety = Math.round(tileoffsety); |
|---|
| | 344 | |
|---|
| | 345 | this.origin = new OpenLayers.Pixel(tileoffsetx, tileoffsety); |
|---|
| | 346 | |
|---|
| | 347 | var startX = tileoffsetx; |
|---|
| | 348 | var startLon = tileoffsetlon; |
|---|
| | 349 | |
|---|
| | 350 | var rowidx = 0; |
|---|
| | 351 | |
|---|
| | 352 | do { |
|---|
| | 353 | var row = this.grid[rowidx++]; |
|---|
| | 354 | if (!row) { |
|---|
| | 355 | row = new Array(); |
|---|
| | 356 | this.grid.push(row); |
|---|
| | 357 | } |
|---|
| | 358 | |
|---|
| | 359 | tileoffsetlon = startLon; |
|---|
| | 360 | tileoffsetx = startX; |
|---|
| | 361 | var colidx = 0; |
|---|
| 214 | | do { |
|---|
| 215 | | var tileBounds = new OpenLayers.Bounds(tileoffsetlon, |
|---|
| 216 | | tileoffsetlat, |
|---|
| 217 | | tileoffsetlon + tilelon, |
|---|
| 218 | | tileoffsetlat + tilelat); |
|---|
| 219 | | |
|---|
| 220 | | var x = tileoffsetx; |
|---|
| 221 | | x -= parseInt(this.map.layerContainerDiv.style.left); |
|---|
| 222 | | |
|---|
| 223 | | var y = tileoffsety; |
|---|
| 224 | | y -= parseInt(this.map.layerContainerDiv.style.top); |
|---|
| 225 | | |
|---|
| 226 | | var px = new OpenLayers.Pixel(x, y); |
|---|
| 227 | | var tile = row[colidx++]; |
|---|
| 228 | | if (!tile) { |
|---|
| 229 | | tile = this.addTile(tileBounds, px); |
|---|
| 230 | | row.push(tile); |
|---|
| 231 | | } else { |
|---|
| 232 | | tile.moveTo(tileBounds, px, false); |
|---|
| | 363 | do { |
|---|
| | 364 | var tileBounds = new OpenLayers.Bounds(tileoffsetlon, |
|---|
| | 365 | tileoffsetlat, |
|---|
| | 366 | tileoffsetlon + tilelon, |
|---|
| | 367 | tileoffsetlat + tilelat); |
|---|
| | 368 | |
|---|
| | 369 | var x = tileoffsetx; |
|---|
| | 370 | x -= layContainerDivleft; |
|---|
| | 371 | |
|---|
| | 372 | var y = tileoffsety; |
|---|
| | 373 | y -= layContainerDivtop; |
|---|
| | 374 | |
|---|
| | 375 | var px = new OpenLayers.Pixel(x, y); |
|---|
| | 376 | var tile = row[colidx++]; |
|---|
| | 377 | if (!tile) { |
|---|
| | 378 | tile = this.addTile(tileBounds, px); |
|---|
| | 379 | row.push(tile); |
|---|
| | 380 | } else { |
|---|
| | 381 | tile.moveTo(tileBounds, px, false); |
|---|
| | 382 | } |
|---|
| | 383 | |
|---|
| | 384 | tileoffsetlon += tilelon; |
|---|
| | 385 | tileoffsetx += this.tileSize.w; |
|---|
| | 386 | } while ((tileoffsetlon <= bounds.right + tilelon * this.buffer) |
|---|
| | 387 | || colidx < minCols) |
|---|
| | 388 | |
|---|
| | 389 | tileoffsetlat -= tilelat; |
|---|
| | 390 | tileoffsety += this.tileSize.h; |
|---|
| | 391 | } while((tileoffsetlat >= bounds.bottom - tilelat * this.buffer) |
|---|
| | 392 | || rowidx < minRows) |
|---|
| | 393 | |
|---|
| | 394 | // remove extra rows |
|---|
| | 395 | while (this.grid.length > rowidx) { |
|---|
| | 396 | var row = this.grid.pop(); |
|---|
| | 397 | for (var i=0, l=row.length; i<l; i++) { |
|---|
| | 398 | row[i].destroy(); |
|---|