package com.robert.maps.applib.overlays;
import org.andnav.osm.util.BoundingBoxE6;
import org.andnav.osm.util.GeoPoint;
import org.andnav.osm.util.MyMath;
import org.andnav.osm.util.constants.OpenStreetMapConstants;
import org.andnav.osm.views.util.Util;
import org.andnav.osm.views.util.constants.OpenStreetMapViewConstants;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import com.robert.maps.applib.tileprovider.MessageHandlerConstants;
import com.robert.maps.applib.tileprovider.TileSource;
import com.robert.maps.applib.utils.Ut;
import com.robert.maps.applib.view.TileView;
import com.robert.maps.applib.view.TileViewOverlay;
public class YandexTrafficOverlay extends TileViewOverlay implements OpenStreetMapConstants,
OpenStreetMapViewConstants {
private TileView mMapView;
private final Paint mPaint = new Paint();
private TileSource mTileSource;
private SimpleInvalidationHandler mHandler = new SimpleInvalidationHandler();
public YandexTrafficOverlay(Context ctx, TileView mapView) {
mMapView = mapView;
try {
mTileSource = new TileSource(ctx, "yandextraffic");
} catch (Exception e) {
}
mTileSource.setHandler(mHandler);
}
public void Free() {
mTileSource.Free();
}
private static final int LATITUDE = 0;
private static final int LONGITUDE = 1;
@Override
protected void onDraw(Canvas c, TileView osmv) {
final int zoomLevel = mMapView.getZoomLevel();
final int viewWidth = mMapView.getWidth();
final int viewHeight = mMapView.getHeight();
final GeoPoint centerGeoPoint = mMapView.getMapCenter();
if (mTileSource != null) {
}
final int tileSizePxNotScale = mTileSource.getTileSizePx(zoomLevel);
final int tileSizePx = (int)(this.mTileSource.getTileSizePx(zoomLevel) * mMapView.mTouchScale);
final int[] centerMapTileCoords = Util.getMapTileFromCoordinates(centerGeoPoint.getLatitudeE6(), centerGeoPoint.getLongitudeE6(), zoomLevel, null,
mTileSource.PROJECTION);
/*
* Calculate the Latitude/Longitude on the left-upper ScreenCoords
* of the center MapTile. So in the end we can determine which
* MapTiles we additionally need next to the centerMapTile.
*/
final Point upperLeftCornerOfCenterMapTileNotScale = getUpperLeftCornerOfCenterMapTileInScreen(
centerMapTileCoords, tileSizePxNotScale, null);
final int centerMapTileScreenLeftNotScale = upperLeftCornerOfCenterMapTileNotScale.x;
final int centerMapTileScreenTopNotScale = upperLeftCornerOfCenterMapTileNotScale.y;
final int centerMapTileScreenRightNotScale = centerMapTileScreenLeftNotScale
+ tileSizePxNotScale;
final int centerMapTileScreenBottomNotScale = centerMapTileScreenTopNotScale
+ tileSizePxNotScale;
final Point upperLeftCornerOfCenterMapTile = getUpperLeftCornerOfCenterMapTileInScreen(
centerMapTileCoords, tileSizePx, null);
final int centerMapTileScreenLeft = upperLeftCornerOfCenterMapTile.x;
final int centerMapTileScreenTop = upperLeftCornerOfCenterMapTile.y;
final int iDelta = 0;
final int additionalTilesNeededToLeftOfCenter = iDelta
+ (int) Math.ceil((float) centerMapTileScreenLeftNotScale
/ tileSizePxNotScale); // i.e.
final int additionalTilesNeededToRightOfCenter = iDelta
+ (int) Math
.ceil((float) (viewWidth - centerMapTileScreenRightNotScale)
/ tileSizePxNotScale);
final int additionalTilesNeededToTopOfCenter = iDelta
+ (int) Math.ceil((float) centerMapTileScreenTopNotScale
/ tileSizePxNotScale); // i.e.
final int additionalTilesNeededToBottomOfCenter = iDelta
+ (int) Math
.ceil((float) (viewHeight - centerMapTileScreenBottomNotScale)
/ tileSizePxNotScale);
final int mapTileUpperBound = mTileSource.getTileUpperBound(zoomLevel);
final int[] mapTileCoords = new int[] {
centerMapTileCoords[LATITUDE],
centerMapTileCoords[LONGITUDE] };
mTileSource.getTileProvider().ResizeCashe((additionalTilesNeededToTopOfCenter+additionalTilesNeededToBottomOfCenter+1)*(additionalTilesNeededToLeftOfCenter+additionalTilesNeededToRightOfCenter+1));
/* Draw all the MapTiles (from the upper left to the lower right). */
for (int y = -additionalTilesNeededToTopOfCenter; y <= additionalTilesNeededToBottomOfCenter; y++) {
for (int x = -additionalTilesNeededToLeftOfCenter; x <= additionalTilesNeededToRightOfCenter; x++) {
mapTileCoords[LATITUDE] = MyMath.mod(
centerMapTileCoords[LATITUDE] + y,
mapTileUpperBound);
mapTileCoords[LONGITUDE] = MyMath.mod(
centerMapTileCoords[LONGITUDE] + x,
mapTileUpperBound);
final Bitmap currentMapTile = this.mTileSource.getTile(
mapTileCoords[LONGITUDE], mapTileCoords[LATITUDE],
zoomLevel);
if (currentMapTile != null) {
final int tileLeft = centerMapTileScreenLeft + (x * tileSizePx);
final int tileTop = centerMapTileScreenTop + (y * tileSizePx);
final Rect r = new Rect(tileLeft, tileTop, tileLeft
+ tileSizePx, tileTop + tileSizePx);
if (!currentMapTile.isRecycled())
c.drawBitmap(currentMapTile, null, r, mPaint);
}
}
}
mTileSource.getTileProvider().CommitCashe();
}
@Override
protected void onDrawFinished(Canvas c, TileView osmv) {
}
private class SimpleInvalidationHandler extends Handler {
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case MessageHandlerConstants.MAPTILEFSLOADER_SUCCESS_ID:
case Ut.MAPTILEFSLOADER_SUCCESS_ID:
mMapView.invalidate();
break;
}
}
}
private Point getUpperLeftCornerOfCenterMapTileInScreen(final int[] centerMapTileCoords, final int tileSizePx,
final Point reuse) {
final GeoPoint centerGeoPoint = mMapView.getMapCenter();
final Point out = (reuse != null) ? reuse : new Point();
final int viewWidth = mMapView.getWidth();
final int viewWidth_2 = viewWidth / 2;
final int viewHeight = mMapView.getHeight();
final int viewHeight_2 = viewHeight / 2;
/*
* Calculate the Latitude/Longitude on the left-upper ScreenCoords of
* the center MapTile. So in the end we can determine which MapTiles we
* additionally need next to the centerMapTile.
*/
final BoundingBoxE6 bb = Util.getBoundingBoxFromMapTile(centerMapTileCoords,
mMapView.getZoomLevel(), mTileSource.PROJECTION);
final float[] relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithLinearInterpolation(
centerGeoPoint.getLatitudeE6(), centerGeoPoint.getLongitudeE6(), null);
final int centerMapTileScreenLeft = viewWidth_2
- (int) (0.5f + (relativePositionInCenterMapTile[LONGITUDE] * tileSizePx));
final int centerMapTileScreenTop = viewHeight_2
- (int) (0.5f + (relativePositionInCenterMapTile[LATITUDE] * tileSizePx));
out.set(centerMapTileScreenLeft, centerMapTileScreenTop);
return out;
}
}