package com.robert.maps.applib.overlays; import org.andnav.osm.util.BoundingBoxE6; 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.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; 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.IMoveListener; import com.robert.maps.applib.view.TileView; import com.robert.maps.applib.view.TileViewOverlay; public class TileOverlay extends TileViewOverlay implements OpenStreetMapConstants, OpenStreetMapViewConstants { private TileSource mTileSource; private double mOffsetLat, mOffsetLon; final Matrix mMatrixBearing = new Matrix(); final Rect mRectDraw = new Rect(); final Paint mPaint = new Paint(); private TileMapHandler mTileMapHandler = new TileMapHandler(); private TileView mTileView; private boolean mAsOverlay; private IMoveListener mMoveListener; public TileOverlay(TileView tileView, boolean asOverlay) { super(); mPaint.setFilterBitmap(true); mPaint.setAntiAlias(true); mTileView = tileView; mAsOverlay = asOverlay; mMoveListener = null; } public void setTileSource(TileSource tileSource) { if(mTileSource != null) mTileSource.Free(); mTileSource = tileSource; mTileSource.setHandler(mTileMapHandler); mOffsetLat = mTileSource.OFFSET_LAT; mOffsetLon = mTileSource.OFFSET_LON; } public TileSource getTileSource() { return mTileSource; } public void setMoveListener(IMoveListener moveListener) { mMoveListener = moveListener; } public void setOffset(double lat, double lon) { mOffsetLat = lat; mOffsetLon = lon; } @Override public void Free() { if(mTileSource != null) mTileSource.Free(); super.Free(); } @Override protected void onDraw(Canvas c, TileView tileView) { if (mTileSource != null) { final int tileSizePxNotScale = mTileSource.getTileSizePx(tileView.getZoomLevel()); final int tileSizePx = (int) (tileSizePxNotScale * tileView.mTouchScale); final int[] centerMapTileCoords = Util.getMapTileFromCoordinates(tileView.mLatitudeE6 + (int)(1E6 * mOffsetLat), tileView.mLongitudeE6 + (int)(1E6 * mOffsetLon), tileView.getZoomLevel(), null, mTileSource.PROJECTION); final Point upperLeftCornerOfCenterMapTile = getUpperLeftCornerOfCenterMapTileInScreen(tileView, centerMapTileCoords, tileSizePx, mOffsetLat, mOffsetLon, null); final int centerMapTileScreenLeft = upperLeftCornerOfCenterMapTile.x; final int centerMapTileScreenTop = upperLeftCornerOfCenterMapTile.y; final int mapTileUpperBound = mTileSource.getTileUpperBound(tileView.getZoomLevel()); final int[] mapTileCoords = new int[] { centerMapTileCoords[LATITUDE], centerMapTileCoords[LONGITUDE] }; boolean tileIn = true; int x = 0, y = 0, radius = 0, tilecnt = 0; mMatrixBearing.reset(); mMatrixBearing.setRotate(360 - tileView.getBearing(), tileView.getWidth() / 2, tileView.getHeight() / 2); while (tileIn) { tileIn = false; for(x = -radius; x <= radius; x++) { for(y = -radius; y <= radius; y++) { if(x != -radius && x != radius && y != -radius && y != radius) continue; mapTileCoords[LATITUDE] = MyMath.mod(centerMapTileCoords[LATITUDE] + y, mapTileUpperBound); mapTileCoords[LONGITUDE] = MyMath.mod(centerMapTileCoords[LONGITUDE] + x, mapTileUpperBound); final int tileLeft = centerMapTileScreenLeft + (x * tileSizePx); final int tileTop = centerMapTileScreenTop + (y * tileSizePx); mRectDraw.set(tileLeft, tileTop, tileLeft + tileSizePx, tileTop + tileSizePx); float arr[] = {mRectDraw.left, mRectDraw.top, mRectDraw.right, mRectDraw.top, mRectDraw.right, mRectDraw.bottom, mRectDraw.left, mRectDraw.bottom, mRectDraw.left, mRectDraw.top}; mMatrixBearing.mapPoints(arr); if(Ut.Algorithm.isIntersected((int)(tileView.getWidth()*(1-tileView.mTouchScale)/2), (int)(tileView.getHeight()*(1-tileView.mTouchScale)/2), (int)(tileView.getWidth()*(1+tileView.mTouchScale)/2), (int)(tileView.getHeight()*(1+tileView.mTouchScale)/2), arr)) { tileIn = true; tilecnt++; final Bitmap currentMapTile = this.mTileSource.getTile(mapTileCoords[LONGITUDE], mapTileCoords[LATITUDE], tileView.getZoomLevel()); if (currentMapTile != null) { if (!currentMapTile.isRecycled()) c.drawBitmap(currentMapTile, null, mRectDraw, mPaint); if (tileView.mDrawTileGrid || OpenStreetMapViewConstants.DEBUGMODE) { c.drawLine(tileLeft, tileTop, tileLeft + tileSizePx, tileTop, mPaint); c.drawLine(tileLeft, tileTop, tileLeft, tileTop + tileSizePx, mPaint); c.drawText("y x = " + mapTileCoords[LATITUDE] + " " + mapTileCoords[LONGITUDE] + " zoom " + tileView.getZoomLevel() + " ", tileLeft + 5, tileTop + 15, mPaint); } } } } } radius++; } mTileSource.getTileProvider().ResizeCashe(tilecnt); mTileSource.setReloadTileMode(false); } } @Override protected void onDrawFinished(Canvas c, TileView tileView) { } // TODO ���� ��������� ��� �������� � ��������� private static final int LATITUDE = 0; private static final int LONGITUDE = 1; public Point getUpperLeftCornerOfCenterMapTileInScreen(TileView tileView, final int[] centerMapTileCoords, final int tileSizePx, final Point reuse) { return getUpperLeftCornerOfCenterMapTileInScreen(tileView, centerMapTileCoords, tileSizePx, 0, 0, reuse); } public Point getUpperLeftCornerOfCenterMapTileInScreen(TileView tileView, final int[] centerMapTileCoords, final int tileSizePx, final double offsetLat, final double offsetLon, final Point reuse) { final Point out = (reuse != null) ? reuse : new Point(); final int viewWidth = tileView.getWidth(); final int viewWidth_2 = viewWidth / 2; final int viewHeight = tileView.getHeight(); final int viewHeight_2 = viewHeight / 2; final BoundingBoxE6 bb = Util.getBoundingBoxFromMapTile(centerMapTileCoords, tileView.getZoomLevel(), mTileSource.PROJECTION); final float[] relativePositionInCenterMapTile = bb .getRelativePositionOfGeoPointInBoundingBoxWithLinearInterpolation( tileView.mLatitudeE6 + (int)(1E6 * offsetLat), tileView.mLongitudeE6 + (int)(1E6 * offsetLon), 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; } private class TileMapHandler extends Handler { @Override public void handleMessage(final Message msg) { switch (msg.what) { case MessageHandlerConstants.MAPTILEFSLOADER_SUCCESS_ID: mTileView.invalidate(); break; case MessageHandlerConstants.MAPTILEFSLOADER_INDEXIND_SUCCESS_ID: mTileSource.postIndex(); if(!mAsOverlay) { mTileView.setZoomLevel(mTileView.getZoomLevel()); if(mMoveListener != null) mMoveListener.onZoomDetected(); } break; } } } }