Ignore:
Timestamp:
2016-07-26T21:44:16+02:00 (8 years ago)
Author:
Don-vip
Message:

fix #13210 - Start extracting coordinate conversion out of tile source (patch by michael2402, modified) - gsoc-core

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
1 added
2 edited

Legend:

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

    r10596 r10651  
    88import java.awt.geom.Point2D;
    99import java.awt.geom.Point2D.Double;
     10import java.awt.geom.Rectangle2D;
    1011
    1112import javax.swing.JComponent;
     
    144145
    145146    /**
     147     * Gets the {@link MapViewPoint} for the given {@link LatLon} coordinate.
     148     * @param latlon the position
     149     * @return The point for that position.
     150     * @since 10651
     151     */
     152    public MapViewPoint getPointFor(LatLon latlon) {
     153        return getPointFor(getProjection().latlon2eastNorth(latlon));
     154    }
     155
     156    /**
    146157     * Gets a rectangle representing the whole view area.
    147158     * @return The rectangle.
     
    351362            return projection.eastNorth2latlon(getEastNorth());
    352363        }
     364
     365        /**
     366         * Add the given offset to this point
     367         * @param en The offset in east/north space.
     368         * @return The new point
     369         * @since 10651
     370         */
     371        public MapViewPoint add(EastNorth en) {
     372            return new MapViewEastNorthPoint(getEastNorth().add(en));
     373        }
    353374    }
    354375
     
    455476            return projection.getLatLonBoundsBox(getProjectionBounds());
    456477        }
     478
     479        /**
     480         * Gets this rectangle on the screen.
     481         * @return The rectangle.
     482         * @since 10651
     483         */
     484        public Rectangle2D getInView() {
     485            double x1 = p1.getInViewX();
     486            double y1 = p1.getInViewY();
     487            double x2 = p2.getInViewX();
     488            double y2 = p2.getInViewY();
     489            return new Rectangle2D.Double(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
     490        }
    457491    }
    458492
  • trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java

    r10634 r10651  
    1313import java.awt.Image;
    1414import java.awt.Point;
    15 import java.awt.Rectangle;
    1615import java.awt.Toolkit;
    1716import java.awt.event.ActionEvent;
    1817import java.awt.event.MouseAdapter;
    1918import java.awt.event.MouseEvent;
     19import java.awt.geom.Point2D;
     20import java.awt.geom.Rectangle2D;
    2021import java.awt.image.BufferedImage;
    2122import java.awt.image.ImageObserver;
     
    3738import java.util.concurrent.ConcurrentSkipListSet;
    3839import java.util.concurrent.atomic.AtomicInteger;
     40import java.util.stream.Stream;
    3941
    4042import javax.swing.AbstractAction;
     
    6870import org.openstreetmap.josm.actions.SaveActionBase;
    6971import org.openstreetmap.josm.data.Bounds;
     72import org.openstreetmap.josm.data.ProjectionBounds;
    7073import org.openstreetmap.josm.data.coor.EastNorth;
    7174import org.openstreetmap.josm.data.coor.LatLon;
     
    7881import org.openstreetmap.josm.gui.MapFrame;
    7982import org.openstreetmap.josm.gui.MapView;
     83import org.openstreetmap.josm.gui.MapViewState.MapViewRectangle;
    8084import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener;
    8185import org.openstreetmap.josm.gui.PleaseWaitRunnable;
     
    8387import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
    8488import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener;
     89import org.openstreetmap.josm.gui.layer.imagery.TileCoordinateConverter;
    8590import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings;
    8691import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings.DisplaySettingsChangeEvent;
     
    170175
    171176    private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this);
     177    // prepared to be moved to the painter
     178    private TileCoordinateConverter coordinateConverter;
    172179
    173180    /**
     
    224231
    225232    protected void initTileSource(T tileSource) {
     233        coordinateConverter = new TileCoordinateConverter(Main.map.mapView, getDisplaySettings());
    226234        attribution.initialize(tileSource);
    227235
     
    421429                ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Tile Info"), new String[]{tr("OK")});
    422430                JPanel panel = new JPanel(new GridBagLayout());
    423                 Rectangle displaySize = tileToRect(clickedTile);
     431                Rectangle2D displaySize = coordinateConverter.getRectangleForTile(clickedTile);
    424432                String url = "";
    425433                try {
     
    434442                        {"Tile url", url},
    435443                        {"Tile size", getSizeString(clickedTile.getTileSource().getTileSize()) },
    436                         {"Tile display size", new StringBuilder().append(displaySize.width).append('x').append(displaySize.height).toString()},
     444                        {"Tile display size", new StringBuilder().append(displaySize.getWidth())
     445                                                                 .append('x')
     446                                                                 .append(displaySize.getHeight()).toString()},
    437447                };
    438448
     
    10001010    private TileSet getVisibleTileSet() {
    10011011        MapView mv = Main.map.mapView;
    1002         EastNorth topLeft = mv.getEastNorth(0, 0);
    1003         EastNorth botRight = mv.getEastNorth(mv.getWidth(), mv.getHeight());
    1004         return new MapWrappingTileSet(topLeft, botRight, currentZoomLevel);
     1012        MapViewRectangle area = mv.getState().getViewArea();
     1013        ProjectionBounds bounds = area.getProjectionBounds();
     1014        return getTileSet(bounds.getMin(), bounds.getMax(), currentZoomLevel);
    10051015    }
    10061016
     
    10571067    }
    10581068
    1059     private Rectangle tileToRect(Tile t1) {
    1060         /*
    1061          * We need to get a box in which to draw, so advance by one tile in
    1062          * each direction to find the other corner of the box.
    1063          * Note: this somewhat pollutes the tile cache
    1064          */
    1065         Tile t2 = tempCornerTile(t1);
    1066         Rectangle rect = new Rectangle(pixelPos(t1));
    1067         rect.add(pixelPos(t2));
    1068         return rect;
    1069     }
    1070 
    10711069    // 'source' is the pixel coordinates for the area that
    10721070    // the img is capable of filling in.  However, we probably
     
    10751073    // 'border' is the screen cordinates that need to be drawn.
    10761074    //  We must not draw outside of it.
    1077     private void drawImageInside(Graphics g, Image sourceImg, Rectangle source, Rectangle border) {
    1078         Rectangle target = source;
     1075    private void drawImageInside(Graphics g, Image sourceImg, Rectangle2D source, Rectangle2D border) {
     1076        Rectangle2D target = source;
    10791077
    10801078        // If a border is specified, only draw the intersection
    10811079        // if what we have combined with what we are supposed to draw.
    10821080        if (border != null) {
    1083             target = source.intersection(border);
     1081            target = source.createIntersection(border);
    10841082            if (Main.isDebugEnabled()) {
    10851083                Main.debug("source: " + source + "\nborder: " + border + "\nintersection: " + target);
     
    10981096
    10991097        // How many pixels into the 'source' rectangle are we drawing?
    1100         int screenXoffset = target.x - source.x;
    1101         int screenYoffset = target.y - source.y;
     1098        double screenXoffset = target.getX() - source.getX();
     1099        double screenYoffset = target.getY() - source.getY();
    11021100        // And how many pixels into the image itself does that correlate to?
    11031101        int imgXoffset = (int) (screenXoffset * imageXScaling + 0.5);
     
    11121110        }
    11131111        g.drawImage(sourceImg,
    1114                 target.x, target.y,
    1115                 target.x + target.width, target.y + target.height,
     1112                (int) target.getX(), (int) target.getY(),
     1113                (int) target.getMaxX(), (int) target.getMaxY(),
    11161114                imgXoffset, imgYoffset,
    11171115                imgXend, imgYend,
     
    11201118            // dimm by painting opaque rect...
    11211119            g.setColor(getFadeColorWithAlpha());
    1122             g.fillRect(target.x, target.y,
    1123                     target.width, target.height);
     1120            ((Graphics2D) g).fill(target);
    11241121        }
    11251122    }
     
    11361133    private List<Tile> paintTileImages(Graphics g, TileSet ts, int zoom, Tile border) {
    11371134        if (zoom <= 0) return Collections.emptyList();
    1138         Rectangle borderRect = null;
     1135        Rectangle2D borderRect = null;
    11391136        if (border != null) {
    1140             borderRect = tileToRect(border);
     1137            borderRect = coordinateConverter.getRectangleForTile(border);
    11411138        }
    11421139        List<Tile> missedTiles = new LinkedList<>();
     
    11581155            img = applyImageProcessors((BufferedImage) img);
    11591156
    1160             Rectangle sourceRect = tileToRect(tile);
     1157            Rectangle2D sourceRect = coordinateConverter.getRectangleForTile(tile);
    11611158            if (borderRect != null && !sourceRect.intersects(borderRect)) {
    11621159                continue;
     
    11951192
    11961193    private void paintTileText(TileSet ts, Tile tile, Graphics g, MapView mv, int zoom, Tile t) {
     1194        if (tile == null) {
     1195            return;
     1196        }
     1197        Point2D p = coordinateConverter.getPixelForTile(t);
    11971198        int fontHeight = g.getFontMetrics().getHeight();
    1198         if (tile == null)
    1199             return;
    1200         Point p = pixelPos(t);
    1201         int texty = p.y + 2 + fontHeight;
     1199        int x = (int) p.getX();
     1200        int y = (int) p.getY();
     1201        int texty = y + 2 + fontHeight;
    12021202
    12031203        /*if (PROP_DRAW_DEBUG.get()) {
     
    12171217
    12181218        if (tile.hasError() && getDisplaySettings().isShowErrors()) {
    1219             myDrawString(g, tr("Error") + ": " + tr(tile.getErrorMessage()), p.x + 2, texty);
     1219            myDrawString(g, tr("Error") + ": " + tr(tile.getErrorMessage()), x + 2, texty);
    12201220            //texty += 1 + fontHeight;
    12211221        }
     
    12261226            if (yCursor < t.getYtile()) {
    12271227                if (t.getYtile() % 32 == 31) {
    1228                     g.fillRect(0, p.y - 1, mv.getWidth(), 3);
     1228                    g.fillRect(0, y - 1, mv.getWidth(), 3);
    12291229                } else {
    1230                     g.drawLine(0, p.y, mv.getWidth(), p.y);
     1230                    g.drawLine(0, y, mv.getWidth(), y);
    12311231                }
    12321232                //yCursor = t.getYtile();
     
    12361236                if (t.getXtile() % 32 == 0) {
    12371237                    // level 7 tile boundary
    1238                     g.fillRect(p.x - 1, 0, 3, mv.getHeight());
     1238                    g.fillRect(x - 1, 0, 3, mv.getHeight());
    12391239                } else {
    1240                     g.drawLine(p.x, 0, p.x, mv.getHeight());
     1240                    g.drawLine(x, 0, x, mv.getHeight());
    12411241                }
    12421242                //xCursor = t.getXtile();
    12431243            }
    12441244        }
    1245     }
    1246 
    1247     private Point pixelPos(LatLon ll) {
    1248         return Main.map.mapView.getPoint(Main.getProjection().latlon2eastNorth(ll).add(getDx(), getDy()));
    1249     }
    1250 
    1251     private Point pixelPos(Tile t) {
    1252         ICoordinate coord = tileSource.tileXYToLatLon(t);
    1253         return pixelPos(new LatLon(coord));
    12541245    }
    12551246
     
    12691260    private final TileSet nullTileSet = new TileSet();
    12701261
    1271     private final class MapWrappingTileSet extends TileSet {
    1272         private MapWrappingTileSet(EastNorth topLeft, EastNorth botRight, int zoom) {
    1273             this(getShiftedLatLon(topLeft), getShiftedLatLon(botRight), zoom);
    1274         }
    1275 
    1276         private MapWrappingTileSet(LatLon topLeft, LatLon botRight, int zoom) {
    1277             super(topLeft, botRight, zoom);
    1278             double centerLon = getShiftedLatLon(Main.map.mapView.getCenter()).lon();
    1279 
    1280             if (topLeft.lon() > centerLon) {
    1281                 x0 = tileSource.getTileXMin(zoom);
    1282             }
    1283             if (botRight.lon() < centerLon) {
    1284                 x1 = tileSource.getTileXMax(zoom);
    1285             }
     1262    /**
     1263     * This is a rectangular range of tiles.
     1264     */
     1265    private static class TileRange {
     1266        int minX, maxX, minY, maxY;
     1267        int zoom;
     1268
     1269        private TileRange() {
     1270        }
     1271
     1272        protected TileRange(TileXY t1, TileXY t2, int zoom) {
     1273            minX = (int) Math.floor(Math.min(t1.getX(), t2.getX()));
     1274            minY = (int) Math.floor(Math.min(t1.getY(), t2.getY()));
     1275            maxX = (int) Math.ceil(Math.max(t1.getX(), t2.getX()));
     1276            maxY = (int) Math.ceil(Math.max(t1.getY(), t2.getY()));
     1277            this.zoom = zoom;
     1278        }
     1279
     1280        protected double tilesSpanned() {
     1281            return Math.sqrt(1.0 * this.size());
     1282        }
     1283
     1284        protected int size() {
     1285            int xSpan = maxX - minX + 1;
     1286            int ySpan = maxY - minY + 1;
     1287            return xSpan * ySpan;
     1288        }
     1289    }
     1290
     1291    private class TileSet extends TileRange {
     1292
     1293        protected TileSet(TileXY t1, TileXY t2, int zoom) {
     1294            super(t1, t2, zoom);
    12861295            sanitize();
    1287         }
    1288     }
    1289 
    1290     private class TileSet {
    1291         int x0, x1, y0, y1;
    1292         int zoom;
    1293 
    1294         /**
    1295          * Create a TileSet by EastNorth bbox taking a layer shift in account
    1296          * @param topLeft top-left lat/lon
    1297          * @param botRight bottom-right lat/lon
    1298          * @param zoom zoom level
    1299          */
    1300         protected TileSet(EastNorth topLeft, EastNorth botRight, int zoom) {
    1301             this(getShiftedLatLon(topLeft), getShiftedLatLon(botRight), zoom);
    1302         }
    1303 
    1304         /**
    1305          * Create a TileSet by known LatLon bbox without layer shift correction
    1306          * @param topLeft top-left lat/lon
    1307          * @param botRight bottom-right lat/lon
    1308          * @param zoom zoom level
    1309          */
    1310         protected TileSet(LatLon topLeft, LatLon botRight, int zoom) {
    1311             this.zoom = zoom;
    1312             if (zoom == 0)
    1313                 return;
    1314 
    1315             TileXY t1 = tileSource.latLonToTileXY(topLeft.toCoordinate(), zoom);
    1316             TileXY t2 = tileSource.latLonToTileXY(botRight.toCoordinate(), zoom);
    1317 
    1318             x0 = (int) Math.floor(t1.getX());
    1319             y0 = (int) Math.floor(t1.getY());
    1320             x1 = (int) Math.ceil(t2.getX());
    1321             y1 = (int) Math.ceil(t2.getY());
    1322             sanitize();
    1323 
    13241296        }
    13251297
     
    13321304
    13331305        protected void sanitize() {
    1334             if (x0 > x1) {
    1335                 int tmp = x0;
    1336                 x0 = x1;
    1337                 x1 = tmp;
    1338             }
    1339             if (y0 > y1) {
    1340                 int tmp = y0;
    1341                 y0 = y1;
    1342                 y1 = tmp;
    1343             }
    1344 
    1345             if (x0 < tileSource.getTileXMin(zoom)) {
    1346                 x0 = tileSource.getTileXMin(zoom);
    1347             }
    1348             if (y0 < tileSource.getTileYMin(zoom)) {
    1349                 y0 = tileSource.getTileYMin(zoom);
    1350             }
    1351             if (x1 > tileSource.getTileXMax(zoom)) {
    1352                 x1 = tileSource.getTileXMax(zoom);
    1353             }
    1354             if (y1 > tileSource.getTileYMax(zoom)) {
    1355                 y1 = tileSource.getTileYMax(zoom);
     1306            if (minX < tileSource.getTileXMin(zoom)) {
     1307                minX = tileSource.getTileXMin(zoom);
     1308            }
     1309            if (minY < tileSource.getTileYMin(zoom)) {
     1310                minY = tileSource.getTileYMin(zoom);
     1311            }
     1312            if (maxX > tileSource.getTileXMax(zoom)) {
     1313                maxX = tileSource.getTileXMax(zoom);
     1314            }
     1315            if (maxY > tileSource.getTileYMax(zoom)) {
     1316                maxY = tileSource.getTileYMax(zoom);
    13561317            }
    13571318        }
     
    13671328        private boolean insane() {
    13681329            return tileCache == null || size() > tileCache.getCacheSize();
    1369         }
    1370 
    1371         private double tilesSpanned() {
    1372             return Math.sqrt(1.0 * this.size());
    1373         }
    1374 
    1375         private int size() {
    1376             int xSpan = x1 - x0 + 1;
    1377             int ySpan = y1 - y0 + 1;
    1378             return xSpan * ySpan;
    13791330        }
    13801331
     
    13961347                return Collections.emptyList();
    13971348            List<Tile> ret = new ArrayList<>();
    1398             for (int x = x0; x <= x1; x++) {
    1399                 for (int y = y0; y <= y1; y++) {
     1349            for (int x = minX; x <= maxX; x++) {
     1350                for (int y = minY; y <= maxY; y++) {
    14001351                    Tile t;
    14011352                    if (create) {
     
    14251376         */
    14261377        private Comparator<Tile> getTileDistanceComparator() {
    1427             final int centerX = (int) Math.ceil((x0 + x1) / 2d);
    1428             final int centerY = (int) Math.ceil((y0 + y1) / 2d);
     1378            final int centerX = (int) Math.ceil((minX + maxX) / 2d);
     1379            final int centerY = (int) Math.ceil((minY + maxY) / 2d);
    14291380            return new Comparator<Tile>() {
    14301381                private int getDistance(Tile t) {
     
    14631414        @Override
    14641415        public String toString() {
    1465             return getClass().getName() + ": zoom: " + zoom + " X(" + x0 + ", " + x1 + ") Y(" + y0 + ", " + y1 + ") size: " + size();
    1466         }
     1416            return getClass().getName() + ": zoom: " + zoom + " X(" + minX + ", " + maxX + ") Y(" + minY + ", " + maxY + ") size: " + size();
     1417        }
     1418    }
     1419
     1420    /**
     1421     * Create a TileSet by EastNorth bbox taking a layer shift in account
     1422     * @param topLeft top-left lat/lon
     1423     * @param botRight bottom-right lat/lon
     1424     * @param zoom zoom level
     1425     * @return the tile set
     1426     * @since 10651
     1427     */
     1428    protected TileSet getTileSet(EastNorth topLeft, EastNorth botRight, int zoom) {
     1429        return getTileSet(getShiftedLatLon(topLeft), getShiftedLatLon(botRight), zoom);
     1430    }
     1431
     1432    /**
     1433     * Create a TileSet by known LatLon bbox without layer shift correction
     1434     * @param topLeft top-left lat/lon
     1435     * @param botRight bottom-right lat/lon
     1436     * @param zoom zoom level
     1437     * @return the tile set
     1438     * @since 10651
     1439     */
     1440    protected TileSet getTileSet(LatLon topLeft, LatLon botRight, int zoom) {
     1441        if (zoom == 0)
     1442            return new TileSet();
     1443
     1444        TileXY t1 = tileSource.latLonToTileXY(topLeft.toCoordinate(), zoom);
     1445        TileXY t2 = tileSource.latLonToTileXY(botRight.toCoordinate(), zoom);
     1446        return new TileSet(t1, t2, zoom);
    14671447    }
    14681448
     
    14941474
    14951475    private class DeepTileSet {
    1496         private final EastNorth topLeft, botRight;
     1476        private final ProjectionBounds bounds;
    14971477        private final int minZoom, maxZoom;
    14981478        private final TileSet[] tileSets;
     
    15001480
    15011481        @SuppressWarnings("unchecked")
    1502         DeepTileSet(EastNorth topLeft, EastNorth botRight, int minZoom, int maxZoom) {
    1503             this.topLeft = topLeft;
    1504             this.botRight = botRight;
     1482        DeepTileSet(ProjectionBounds bounds, int minZoom, int maxZoom) {
     1483            this.bounds = bounds;
    15051484            this.minZoom = minZoom;
    15061485            this.maxZoom = maxZoom;
     
    15151494                TileSet ts = tileSets[zoom-minZoom];
    15161495                if (ts == null) {
    1517                     ts = new MapWrappingTileSet(topLeft, botRight, zoom);
     1496                    ts = AbstractTileSourceLayer.this.getTileSet(bounds.getMin(), bounds.getMax(), zoom);
    15181497                    tileSets[zoom-minZoom] = ts;
    15191498                }
     
    15381517    @Override
    15391518    public void paint(Graphics2D g, MapView mv, Bounds bounds) {
    1540         EastNorth topLeft = mv.getEastNorth(0, 0);
    1541         EastNorth botRight = mv.getEastNorth(mv.getWidth(), mv.getHeight());
    1542 
    1543         if (botRight.east() == 0 || botRight.north() == 0) {
    1544             /*Main.debug("still initializing??");*/
    1545             // probably still initializing
    1546             return;
    1547         }
     1519        ProjectionBounds pb = mv.getState().getViewArea().getProjectionBounds();
    15481520
    15491521        needRedraw = false;
     
    15541526        }
    15551527
    1556         DeepTileSet dts = new DeepTileSet(topLeft, botRight, getMinZoomLvl(), zoom);
     1528        DeepTileSet dts = new DeepTileSet(pb, getMinZoomLvl(), zoom);
    15571529        TileSet ts = dts.getTileSet(zoom);
    15581530
     
    16331605                }
    16341606                Tile t2 = tempCornerTile(missed);
    1635                 TileSet ts2 = new TileSet(
     1607                TileSet ts2 = getTileSet(
    16361608                        getShiftedLatLon(tileSource.tileXYToLatLon(missed)),
    16371609                        getShiftedLatLon(tileSource.tileXYToLatLon(t2)),
     
    16611633        }
    16621634
    1663         attribution.paintAttribution(g, mv.getWidth(), mv.getHeight(), getShiftedCoord(topLeft), getShiftedCoord(botRight),
     1635        EastNorth min = pb.getMin();
     1636        EastNorth max = pb.getMax();
     1637        attribution.paintAttribution(g, mv.getWidth(), mv.getHeight(), getShiftedCoord(min), getShiftedCoord(max),
    16641638                displayZoomLevel, this);
    16651639
     
    17111685        EastNorth botRight = mv.getEastNorth(mv.getWidth(), mv.getHeight());
    17121686        int z = currentZoomLevel;
    1713         TileSet ts = new TileSet(topLeft, botRight, z);
     1687        TileSet ts = getTileSet(topLeft, botRight, z);
    17141688
    17151689        if (!ts.tooLarge()) {
    17161690            ts.loadAllTiles(false); // make sure there are tile objects for all tiles
    17171691        }
    1718         Tile clickedTile = null;
    1719         for (Tile t1 : ts.allExistingTiles()) {
    1720             Tile t2 = tempCornerTile(t1);
    1721             Rectangle r = new Rectangle(pixelPos(t1));
    1722             r.add(pixelPos(t2));
    1723             if (Main.isDebugEnabled()) {
    1724                 Main.debug("r: " + r + " clicked: " + clicked);
    1725             }
    1726             if (!r.contains(clicked)) {
    1727                 continue;
    1728             }
    1729             clickedTile = t1;
    1730             break;
    1731         }
    1732         if (clickedTile == null)
    1733             return null;
     1692        Stream<Tile> clickedTiles = ts.allExistingTiles().stream()
     1693                .filter(t -> coordinateConverter.getRectangleForTile(t).contains(clicked));
    17341694        if (Main.isTraceEnabled()) {
    1735             Main.trace("Clicked on tile: " + clickedTile.getXtile() + ' ' + clickedTile.getYtile() +
    1736                 " currentZoomLevel: " + currentZoomLevel);
    1737         }
    1738         return clickedTile;
     1695            clickedTiles = clickedTiles.peek(t -> Main.trace("Clicked on tile: " + t.getXtile() + ' ' + t.getYtile() +
     1696                    " currentZoomLevel: " + currentZoomLevel));
     1697        }
     1698        return clickedTiles.findAny().orElse(null);
    17391699    }
    17401700
Note: See TracChangeset for help on using the changeset viewer.