package org.osmdroid.google.overlay; import org.osmdroid.tileprovider.MapTile; import org.osmdroid.tileprovider.MapTileProviderBase; import org.osmdroid.util.MyMath; import org.osmdroid.views.util.Mercator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.Log; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; import com.google.android.maps.Projection; import org.osmdroid.thirdparty.Constants; /** * This class represents an OSM Tiles Overlay at a Google Map. It is a copy from * the class org.osmdroid.views.overlay.TilesOverlay (r789) (formerly known as * org.andnav.osm.views.overlay.OpenStreetMapTilesOverlay) and modified to make * it working. * */ public class GoogleTilesOverlay extends Overlay { private static final boolean DEBUGMODE = false; /** Current tile source */ protected final MapTileProviderBase mTileProvider; /* to avoid allocations during draw */ protected final Paint mPaint = new Paint(); private final Rect mTileRect = new Rect(); private final Point mTilePos = new Point(); public GoogleTilesOverlay(final MapTileProviderBase aTileProvider, final Context aContext) { this(aTileProvider); } public GoogleTilesOverlay(final MapTileProviderBase aTileProvider) { // Original line in org.osmdroid.views.overlay.TilesOverlay.java // super(pResourceProxy); if (aTileProvider == null) { throw new IllegalArgumentException("You must pass a valid tile provider to the tiles overlay."); } this.mTileProvider = aTileProvider; } public void setAlpha(final int a) { this.mPaint.setAlpha(a); } public int getMinimumZoomLevel() { return mTileProvider.getMinimumZoomLevel(); } public int getMaximumZoomLevel() { return mTileProvider.getMaximumZoomLevel(); } /** * Whether to use the network connection if it's available. */ public boolean useDataConnection() { return mTileProvider.useDataConnection(); } /** * Set whether to use the network connection if it's available. * * @param aMode * if true use the network connection if it's available. if false * don't use the network connection even if it's available. */ public void setUseDataConnection(final boolean aMode) { mTileProvider.setUseDataConnection(aMode); } @Override public void draw(final Canvas c, final MapView osmv, final boolean shadow) { if (DEBUGMODE) { Log.d(Constants.LOGTAG, "draw"); } // Calculate the half-world size final Projection pj = osmv.getProjection(); final int zoomLevel = osmv.getZoomLevel() - 1; final int tileSizePx = this.mTileProvider.getTileSource().getTileSizePixels(); // Calculate the tiles needed for each side around the center one. final int latSpan = osmv.getLatitudeSpan(); final int longSpan = osmv.getLongitudeSpan(); final int topLatitude = osmv.getMapCenter().getLatitudeE6() + latSpan/2; final int leftLongitude = osmv.getMapCenter().getLongitudeE6() - longSpan/2; final int bottomLatitude = osmv.getMapCenter().getLatitudeE6() - latSpan/2; final int rightLongitude = osmv.getMapCenter().getLongitudeE6() + longSpan/2; final Point leftTopXY = Mercator.projectGeoPoint(topLatitude*1E-6, leftLongitude*1E-6, zoomLevel, new Point(0,0)); final Point rightBottomXY = Mercator.projectGeoPoint(bottomLatitude*1E-6, rightLongitude*1E-6, zoomLevel, new Point(0,0)); final int tileNeededAtLeft = leftTopXY.x; final int tileNeededAtRight = rightBottomXY.x; final int tileNeededAtTop = leftTopXY.y; final int tileNeededAtBottom = rightBottomXY.y; final int mapTileUpperBound = 1 << zoomLevel; // make sure the cache is big enough for all the tiles final int numNeeded = (tileNeededAtBottom - tileNeededAtTop + 1) * (tileNeededAtRight - tileNeededAtLeft + 1); mTileProvider.ensureCapacity(numNeeded); /* Draw all the MapTiles (from the upper left to the lower right). */ for (int y = tileNeededAtTop; y <= tileNeededAtBottom; y++) { for (int x = tileNeededAtLeft; x <= tileNeededAtRight; x++) { // Construct a MapTile to request from the tile provider. final int tileY = MyMath.mod(y, mapTileUpperBound); final int tileX = MyMath.mod(x, mapTileUpperBound); final MapTile tile = new MapTile(zoomLevel, tileX, tileY); final Drawable currentMapTile = mTileProvider.getMapTile(tile); if (currentMapTile != null) { final GeoPoint gp = new GeoPoint( (int) (Mercator.tile2lat(y, zoomLevel) * 1E6), (int) (Mercator.tile2lon(x, zoomLevel) * 1E6)); pj.toPixels(gp, mTilePos); mTileRect.set(mTilePos.x, mTilePos.y, mTilePos.x + tileSizePx, mTilePos.y + tileSizePx); currentMapTile.setBounds(mTileRect); currentMapTile.draw(c); } if (DEBUGMODE) { c.drawText(tile.toString(), mTileRect.left + 1, mTileRect.top + mPaint.getTextSize(), mPaint); c.drawLine(mTileRect.left, mTileRect.top, mTileRect.right, mTileRect.top, mPaint); c.drawLine(mTileRect.left, mTileRect.top, mTileRect.left, mTileRect.bottom, mPaint); } } } // draw a cross at center in debug mode if (DEBUGMODE) { final GeoPoint center = osmv.getMapCenter(); final Point centerPoint = pj.toPixels(center, null); c.drawLine(centerPoint.x, centerPoint.y - 9, centerPoint.x, centerPoint.y + 9, mPaint); c.drawLine(centerPoint.x - 9, centerPoint.y, centerPoint.x + 9, centerPoint.y, mPaint); } } }