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


Ignore:
Timestamp:
2011-01-12T19:13:24+01:00 (14 years ago)
Author:
Upliner
Message:

TMSLayer: get rid of "lastImageScale" hack and fix stack overflow caused by it

File:
1 edited

Legend:

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

    r3778 r3785  
    7272 * @author LuVar <lubomir.varga@freemap.sk>
    7373 * @author Dave Hansen <dave@sr71.net>
     74 * @author Upliner <upliner@gmail.com>
    7475 *
    7576 */
     
    148149     */
    149150    public int currentZoomLevel;
    150     /**
    151      * Optimal TMS Zoomlevel for current mapview.
    152      * Works correctly only for Mercatator, so currently used only for initial zoom.
    153      */
    154     public int bestZoomLevel;
    155     /**
    156      * Painting zoomlevel. Set to the currentZoomLevel when first tile at this zoomlevel is loaded.
    157      */
    158     public int displayZoomLevel = 0;
    159151
    160152    private Tile clickedTile;
    161153    private boolean needRedraw;
    162     private boolean overZoomed;
    163     private boolean overZoomedFlag;
    164154    private JPopupMenu tileOptionMenu;
    165155    JCheckBoxMenuItem autoZoomPopup;
     
    266256        }
    267257
    268         updateBestZoom();
    269         currentZoomLevel = bestZoomLevel;
     258        currentZoomLevel = getBestZoom();
    270259
    271260        clearTileCache();
     
    289278    }
    290279
    291     private double getPPDeg() {
     280    /**
     281     * Returns average number of screen pixels per tile pixel for current mapview
     282     */
     283    private double getScaleFactor(int zoom) {
     284        if (Main.map == null || Main.map.mapView == null) return 1;
    292285        MapView mv = Main.map.mapView;
    293         return mv.getWidth()/(mv.getLatLon(mv.getWidth(), mv.getHeight()/2).lon()-mv.getLatLon(0, mv.getHeight()/2).lon());
     286        LatLon topLeft = mv.getLatLon(0, 0);
     287        LatLon botRight = mv.getLatLon(mv.getWidth(), mv.getHeight());
     288        double x1 = lonToTileX(topLeft.lon(), zoom);
     289        double y1 = latToTileY(topLeft.lat(), zoom);
     290        double x2 = lonToTileX(botRight.lon(), zoom);
     291        double y2 = latToTileY(botRight.lat(), zoom);
     292
     293        int screenPixels = mv.getWidth()*mv.getHeight();
     294        double tilePixels = Math.abs((y2-y1)*(x2-x1)*tileSource.getTileSize()*tileSource.getTileSize());
     295        if (screenPixels == 0 || tilePixels == 0) return 1;
     296        return screenPixels/tilePixels;
    294297    }
    295298
    296299    private int getBestZoom() {
    297         if (Main.map == null || Main.map.mapView == null) return 3;
    298         double ret = Math.log(getPPDeg()*360/tileSource.getTileSize())/Math.log(2);
    299         return (int)Math.round(ret);
    300     }
    301 
    302     private void updateBestZoom() {
    303         bestZoomLevel = getBestZoom();
    304         if (bestZoomLevel > getMaxZoomLvl()) {
    305             bestZoomLevel = getMaxZoomLvl();
    306         }
    307         if (bestZoomLevel < getMinZoomLvl()) {
    308             bestZoomLevel = getMinZoomLvl();
    309         }
     300        double factor = getScaleFactor(1);
     301        double result = Math.log(factor)/Math.log(2)/2+1;
     302        int intResult = (int)Math.round(result);
     303        if (intResult > getMaxZoomLvl())
     304            return getMaxZoomLvl();
     305        if (intResult < getMinZoomLvl())
     306            return getMinZoomLvl();
     307        return intResult;
    310308    }
    311309
     
    413411                    @Override
    414412                    public void actionPerformed(ActionEvent ae) {
    415                         if (lastImageScale == null) {
    416                             out("please wait for a tile to be loaded before snapping");
    417                             return;
    418                         }
    419                         double new_factor = Math.sqrt(lastImageScale);
    420                         if (debug) {
    421                             out("tile snap: scale was: " + lastImageScale + ", new factor: " + new_factor);
    422                         }
     413                        double new_factor = Math.sqrt(getScaleFactor(currentZoomLevel));
    423414                        Main.map.mapView.zoomToFactor(new_factor);
    424415                        redraw();
     
    517508    }
    518509
    519     boolean isOverZoomed() {
    520         return overZoomed || overZoomedFlag;
    521     }
    522 
    523510    /**
    524511     * Zoom in, go closer to map.
     
    528515    public boolean zoomIncreaseAllowed()
    529516    {
    530         boolean zia = currentZoomLevel < this.getMaxZoomLvl() && !isOverZoomed();
     517        boolean zia = currentZoomLevel < this.getMaxZoomLvl();
    531518        if (debug) {
    532519            out("zoomIncreaseAllowed(): " + zia + " " + currentZoomLevel + " vs. " + this.getMaxZoomLvl() );
     
    536523    public boolean increaseZoomLevel()
    537524    {
    538         lastImageScale = null;
    539525        if (zoomIncreaseAllowed()) {
    540526            currentZoomLevel++;
     
    553539    public boolean setZoomLevel(int zoom)
    554540    {
     541        if (zoom == currentZoomLevel) return true;
    555542        if (zoom > this.getMaxZoomLvl()) return false;
    556543        if (zoom < this.getMinZoomLvl()) return false;
    557544        currentZoomLevel = zoom;
    558         lastImageScale = null;
    559545        zoomChanged();
    560546        return true;
     
    572558    public boolean decreaseZoomLevel() {
    573559        int minZoom = this.getMinZoomLvl();
    574         lastImageScale = null;
    575560        if (zoomDecreaseAllowed()) {
    576561            if (debug) {
     
    689674    }
    690675
    691     double getImageScaling(Image img, Rectangle r) {
    692         int realWidth = -1;
    693         int realHeight = -1;
    694         if (img != null) {
    695             realWidth = img.getHeight(this);
    696             realWidth = img.getWidth(this);
    697         }
    698         if (realWidth == -1 || realHeight == -1) {
    699             /*
    700              * We need a good image against which to work. If
    701              * the current one isn't loaded, then try the last one.
    702              * Should be good enough. If we've never seen one, then
    703              * guess.
    704              */
    705             if (lastScaledImage != null)
    706                 return getImageScaling(lastScaledImage, r);
    707             realWidth = 256;
    708             realHeight = 256;
    709         } else {
    710             lastScaledImage = img;
    711         }
    712         /*
    713          * If the zoom scale gets really, really off, these can get into
    714          * the millions, so make this a double to prevent integer
    715          * overflows.
    716          */
    717         double drawWidth = r.width;
    718         double drawHeight = r.height;
    719         // stem.out.println("drawWidth: " + drawWidth + " drawHeight: " +
    720         // drawHeight);
    721 
    722         double drawArea = drawWidth * drawHeight;
    723         double realArea = realWidth * realHeight;
    724 
    725         return drawArea / realArea;
    726     }
    727 
    728676    LatLon tileLatLon(Tile t)
    729677    {
     
    733681    }
    734682
    735     int paintFromOtherZooms(Graphics g, Tile topLeftTile, Tile botRightTile)
    736     {
    737         LatLon topLeft  = tileLatLon(topLeftTile);
    738         LatLon botRight = tileLatLon(botRightTile);
    739 
    740 
    741         /*
    742          * Go looking for tiles in zoom levels *other* than the current
    743          * one. Even if they might look bad, they look better than a
    744          * blank tile.
    745          *
    746          * Make darn sure that the tilesCache can either hold all of
    747          * these "fake" tiles or that they don't get inserted in it to
    748          * begin with.
    749          */
    750         //int otherZooms[] = {-5, -4, -3, 2, -2, 1, -1};
    751         int otherZooms[] = { -1, 1, -2, 2, -3, -4, -5};
    752         int painted = 0;
    753         debug = true;
    754         for (int zoomOff : otherZooms) {
    755             int zoom = displayZoomLevel + zoomOff;
    756             if ((zoom < this.getMinZoomLvl()) ||
    757                     (zoom > this.getMaxZoomLvl())) {
    758                 continue;
    759             }
    760             TileSet ts = new TileSet(topLeft, botRight, zoom);
    761             int zoom_painted = 0;
    762             this.paintTileImages(g, ts, zoom, null);
    763             if (debug && zoom_painted > 0) {
    764                 out("painted " + zoom_painted + "/"+ ts.size() +
    765                         " tiles from zoom("+zoomOff+"): " + zoom);
    766             }
    767             painted += zoom_painted;
    768             if (zoom_painted >= ts.size()) {
    769                 if (debug) {
    770                     out("broke after drawing " + zoom_painted + "/"+ ts.size() + " at zoomOff: " + zoomOff);
    771                 }
    772                 break;
    773             }
    774         }
    775         debug = false;
    776         return painted;
    777     }
    778683    Rectangle tileToRect(Tile t1)
    779684    {
     
    847752        }
    848753    }
    849     Double lastImageScale = null;
    850754    // This function is called for several zoom levels, not just
    851755    // the current one.  It should not trigger any tiles to be
     
    864768        }
    865769        List<Tile> missedTiles = new LinkedList<Tile>();
    866         boolean imageScaleRecorded = false;
    867770        for (Tile tile : ts.allTiles()) {
    868771            Image img = getLoadedTileImage(tile);
     
    879782            }
    880783            drawImageInside(g, img, sourceRect, borderRect);
    881             if (!imageScaleRecorded && zoom == displayZoomLevel) {
    882                 lastImageScale = new Double(getImageScaling(img, sourceRect));
    883                 imageScaleRecorded = true;
    884             }
    885784        }// end of for
    886785        return missedTiles;
     
    978877        return new Coordinate(ll.lat(),ll.lon());
    979878    }
     879    private final TileSet nullTileSet = new TileSet((LatLon)null, (LatLon)null, 0);
    980880    private class TileSet {
    981881        int x0, x1, y0, y1;
     
    995895        TileSet(LatLon topLeft, LatLon botRight, int zoom) {
    996896            this.zoom = zoom;
    997 
    998             x0 = lonToTileX(topLeft.lon(),  zoom);
    999             y0 = latToTileY(topLeft.lat(),  zoom);
    1000             x1 = lonToTileX(botRight.lon(), zoom);
    1001             y1 = latToTileY(botRight.lat(), zoom);
     897            if (zoom == 0)
     898                return;
     899
     900            x0 = (int)lonToTileX(topLeft.lon(),  zoom);
     901            y0 = (int)latToTileY(topLeft.lat(),  zoom);
     902            x1 = (int)lonToTileX(botRight.lon(), zoom);
     903            y1 = (int)latToTileY(botRight.lat(), zoom);
    1002904            if (x0 > x1) {
    1003905                int tmp = x0;
     
    1037939        }
    1038940
    1039         double size() {
    1040             double x_span = x1 - x0 + 1.0;
    1041             double y_span = y1 - y0 + 1.0;
     941        int size() {
     942            int x_span = x1 - x0 + 1;
     943            int y_span = y1 - y0 + 1;
    1042944            return x_span * y_span;
    1043945        }
     
    1053955        private List<Tile> allTiles(boolean create)
    1054956        {
     957            // Tileset is either empty or too large
     958            if (zoom == 0 || this.insane())
     959                return Collections.emptyList();
    1055960            List<Tile> ret = new ArrayList<Tile>();
    1056             // Don't even try to iterate over the set.
    1057             // Someone created a crazy number of them
    1058             if (this.insane())
    1059                 return ret;
    1060961            for (int x = x0; x <= x1; x++) {
    1061962                for (int y = y0; y <= y1; y++) {
     
    1074975        }
    1075976
    1076         int totalTiles() {
    1077             return (y1 - y0 + 1) * (x1 - x0 + 1);
    1078         }
    1079 
    1080977        void loadAllTiles(boolean force)
    1081978        {
     
    1096993    }
    1097994
    1098     boolean az_disable = false;
    1099     boolean autoZoomEnabled()
    1100     {
    1101         if (az_disable)
    1102             return false;
    1103         return autoZoom;
    1104     }
     995
     996    private static class TileSetInfo {
     997        public boolean hasVisibleTiles = false;
     998        public boolean hasOverzoomedTiles = false;
     999        public boolean hasLoadingTiles = false;
     1000    }
     1001
     1002    private static TileSetInfo getTileSetInfo(TileSet ts) {
     1003        List<Tile> allTiles = ts.allTiles();
     1004        TileSetInfo result = new TileSetInfo();
     1005        result.hasLoadingTiles = allTiles.size() < ts.size();
     1006        for (Tile t : allTiles) {
     1007            if (t.isLoaded()) {
     1008                if (!t.hasError()) {
     1009                    result.hasVisibleTiles = true;
     1010                }
     1011                if ("no-tile".equals(t.getValue("tile-info"))) {
     1012                    result.hasOverzoomedTiles = true;
     1013                }
     1014            } else {
     1015                result.hasLoadingTiles = true;
     1016            }
     1017        }
     1018        return result;
     1019    }
     1020
     1021    private class DeepTileSet {
     1022        final EastNorth topLeft, botRight;
     1023        final int minZoom;
     1024        private final TileSet[] tileSets;
     1025        private final TileSetInfo[] tileSetInfos;
     1026        public DeepTileSet(EastNorth topLeft, EastNorth botRight, int minZoom, int maxZoom) {
     1027            this.topLeft = topLeft;
     1028            this.botRight = botRight;
     1029            this.minZoom = minZoom;
     1030            this.tileSets = new TileSet[maxZoom - minZoom + 1];
     1031            this.tileSetInfos = new TileSetInfo[maxZoom - minZoom + 1];
     1032        }
     1033        public TileSet getTileSet(int zoom) {
     1034            if (zoom < minZoom)
     1035                return nullTileSet;
     1036            TileSet ts = tileSets[zoom-minZoom];
     1037            if (ts == null) {
     1038                ts = new TileSet(topLeft, botRight, zoom);
     1039                tileSets[zoom-minZoom] = ts;
     1040            }
     1041            return ts;
     1042        }
     1043        public TileSetInfo getTileSetInfo(int zoom) {
     1044            if (zoom < minZoom)
     1045                return new TileSetInfo();
     1046            TileSetInfo tsi = tileSetInfos[zoom-minZoom];
     1047            if (tsi == null) {
     1048                tsi = TMSLayer.getTileSetInfo(getTileSet(zoom));
     1049                tileSetInfos[zoom-minZoom] = tsi;
     1050            }
     1051            return tsi;
     1052        }
     1053    }
     1054
    11051055    /**
    11061056     */
     
    11201070
    11211071        int zoom = currentZoomLevel;
    1122         TileSet ts = new TileSet(topLeft, botRight, zoom);
    1123 
    1124         if (autoZoomEnabled()) {
    1125             if (zoomDecreaseAllowed() && ts.tooLarge()) {
    1126                 if (debug) {
    1127                     out("too many tiles, decreasing zoom from " + currentZoomLevel);
    1128                 }
    1129                 if (decreaseZoomLevel()) {
    1130                     this.paint(g, mv, bounds);
    1131                     return;
    1132                 }
    1133             }
    1134 
    1135             // Auto-detection of Bing zoomlevel
    1136             if (tileSource instanceof BingAerialTileSource) {
    1137                 List<Tile> allTiles = ts.allTiles();
    1138                 boolean hasVisibleTiles = false;
    1139                 boolean hasOverzoomedTiles = false;
    1140                 boolean hasLoadingTiles = allTiles.size() < ts.totalTiles();
    1141                 for (Tile t : allTiles) {
    1142                     if (t.isLoaded()) {
    1143                         if (!t.hasError()) {
    1144                             hasVisibleTiles = true;
    1145                         }
    1146                         if ("no-tile".equals(t.getValue("tile-info"))) {
    1147                             hasOverzoomedTiles = true;
    1148                         }
    1149                     } else {
    1150                         hasLoadingTiles = true;
    1151                     }
    1152                 }
    1153                 if (!hasLoadingTiles) {
    1154                     overZoomed = false;
    1155                 }
    1156                 if (!hasVisibleTiles && hasOverzoomedTiles) {
    1157                     overZoomed = true;
    1158                     if (displayZoomLevel == 0 || !hasLoadingTiles) {
    1159                         boolean tmp = overZoomedFlag;
    1160                         overZoomedFlag = true;
    1161                         if (decreaseZoomLevel()) {
    1162                             this.paint(g, mv, bounds);
    1163                             overZoomedFlag = tmp;
    1164                             return;
    1165                         }
    1166                         overZoomedFlag = tmp;
    1167                     }
    1168                 } else if (hasVisibleTiles) {
    1169                     displayZoomLevel = currentZoomLevel;
    1170                 }
    1171             } else {
    1172                 displayZoomLevel = currentZoomLevel;
    1173                 if (zoomIncreaseAllowed() && ts.tooSmall()) {
    1174                     if (debug) {
    1175                         out("too zoomed in, (" + ts.tilesSpanned()
    1176                                 + "), increasing zoom from " + currentZoomLevel);
    1177                     }
    1178                     // This is a hack.  ts.tooSmall() is proabably a bad thing, and this works
    1179                     // around it.  If we have a very small window, the tileSet may be well
    1180                     // less than 1 real tile wide, but that's expected.  But, this sees the
    1181                     // tile set as too small and zooms in.  The code below that checks for
    1182                     // pixel stretching disagrees and tries to zoom out.  Both calls recurse,
    1183                     // hillarity ensues, and the stack overflows.
    1184                     //
    1185                     // This really needs to get fixed properly.  We probably shouldn't even
    1186                     // have the tooSmall() check on tileSets.  But, this also helps the zoom
    1187                     // converge to the correct place much faster.
    1188                     boolean tmp = az_disable;
    1189                     az_disable = true;
    1190                     increaseZoomLevel();
    1191                     this.paint(g, mv, bounds);
    1192                     az_disable = tmp;
    1193                     return;
    1194                 }
    1195             }
    1196         } else {
    1197             displayZoomLevel = currentZoomLevel;
     1072        if (autoZoom) {
     1073            double pixelScaling = getScaleFactor(zoom);
     1074            if (pixelScaling > 3 || pixelScaling < 0.45) {
     1075                zoom = getBestZoom();
     1076            }
     1077        }
     1078
     1079        DeepTileSet dts = new DeepTileSet(topLeft, botRight, getMinZoomLvl(), getMaxZoomLvl());
     1080        TileSet ts = dts.getTileSet(zoom);
     1081
     1082        int displayZoomLevel = zoom;
     1083
     1084        boolean noTilesAtZoom = false;
     1085        if (autoZoom && autoLoad) {
     1086            // Auto-detection of tilesource maxzoom (currently fully works only for Bing)
     1087            TileSetInfo tsi = dts.getTileSetInfo(zoom);
     1088            if (!tsi.hasVisibleTiles && (!tsi.hasLoadingTiles || tsi.hasOverzoomedTiles)) {
     1089                noTilesAtZoom = true;
     1090            }
     1091            if (!tsi.hasVisibleTiles && tsi.hasOverzoomedTiles) {
     1092                while (displayZoomLevel > dts.minZoom && !tsi.hasVisibleTiles && tsi.hasOverzoomedTiles){
     1093                    displayZoomLevel--;
     1094                    tsi = dts.getTileSetInfo(displayZoomLevel);
     1095                }
     1096                if (zoom > displayZoomLevel && !dts.getTileSetInfo(displayZoomLevel+1).hasLoadingTiles) {
     1097                    zoom = displayZoomLevel+1;
     1098                } else {
     1099                    zoom = displayZoomLevel;
     1100                }
     1101                while (displayZoomLevel >= dts.minZoom && !tsi.hasVisibleTiles){
     1102                    displayZoomLevel--;
     1103                    tsi = dts.getTileSetInfo(displayZoomLevel);
     1104                }
     1105                if (displayZoomLevel < dts.minZoom) {
     1106                    displayZoomLevel = 0;
     1107                }
     1108                tsi = dts.getTileSetInfo(zoom);
     1109            }
     1110            setZoomLevel(zoom);
     1111            // When we have overzoomed tiles and all tiles at current zoomlevel is loaded,
     1112            // load tiles at previovus zoomlevels until we have all tiles on screen is loaded.
     1113            while (zoom > dts.minZoom && tsi.hasOverzoomedTiles && !tsi.hasLoadingTiles) {
     1114                zoom--;
     1115                tsi = dts.getTileSetInfo(zoom);
     1116            }
     1117            ts = dts.getTileSet(zoom);
     1118        } else if (autoZoom) {
     1119            setZoomLevel(zoom);
    11981120        }
    11991121
     
    12051127
    12061128        if (displayZoomLevel != zoom) {
    1207             ts = new TileSet(topLeft, botRight, displayZoomLevel);
     1129            ts = dts.getTileSet(displayZoomLevel);
    12081130        }
    12091131
     
    12131135        int otherZooms[] = { -1, 1, -2, 2, -3, -4, -5};
    12141136        for (int zoomOffset : otherZooms) {
    1215             if (!autoZoomEnabled()) {
     1137            if (!autoZoom) {
    12161138                break;
    12171139            }
     
    12251147            List<Tile> newlyMissedTiles = new LinkedList<Tile>();
    12261148            for (Tile missed : missedTiles) {
     1149                if ("no-tile".equals(missed.getValue("tile-info")) && zoomOffset > 0) {
     1150                    // Don't try to paint from higher zoom levels when tile is overzoomed
     1151                    newlyMissedTiles.add(missed);
     1152                    continue;
     1153                }
    12271154                Tile t2 = tempCornerTile(missed);
    12281155                LatLon topLeft2  = tileLatLon(missed);
     
    12891216        }
    12901217
    1291         if (autoZoomEnabled() && lastImageScale != null) {
    1292             // If each source image pixel is being stretched into > 3
    1293             // drawn pixels, zoom in... getting too pixelated
    1294             if (lastImageScale > 3 && zoomIncreaseAllowed()) {
    1295                 if (debug) {
    1296                     out("autozoom increase: scale: " + lastImageScale);
    1297                 }
    1298                 increaseZoomLevel();
    1299                 this.paint(g, mv, bounds);
    1300                 // If each source image pixel is being squished into > 0.32
    1301                 // of a drawn pixels, zoom out.
    1302             } else if ((lastImageScale < 0.45) && (lastImageScale > 0) && zoomDecreaseAllowed()) {
    1303                 if (debug) {
    1304                     out("autozoom decrease: scale: " + lastImageScale);
    1305                 }
    1306                 decreaseZoomLevel();
    1307                 this.paint(g, mv, bounds);
    1308             }
    1309         }
    13101218        //g.drawString("currentZoomLevel=" + currentZoomLevel, 120, 120);
    13111219        g.setColor(Color.lightGray);
     
    13191227            }
    13201228        }
    1321         if (isOverZoomed()) {
     1229        if (noTilesAtZoom) {
    13221230            myDrawString(g, tr("No tiles at this zoom level"), 120, 120);
    13231231        }
     
    13251233            myDrawString(g, tr("Current zoom: {0}", currentZoomLevel), 50, 140);
    13261234            myDrawString(g, tr("Display zoom: {0}", displayZoomLevel), 50, 155);
     1235            myDrawString(g, tr("Pixel scale: {0}", getScaleFactor(currentZoomLevel)), 50, 170);
     1236            myDrawString(g, tr("Best zoom: {0}", Math.log(getScaleFactor(1))/Math.log(2)/2+1), 50, 185);
    13271237        }
    13281238    }// end of paint method
     
    13631273            return null;
    13641274        System.out.println("clicked on tile: " + clickedTile.getXtile() + " " + clickedTile.getYtile() +
    1365                 " scale: " + lastImageScale + " currentZoomLevel: " + currentZoomLevel);
     1275                " currentZoomLevel: " + currentZoomLevel);
    13661276        return clickedTile;
    13671277    }
     
    13941304    }
    13951305
    1396     private int latToTileY(double lat, int zoom) {
     1306    private static double latToTileY(double lat, int zoom) {
    13971307        double l = lat / 180 * Math.PI;
    13981308        double pf = Math.log(Math.tan(l) + (1 / Math.cos(l)));
    1399         return (int) (Math.pow(2.0, zoom - 1) * (Math.PI - pf) / Math.PI);
    1400     }
    1401 
    1402     private int lonToTileX(double lon, int zoom) {
    1403         return (int) (Math.pow(2.0, zoom - 3) * (lon + 180.0) / 45.0);
    1404     }
    1405 
    1406     private double tileYToLat(int y, int zoom) {
     1309        return Math.pow(2.0, zoom - 1) * (Math.PI - pf) / Math.PI;
     1310    }
     1311
     1312    private static double lonToTileX(double lon, int zoom) {
     1313        return Math.pow(2.0, zoom - 3) * (lon + 180.0) / 45.0;
     1314    }
     1315
     1316    private static double tileYToLat(int y, int zoom) {
    14071317        return Math.atan(Math.sinh(Math.PI
    14081318                - (Math.PI * y / Math.pow(2.0, zoom - 1))))
     
    14101320    }
    14111321
    1412     private double tileXToLon(int x, int zoom) {
     1322    private static double tileXToLon(int x, int zoom) {
    14131323        return x * 45.0 / Math.pow(2.0, zoom - 3) - 180.0;
    14141324    }
Note: See TracChangeset for help on using the changeset viewer.