package com.robert.maps.applib.view;
import java.util.ArrayList;
import java.util.List;
import org.andnav.osm.util.BoundingBoxE6;
import org.andnav.osm.util.GeoPoint;
import org.andnav.osm.views.util.Util;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.preference.PreferenceManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import com.robert.maps.applib.overlays.TileOverlay;
import com.robert.maps.applib.reflection.OnExGestureListener;
import com.robert.maps.applib.reflection.RGestureHelper;
import com.robert.maps.applib.reflection.VerGestureDetector;
import com.robert.maps.applib.reflection.VerScaleGestureDetector;
import com.robert.maps.applib.tileprovider.TileSource;
public class TileView extends View {
private static final int LATITUDE = 0;
private static final int LONGITUDE = 1;
public int mLatitudeE6 = 0, mLongitudeE6 = 0;
private double mOffsetLat, mOffsetLon;
private int mZoom = 0;
private float mBearing = 0;
final Paint mPaint = new Paint();
final Matrix mMatrixBearing = new Matrix();
final Rect mRectDraw = new Rect();
public final boolean mDrawTileGrid;
private boolean mStopProcessing;
private boolean mSetOffsetMode;
public double mTouchScale = 1;
private TileSource mTileSource;
//private TileMapHandler mTileMapHandler = new TileMapHandler();
protected final List<TileViewOverlay> mOverlays = new ArrayList<TileViewOverlay>();
private TileOverlay mTileOverlay;
private GestureDetector mDetector = VerGestureDetector.newInstance().getGestureDetector(getContext(), new TouchListener());
private VerScaleGestureDetector mScaleDetector = VerScaleGestureDetector.newInstance(getContext(), new ScaleListener());
private class ScaleListener implements VerScaleGestureDetector.OnGestureListener {
// private double mPrevScaleFactor = 1.0;
public void onScale(double aScaleFactor) {
mTouchScale = aScaleFactor;
// mTouchScale = mPrevScaleFactor + (aScaleFactor >= 1.0 ? (aScaleFactor /*- 1.0*/) : (1 - 1 / aScaleFactor));
// if(mTouchScale < 0.0)
// mTouchScale = - 1 / mTouchScale;
// Ut.e("aScaleFactor = "+aScaleFactor+" mTouchScale="+mTouchScale+" d="+(aScaleFactor >= 1.0 ? (aScaleFactor - 1.0) : (1 - 1 / aScaleFactor)));
if(mMoveListener != null)
mMoveListener.onZoomDetected();
invalidate(); //postInvalidate();
}
public void onScaleEnd() {
int zoom = 0;
if(mTileSource.ZOOM_MAXLEVEL == getZoomLevel() && mTouchScale > 1) {
// mPrevScaleFactor = mTouchScale;
return;
} else if(mTouchScale > 1) {
// mPrevScaleFactor = 1.0;
zoom = getZoomLevel()+(int)Math.round(mTouchScale)-1;
} else {
// mPrevScaleFactor = 1.0;
zoom = getZoomLevel()-(int)Math.round(1/mTouchScale)+1;
}
setZoomLevel(zoom);
}
}
private class TouchListener implements OnExGestureListener {
public boolean onDown(MotionEvent e) {
for (TileViewOverlay osmvo : mOverlays) {
if(osmvo.onDown(e, TileView.this))
break;
}
return true;
}
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public boolean onSingleTapConfirmed(MotionEvent e) {
for (TileViewOverlay osmvo : mOverlays)
if (osmvo.onSingleTapUp(e, TileView.this)) {
invalidate();
return true;
}
invalidate();
return false;
}
public void onLongPress(MotionEvent e) {
int ret = 0;
for (TileViewOverlay osmvo : mOverlays) {
ret = osmvo.onLongPress(e, TileView.this);
if(ret == 1) {
break;
} else if(ret == 2) {
return;
}
}
showContextMenu();
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
for (TileViewOverlay osmvo : mOverlays) {
if(osmvo.onScroll(e1, e2, distanceX, distanceY, TileView.this))
return false;
}
final float aRotateToAngle = 360 - mBearing;
final int viewWidth_2 = TileView.this.getWidth() / 2;
final int viewHeight_2 = TileView.this.getHeight() / 2;
final int TouchMapOffsetX = (int) (Math.sin(Math.toRadians(aRotateToAngle)) * (distanceY / mTouchScale))
+ (int) (Math.cos(Math.toRadians(aRotateToAngle)) * (distanceX / mTouchScale));
final int TouchMapOffsetY = (int) (Math.cos(Math.toRadians(aRotateToAngle)) * (distanceY / mTouchScale))
- (int) (Math.sin(Math.toRadians(aRotateToAngle)) * (distanceX / mTouchScale));
final GeoPoint newCenter = TileView.this.getProjection().fromPixels(viewWidth_2 + TouchMapOffsetX,
viewHeight_2 + TouchMapOffsetY);
if(mSetOffsetMode && ((RGestureHelper) mDetector).getPointerCount(e2) == 1) {
mOffsetLat = mOffsetLat + (newCenter.getLatitudeE6() - mLatitudeE6) / 1E6;
mOffsetLon = mOffsetLon + (newCenter.getLongitudeE6() - mLongitudeE6) / 1E6;
mTileOverlay.setOffset(mOffsetLat, mOffsetLon);
TileView.this.invalidate(); //postInvalidate();
} else {
TileView.this.setMapCenter(newCenter);
}
if (mMoveListener != null)
mMoveListener.onMoveDetected();
return false;
}
public boolean onDoubleTap(MotionEvent e) {
if (mBearing != 0) {
mBearing = 0;
} else {
final GeoPoint newCenter = TileView.this.getProjection().fromPixels(e.getX(), e.getY());
setMapCenter(newCenter);
setZoomLevel(getZoomLevel() + 1);
}
return true;
}
public void onShowPress(MotionEvent e) {
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
public void onUp(MotionEvent e) {
for (TileViewOverlay osmvo : mOverlays) {
osmvo.onUp(e, TileView.this);
}
}
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
}
// private class TileMapHandler extends Handler {
//
// @Override
// public void handleMessage(final Message msg) {
// switch (msg.what) {
// case MessageHandlerConstants.MAPTILEFSLOADER_SUCCESS_ID:
// invalidate();
// break;
// case MessageHandlerConstants.MAPTILEFSLOADER_INDEXIND_SUCCESS_ID:
// mTileSource.postIndex();
// setZoomLevel(getZoomLevel());
// if(mMoveListener != null)
// mMoveListener.onZoomDetected();
// break;
// }
// }
// }
public TileView(Context context) {
super(context);
mPaint.setFilterBitmap(true);
mPaint.setAntiAlias(true);
final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
mDrawTileGrid = pref.getBoolean("pref_drawtilegrid", false);
mSetOffsetMode = false;
setFocusable(true);
setFocusableInTouchMode(true);
mTileOverlay = new TileOverlay(this, false);
}
public PoiMenuInfo mPoiMenuInfo = new PoiMenuInfo(-1);
public class PoiMenuInfo implements ContextMenuInfo {
public int MarkerIndex;
public GeoPoint EventGeoPoint;
public double Elevation;
public PoiMenuInfo(int markerIndex) {
super();
MarkerIndex = markerIndex;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
for (TileViewOverlay osmvo : mOverlays) {
if(osmvo.onKeyDown(keyCode, event, TileView.this))
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
boolean result = false;
if(!mDisableControl) {
mScaleDetector.onTouchEvent(event);
result = mDetector.onTouchEvent(event);
if (!result) {
if (event.getAction() == MotionEvent.ACTION_UP) {
result = true;
}
}
}
return result;
}
@Override
protected void onDraw(Canvas c) {
c.save();
final float aRotateToAngle = 360 - mBearing;
c.rotate(aRotateToAngle, this.getWidth() / 2, this.getHeight() / 2);
c.drawRGB(255, 255, 255);
if (mTileSource != null) {
mTileOverlay.onManagedDraw(c, this);
/* Draw all Overlays. */
for (TileViewOverlay osmvo : this.mOverlays)
osmvo.onManagedDraw(c, this);
}
c.restore();
super.onDraw(c);
}
public List<TileViewOverlay> getOverlays() {
return mOverlays;
}
public void setTileSource(TileSource tileSource) {
if(mTileSource != null)
mTileSource.Free();
mTileSource = tileSource;
//mTileSource.setHandler(mTileMapHandler);
mOffsetLat = mTileSource.OFFSET_LAT;
mOffsetLon = mTileSource.OFFSET_LON;
mTileOverlay.setTileSource(tileSource);
setZoomLevel(getZoomLevel());
invalidate();
}
public TileSource getTileSource() {
return mTileSource;
}
public void setMapCenter(final GeoPoint aCenter) {
this.setMapCenter(aCenter.getLatitudeE6(), aCenter.getLongitudeE6());
}
public void setMapCenter(final double aLatitude, final double aLongitude) {
this.setMapCenter((int) (aLatitude * 1E6), (int) (aLongitude * 1E6));
}
public void setMapCenter(final int aLatitudeE6, final int aLongitudeE6) {
this.setMapCenter(aLatitudeE6, aLongitudeE6, true);
}
public GeoPoint getMapCenter() {
return new GeoPoint(this.mLatitudeE6, this.mLongitudeE6);
}
protected void setMapCenter(final int aLatitudeE6, final int aLongitudeE6,
final boolean doPassFurther) {
this.mLatitudeE6 = aLatitudeE6;
this.mLongitudeE6 = aLongitudeE6;
if(mMoveListener != null)
mMoveListener.onCenterDetected();
this.postInvalidate();
}
public int getZoomLevel() {
return mZoom;
}
public double getZoomLevelScaled() {
if(mTouchScale == 1)
return getZoomLevel();
else if(mTouchScale > 1)
return getZoomLevel()+Math.round(mTouchScale)-1;
else
return getZoomLevel()-Math.round(1/mTouchScale)+1;
}
public void setZoomLevel(final int zoom) {
if(mTileSource == null)
mZoom = zoom;
else
mZoom = Math.max(mTileSource.ZOOM_MINLEVEL, Math.min(mTileSource.ZOOM_MAXLEVEL, zoom));
mTouchScale = 1;
if(mMoveListener != null)
mMoveListener.onZoomDetected();
this.postInvalidate();
}
public void setBearing(final float aBearing){
this.mBearing = aBearing;
}
public float getBearing() {
return this.mBearing;
}
public OpenStreetMapViewProjection getProjection() {
return new OpenStreetMapViewProjection();
}
public OpenStreetMapViewProjection getProjection(int zoom, double touchScale) {
return new OpenStreetMapViewProjection(zoom, touchScale);
}
public class OpenStreetMapViewProjection {
final int viewWidth;
final int viewHeight;
final BoundingBoxE6 bb;
final int zoomLevel;
final int tileSizePx;
final int[] centerMapTileCoords;
final Point upperLeftCornerOfCenterMapTile;
public OpenStreetMapViewProjection() {
this(mZoom, mTouchScale);
}
public OpenStreetMapViewProjection(int zoom, double touchScale) {
viewWidth = getWidth();
viewHeight = getHeight();
/*
* Do some calculations and drag attributes to local variables to
* save some performance.
*/
zoomLevel = zoom; // LATER Draw to
// attributes and so
// make it only
// 'valid' for a
// short time.
tileSizePx = (int)(mTileSource.getTileSizePx(zoomLevel) * touchScale);
/*
* Get the center MapTile which is above this.mLatitudeE6 and
* this.mLongitudeE6 .
*/
centerMapTileCoords = Util.getMapTileFromCoordinates(
mLatitudeE6, mLongitudeE6,
zoomLevel, null, mTileSource.PROJECTION);
upperLeftCornerOfCenterMapTile = mTileOverlay.getUpperLeftCornerOfCenterMapTileInScreen(TileView.this,
centerMapTileCoords, tileSizePx, null);
bb = getDrawnBoundingBoxE6();
}
/**
* Converts x/y ScreenCoordinates to the underlying GeoPoint.
*
* @param x
* @param y
* @return GeoPoint under x/y.
*/
public GeoPoint fromPixels(float x, float y) {
/* Subtract the offset caused by touch. */
//Log.d(DEBUGTAG, "x = "+x+" mTouchMapOffsetX = "+mTouchMapOffsetX+" ");
x -= 0;
y -= 0;
//int xx = centerMapTileCoords[0]*tileSizePx+(int)x-upperLeftCornerOfCenterMapTile.x;
//int asd = Util.x2lon(xx, zoomLevel, tileSizePx);
GeoPoint p = bb.getGeoPointOfRelativePositionWithLinearInterpolation(x / viewWidth, y
/ viewHeight);
//Log.d(DEBUGTAG, "lon "+p.getLongitudeE6()+" "+xx+" "+asd+" OffsetX = "+mTouchMapOffsetX);
//Log.d(DEBUGTAG, " "+centerMapTileCoords[0]+" "+tileSizePx+" "+x+" "+upperLeftCornerOfCenterMapTile.x);
//p.setLongitudeE6(asd);
//for(int i =0; i<=tileSizePx*(1<<zoomLevel); i++){int Q = Util.x2lon(i, zoomLevel, tileSizePx);Log.d(DEBUGTAG, "lon "+i+" "+Q);}
return p;
}
public GeoPoint fromPixels(float x, float y, double bearing){
final int x1 = (int) (x - getWidth()/2);
final int y1 = (int) (y - getHeight()/2);
final double hypot = Math.hypot(x1, y1);
final double angle = -1 * Math.signum(y1) * Math.toDegrees(Math.acos(x1/hypot));
final double angle2 = angle - bearing;
final int x2 = (int)(Math.cos(Math.toRadians(angle2))*hypot);
final int y2 = (int)(Math.sin(Math.toRadians(angle2-180))*hypot);
return fromPixels((float)(getWidth()/2 + x2), (float)(getHeight()/2 + y2));
}
private static final int EQUATORCIRCUMFENCE = 40075676; //40075004;
public float metersToEquatorPixels(final float aMeters) {
return aMeters / EQUATORCIRCUMFENCE
* mTileSource.getTileSizePx(zoomLevel);
}
/**
* Converts a GeoPoint to its ScreenCoordinates. <br/>
* <br/>
* <b>CAUTION</b> ! Conversion currently has a large error on
* <code>zoomLevels <= 7</code>.<br/>
* The Error on ZoomLevels higher than 7, the error is below
* <code>1px</code>.<br/>
* LATER: Add a linear interpolation to minimize this error.
*
* <PRE>
* Zoom Error(m) Error(px)
* 11 6m 1/12px
* 10 24m 1/6px
* 8 384m 1/2px
* 6 6144m 3px
* 4 98304m 10px
* </PRE>
*
* @param in
* the GeoPoint you want the onScreenCoordinates of.
* @param reuse
* just pass null if you do not have a Point to be
* 'recycled'.
* @return the Point containing the approximated ScreenCoordinates of
* the GeoPoint passed.
*/
public Point toPixels(final GeoPoint in, final Point reuse) {
return toPixels(in, reuse, true);
}
public Point toPixels(final GeoPoint in, final double bearing, final Point reuse){
final Point point = toPixels(in, reuse, true);
final Point out = (reuse != null) ? reuse : new Point();
final int x1 = point.x - getWidth()/2;
final int y1 = point.y - getHeight()/2;
final double hypot = Math.hypot(x1, y1);
final double angle = -1 * Math.signum(y1) * Math.toDegrees(Math.acos(x1/hypot));
final double angle2 = angle + bearing;
final int x2 = (int)(Math.cos(Math.toRadians(angle2))*hypot);
final int y2 = (int)(Math.sin(Math.toRadians(angle2-180))*hypot);
out.set(getWidth()/2 + x2, getHeight()/2 + y2);
return out;
}
protected Point toPixels(final GeoPoint in, final Point reuse, final boolean doGudermann) {
final Point out = (reuse != null) ? reuse : new Point();
final int[] underGeopointTileCoords = Util.getMapTileFromCoordinates(
in.getLatitudeE6(), in.getLongitudeE6(), zoomLevel, null, mTileSource.PROJECTION);
/*
* Calculate the Latitude/Longitude on the left-upper ScreenCoords
* of the MapTile.
*/
final BoundingBoxE6 bb = Util.getBoundingBoxFromMapTile(underGeopointTileCoords,
zoomLevel, mTileSource.PROJECTION);
final float[] relativePositionInCenterMapTile;
if (doGudermann && zoomLevel < 7)
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithExactGudermannInterpolation(
in.getLatitudeE6(), in.getLongitudeE6(), null);
else
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithLinearInterpolation(in
.getLatitudeE6(), in.getLongitudeE6(), null);
final int tileDiffX = centerMapTileCoords[LONGITUDE]
- underGeopointTileCoords[LONGITUDE];
final int tileDiffY = centerMapTileCoords[LATITUDE]
- underGeopointTileCoords[LATITUDE];
final int underGeopointTileScreenLeft = upperLeftCornerOfCenterMapTile.x
- (tileSizePx * tileDiffX);
final int underGeopointTileScreenTop = upperLeftCornerOfCenterMapTile.y
- (tileSizePx * tileDiffY);
final int x = underGeopointTileScreenLeft
+ (int) (relativePositionInCenterMapTile[LONGITUDE] * tileSizePx);
final int y = underGeopointTileScreenTop
+ (int) (relativePositionInCenterMapTile[LATITUDE] * tileSizePx);
/* Add up the offset caused by touch. */
out.set(x + 0, y
+ 0);
return out;
}
public Point toPixels2(final GeoPoint in) {
final Point out = new Point();
final boolean doGudermann = true;
final int[] underGeopointTileCoords = Util.getMapTileFromCoordinates(
in.getLatitudeE6(), in.getLongitudeE6(), zoomLevel, null, mTileSource.PROJECTION);
/*
* Calculate the Latitude/Longitude on the left-upper ScreenCoords
* of the MapTile.
*/
final BoundingBoxE6 bb = Util.getBoundingBoxFromMapTile(underGeopointTileCoords,
zoomLevel, mTileSource.PROJECTION);
final float[] relativePositionInCenterMapTile;
if (doGudermann && zoomLevel < 7)
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithExactGudermannInterpolation(
in.getLatitudeE6(), in.getLongitudeE6(), null);
else
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithLinearInterpolation(in
.getLatitudeE6(), in.getLongitudeE6(), null);
final int tileDiffX = centerMapTileCoords[LONGITUDE]
- underGeopointTileCoords[LONGITUDE];
final int tileDiffY = centerMapTileCoords[LATITUDE]
- underGeopointTileCoords[LATITUDE];
final int underGeopointTileScreenLeft = upperLeftCornerOfCenterMapTile.x
- (tileSizePx * tileDiffX);
final int underGeopointTileScreenTop = upperLeftCornerOfCenterMapTile.y
- (tileSizePx * tileDiffY);
final int x = underGeopointTileScreenLeft
+ (int) (relativePositionInCenterMapTile[LONGITUDE] * tileSizePx);
final int y = underGeopointTileScreenTop
+ (int) (relativePositionInCenterMapTile[LATITUDE] * tileSizePx);
/* Add up the offset caused by touch. */
out.set(x, y);
return out;
}
public Path toPixels(final List<GeoPoint> in, final Path reuse) {
return toPixels(in, reuse, true);
}
protected Path toPixels(final List<GeoPoint> in, final Path reuse, final boolean doGudermann)
throws IllegalArgumentException {
if (in.size() < 2)
throw new IllegalArgumentException("List of GeoPoints needs to be at least 2.");
final Path out = (reuse != null) ? reuse : new Path();
int i = 0;
for (GeoPoint gp : in) {
i++;
final int[] underGeopointTileCoords = Util.getMapTileFromCoordinates(gp
.getLatitudeE6(), gp.getLongitudeE6(), zoomLevel, null, mTileSource.PROJECTION);
/*
* Calculate the Latitude/Longitude on the left-upper
* ScreenCoords of the MapTile.
*/
final BoundingBoxE6 bb = Util.getBoundingBoxFromMapTile(underGeopointTileCoords,
zoomLevel, mTileSource.PROJECTION);
final float[] relativePositionInCenterMapTile;
if (doGudermann && zoomLevel < 7)
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithExactGudermannInterpolation(
gp.getLatitudeE6(), gp.getLongitudeE6(), null);
else
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithLinearInterpolation(gp
.getLatitudeE6(), gp.getLongitudeE6(), null);
final int tileDiffX = centerMapTileCoords[LONGITUDE]
- underGeopointTileCoords[LONGITUDE];
final int tileDiffY = centerMapTileCoords[LATITUDE]
- underGeopointTileCoords[LATITUDE];
final int underGeopointTileScreenLeft = upperLeftCornerOfCenterMapTile.x
- (tileSizePx * tileDiffX);
final int underGeopointTileScreenTop = upperLeftCornerOfCenterMapTile.y
- (tileSizePx * tileDiffY);
final int x = underGeopointTileScreenLeft
+ (int) (relativePositionInCenterMapTile[LONGITUDE] * tileSizePx);
final int y = underGeopointTileScreenTop
+ (int) (relativePositionInCenterMapTile[LATITUDE] * tileSizePx);
/* Add up the offset caused by touch. */
if (i == 0)
out.moveTo(x, y);
else
out.lineTo(x, y);
}
return out;
}
public void StopProcessing() {
mStopProcessing = true;
}
private boolean Stop() {
if(mStopProcessing) {
mStopProcessing = false;
return true;
}
return false;
}
public Path toPixelsTrackPoints(Cursor cursor, Point baseCoord, GeoPoint baseLocation) throws IllegalArgumentException {
mStopProcessing = false;
Path out = new Path();
final boolean doGudermann = true;
int lat, lon;
int i = 0;
int lastX = 0, lastY = 0;
if(cursor != null) {
if(cursor.moveToFirst()) {
do {
if(Stop()) {
out = null;
break;
}
lat = (int) (cursor.getDouble(0) * 1E6);
lon = (int) (cursor.getDouble(1) * 1E6);
final int[] underGeopointTileCoords = Util.getMapTileFromCoordinates(lat, lon, zoomLevel, null, mTileSource.PROJECTION);
/*
* Calculate the Latitude/Longitude on the left-upper ScreenCoords of the MapTile.
*/
final BoundingBoxE6 bb = Util.getBoundingBoxFromMapTile(underGeopointTileCoords, zoomLevel,
mTileSource.PROJECTION);
final float[] relativePositionInCenterMapTile;
if (doGudermann && zoomLevel < 7)
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithExactGudermannInterpolation(lat, lon, null);
else
relativePositionInCenterMapTile = bb
.getRelativePositionOfGeoPointInBoundingBoxWithLinearInterpolation(lat, lon, null);
final int tileDiffX = centerMapTileCoords[LONGITUDE]
- underGeopointTileCoords[LONGITUDE];
final int tileDiffY = centerMapTileCoords[LATITUDE]
- underGeopointTileCoords[LATITUDE];
final int underGeopointTileScreenLeft = upperLeftCornerOfCenterMapTile.x - (tileSizePx * tileDiffX);
final int underGeopointTileScreenTop = upperLeftCornerOfCenterMapTile.y - (tileSizePx * tileDiffY);
final int x = underGeopointTileScreenLeft
+ (int) (relativePositionInCenterMapTile[LONGITUDE] * tileSizePx);
final int y = underGeopointTileScreenTop
+ (int) (relativePositionInCenterMapTile[LATITUDE] * tileSizePx);
/* Add up the offset caused by touch. */
if (i == 0) {
out.setLastPoint(x, y);
lastX = x;
lastY = y;
baseCoord.x = x;
baseCoord.y = y;
baseLocation.setCoordsE6(lat, lon);
i++;
} else {
if (Math.abs(lastX - x) > 5 || Math.abs(lastY - y) > 5) {
out.lineTo(x, y);
lastX = x;
lastY = y;
i++;
}
}
} while(cursor.moveToNext());
}
cursor.close();
}
return out;
}
}
private IMoveListener mMoveListener;
private boolean mDisableControl;
// TODO ���� ��������� ��� �������� � ���������
public BoundingBoxE6 getVisibleBoundingBoxE6() {
// final ViewParent parent = this.getParent();
// if(parent instanceof RotateView){
// final RotateView par = (RotateView)parent;
// return getBoundingBox(par.getMeasuredWidth(), par.getMeasuredHeight());
// }else{
return getBoundingBox(this.getWidth(), this.getHeight());
// }
}
private BoundingBoxE6 getBoundingBox(final int pViewWidth, final int pViewHeight){
/* Get the center MapTile which is above this.mLatitudeE6 and this.mLongitudeE6 .*/
final int[] centerMapTileCoords = Util.getMapTileFromCoordinates(this.mLatitudeE6, this.mLongitudeE6, this.mZoom, null, this.mTileSource.PROJECTION);
final BoundingBoxE6 tmp = Util.getBoundingBoxFromMapTile(centerMapTileCoords, this.mZoom, mTileSource.PROJECTION);
final int mLatitudeSpan_2 = (int)(1.0f * tmp.getLatitudeSpanE6() * pViewHeight / this.mTileSource.getTileSizePx(this.mZoom)) / 2;
final int mLongitudeSpan_2 = (int)(1.0f * tmp.getLongitudeSpanE6() * pViewWidth / this.mTileSource.getTileSizePx(this.mZoom)) / 2;
final int north = this.mLatitudeE6 + mLatitudeSpan_2;
final int south = this.mLatitudeE6 - mLatitudeSpan_2;
final int west = this.mLongitudeE6 - mLongitudeSpan_2;
final int east = this.mLongitudeE6 + mLongitudeSpan_2;
return new BoundingBoxE6(north, east, south, west);
}
public BoundingBoxE6 getDrawnBoundingBoxE6() {
return getBoundingBox(this.getWidth(), this.getHeight());
}
public void setMoveListener(IMoveListener moveListener) {
mMoveListener = moveListener;
mTileOverlay.setMoveListener(moveListener);
}
public void setDisableControl(boolean b) {
mDisableControl = true;
}
public double[] getCurrentOffset() {
final double[] offset = {mOffsetLat, mOffsetLon};
return offset;
}
public void setOffsetMode(boolean mode) {
mSetOffsetMode = mode;
}
}