001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer.imagery; 003 004import java.awt.geom.Point2D; 005import java.awt.geom.Rectangle2D; 006 007import org.openstreetmap.gui.jmapviewer.Tile; 008import org.openstreetmap.gui.jmapviewer.TileXY; 009import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate; 010import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 011import org.openstreetmap.josm.data.coor.LatLon; 012import org.openstreetmap.josm.data.projection.Projecting; 013import org.openstreetmap.josm.data.projection.ShiftedProjecting; 014import org.openstreetmap.josm.gui.MapView; 015import org.openstreetmap.josm.gui.MapViewState.MapViewPoint; 016 017/** 018 * This class handles tile coordinate management and computes their position in the map view. 019 * @author Michael Zangl 020 * @since 10651 021 */ 022public class TileCoordinateConverter { 023 private final MapView mapView; 024 private final TileSourceDisplaySettings settings; 025 private final TileSource tileSource; 026 027 /** 028 * Create a new coordinate converter for the map view. 029 * @param mapView The map view. 030 * @param tileSource The tile source to use when converting coordinates. 031 * @param settings displacement settings. 032 */ 033 public TileCoordinateConverter(MapView mapView, TileSource tileSource, TileSourceDisplaySettings settings) { 034 this.mapView = mapView; 035 this.tileSource = tileSource; 036 this.settings = settings; 037 } 038 039 private MapViewPoint pos(ICoordinate ll) { 040 return mapView.getState().getPointFor(new LatLon(ll)).add(settings.getDisplacement()); 041 } 042 043 /** 044 * Gets the projecting instance to use to convert between latlon and eastnorth coordinates. 045 * @return The {@link Projecting} instance. 046 */ 047 public Projecting getProjecting() { 048 return new ShiftedProjecting(mapView.getProjection(), settings.getDisplacement()); 049 } 050 051 /** 052 * Gets the top left position of the tile inside the map view. 053 * @param tile The tile 054 * @return The positon. 055 */ 056 public Point2D getPixelForTile(Tile tile) { 057 ICoordinate coord = tile.getTileSource().tileXYToLatLon(tile); 058 return pos(coord).getInView(); 059 } 060 061 /** 062 * Gets the position of the tile inside the map view. 063 * @param tile The tile 064 * @return The positon. 065 */ 066 public Rectangle2D getRectangleForTile(Tile tile) { 067 ICoordinate c1 = tile.getTileSource().tileXYToLatLon(tile); 068 ICoordinate c2 = tile.getTileSource().tileXYToLatLon(tile.getXtile() + 1, tile.getYtile() + 1, tile.getZoom()); 069 070 return pos(c1).rectTo(pos(c2)).getInView(); 071 } 072 073 /** 074 * Returns average number of screen pixels per tile pixel for current mapview 075 * @param zoom zoom level 076 * @return average number of screen pixels per tile pixel 077 */ 078 public double getScaleFactor(int zoom) { 079 LatLon topLeft = mapView.getLatLon(0, 0); 080 LatLon botRight = mapView.getLatLon(mapView.getWidth(), mapView.getHeight()); 081 TileXY t1 = tileSource.latLonToTileXY(topLeft.toCoordinate(), zoom); 082 TileXY t2 = tileSource.latLonToTileXY(botRight.toCoordinate(), zoom); 083 084 int screenPixels = mapView.getWidth()*mapView.getHeight(); 085 double tilePixels = Math.abs((t2.getY()-t1.getY())*(t2.getX()-t1.getX())*tileSource.getTileSize()*tileSource.getTileSize()); 086 if (screenPixels == 0 || tilePixels == 0) return 1; 087 return screenPixels/tilePixels; 088 } 089}