Ignore:
Timestamp:
2009-07-12T20:33:41+02:00 (15 years ago)
Author:
dhansen
Message:

This fixes up a bunch of inconsistent spacing, and quiets
down the debug messages.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapLayer.java

    r16462 r16463  
    2020import java.util.Hashtable;
    2121import java.util.List;
     22import java.util.LinkedList;
    2223import java.util.TreeSet;
    2324
     
    4647 * @author LuVar <lubomir.varga@freemap.sk>
    4748 * @author Dave Hansen <dave@sr71.net>
    48  * 
     49 *
    4950 */
    5051public class SlippyMapLayer extends Layer implements ImageObserver,
     
    6566    private JPopupMenu tileOptionMenu;
    6667
     68    static void debug(String msg)
     69    {
     70
     71    }
    6772    @SuppressWarnings("serial")
    6873    public SlippyMapLayer() {
     
    131136                    }
    132137                }));
    133        
     138
    134139        tileOptionMenu.add(new JMenuItem(
    135140                new AbstractAction(tr("Flush Tile Cache")) {
     
    177182    /**
    178183     * Zoom in, go closer to map.
    179      * 
    180      * @return  true, if zoom increasing was successfull, false othervise
     184     *
     185     * @return    true, if zoom increasing was successfull, false othervise
    181186     */
    182187    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()) {
    188197            currentZoomLevel++;
    189             Main.debug("increasing zoom level to: " + currentZoomLevel);
     198            this.debug("increasing zoom level to: " + currentZoomLevel);
    190199            needRedraw = true;
    191200        } else {
     
    193202                             "MaxZoomLvl ("+SlippyMapPreferences.getMaxZoomLvl()+") reached.");
    194203            return false;
    195             }
     204        }
    196205        return true;
    197206    }
     
    199208    /**
    200209     * Zoom out from map.
    201      * 
    202      * @return  true, if zoom increasing was successfull, false othervise
     210     *
     211     * @return    true, if zoom increasing was successfull, false othervise
    203212     */
    204213    public boolean zoomDecreaseAllowed()
    205         {
     214    {
    206215        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);
    212222            currentZoomLevel--;
    213223            needRedraw = true;
     
    222232        // when max zoom lvl is begin saved, this method is called and probably
    223233        // the setting isnt saved yet.
    224         int maxZoom = SlippyMapPreferences.getMaxZoomLvl();
     234        int maxZoom = SlippyMapPreferences.getMaxZoomLvl();
    225235        tileStorage = new Hashtable<SlippyMapKey, SlippyMapTile>();
    226236        checkTileStorage();
     
    254264        TreeSet<SlippyMapTile> tiles = new TreeSet<SlippyMapTile>(new TileTimeComp());
    255265        tiles.addAll(tileStorage.values());
    256         if (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");
    262272        for (SlippyMapTile t : tiles) {
    263273            if (nr_to_drop <= 0)
    264                     break;
     274                break;
    265275            t.dropImage();
    266276            nr_to_drop--;
    267             tileStorage.remove(t.getKey());
     277            //tileStorage.remove(t.getKey());
    268278        }
    269279    }
    270280    long lastCheck = 0;
    271281    public void checkTileStorage() {
    272         int maxZoom = 30; // SlippyMapPreferences.getMaxZoomLvl();
    273282        long now = System.currentTimeMillis();
    274283        if (now - lastCheck < 1000)
    275                 return;
     284            return;
    276285        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)
    281294    {
    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        }
    284333    }
    285334
    286335    synchronized SlippyMapTile getTile(int x, int y, int zoom) {
    287                 SlippyMapKey key = new SlippyMapKey(x, y, zoom);
    288                 if (!key.valid) {
    289                         key = null;
    290                 }
    291                 return tileStorage.get(key);
    292         }
    293 
    294         synchronized SlippyMapTile putTile(SlippyMapTile tile, int x, int y, int zoom) {
    295                 SlippyMapKey key = new SlippyMapKey(x, y, zoom);
    296                 if (!key.valid) {
    297                         key = null;
    298                 }
    299                 return tileStorage.put(key, tile);
    300         }
    301 
    302         synchronized SlippyMapTile getOrCreateTile(int x, int y, int zoom) {
    303                 SlippyMapTile tile = getTile(x, y, zoom);
    304                 if (tile != null) {
    305                         return tile;
    306                 }
    307                 tile = new SlippyMapTile(x, y, zoom);
    308                 putTile(tile, x, y, zoom);
    309                 return tile;
    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
    312361    void loadAllTiles() {
    313362        MapView mv = Main.map.mapView;
     
    316365
    317366        TileSet ts = new TileSet(topLeft, botRight, currentZoomLevel);
    318        
     367
    319368        // if there is more than 18 tiles on screen in any direction, do not
    320369        // load all tiles!
    321370        if (ts.tilesSpanned() > (18*18)) {
    322                 System.out.println("Not downloading all tiles because there is more than 18 tiles on an axis!");
    323                 return;
     371            System.out.println("Not downloading all tiles because there is more than 18 tiles on an axis!");
     372            return;
    324373        }
    325374
    326375        for (Tile t : ts.allTiles()) {
    327                 SlippyMapTile tile = getOrCreateTile(t.x, t.y, currentZoomLevel);
    328                 if (tile.getImage() == null) {
    329                         this.loadSingleTile(tile);
    330                 }
     376            SlippyMapTile tile = getOrCreateTile(t.x, t.y, currentZoomLevel);
     377            if (tile.getImage() == null) {
     378                this.loadSingleTile(tile);
     379            }
    331380        }//end of for Tile t
    332381    }
    333382
    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;
    369422        double realArea = realWidth * realHeight;
    370423
     
    372425    }
    373426
    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()
    532593        {
    533594            List<Tile> ret = new ArrayList<Tile>();
     
    541602        }
    542603
    543                 boolean topTile(Tile t) {
    544                         if (t.y == z12y0 )
    545                                 return true;
    546                         return false;
    547                 }
    548 
    549                 boolean leftTile(Tile t) {
    550                         if (t.x == z12x0 )
    551                                 return true;
    552                         return false;
    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   
    556617    /**
    557618     */
    558619    @Override
    559620    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);
    589652            if (decreaseZoomLevel())
    590                                 this.paint(oldg, mv);
    591                         return;
    592                 }
    593                 if (zoomIncreaseAllowed() && (ts.tilesSpanned() < 1.0)) {
    594                         this.debug("doesn't even cover one tile (" + ts.tilesSpanned()
    595                                            + "), increasing zoom from " + currentZoomLevel);
     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);
    596659            if (increaseZoomLevel())
    597660                 this.paint(oldg, mv);
     
    599662        }
    600663
    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
    671741
    672742    /**
     
    675745     */
    676746    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;
    685756        for (Tile t1 : ts.allTiles()) {
    686757            Tile t2 = new Tile(t1.x+1, t1.y+1);
    687             Point p1 = t1.pixelPos(z);
    688             Point p2 = t2.pixelPos(z);
     758            p1 = t1.pixelPos(z);
     759            p2 = t2.pixelPos(z);
    689760            Rectangle r = new Rectangle(p1,new Dimension(p2.x, p2.y));
    690761            if (!r.contains(clicked))
     
    695766        if (clickedTile == null)
    696767             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);
    698770        SlippyMapTile tile = getOrCreateTile(clickedTile.x, clickedTile.y, currentZoomLevel);
    699771        checkTileStorage();
     
    748820
    749821    private int lonToTileX(double lon, int zoom) {
    750         return (int) (Math.pow(2.0, zoom - 3) * (lon + 180.0) / 45.0);
     822        return (int) (Math.pow(2.0, zoom - 3) * (lon + 180.0) / 45.0);
    751823    }
    752824
    753825    private double tileYToLat(int y, int zoom) {
    754826        return Math.atan(Math.sinh(Math.PI
    755                         - (Math.PI * y / Math.pow(2.0, zoom - 1))))
     827                - (Math.PI * y / Math.pow(2.0, zoom - 1))))
    756828                * 180 / Math.PI;
    757829    }
    758830
    759831    private double tileXToLon(int x, int zoom) {
    760         return x * 45.0 / Math.pow(2.0, zoom - 3) - 180.0;
     832        return x * 45.0 / Math.pow(2.0, zoom - 3) - 180.0;
    761833    }
    762834
    763835    private SlippyMapTile imgToTile(Image img) {
    764                 // we use the enumeration to avoid ConcurrentUpdateExceptions
    765                 // with other users of the tileStorage
    766                 Enumeration<SlippyMapTile> e = tileStorage.elements();
    767                 while (e.hasMoreElements()) {
    768                         SlippyMapTile t = e.nextElement();
    769                         if (t.getImageNoTimestamp() != img) {
    770                                 continue;
    771                         }
    772                         return t;
    773                 }
    774                 return null;
    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
    777849    private static int nr_loaded = 0;
    778850    private static int at_zoom = -1;
    779    
     851
    780852    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    }
    813892
    814893    /*
Note: See TracChangeset for help on using the changeset viewer.