Changeset 3774 in josm for trunk/src/org/openstreetmap/josm


Ignore:
Timestamp:
2011-01-06T16:06:50+01:00 (13 years ago)
Author:
Upliner
Message:

Auto-detection of Bing zoomlevel, fixes #5741

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java

    r3773 r3774  
    2222import java.net.URISyntaxException;
    2323import java.util.ArrayList;
     24import java.util.Collections;
    2425import java.util.HashMap;
    2526import java.util.HashSet;
     
    111112        Main.map.repaint(100);
    112113        tileRequestsOutstanding.remove(tile);
    113         if (success) {
    114             displayZoomLevel = tile.getZoom();
    115         }
    116114        if (debug) {
    117115            out("tileLoadingFinished() tile: " + tile + " success: " + success);
     
    133131
    134132    /**
    135      * Actual zoom lvl. Initial zoom lvl is set to
     133     * Zoomlevel at which tiles is currently downloaded.
     134     * Initial zoom lvl is set to bestZoom
    136135     */
    137136    public int currentZoomLevel;
     137    /**
     138     * Optimal TMS Zoomlevel for current mapview.
     139     * Works correctly only for Mercatator, so currently used only for initial zoom.
     140     */
    138141    public int bestZoomLevel;
     142    /**
     143     * Painting zoomlevel. Set to the currentZoomLevel when first tile at this zoomlevel is loaded.
     144     */
    139145    public int displayZoomLevel = 0;
    140146
    141147    private Tile clickedTile;
    142148    private boolean needRedraw;
     149    private boolean overZoomed;
     150    private boolean overZoomedFlag;
    143151    private JPopupMenu tileOptionMenu;
    144152    JCheckBoxMenuItem autoZoomPopup;
     
    487495    }
    488496
     497    boolean isOverZoomed() {
     498        return overZoomed || overZoomedFlag;
     499    }
     500
    489501    /**
    490502     * Zoom in, go closer to map.
     
    494506    public boolean zoomIncreaseAllowed()
    495507    {
    496         boolean zia = currentZoomLevel < this.getMaxZoomLvl();
     508        boolean zia = currentZoomLevel < this.getMaxZoomLvl() && !isOverZoomed();
    497509        if (debug) {
    498510            out("zoomIncreaseAllowed(): " + zia + " " + currentZoomLevel + " vs. " + this.getMaxZoomLvl() );
     
    719731        debug = true;
    720732        for (int zoomOff : otherZooms) {
    721             int zoom = currentZoomLevel + zoomOff;
     733            int zoom = displayZoomLevel + zoomOff;
    722734            if ((zoom < this.getMinZoomLvl()) ||
    723735                    (zoom > this.getMaxZoomLvl())) {
     
    821833    // The "border" tile tells us the boundaries of where we may
    822834    // draw.  It will not be from the zoom level that is being
    823     // drawn currently.  If drawing the currentZoomLevel,
     835    // drawn currently.  If drawing the displayZoomLevel,
    824836    // border is null and we draw the entire tile set.
    825837    List<Tile> paintTileImages(Graphics g, TileSet ts, int zoom, Tile border) {
     838        if (zoom <= 0) return Collections.emptyList();
    826839        Rectangle borderRect = null;
    827840        if (border != null) {
     
    844857            }
    845858            drawImageInside(g, img, sourceRect, borderRect);
    846             if (!imageScaleRecorded && zoom == currentZoomLevel) {
     859            if (!imageScaleRecorded && zoom == displayZoomLevel) {
    847860                lastImageScale = new Double(getImageScaling(img, sourceRect));
    848861                imageScaleRecorded = true;
     
    897910        }
    898911
    899         if (tile.hasError() && (displayZoomLevel == 0 || !"no-tile".equals(tile.getValue("tile-info")))) {
     912        if (tile.hasError()) {
    900913            myDrawString(g, tr("Error") + ": " + tr(tile.getErrorMessage()), p.x + 2, texty);
    901914            texty += 1 + fontHeight;
     
    944957    }
    945958    private class TileSet {
    946         int z12x0, z12x1, z12y0, z12y1;
     959        int x0, x1, y0, y1;
    947960        int zoom;
    948961        int tileMax = -1;
     
    961974            this.zoom = zoom;
    962975
    963             z12x0 = lonToTileX(topLeft.lon(),  zoom);
    964             z12y0 = latToTileY(topLeft.lat(),  zoom);
    965             z12x1 = lonToTileX(botRight.lon(), zoom);
    966             z12y1 = latToTileY(botRight.lat(), zoom);
    967             if (z12x0 > z12x1) {
    968                 int tmp = z12x0;
    969                 z12x0 = z12x1;
    970                 z12x1 = tmp;
    971             }
    972             if (z12y0 > z12y1) {
    973                 int tmp = z12y0;
    974                 z12y0 = z12y1;
    975                 z12y1 = tmp;
     976            x0 = lonToTileX(topLeft.lon(),  zoom);
     977            y0 = latToTileY(topLeft.lat(),  zoom);
     978            x1 = lonToTileX(botRight.lon(), zoom);
     979            y1 = latToTileY(botRight.lat(), zoom);
     980            if (x0 > x1) {
     981                int tmp = x0;
     982                x0 = x1;
     983                x1 = tmp;
     984            }
     985            if (y0 > y1) {
     986                int tmp = y0;
     987                y0 = y1;
     988                y1 = tmp;
    976989            }
    977990            tileMax = (int)Math.pow(2.0, zoom);
    978             if (z12x0 < 0) {
    979                 z12x0 = 0;
    980             }
    981             if (z12y0 < 0) {
    982                 z12y0 = 0;
    983             }
    984             if (z12x1 > tileMax) {
    985                 z12x1 = tileMax;
    986             }
    987             if (z12y1 > tileMax) {
    988                 z12y1 = tileMax;
     991            if (x0 < 0) {
     992                x0 = 0;
     993            }
     994            if (y0 < 0) {
     995                y0 = 0;
     996            }
     997            if (x1 > tileMax) {
     998                x1 = tileMax;
     999            }
     1000            if (y1 > tileMax) {
     1001                y1 = tileMax;
    9891002            }
    9901003        }
     
    10031016
    10041017        double size() {
    1005             double x_span = z12x1 - z12x0 + 1.0;
    1006             double y_span = z12y1 - z12y0 + 1.0;
     1018            double x_span = x1 - x0 + 1.0;
     1019            double y_span = y1 - y0 + 1.0;
    10071020            return x_span * y_span;
    10081021        }
     
    10231036            if (this.insane())
    10241037                return ret;
    1025             for (int x = z12x0; x <= z12x1; x++) {
    1026                 for (int y = z12y0; y <= z12y1; y++) {
     1038            for (int x = x0; x <= x1; x++) {
     1039                for (int y = y0; y <= y1; y++) {
    10271040                    Tile t;
    10281041                    if (create) {
     
    10381051            return ret;
    10391052        }
     1053
     1054        int totalTiles() {
     1055            return (y1 - y0 + 1) * (x1 - x0 + 1);
     1056        }
     1057
    10401058        void loadAllTiles(boolean force)
    10411059        {
     
    10891107                if (decreaseZoomLevel()) {
    10901108                    this.paint(g, mv, bounds);
    1091                 }
    1092                 return;
    1093             }
    1094             if (zoomIncreaseAllowed() && ts.tooSmall()) {
    1095                 if (debug) {
    1096                     out("too zoomed in, (" + ts.tilesSpanned()
    1097                             + "), increasing zoom from " + currentZoomLevel);
    1098                 }
    1099                 // This is a hack.  ts.tooSmall() is proabably a bad thing, and this works
    1100                 // around it.  If we have a very small window, the tileSet may be well
    1101                 // less than 1 real tile wide, but that's expected.  But, this sees the
    1102                 // tile set as too small and zooms in.  The code below that checks for
    1103                 // pixel stretching disagrees and tries to zoom out.  Both calls recurse,
    1104                 // hillarity ensues, and the stack overflows.
    1105                 //
    1106                 // This really needs to get fixed properly.  We probably shouldn't even
    1107                 // have the tooSmall() check on tileSets.  But, this also helps the zoom
    1108                 // converge to the correct place much faster.
    1109                 boolean tmp = az_disable;
    1110                 az_disable = true;
    1111                 if (increaseZoomLevel()) {
     1109                    return;
     1110                }
     1111            }
     1112
     1113            // Auto-detection of Bing zoomlevel
     1114            if (tileSource instanceof BingAerialTileSource) {
     1115                List<Tile> allTiles = ts.allTiles();
     1116                boolean hasVisibleTiles = false;
     1117                boolean hasOverzoomedTiles = false;
     1118                boolean hasLoadingTiles = allTiles.size() < ts.totalTiles();
     1119                for (Tile t : allTiles) {
     1120                    if (t.isLoaded()) {
     1121                        if (!t.hasError()) {
     1122                            hasVisibleTiles = true;
     1123                        }
     1124                        if ("no-tile".equals(t.getValue("tile-info"))) {
     1125                            hasOverzoomedTiles = true;
     1126                        }
     1127                    } else {
     1128                        hasLoadingTiles = true;
     1129                    }
     1130                }
     1131                if (!hasLoadingTiles) {
     1132                    overZoomed = false;
     1133                }
     1134                if (!hasVisibleTiles && hasOverzoomedTiles) {
     1135                    overZoomed = true;
     1136                    if (displayZoomLevel == 0 || !hasLoadingTiles) {
     1137                        boolean tmp = overZoomedFlag;
     1138                        overZoomedFlag = true;
     1139                        if (decreaseZoomLevel()) {
     1140                            this.paint(g, mv, bounds);
     1141                            overZoomedFlag = tmp;
     1142                            return;
     1143                        }
     1144                        overZoomedFlag = tmp;
     1145                    }
     1146                } else if (hasVisibleTiles) {
     1147                    displayZoomLevel = currentZoomLevel;
     1148                }
     1149            } else {
     1150                displayZoomLevel = currentZoomLevel;
     1151                if (zoomIncreaseAllowed() && ts.tooSmall()) {
     1152                    if (debug) {
     1153                        out("too zoomed in, (" + ts.tilesSpanned()
     1154                                + "), increasing zoom from " + currentZoomLevel);
     1155                    }
     1156                    // This is a hack.  ts.tooSmall() is proabably a bad thing, and this works
     1157                    // around it.  If we have a very small window, the tileSet may be well
     1158                    // less than 1 real tile wide, but that's expected.  But, this sees the
     1159                    // tile set as too small and zooms in.  The code below that checks for
     1160                    // pixel stretching disagrees and tries to zoom out.  Both calls recurse,
     1161                    // hillarity ensues, and the stack overflows.
     1162                    //
     1163                    // This really needs to get fixed properly.  We probably shouldn't even
     1164                    // have the tooSmall() check on tileSets.  But, this also helps the zoom
     1165                    // converge to the correct place much faster.
     1166                    boolean tmp = az_disable;
     1167                    az_disable = true;
     1168                    increaseZoomLevel();
    11121169                    this.paint(g, mv, bounds);
    1113                 }
    1114                 az_disable = tmp;
    1115                 return;
    1116             }
    1117         }
    1118 
    1119         // Too many tiles... refuse to draw
     1170                    az_disable = tmp;
     1171                    return;
     1172                }
     1173            }
     1174        } else {
     1175            displayZoomLevel = currentZoomLevel;
     1176        }
     1177
     1178        // Too many tiles... refuse to download
    11201179        if (!ts.tooLarge()) {
    11211180            //out("size: " + ts.size() + " spanned: " + ts.tilesSpanned());
     
    11231182        }
    11241183
     1184        if (displayZoomLevel != zoom) {
     1185            ts = new TileSet(topLeft, botRight, displayZoomLevel);
     1186        }
     1187
    11251188        g.setColor(Color.DARK_GRAY);
    11261189
    1127         List<Tile> missedTiles = this.paintTileImages(g, ts, currentZoomLevel, null);
     1190        List<Tile> missedTiles = this.paintTileImages(g, ts, displayZoomLevel, null);
    11281191        int otherZooms[] = { -1, 1, -2, 2, -3, -4, -5};
    11291192        for (int zoomOffset : otherZooms) {
     
    11341197                break;
    11351198            }
    1136             int newzoom = currentZoomLevel + zoomOffset;
     1199            int newzoom = displayZoomLevel + zoomOffset;
    11371200            if (missedTiles.size() <= 0) {
    11381201                break;
     
    11601223        // its tiles
    11611224        for (Tile t : ts.allTiles()) {
    1162             this.paintTileText(ts, t, g, mv, currentZoomLevel, t);
     1225            this.paintTileText(ts, t, g, mv, displayZoomLevel, t);
    11631226        }
    11641227
     
    12251288        //g.drawString("currentZoomLevel=" + currentZoomLevel, 120, 120);
    12261289        g.setColor(Color.lightGray);
    1227         if (ts.insane()) {
    1228             myDrawString(g, "zoom in to load any tiles", 120, 120);
    1229         } else if (ts.tooLarge()) {
    1230             myDrawString(g, "zoom in to load more tiles", 120, 120);
    1231         } else if (ts.tooSmall()) {
    1232             myDrawString(g, "increase zoom level to see more detail", 120, 120);
     1290        if (!autoZoom) {
     1291            if (ts.insane()) {
     1292                myDrawString(g, tr("zoom in to load any tiles"), 120, 120);
     1293            } else if (ts.tooLarge()) {
     1294                myDrawString(g, tr("zoom in to load more tiles"), 120, 120);
     1295            } else if (ts.tooSmall()) {
     1296                myDrawString(g, tr("increase zoom level to see more detail"), 120, 120);
     1297            }
     1298        }
     1299        if (isOverZoomed()) {
     1300            myDrawString(g, tr("No tiles at this zoom level"), 120, 120);
     1301        }
     1302        if (debug) {
     1303            myDrawString(g, tr("Current zoom: {0}", currentZoomLevel), 50, 140);
     1304            myDrawString(g, tr("Display zoom: {0}", displayZoomLevel), 50, 155);
    12331305        }
    12341306    }// end of paint method
Note: See TracChangeset for help on using the changeset viewer.