I'm seeing some regressions in the imagery portion of JOSM.  It does not
seem to be drawing tiles from the non-current zoom level.  It used to do
this.  To reproduce:

1. Load an imagery layer
2. Turn off autozoom
3. Zoom out.  As soon as the autozoom changes, you get a blank screen
   instead of the tiles that were loaded at other zoom levels.

The basic problem here is that paintTileImages() is assuming that
tileSet.allTiles() will actually return all tiles. :)  In practice it
only returns tiles which already exist in the cache.  This was OK before
since it was inefficient and we just looped around all the levels.

But, now, it tries to be really smart with the missedTiles list.
However, since tileSet.allTiles() only returns _cached_ files, it skips
over quite a few tiles.  To fix this, I've decided to have
paintTileImages() unconditionally instantiate all tiles in a tileSet.
This is slow with large sets so I also included an optimization to skip
this instantiation on tile sets with no loaded tiles.

Thoughts?  A patch to fix this is attached.

Note this includes some other tweaks that I posted to the josm-dev@
list.

-- Dave
Index: gui/layer/TMSLayer.java
===================================================================
--- gui/layer/TMSLayer.java	(revision 4323)
+++ gui/layer/TMSLayer.java	(working copy)
@@ -105,7 +105,7 @@
         PROP_TILECACHE_DIR = new StringProperty(PREFERENCE_PREFIX + ".tilecache_path", defPath);
     }
 
-    /*boolean debug = false;*/
+    /*boolean debug = true;*/
 
     protected MemoryTileCache tileCache;
     protected TileSource tileSource;
@@ -310,7 +310,11 @@
     private int getBestZoom() {
         double factor = getScaleFactor(1);
         double result = Math.log(factor)/Math.log(2)/2+1;
-        int intResult = (int)Math.round(result);
+        // In general, smaller zoom levels are more readable.  We prefer big,
+        // block, pixelated (but readable) map text to small, smeared,
+        // unreadable underzoomed text.  So, use .floor() instead of rounding
+        // to skew things a bit toward the lower zooms.
+        int intResult = (int)Math.floor(result);
         if (intResult > getMaxZoomLvl())
             return getMaxZoomLvl();
         if (intResult < getMinZoomLvl())
@@ -821,7 +825,12 @@
             borderRect = tileToRect(border);
         }
         List<Tile> missedTiles = new LinkedList<Tile>();
-        for (Tile tile : ts.allTiles()) {
+        // The callers of this code *require* that we return any tiles
+        // that we do not draw in missedTiles.  ts.allTiles() by default
+        // will only return already-existing tiles.  However, we need
+        // to return *all* tiles to the callers, so force creation here.
+        boolean forceTileCreation = true;
+        for (Tile tile : ts.allTiles(forceTileCreation)) {
             Image img = getLoadedTileImage(tile);
             if (img == null || tile.hasError()) {
                 /*if (debug) {
@@ -1027,6 +1036,15 @@
             }
             return ret;
         }
+        private List<Tile> allLoadedTiles()
+        {
+            List<Tile> ret = new ArrayList<Tile>();
+            for (Tile t : this.allTiles()) {
+                if (t.isLoaded())
+                    ret.add(t);
+            }
+            return ret;
+        }
 
         void loadAllTiles(boolean force)
         {
@@ -1129,7 +1147,7 @@
         int zoom = currentZoomLevel;
         if (autoZoom) {
             double pixelScaling = getScaleFactor(zoom);
-            if (pixelScaling > 3 || pixelScaling < 0.45) {
+            if (pixelScaling > 3 || pixelScaling < 0.7) {
                 zoom = getBestZoom();
             }
         }
@@ -1191,13 +1209,11 @@
         List<Tile> missedTiles = this.paintTileImages(g, ts, displayZoomLevel, null);
         int otherZooms[] = { -1, 1, -2, 2, -3, -4, -5};
         for (int zoomOffset : otherZooms) {
-            if (!autoZoom) {
+            if (!autoZoom)
                 break;
-            }
-            if (!autoLoad) {
-                break;
-            }
             int newzoom = displayZoomLevel + zoomOffset;
+            if (newzoom < MIN_ZOOM)
+                continue;
             if (missedTiles.size() <= 0) {
                 break;
             }
@@ -1212,6 +1228,12 @@
                 LatLon topLeft2  = tileLatLon(missed);
                 LatLon botRight2 = tileLatLon(t2);
                 TileSet ts2 = new TileSet(topLeft2, botRight2, newzoom);
+                // Instantiating large TileSets is expensive.  If there
+                // are no loaded tiles, don't bother even trying.
+                if (ts2.allLoadedTiles().size() == 0) {
+                    newlyMissedTiles.add(missed);
+                    continue;
+                }
                 if (ts2.tooLarge()) {
                     continue;
                 }
_______________________________________________
josm-dev mailing list
josm-dev@openstreetmap.org
http://lists.openstreetmap.org/listinfo/josm-dev

Reply via email to