Changeset 16463 in osm for applications/editors/josm/plugins/slippymap/src
- Timestamp:
- 2009-07-12T20:33:41+02:00 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java
r16462 r16463 20 20 import java.util.Hashtable; 21 21 import java.util.List; 22 import java.util.LinkedList; 22 23 import java.util.TreeSet; 23 24 … … 46 47 * @author LuVar <lubomir.varga@freemap.sk> 47 48 * @author Dave Hansen <dave@sr71.net> 48 * 49 * 49 50 */ 50 51 public class SlippyMapLayer extends Layer implements ImageObserver, … … 65 66 private JPopupMenu tileOptionMenu; 66 67 68 static void debug(String msg) 69 { 70 71 } 67 72 @SuppressWarnings("serial") 68 73 public SlippyMapLayer() { … … 131 136 } 132 137 })); 133 138 134 139 tileOptionMenu.add(new JMenuItem( 135 140 new AbstractAction(tr("Flush Tile Cache")) { … … 177 182 /** 178 183 * Zoom in, go closer to map. 179 * 180 * @return 184 * 185 * @return true, if zoom increasing was successfull, false othervise 181 186 */ 182 187 public boolean zoomIncreaseAllowed() 183 { 184 return currentZoomLevel < SlippyMapPreferences.getMaxZoomLvl(); 185 } 186 public boolean increaseZoomLevel() { 187 if (zoomIncreaseAllowed()) { 188 { 189 boolean zia = currentZoomLevel < SlippyMapPreferences.getMaxZoomLvl(); 190 this.debug("zoomIncreaseAllowed(): " + zia + " " + currentZoomLevel + " vs. " + SlippyMapPreferences.getMaxZoomLvl() ); 191 return zia; 192 } 193 public boolean increaseZoomLevel() 194 { 195 lastImageScale = null; 196 if (zoomIncreaseAllowed()) { 188 197 currentZoomLevel++; 189 Main.debug("increasing zoom level to: " + currentZoomLevel);198 this.debug("increasing zoom level to: " + currentZoomLevel); 190 199 needRedraw = true; 191 200 } else { … … 193 202 "MaxZoomLvl ("+SlippyMapPreferences.getMaxZoomLvl()+") reached."); 194 203 return false; 195 204 } 196 205 return true; 197 206 } … … 199 208 /** 200 209 * Zoom out from map. 201 * 202 * @return 210 * 211 * @return true, if zoom increasing was successfull, false othervise 203 212 */ 204 213 public boolean zoomDecreaseAllowed() 205 214 { 206 215 return currentZoomLevel > SlippyMapPreferences.getMinZoomLvl(); 207 } 208 public boolean decreaseZoomLevel() { 209 int minZoom = SlippyMapPreferences.getMinZoomLvl(); 210 if (zoomDecreaseAllowed()) { 211 Main.debug("decreasing zoom level to: " + currentZoomLevel); 216 } 217 public boolean decreaseZoomLevel() { 218 int minZoom = SlippyMapPreferences.getMinZoomLvl(); 219 lastImageScale = null; 220 if (zoomDecreaseAllowed()) { 221 this.debug("decreasing zoom level to: " + currentZoomLevel); 212 222 currentZoomLevel--; 213 223 needRedraw = true; … … 222 232 // when max zoom lvl is begin saved, this method is called and probably 223 233 // the setting isnt saved yet. 224 234 int maxZoom = SlippyMapPreferences.getMaxZoomLvl(); 225 235 tileStorage = new Hashtable<SlippyMapKey, SlippyMapTile>(); 226 236 checkTileStorage(); … … 254 264 TreeSet<SlippyMapTile> tiles = new TreeSet<SlippyMapTile>(new TileTimeComp()); 255 265 tiles.addAll(tileStorage.values()); 256 i f (tiles.size() < maxNrTiles) {257 Main.debug("total of " + tiles.size() + " loaded tiles, size OK (< " + maxNrTiles + ")");258 return;259 }260 int nr_to_drop = tiles.size() - maxNrTiles;;261 Main.debug("total of " + tiles.size() + " tiles, need to flush " + nr_to_drop + " tiles");266 int nr_to_drop = tiles.size() - maxNrTiles; 267 if (nr_to_drop <= 0) { 268 this.debug("total of " + tiles.size() + " loaded tiles, size OK (< " + maxNrTiles + ")"); 269 return; 270 } 271 this.debug("total of " + tiles.size() + " tiles, need to flush " + nr_to_drop + " tiles"); 262 272 for (SlippyMapTile t : tiles) { 263 273 if (nr_to_drop <= 0) 264 274 break; 265 275 t.dropImage(); 266 276 nr_to_drop--; 267 tileStorage.remove(t.getKey());277 //tileStorage.remove(t.getKey()); 268 278 } 269 279 } 270 280 long lastCheck = 0; 271 281 public void checkTileStorage() { 272 int maxZoom = 30; // SlippyMapPreferences.getMaxZoomLvl();273 282 long now = System.currentTimeMillis(); 274 283 if (now - lastCheck < 1000) 275 284 return; 276 285 lastCheck = now; 277 shrinkTileStorage(150); 278 } 279 280 void loadSingleTile(SlippyMapTile tile) 286 shrinkTileStorage(200); 287 } 288 289 LinkedList<SlippyMapTile> downloadQueue = new LinkedList<SlippyMapTile>(); 290 LinkedList<Image> downloadList = new LinkedList<Image>(); 291 int simultaneousTileDownloads = 5; 292 int maxQueueSize = 50; 293 synchronized void markDone(Image i) 281 294 { 282 tile.loadImage(); 283 this.checkTileStorage(); 295 boolean inList = downloadList.remove(i); 296 if (!inList) { 297 Main.debug("ERROR: downloaded image was not queued"); 298 return; 299 } 300 //System.out.print("currently downloading: " + downloadList.size() + 301 // " queue size: " + downloadQueue.size() +" \r"); 302 if (downloadQueue.size() > 0) 303 loadSingleTile(downloadQueue.getLast()); 304 } 305 synchronized void loadSingleTile(SlippyMapTile tile) 306 { 307 // this moves the tile to the front of the line 308 if (downloadQueue.contains(tile)) 309 downloadQueue.remove(tile); 310 downloadQueue.addLast(tile); 311 // We assume that a queue larger than this is 312 // too big and the downloads at the end of it 313 // too old to be relevant. 314 while (downloadQueue.size() > maxQueueSize) 315 downloadQueue.removeFirst(); 316 if (downloadList.size() > simultaneousTileDownloads) 317 return; 318 //System.out.print("currently downloading: " + downloadList.size() + 319 // " queue size: " + downloadQueue.size() + " \r"); 320 while (!downloadQueue.isEmpty()) { 321 // This is a FIFO queue. The reasoning is 322 // that we want to draw the most recently 323 // requested images now. We may have panned 324 // or zoomed away 325 tile = downloadQueue.removeLast(); 326 Image img = tile.loadImage(); 327 if (imageLoaded(img)) 328 continue; 329 Toolkit.getDefaultToolkit().prepareImage(img, -1, -1, this); 330 downloadList.add(img); 331 break; 332 } 284 333 } 285 334 286 335 synchronized SlippyMapTile getTile(int x, int y, int zoom) { 287 288 289 key =null;290 291 292 293 294 295 296 297 key =null;298 299 300 301 302 303 304 305 306 307 308 309 310 311 336 SlippyMapKey key = new SlippyMapKey(x, y, zoom); 337 if (!key.valid) { 338 return null; 339 } 340 return tileStorage.get(key); 341 } 342 343 synchronized SlippyMapTile putTile(SlippyMapTile tile, int x, int y, int zoom) { 344 SlippyMapKey key = new SlippyMapKey(x, y, zoom); 345 if (!key.valid) { 346 return null; 347 } 348 return tileStorage.put(key, tile); 349 } 350 351 synchronized SlippyMapTile getOrCreateTile(int x, int y, int zoom) { 352 SlippyMapTile tile = getTile(x, y, zoom); 353 if (tile != null) { 354 return tile; 355 } 356 tile = new SlippyMapTile(x, y, zoom); 357 putTile(tile, x, y, zoom); 358 return tile; 359 } 360 312 361 void loadAllTiles() { 313 362 MapView mv = Main.map.mapView; … … 316 365 317 366 TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel); 318 367 319 368 // if there is more than 18 tiles on screen in any direction, do not 320 369 // load all tiles! 321 370 if (ts.tilesSpanned() > (18*18)) { 322 323 371 System.out.println("Not downloading all tiles because there is more than 18 tiles on an axis!"); 372 return; 324 373 } 325 374 326 375 for (Tile t : ts.allTiles()) { 327 328 329 330 376 SlippyMapTile tile = getOrCreateTile(t.x, t.y, currentZoomLevel); 377 if (tile.getImage() == null) { 378 this.loadSingleTile(tile); 379 } 331 380 }//end of for Tile t 332 381 } 333 382 334 /* 335 * Attempt to approximate how much the image is being scaled. For instance, 336 * a 100x100 image being scaled to 50x50 would return 0.25. 337 */ 338 Image lastScaledImage = null; 339 340 double getImageScaling(Image img, Point p0, Point p1) { 341 int realWidth = img.getWidth(this); 342 int realHeight = img.getHeight(this); 343 if (realWidth == -1 || realHeight == -1) { 344 /* 345 * We need a good image against which to work. If 346 * the current one isn't loaded, then try the last one. 347 * Should be good enough. If we've never seen one, then 348 * guess. 349 */ 350 if (lastScaledImage != null) { 351 return getImageScaling(lastScaledImage, p0, p1); 352 } 353 realWidth = 256; 354 realHeight = 256; 355 } else { 356 lastScaledImage = img; 357 } 358 /* 359 * If the zoom scale gets really, really off, these can get into 360 * the millions, so make this a double to prevent integer 361 * overflows. 362 */ 363 double drawWidth = p1.x - p0.x; 364 double drawHeight = p1.x - p0.x; 365 // stem.out.println("drawWidth: " + drawWidth + " drawHeight: " + 366 // drawHeight); 367 368 double drawArea = drawWidth * drawHeight; 383 /* 384 * Attempt to approximate how much the image is being scaled. For instance, 385 * a 100x100 image being scaled to 50x50 would return 0.25. 386 */ 387 Image lastScaledImage = null; 388 389 double getImageScaling(Image img, Point p0, Point p1) { 390 int realWidth = -1; 391 int realHeight = -1; 392 if (img != null) { 393 realWidth = img.getHeight(this); 394 realWidth = img.getWidth(this); 395 } 396 if (realWidth == -1 || realHeight == -1) { 397 /* 398 * We need a good image against which to work. If 399 * the current one isn't loaded, then try the last one. 400 * Should be good enough. If we've never seen one, then 401 * guess. 402 */ 403 if (lastScaledImage != null) { 404 return getImageScaling(lastScaledImage, p0, p1); 405 } 406 realWidth = 256; 407 realHeight = 256; 408 } else { 409 lastScaledImage = img; 410 } 411 /* 412 * If the zoom scale gets really, really off, these can get into 413 * the millions, so make this a double to prevent integer 414 * overflows. 415 */ 416 double drawWidth = p1.x - p0.x; 417 double drawHeight = p1.x - p0.x; 418 // stem.out.println("drawWidth: " + drawWidth + " drawHeight: " + 419 // drawHeight); 420 421 double drawArea = drawWidth * drawHeight; 369 422 double realArea = realWidth * realHeight; 370 423 … … 372 425 } 373 426 374 boolean imageLoaded(Image i) { 375 if (i == null) 376 return false; 377 378 int status = Toolkit.getDefaultToolkit().checkImage(i, -1, -1, this); 379 if ((status & ALLBITS) != 0) 380 return true; 381 return false; 382 } 383 384 Double paintTileImages(Graphics g, TileSet ts, int zoom) { 385 Double imageScale = null; 386 Image img = null; 387 for (Tile t : ts.allTiles()) { 388 SlippyMapTile tile = getTile(t.x, t.y, zoom); 389 if (tile == null) { 390 // Don't trigger tile loading if this isn't 391 // the exact zoom level we're looking for 392 if (zoom != currentZoomLevel) 393 continue; 394 tile = getOrCreateTile(t.x, t.y, zoom); 395 if (SlippyMapPreferences.getAutoloadTiles()) 396 loadSingleTile(tile); 397 } 398 img = tile.getImage(); 399 if (img == null) 400 continue; 401 if ((zoom != currentZoomLevel) && !tile.isDownloaded()) 402 continue; 403 Point p = t.pixelPos(zoom); 404 /* 405 * We need to get a box in which to draw, so advance by one tile in 406 * each direction to find the other corner of the box 407 */ 408 Tile t2 = new Tile(t.x + 1, t.y + 1); 409 Point p2 = t2.pixelPos(zoom); 410 411 g.drawImage(img, p.x, p.y, p2.x - p.x, p2.y - p.y, this); 412 if (img == null) 413 continue; 414 if (imageScale == null && zoom == currentZoomLevel) 415 imageScale = new Double(getImageScaling(img, p, p2)); 416 float fadeBackground = SlippyMapPreferences.getFadeBackground(); 417 if (fadeBackground != 0f) { 418 // dimm by painting opaque rect... 419 g.setColor(new Color(1f, 1f, 1f, fadeBackground)); 420 g.fillRect(p.x, p.y, p2.x - p.x, p2.y - p.y); 421 } 422 }// end of for 423 return imageScale; 424 } 425 426 void paintTileText(TileSet ts, Graphics g, MapView mv, int zoom, Tile t) { 427 int fontHeight = g.getFontMetrics().getHeight(); 428 429 SlippyMapTile tile = getTile(t.x, t.y, zoom); 430 if (tile == null) { 431 return; 432 } 433 if (tile.getImage() == null) { 434 loadSingleTile(tile); 435 } 436 Point p = t.pixelPos(zoom); 437 int texty = p.y + 2 + fontHeight; 438 439 if (SlippyMapPreferences.getDrawDebug()) { 440 g.drawString("x=" + t.x + " y=" + t.y + " z=" + zoom + "", p.x + 2, texty); 441 texty += 1 + fontHeight; 442 if ((t.x % 32 == 0) && (t.y % 32 == 0)) { 443 g.drawString("x=" + t.x / 32 + " y=" + t.y / 32 + " z=7", p.x + 2, texty); 444 texty += 1 + fontHeight; 445 } 446 }// end of if draw debug 447 448 String md = tile.getMetadata(); 449 if (md != null) { 450 g.drawString(md, p.x + 2, texty); 451 texty += 1 + fontHeight; 452 } 453 454 Image tileImage = tile.getImage(); 455 if (tileImage == null) { 456 g.drawString(tr("image not loaded"), p.x + 2, texty); 457 texty += 1 + fontHeight; 458 } 459 if (!imageLoaded(tileImage)) { 460 g.drawString(tr("image loading..."), p.x + 2, texty); 461 needRedraw = true; 462 Main.map.repaint(100); 463 texty += 1 + fontHeight; 464 } 465 466 if (SlippyMapPreferences.getDrawDebug()) { 467 if (ts.leftTile(t)) { 468 if (t.y % 32 == 31) { 469 g.fillRect(0, p.y - 1, mv.getWidth(), 3); 470 } else { 471 g.drawLine(0, p.y, mv.getWidth(), p.y); 472 } 473 } 474 }// /end of if draw debug 475 } 476 477 private class Tile { 478 public int x; 479 public int y; 480 481 Tile(int x, int y) { 482 this.x = x; 483 this.y = y; 484 } 485 486 public Point pixelPos(int zoom) { 487 double lon = tileXToLon(this.x, zoom); 488 LatLon tmpLL = new LatLon(tileYToLat(this.y, zoom), lon); 489 MapView mv = Main.map.mapView; 490 return mv.getPoint(Main.proj.latlon2eastNorth(tmpLL)); 491 } 492 } 493 494 private class TileSet { 495 int z12x0, z12x1, z12y0, z12y1; 496 int zoom; 497 int tileMax; 498 TileSet(LatLon topLeft, LatLon botRight, int zoom) { 499 this.zoom = zoom; 500 z12x0 = lonToTileX(topLeft.lon(), zoom) - 1; 501 z12y0 = latToTileY(topLeft.lat(), zoom) - 1; 502 z12x1 = lonToTileX(botRight.lon(), zoom) + 1; 503 z12y1 = latToTileY(botRight.lat(), zoom) + 1; 504 if (z12x0 > z12x1) { 505 int tmp = z12x0; 506 z12x0 = z12x1; 507 z12x1 = tmp; 508 } 509 if (z12y0 > z12y1) { 510 int tmp = z12y0; 511 z12y0 = z12y1; 512 z12y1 = tmp; 513 } 514 tileMax = (int)Math.pow(2.0, zoom); 515 if (z12x0 < 0) z12x0 = 0; 516 if (z12y0 < 0) z12y0 = 0; 517 if (z12x1 > tileMax) z12x1 = tileMax; 518 if (z12y1 > tileMax) z12y1 = tileMax; 519 } 520 521 double tilesSpanned() { 522 int x_span = z12x1 - z12x0; 523 int y_span = z12y1 - z12y0; 524 return Math.sqrt(1.0 * x_span * y_span); 525 } 526 527 /* 528 * This is pretty silly. Should probably just be implemented as an 529 * iterator to keep from having to instantiate all these tiles. 530 */ 531 List<Tile> allTiles() 427 boolean imageLoaded(Image i) { 428 if (i == null) 429 return false; 430 431 int status = Toolkit.getDefaultToolkit().checkImage(i, -1, -1, this); 432 if ((status & ALLBITS) != 0) 433 return true; 434 return false; 435 } 436 437 Double lastImageScale = null; 438 int paintTileImages(Graphics g, TileSet ts, int zoom) { 439 int paintedTiles = 0; 440 boolean imageScaleRecorded = false; 441 Image img = null; 442 for (Tile t : ts.allTiles()) { 443 SlippyMapTile tile = getTile(t.x, t.y, zoom); 444 if (tile == null) { 445 // Don't trigger tile loading if this isn't 446 // the exact zoom level we're looking for 447 if (zoom != currentZoomLevel) 448 continue; 449 tile = getOrCreateTile(t.x, t.y, zoom); 450 if (SlippyMapPreferences.getAutoloadTiles()) 451 loadSingleTile(tile); 452 } 453 img = tile.getImage(); 454 if (img == null) 455 continue; 456 if ((zoom != currentZoomLevel) && !tile.isDownloaded()) 457 continue; 458 Point p = t.pixelPos(zoom); 459 /* 460 * We need to get a box in which to draw, so advance by one tile in 461 * each direction to find the other corner of the box 462 */ 463 Tile t2 = new Tile(t.x + 1, t.y + 1); 464 Point p2 = t2.pixelPos(zoom); 465 if (imageLoaded(img)) { 466 g.drawImage(img, p.x, p.y, p2.x - p.x, p2.y - p.y, this); 467 paintedTiles++; 468 } 469 if (img == null) 470 continue; 471 if (!imageScaleRecorded && zoom == currentZoomLevel) { 472 lastImageScale = new Double(getImageScaling(img, p, p2)); 473 imageScaleRecorded = true; 474 } 475 float fadeBackground = SlippyMapPreferences.getFadeBackground(); 476 if (fadeBackground != 0f) { 477 // dimm by painting opaque rect... 478 g.setColor(new Color(1f, 1f, 1f, fadeBackground)); 479 g.fillRect(p.x, p.y, p2.x - p.x, p2.y - p.y); 480 } 481 }// end of for 482 return paintedTiles; 483 } 484 485 void paintTileText(TileSet ts, Graphics g, MapView mv, int zoom, Tile t) { 486 int fontHeight = g.getFontMetrics().getHeight(); 487 488 SlippyMapTile tile = getTile(t.x, t.y, zoom); 489 if (tile == null) { 490 return; 491 } 492 if (tile.getImage() == null) { 493 loadSingleTile(tile); 494 } 495 Point p = t.pixelPos(zoom); 496 int texty = p.y + 2 + fontHeight; 497 498 if (SlippyMapPreferences.getDrawDebug()) { 499 g.drawString("x=" + t.x + " y=" + t.y + " z=" + zoom + "", p.x + 2, texty); 500 texty += 1 + fontHeight; 501 if ((t.x % 32 == 0) && (t.y % 32 == 0)) { 502 g.drawString("x=" + t.x / 32 + " y=" + t.y / 32 + " z=7", p.x + 2, texty); 503 texty += 1 + fontHeight; 504 } 505 }// end of if draw debug 506 507 String md = tile.getMetadata(); 508 if (md != null) { 509 g.drawString(md, p.x + 2, texty); 510 texty += 1 + fontHeight; 511 } 512 513 String tileStatus = tile.getStatus(); 514 Image tileImage = tile.getImage(); 515 if (!imageLoaded(tileImage)) { 516 g.drawString(tr("image " + tileStatus), p.x + 2, texty); 517 texty += 1 + fontHeight; 518 } 519 /* 520 We already do repaint when the images load 521 we don't need to poll like this 522 */ 523 if (!imageLoaded(tileImage)) { 524 needRedraw = true; 525 Main.map.repaint(100); 526 } 527 528 if (SlippyMapPreferences.getDrawDebug()) { 529 if (ts.leftTile(t)) { 530 if (t.y % 32 == 31) { 531 g.fillRect(0, p.y - 1, mv.getWidth(), 3); 532 } else { 533 g.drawLine(0, p.y, mv.getWidth(), p.y); 534 } 535 } 536 }// /end of if draw debug 537 } 538 539 private class Tile { 540 public int x; 541 public int y; 542 543 Tile(int x, int y) { 544 this.x = x; 545 this.y = y; 546 } 547 548 public Point pixelPos(int zoom) { 549 double lon = tileXToLon(this.x, zoom); 550 LatLon tmpLL = new LatLon(tileYToLat(this.y, zoom), lon); 551 MapView mv = Main.map.mapView; 552 return mv.getPoint(tmpLL); 553 } 554 } 555 private class TileSet { 556 int z12x0, z12x1, z12y0, z12y1; 557 int zoom; 558 int tileMax = -1; 559 560 TileSet(LatLon topLeft, LatLon botRight, int zoom) { 561 this.zoom = zoom; 562 z12x0 = lonToTileX(topLeft.lon(), zoom) - 1; 563 z12y0 = latToTileY(topLeft.lat(), zoom) - 1; 564 z12x1 = lonToTileX(botRight.lon(), zoom) + 1; 565 z12y1 = latToTileY(botRight.lat(), zoom) + 1; 566 if (z12x0 > z12x1) { 567 int tmp = z12x0; 568 z12x0 = z12x1; 569 z12x1 = tmp; 570 } 571 if (z12y0 > z12y1) { 572 int tmp = z12y0; 573 z12y0 = z12y1; 574 z12y1 = tmp; 575 } 576 tileMax = (int)Math.pow(2.0, zoom); 577 if (z12x0 < 0) z12x0 = 0; 578 if (z12y0 < 0) z12y0 = 0; 579 if (z12x1 > tileMax) z12x1 = tileMax; 580 if (z12y1 > tileMax) z12y1 = tileMax; 581 } 582 double tilesSpanned() { 583 int x_span = z12x1 - z12x0; 584 int y_span = z12y1 - z12y0; 585 return Math.sqrt(1.0 * x_span * y_span); 586 } 587 588 /* 589 * This is pretty silly. Should probably just be implemented as an 590 * iterator to keep from having to instantiate all these tiles. 591 */ 592 List<Tile> allTiles() 532 593 { 533 594 List<Tile> ret = new ArrayList<Tile>(); … … 541 602 } 542 603 543 544 545 546 547 548 549 550 551 552 553 554 555 604 boolean topTile(Tile t) { 605 if (t.y == z12y0 ) 606 return true; 607 return false; 608 } 609 610 boolean leftTile(Tile t) { 611 if (t.x == z12x0 ) 612 return true; 613 return false; 614 } 615 } 616 556 617 /** 557 618 */ 558 619 @Override 559 620 public void paint(Graphics g, MapView mv) { 560 long start = System.currentTimeMillis(); 561 LatLon topLeft = mv.getLatLon(0, 0); 562 LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight()); 563 Graphics oldg = g; 564 565 if (botRight.lon() == 0.0 || botRight.lat() == 0) { 566 // probably still initializing 567 return; 568 } 569 if (lastTopLeft != null && lastBotRight != null && topLeft.equalsEpsilon(lastTopLeft) 570 && botRight.equalsEpsilon(lastBotRight) && bufferImage != null 571 && mv.getWidth() == bufferImage.getWidth(null) && mv.getHeight() == bufferImage.getHeight(null) 572 && !needRedraw) { 573 574 g.drawImage(bufferImage, 0, 0, null); 575 return; 576 } 577 578 needRedraw = false; 579 lastTopLeft = topLeft; 580 lastBotRight = botRight; 581 bufferImage = mv.createImage(mv.getWidth(), mv.getHeight()); 582 g = bufferImage.getGraphics(); 583 584 TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel); 585 int zoom = currentZoomLevel; 586 587 if (zoomDecreaseAllowed() && (ts.tilesSpanned() > 18)) { 588 this.debug("too many tiles, decreasing zoom from " + currentZoomLevel); 621 long start = System.currentTimeMillis(); 622 LatLon topLeft = mv.getLatLon(0, 0); 623 LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight()); 624 Graphics oldg = g; 625 626 if (botRight.lon() == 0.0 || botRight.lat() == 0) { 627 Main.debug("still initializing??"); 628 // probably still initializing 629 return; 630 } 631 if (lastTopLeft != null && lastBotRight != null && topLeft.equalsEpsilon(lastTopLeft) 632 && botRight.equalsEpsilon(lastBotRight) && bufferImage != null 633 && mv.getWidth() == bufferImage.getWidth(null) && mv.getHeight() == bufferImage.getHeight(null) 634 && !needRedraw) { 635 636 this.debug("drawing buffered image"); 637 g.drawImage(bufferImage, 0, 0, null); 638 return; 639 } 640 641 needRedraw = false; 642 lastTopLeft = topLeft; 643 lastBotRight = botRight; 644 bufferImage = mv.createImage(mv.getWidth(), mv.getHeight()); 645 g = bufferImage.getGraphics(); 646 647 TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel); 648 int zoom = currentZoomLevel; 649 650 if (zoomDecreaseAllowed() && (ts.tilesSpanned() > 18)) { 651 this.debug("too many tiles, decreasing zoom from " + currentZoomLevel); 589 652 if (decreaseZoomLevel()) 590 591 592 593 594 595 653 this.paint(oldg, mv); 654 return; 655 } 656 if (zoomIncreaseAllowed() && (ts.tilesSpanned() < 1.0)) { 657 this.debug("doesn't even cover one tile (" + ts.tilesSpanned() 658 + "), increasing zoom from " + currentZoomLevel); 596 659 if (increaseZoomLevel()) 597 660 this.paint(oldg, mv); … … 599 662 } 600 663 601 int fontHeight = g.getFontMetrics().getHeight(); 602 603 g.setColor(Color.DARK_GRAY); 604 605 float fadeBackground = SlippyMapPreferences.getFadeBackground(); 606 607 /* 608 * Go looking for tiles in zoom levels *other* than the current 609 * one. Even if they might look bad, they look better than a 610 * blank tile. 611 */ 612 int otherZooms[] = {2, -2, 1, -1}; 613 for (int zoomOff : otherZooms) { 614 int zoom2 = currentZoomLevel + zoomOff; 615 if ((zoom <= 0) || (zoom > SlippyMapPreferences.getMaxZoomLvl())) { 616 continue; 617 } 618 TileSet ts2 = new TileSet(topLeft, botRight, zoom2); 619 this.paintTileImages(g, ts2, zoom2); 620 } 621 /* 622 * Save this for last since it will get painted over all the others 623 */ 624 Double imageScale = this.paintTileImages(g, ts, currentZoomLevel); 625 g.setColor(Color.red); 626 627 for (Tile t : ts.allTiles()) { 628 // This draws the vertical lines for the entire 629 // column. Only draw them for the top tile in 630 // the column. 631 if (ts.topTile(t)) { 632 Point p = t.pixelPos(currentZoomLevel); 633 if (SlippyMapPreferences.getDrawDebug()) { 634 if (t.x % 32 == 0) { 635 // level 7 tile boundary 636 g.fillRect(p.x - 1, 0, 3, mv.getHeight()); 637 } else { 638 g.drawLine(p.x, 0, p.x, mv.getHeight()); 639 } 640 } 641 } 642 this.paintTileText(ts, g, mv, currentZoomLevel, t); 643 } 644 645 oldg.drawImage(bufferImage, 0, 0, null); 646 647 if (imageScale != null) { 648 // If each source image pixel is being stretched into > 3 649 // drawn pixels, zoom in... getting too pixelated 650 if (imageScale > 3 && zoomIncreaseAllowed()) { 651 if (SlippyMapPreferences.getAutozoom()) { 652 Main.debug("autozoom increase: scale: " + imageScale); 653 increaseZoomLevel(); 654 } 655 this.paint(oldg, mv); 656 } 657 658 // If each source image pixel is being squished into > 0.32 659 // of a drawn pixels, zoom out. 660 if ((imageScale < 0.32) && (imageScale > 0) && zoomDecreaseAllowed()) { 661 if (SlippyMapPreferences.getAutozoom()) { 662 Main.debug("autozoom decrease: scale: " + imageScale); 663 decreaseZoomLevel(); 664 } 665 this.paint(oldg, mv); 666 } 667 } 668 g.setColor(Color.black); 669 g.drawString("currentZoomLevel=" + currentZoomLevel, 120, 120); 670 }// end of paint method 664 if (ts.tilesSpanned() <= 0) { 665 System.out.println("doesn't even cover one tile, increasing zoom from " + currentZoomLevel); 666 if (increaseZoomLevel()) { 667 this.paint(oldg, mv); 668 } 669 return; 670 } 671 672 int fontHeight = g.getFontMetrics().getHeight(); 673 674 g.setColor(Color.DARK_GRAY); 675 676 /* 677 * Go looking for tiles in zoom levels *other* than the current 678 * one. Even if they might look bad, they look better than a 679 * blank tile. 680 */ 681 int otherZooms[] = {-5, -4, -3, 2, -2, 1, -1}; 682 for (int zoomOff : otherZooms) { 683 int zoom2 = currentZoomLevel + zoomOff; 684 if ((zoom2 < SlippyMapPreferences.getMinZoomLvl()) || 685 (zoom2 > SlippyMapPreferences.getMaxZoomLvl())) { 686 continue; 687 } 688 TileSet ts2 = new TileSet(topLeft, botRight, zoom2); 689 int painted = this.paintTileImages(g, ts2, zoom2); 690 //if (painted > 0) 691 // System.out.println("painted " + painted + " tiles from zoom: " + zoom2); 692 } 693 /* 694 * Save this for last since it will get painted over all the others 695 */ 696 this.paintTileImages(g, ts, currentZoomLevel); 697 g.setColor(Color.red); 698 699 for (Tile t : ts.allTiles()) { 700 // This draws the vertical lines for the entire 701 // column. Only draw them for the top tile in 702 // the column. 703 if (ts.topTile(t)) { 704 Point p = t.pixelPos(currentZoomLevel); 705 if (SlippyMapPreferences.getDrawDebug()) { 706 if (t.x % 32 == 0) { 707 // level 7 tile boundary 708 g.fillRect(p.x - 1, 0, 3, mv.getHeight()); 709 } else { 710 g.drawLine(p.x, 0, p.x, mv.getHeight()); 711 } 712 } 713 } 714 this.paintTileText(ts, g, mv, currentZoomLevel, t); 715 } 716 float fadeBackground = SlippyMapPreferences.getFadeBackground(); 717 oldg.drawImage(bufferImage, 0, 0, null); 718 719 if (lastImageScale != null) { 720 // If each source image pixel is being stretched into > 3 721 // drawn pixels, zoom in... getting too pixelated 722 if (lastImageScale > 3 && zoomIncreaseAllowed()) { 723 if (SlippyMapPreferences.getAutozoom()) { 724 this.debug("autozoom increase: scale: " + lastImageScale); 725 increaseZoomLevel(); 726 } 727 this.paint(oldg, mv); 728 // If each source image pixel is being squished into > 0.32 729 // of a drawn pixels, zoom out. 730 } else if ((lastImageScale < 0.45) && (lastImageScale > 0) && zoomDecreaseAllowed()) { 731 if (SlippyMapPreferences.getAutozoom()) { 732 this.debug("autozoom decrease: scale: " + lastImageScale); 733 decreaseZoomLevel(); 734 } 735 this.paint(oldg, mv); 736 } 737 } 738 g.setColor(Color.black); 739 g.drawString("currentZoomLevel=" + currentZoomLevel, 120, 120); 740 }// end of paint method 671 741 672 742 /** … … 675 745 */ 676 746 SlippyMapTile getTileForPixelpos(int px, int py) { 677 MapView mv = Main.map.mapView; 678 Point clicked = new Point(px, py); 679 LatLon topLeft = mv.getLatLon(0, 0); 680 LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight()); 681 TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel); 682 int z = currentZoomLevel; 683 684 Tile clickedTile = null; 747 MapView mv = Main.map.mapView; 748 Point clicked = new Point(px, py); 749 LatLon topLeft = mv.getLatLon(0, 0); 750 LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight()); 751 TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel); 752 int z = currentZoomLevel; 753 754 Tile clickedTile = null; 755 Point p1 = null, p2 = null; 685 756 for (Tile t1 : ts.allTiles()) { 686 757 Tile t2 = new Tile(t1.x+1, t1.y+1); 687 Pointp1 = t1.pixelPos(z);688 Pointp2 = t2.pixelPos(z);758 p1 = t1.pixelPos(z); 759 p2 = t2.pixelPos(z); 689 760 Rectangle r = new Rectangle(p1,new Dimension(p2.x, p2.y)); 690 761 if (!r.contains(clicked)) … … 695 766 if (clickedTile == null) 696 767 return null; 697 System.out.println("clicked on tile: " + clickedTile.x + " " + clickedTile.y); 768 System.out.println("clicked on tile: " + clickedTile.x + " " + clickedTile.y + 769 " scale: " + lastImageScale + " currentZoomLevel: " + currentZoomLevel); 698 770 SlippyMapTile tile = getOrCreateTile(clickedTile.x, clickedTile.y, currentZoomLevel); 699 771 checkTileStorage(); … … 748 820 749 821 private int lonToTileX(double lon, int zoom) { 750 822 return (int) (Math.pow(2.0, zoom - 3) * (lon + 180.0) / 45.0); 751 823 } 752 824 753 825 private double tileYToLat(int y, int zoom) { 754 826 return Math.atan(Math.sinh(Math.PI 755 827 - (Math.PI * y / Math.pow(2.0, zoom - 1)))) 756 828 * 180 / Math.PI; 757 829 } 758 830 759 831 private double tileXToLon(int x, int zoom) { 760 832 return x * 45.0 / Math.pow(2.0, zoom - 3) - 180.0; 761 833 } 762 834 763 835 private SlippyMapTile imgToTile(Image img) { 764 765 766 767 768 769 770 771 772 773 774 775 776 836 // we use the enumeration to avoid ConcurrentUpdateExceptions 837 // with other users of the tileStorage 838 Enumeration<SlippyMapTile> e = tileStorage.elements(); 839 while (e.hasMoreElements()) { 840 SlippyMapTile t = e.nextElement(); 841 if (t.getImageNoTimestamp() != img) { 842 continue; 843 } 844 return t; 845 } 846 return null; 847 } 848 777 849 private static int nr_loaded = 0; 778 850 private static int at_zoom = -1; 779 851 780 852 public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { 781 boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0); 782 SlippyMapTile imageTile = imgToTile(img); 783 if (imageTile == null) { 784 return false; 785 } 786 787 if ((infoflags & ERROR) != 0) { 788 String url; // = "unknown"; 789 url = imageTile.getImageURL().toString(); 790 System.err.println("imageUpdate(" + img + ") error " + url + ")"); 791 } 792 if (((infoflags & ALLBITS) != 0)) { 793 int z = imageTile.getZoom(); 794 if (z == at_zoom) { 795 nr_loaded++; 796 } else { 797 System.out.println("downloaded " + nr_loaded + " at: " + at_zoom + " now going to " + z); 798 nr_loaded = 0; 799 at_zoom = z; 800 } 801 imageTile.markAsDownloaded(); 802 } 803 if ((infoflags & SOMEBITS) != 0) { 804 // if (y%100 == 0) 805 //System.out.println("imageUpdate("+img+") SOMEBITS ("+x+","+y+")"); 806 } 807 // Repaint immediately if we are done, otherwise batch up 808 // repaint requests every 100 milliseconds 809 needRedraw = true; 810 Main.map.repaint(done ? 0 : 100); 811 return !done; 812 } 853 boolean error = (infoflags & ERROR) != 0; 854 boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0); 855 boolean success = ((infoflags & (ALLBITS)) != 0); 856 SlippyMapTile imageTile = imgToTile(img); 857 if (success || error) { 858 this.debug("tile done loading: " + imageTile); 859 markDone(img); 860 } 861 if (imageTile == null) { 862 System.err.println("no tile for image"); 863 return false; 864 } 865 866 if ((infoflags & ERROR) != 0) { 867 String url; // = "unknown"; 868 url = imageTile.getImageURL().toString(); 869 System.err.println("imageUpdate(" + img + ") error " + url + ")"); 870 } 871 if (((infoflags & ALLBITS) != 0)) { 872 int z = imageTile.getZoom(); 873 if (z == at_zoom) { 874 nr_loaded++; 875 } else { 876 //System.out.println("downloaded " + nr_loaded + " at: " + at_zoom + " now going to " + z + 877 // " class: " + img.getClass()); 878 nr_loaded = 0; 879 at_zoom = z; 880 } 881 } 882 if ((infoflags & SOMEBITS) != 0) { 883 // if (y%100 == 0) 884 //System.out.println("imageUpdate("+img+") SOMEBITS ("+x+","+y+")"); 885 } 886 // Repaint immediately if we are done, otherwise batch up 887 // repaint requests every 100 milliseconds 888 needRedraw = true; 889 Main.map.repaint(done ? 0 : 100); 890 return !done; 891 } 813 892 814 893 /*
Note:
See TracChangeset
for help on using the changeset viewer.