moving all animation to MapViewPostion,

- this also allows TileManager to predict next visible tiles
- got rid of zoom-level dependent scale
This commit is contained in:
Hannes Janetzek 2013-03-13 03:01:37 +01:00
parent 246fd40f7a
commit 6b39c95905

View File

@ -21,17 +21,19 @@ import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint; import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.MercatorProjection; import org.oscim.core.MercatorProjection;
import org.oscim.core.Point2D; import org.oscim.core.PointD;
import org.oscim.core.PointF;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.utils.FastMath; import org.oscim.utils.FastMath;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
import android.graphics.Point;
import android.opengl.Matrix; import android.opengl.Matrix;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller; import android.widget.Scroller;
/** /**
@ -48,6 +50,9 @@ public class MapViewPosition {
public final static double MAX_SCALE = ((1 << MAX_ZOOMLEVEL) * MAX_END_SCALE); public final static double MAX_SCALE = ((1 << MAX_ZOOMLEVEL) * MAX_END_SCALE);
public final static double MIN_SCALE = (1 << MIN_ZOOMLEVEL); public final static double MIN_SCALE = (1 << MIN_ZOOMLEVEL);
// needs to fit for int: 2 * 20 * Tile.TILE_SIZE
public final static int ABS_ZOOMLEVEL = 20;
private final static float MAX_ANGLE = 65; private final static float MAX_ANGLE = 65;
private final MapView mMapView; private final MapView mMapView;
@ -55,26 +60,24 @@ public class MapViewPosition {
private double mLatitude; private double mLatitude;
private double mLongitude; private double mLongitude;
private double mMapScale; private double mAbsScale;
private double mAbsX;
private double mAbsY;
// mMapScale * Tile.TILE_SIZE // mAbsScale * Tile.TILE_SIZE
// i.e. size of tile 0/0/0 at current scale in pixel // i.e. size of tile 0/0/0 at current scale in pixel
private double mTileScale; private double mCurScale;
// mAbsX * mCurScale
private double mCurX;
// mAbsY * mCurScale
private double mCurY;
private float mRotation; private float mRotation;
public float mTilt; public float mTilt;
// map center in tile coordinates of current zoom-level
//private double mPosX;
//private double mPosY;
// NB: mMapScale == 2^mZoomLevel * mScale;
private byte mZoomLevel;
// 1.0 - 2.0 scale per level
private float mScale;
private final AnimationHandler mHandler; private final AnimationHandler mHandler;
private final Scroller mScroller; private final Scroller mScroller;
MapViewPosition(MapView mapView) { MapViewPosition(MapView mapView) {
@ -83,10 +86,16 @@ public class MapViewPosition {
mLongitude = Double.NaN; mLongitude = Double.NaN;
mRotation = 0.0f; mRotation = 0.0f;
mTilt = 0; mTilt = 0;
mMapScale = 1; mAbsScale = 1;
mHandler = new AnimationHandler(this); mHandler = new AnimationHandler(this);
mScroller = new Scroller(mapView.getContext()); mScroller = new Scroller(mapView.getContext(), new LinearInterpolator() {
@Override
public float getInterpolation(float input) {
return (float) Math.sqrt(input);
}
});
} }
private final float[] mProjMatrix = new float[16]; private final float[] mProjMatrix = new float[16];
@ -98,7 +107,7 @@ public class MapViewPosition {
private final float[] mTmpMatrix = new float[16]; private final float[] mTmpMatrix = new float[16];
// temporary vars: only use in synchronized functions! // temporary vars: only use in synchronized functions!
private final Point2D mMovePoint = new Point2D(); private final PointD mMovePoint = new PointD();
private final float[] mv = new float[4]; private final float[] mv = new float[4];
private final float[] mu = new float[4]; private final float[] mu = new float[4];
private final float[] mBBoxCoords = new float[8]; private final float[] mBBoxCoords = new float[8];
@ -137,17 +146,18 @@ public class MapViewPosition {
*/ */
public synchronized boolean getMapPosition(MapPosition pos) { public synchronized boolean getMapPosition(MapPosition pos) {
updateTileScale(); int z = FastMath.log2((int) mAbsScale);
z = FastMath.clamp(z, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
float scale = (float) (mAbsScale / (1 << z));
if (pos.lat == mLatitude if (pos.lat == mLatitude
&& pos.lon == mLongitude && pos.lon == mLongitude
&& pos.zoomLevel == mZoomLevel && pos.zoomLevel == z
&& pos.scale == mScale && pos.scale == scale
&& pos.angle == mRotation && pos.angle == mRotation
&& pos.tilt == mTilt) && pos.tilt == mTilt)
return false; return false;
byte z = mZoomLevel;
pos.lat = mLatitude; pos.lat = mLatitude;
pos.lon = mLongitude; pos.lon = mLongitude;
@ -155,11 +165,11 @@ public class MapViewPosition {
pos.tilt = mTilt; pos.tilt = mTilt;
// for tiling // for tiling
pos.scale = mScale; pos.scale = scale;
pos.zoomLevel = z; pos.zoomLevel = (byte)z;
pos.x = mAbsX * (Tile.TILE_SIZE << mZoomLevel); pos.x = mAbsX * (Tile.TILE_SIZE << z);
pos.y = mAbsY * (Tile.TILE_SIZE << mZoomLevel); pos.y = mAbsY * (Tile.TILE_SIZE << z);
return true; return true;
} }
@ -256,9 +266,12 @@ public class MapViewPosition {
if (!isValid()) { if (!isValid()) {
return null; return null;
} }
updateTileScale();
return new MapPosition(mLatitude, mLongitude, mZoomLevel, mScale, mRotation); int z = FastMath.log2((int) mAbsScale);
z = FastMath.clamp(z, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
float scale = (float) (mAbsScale / (1 << z));
return new MapPosition(mLatitude, mLongitude, (byte)z, scale, mRotation);
} }
/** /**
@ -286,8 +299,8 @@ public class MapViewPosition {
double maxY = Double.MIN_VALUE; double maxY = Double.MIN_VALUE;
for (int i = 0; i < 8; i += 2) { for (int i = 0; i < 8; i += 2) {
dx = mRealX - coords[i + 0]; dx = mCurX - coords[i + 0];
dy = mRealY - coords[i + 1]; dy = mCurY - coords[i + 1];
minX = Math.min(minX, dx); minX = Math.min(minX, dx);
maxX = Math.max(maxX, dx); maxX = Math.max(maxX, dx);
@ -295,10 +308,10 @@ public class MapViewPosition {
maxY = Math.max(maxY, dy); maxY = Math.max(maxY, dy);
} }
minX = MercatorProjection.toLongitude(minX, mTileScale); minX = MercatorProjection.toLongitude(minX, mCurScale);
maxX = MercatorProjection.toLongitude(maxX, mTileScale); maxX = MercatorProjection.toLongitude(maxX, mCurScale);
minY = MercatorProjection.toLatitude(minY, mTileScale); minY = MercatorProjection.toLatitude(minY, mCurScale);
maxY = MercatorProjection.toLatitude(maxY, mTileScale); maxY = MercatorProjection.toLatitude(maxY, mCurScale);
// yea, this is upside down.. // yea, this is upside down..
BoundingBox bbox = new BoundingBox(maxY, minX, minY, maxX); BoundingBox bbox = new BoundingBox(maxY, minX, minY, maxX);
@ -317,7 +330,7 @@ public class MapViewPosition {
* @param out Point coords will be set * @param out Point coords will be set
* @return current map scale * @return current map scale
*/ */
public synchronized float getScreenPointOnMap(float x, float y, Point2D out) { public synchronized float getScreenPointOnMap(float x, float y, PointD out) {
// scale to -1..1 // scale to -1..1
float mx = 1 - (x / mWidth * 2); float mx = 1 - (x / mWidth * 2);
@ -325,10 +338,10 @@ public class MapViewPosition {
unproject(-mx, my, getZ(-my), mu, 0); unproject(-mx, my, getZ(-my), mu, 0);
out.x = mRealX + mu[0]; out.x = mCurX + mu[0];
out.y = mRealY + mu[1]; out.y = mCurY + mu[1];
return (float) mMapScale; return (float) mAbsScale;
} }
/** /**
@ -346,10 +359,10 @@ public class MapViewPosition {
unproject(-mx, my, getZ(-my), mu, 0); unproject(-mx, my, getZ(-my), mu, 0);
double dx = mRealX + mu[0]; double dx = mCurX + mu[0];
double dy = mRealY + mu[1]; double dy = mCurY + mu[1];
dx /= mMapScale * Tile.TILE_SIZE; dx /= mAbsScale * Tile.TILE_SIZE;
dy /= mMapScale * Tile.TILE_SIZE; dy /= mAbsScale * Tile.TILE_SIZE;
if (dx > 1) { if (dx > 1) {
while (dx > 1) while (dx > 1)
@ -374,18 +387,16 @@ public class MapViewPosition {
/** /**
* Get the screen pixel for a GeoPoint * Get the screen pixel for a GeoPoint
* *
* @param geoPoint ... * @param geoPoint the GeoPoint
* @param reuse ... * @param out Point projected to screen pixel
* @return ...
*/ */
public synchronized Point project(GeoPoint geoPoint, Point reuse) { public synchronized void project(GeoPoint geoPoint, PointF out) {
Point out = reuse == null ? new Point() : reuse;
double x = MercatorProjection.longitudeToX(geoPoint.getLongitude()) * mTileScale; double x = MercatorProjection.longitudeToX(geoPoint.getLongitude()) * mCurScale;
double y = MercatorProjection.latitudeToY(geoPoint.getLatitude()) * mTileScale; double y = MercatorProjection.latitudeToY(geoPoint.getLatitude()) * mCurScale;
mv[0] = (float) (x - mRealX); mv[0] = (float) (x - mCurX);
mv[1] = (float) (y - mRealY); mv[1] = (float) (y - mCurY);
mv[2] = 0; mv[2] = 0;
mv[3] = 1; mv[3] = 1;
@ -395,8 +406,6 @@ public class MapViewPosition {
// positive direction is down and right; // positive direction is down and right;
out.x = (int) ((mv[0] / mv[3]) * (mWidth / 2)); out.x = (int) ((mv[0] / mv[3]) * (mWidth / 2));
out.y = (int) -((mv[1] / mv[3]) * (mHeight / 2)); out.y = (int) -((mv[1] / mv[3]) * (mHeight / 2));
return out;
} }
private void updateMatrix() { private void updateMatrix() {
@ -463,10 +472,6 @@ public class MapViewPosition {
return true; return true;
} }
//private double mMaxLat = MercatorProjection.latitudeToY(MercatorProjection.LATITUDE_MAX);
private double mAbsX;
private double mAbsY;
/** /**
* Moves this MapViewPosition by the given amount of pixels. * Moves this MapViewPosition by the given amount of pixels.
* *
@ -477,14 +482,14 @@ public class MapViewPosition {
// stop animation // stop animation
mHandler.cancel(); mHandler.cancel();
Point2D p = applyRotation(mx, my); PointD p = applyRotation(mx, my);
move(p.x, p.y); move(p.x, p.y);
} }
private synchronized void move(double mx, double my) { private synchronized void move(double mx, double my) {
mAbsX = (mRealX - mx) / mTileScale; mAbsX = (mCurX - mx) / mCurScale;
mAbsY = (mRealY - my) / mTileScale; mAbsY = (mCurY - my) / mCurScale;
// clamp latitude // clamp latitude
mAbsY = FastMath.clamp(mAbsY, 0, 1); mAbsY = FastMath.clamp(mAbsY, 0, 1);
@ -501,7 +506,28 @@ public class MapViewPosition {
updatePosition(); updatePosition();
} }
private Point2D applyRotation(float mx, float my) { private synchronized void moveAbs(double x, double y) {
double f = Tile.TILE_SIZE << ABS_ZOOMLEVEL;
mAbsX = x / f;
mAbsY = y / f;
// clamp latitude
mAbsY = FastMath.clamp(mAbsY, 0, 1);
// wrap longitude
while (mAbsX > 1)
mAbsX -= 1;
while (mAbsX < 0)
mAbsX += 1;
mLongitude = MercatorProjection.toLongitude(mAbsX);
mLatitude = MercatorProjection.toLatitude(mAbsY);
updatePosition();
}
private PointD applyRotation(float mx, float my) {
if (mMapView.mRotationEnabled || mMapView.mCompassEnabled) { if (mMapView.mRotationEnabled || mMapView.mCompassEnabled) {
double rad = Math.toRadians(mRotation); double rad = Math.toRadians(mRotation);
@ -518,15 +544,6 @@ public class MapViewPosition {
return mMovePoint; return mMovePoint;
} }
private void updateTileScale() {
int z = FastMath.log2((int) mMapScale);
z = FastMath.clamp(z, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
mZoomLevel = (byte) z;
mScale = (float) (mMapScale / (1 << z));
//Log.d(TAG, "updateTileScale " + mZoomLevel + " " + mScale);
}
/** /**
* @param scale map by this factor * @param scale map by this factor
* @param pivotX ... * @param pivotX ...
@ -540,16 +557,16 @@ public class MapViewPosition {
// just sanitize input // just sanitize input
scale = FastMath.clamp(scale, 0.5f, 2); scale = FastMath.clamp(scale, 0.5f, 2);
double newScale = mMapScale * scale; double newScale = mAbsScale * scale;
newScale = FastMath.clamp(newScale, MIN_SCALE, MAX_SCALE); newScale = FastMath.clamp(newScale, MIN_SCALE, MAX_SCALE);
if (newScale == mMapScale) if (newScale == mAbsScale)
return false; return false;
scale = (float) (newScale / mMapScale); scale = (float) (newScale / mAbsScale);
mMapScale = newScale; mAbsScale = newScale;
if (pivotX != 0 || pivotY != 0) if (pivotX != 0 || pivotY != 0)
moveMap(pivotX * (1.0f - scale), moveMap(pivotX * (1.0f - scale),
@ -587,13 +604,14 @@ public class MapViewPosition {
updateMatrix(); updateMatrix();
} }
public synchronized boolean tilt(float move) { public synchronized boolean tiltMap(float move) {
float tilt = FastMath.clamp(mTilt + move, 0, MAX_ANGLE); float tilt = FastMath.clamp(mTilt + move, 0, MAX_ANGLE);
if (mTilt == tilt) if (mTilt == tilt)
return false; return false;
setTilt(tilt); setTilt(tilt);
return true; return true;
} }
@ -607,7 +625,6 @@ public class MapViewPosition {
mLongitude = MercatorProjection.limitLongitude(longitude); mLongitude = MercatorProjection.limitLongitude(longitude);
mAbsX = MercatorProjection.longitudeToX(mLongitude); mAbsX = MercatorProjection.longitudeToX(mLongitude);
mAbsY = MercatorProjection.latitudeToY(mLatitude); mAbsY = MercatorProjection.latitudeToY(mLatitude);
updatePosition(); updatePosition();
} }
@ -617,42 +634,45 @@ public class MapViewPosition {
synchronized void setMapCenter(MapPosition mapPosition) { synchronized void setMapCenter(MapPosition mapPosition) {
setZoomLevelLimit(mapPosition.zoomLevel); setZoomLevelLimit(mapPosition.zoomLevel);
//mMapScale = 1 << mZoomLevel;
setMapCenter(mapPosition.lat, mapPosition.lon); setMapCenter(mapPosition.lat, mapPosition.lon);
} }
synchronized void setZoomLevel(byte zoomLevel) { synchronized void setZoomLevel(byte zoomLevel) {
setZoomLevelLimit(zoomLevel); setZoomLevelLimit(zoomLevel);
//mMapScale = 1 << mZoomLevel;
//mScale = 1;
updatePosition(); updatePosition();
} }
private void setZoomLevelLimit(byte zoomLevel) { private void setZoomLevelLimit(byte zoomLevel) {
mMapScale = FastMath.clamp(1 << zoomLevel, MIN_SCALE, MAX_SCALE); mAbsScale = FastMath.clamp(1 << zoomLevel, MIN_SCALE, MAX_SCALE);
//mMapScale = 1 << zoomLevel;
//mZoomLevel = (byte) FastMath.clamp(zoomLevel, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
} }
private double mRealX;
private double mRealY;
private void updatePosition() { private void updatePosition() {
mTileScale = mMapScale * Tile.TILE_SIZE; mCurScale = mAbsScale * Tile.TILE_SIZE;
mRealX = mAbsX * mTileScale; mCurX = mAbsX * mCurScale;
mRealY = mAbsY * mTileScale; mCurY = mAbsY * mCurScale;
} }
private int mScrollX; /************************************************************************/
private int mScrollY; // TODO move to MapAnimator:
private double mScrollX;
private double mScrollY;
private double mStartX;
private double mStartY;
private double mEndX;
private double mEndY;
private double mStartScale; private double mStartScale;
private double mEndScale; private double mEndScale;
private float mDuration = 500; private float mDuration = 500;
private final static double LOG4 = Math.log(4);
private boolean mAnimMove;
private boolean mAnimFling;
private boolean mAnimScale;
private final DecelerateInterpolator mDecInterpolator = new DecelerateInterpolator(2);
public synchronized void animateTo(BoundingBox bbox) { public synchronized void animateTo(BoundingBox bbox) {
double dx = MercatorProjection.longitudeToX(bbox.getMaxLongitude()) double dx = MercatorProjection.longitudeToX(bbox.getMaxLongitude())
@ -661,69 +681,78 @@ public class MapViewPosition {
- MercatorProjection.latitudeToY(bbox.getMaxLatitude()); - MercatorProjection.latitudeToY(bbox.getMaxLatitude());
double log4 = Math.log(4); double z = Math.min(
-LOG4 * Math.log(dx) + (mWidth / Tile.TILE_SIZE),
-LOG4 * Math.log(dy) + (mHeight / Tile.TILE_SIZE));
double zx = -log4 * Math.log(dx) + (mWidth / Tile.TILE_SIZE); double newScale = Math.pow(2, z - 1);
double zy = -log4 * Math.log(dy) + (mHeight / Tile.TILE_SIZE);
double z = Math.min(zx, zy); newScale = FastMath.clamp(newScale, MIN_SCALE, 1 << ABS_ZOOMLEVEL);
double newScale = Math.pow(2, z); float scale = (float) (newScale / mAbsScale);
//double newScale = (1 << (int)Math.floor(z)); Log.d(TAG, "scale to " + bbox + " " + z + " " + newScale + " " + mAbsScale
newScale = FastMath.clamp(newScale, MIN_SCALE, (1 << 15));
float scale = (float) (newScale / mMapScale);
Log.d(TAG, "scale to " + bbox + " "+ z + " " + newScale + " " + mMapScale
+ " " + FastMath.log2((int) newScale) + " " + scale); + " " + FastMath.log2((int) newScale) + " " + scale);
mEndScale = mMapScale * scale;
mStartScale = mMapScale;
//mMapScale = newScale; mEndScale = mAbsScale * scale - mAbsScale;
//updatePosition(); mStartScale = mAbsScale;
// ----- mScale = FastMath.clamp((float) (1 + (z - mZoomLevel)), 1, MAX_END_SCALE);
//mMapScale = (1 << mZoomLevel) * mScale;
//Log.d(TAG, "zoom: " + bbox + " " + zx + " " + zy + " / " + mScale + " " + mZoomLevel);
//updatePosition();
// reset rotation/tilt // reset rotation/tilt
mTilt = 0; //mTilt = 0;
mRotation = 0; //mRotation = 0;
updateMatrix(); //updateMatrix();
double f = Tile.TILE_SIZE << ABS_ZOOMLEVEL;
mStartX = mAbsX * f;
mStartY = mAbsY * f;
GeoPoint geoPoint = bbox.getCenterPoint(); GeoPoint geoPoint = bbox.getCenterPoint();
//mStartScale = mMapScale; mEndX = MercatorProjection.longitudeToX(geoPoint.getLongitude()) * f;
mEndY = MercatorProjection.latitudeToY(geoPoint.getLatitude()) * f;
double mx = MercatorProjection.longitudeToX(geoPoint.getLongitude()) * mTileScale; mEndX -= mStartX;
double my = MercatorProjection.latitudeToY(geoPoint.getLatitude()) * mTileScale; mEndY -= mStartY;
mx = mRealX - mx; mAnimMove = true;
my = mRealY - my; mAnimScale = true;
mAnimFling = false;
mScrollX = 0;
mScrollY = 0;
mDuration = 500; mDuration = 500;
mScroller.startScroll(0, 0, (int) mx, (int) my, (int)mDuration); // double mx = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(),
// (byte) ABS_ZOOMLEVEL);
// double my = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(),
// (byte) ABS_ZOOMLEVEL);
//
// double f = Tile.TILE_SIZE << ABS_ZOOMLEVEL;
// double x = mAbsX * f;
// double y = mAbsY * f;
//
// mScroller.startScroll((int) x, (int) y, (int) (mx - x), (int) (my - y), (int) mDuration);
// mFling = false;
mHandler.start((int) mDuration); mHandler.start((int) mDuration);
} }
public synchronized void animateTo(GeoPoint geoPoint) { public synchronized void animateTo(GeoPoint geoPoint) {
//MercatorProjection.projectPoint(geoPoint, mZoomLevel, mTmpPoint);
//mEndX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mZoomLevel); double mx = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(),
//mEndY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mZoomLevel); (byte) ABS_ZOOMLEVEL);
//mStartX = mPosX; double my = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(),
//mStartY = mPosY; (byte) ABS_ZOOMLEVEL);
double f = Tile.TILE_SIZE << ABS_ZOOMLEVEL;
double x = mAbsX * f;
double y = mAbsY * f;
mScroller.startScroll((int) x, (int) y, (int) (mx - x), (int) (my - y), (int) mDuration);
mAnimFling = false;
mAnimScale = false;
mAnimMove = false;
mDuration = 300; mDuration = 300;
mHandler.start((int) mDuration); mHandler.start((int) mDuration);
} }
public synchronized void animateFling(int velocityX, int velocityY, public synchronized void animateFling(int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY) { int minX, int maxX, int minY, int maxY) {
@ -731,80 +760,82 @@ public class MapViewPosition {
mScrollY = 0; mScrollY = 0;
mScroller.fling(0, 0, velocityX, velocityY, minX, maxX, minY, maxY); mScroller.fling(0, 0, velocityX, velocityY, minX, maxX, minY, maxY);
mAnimFling = true;
mAnimMove = false;
mAnimScale = false;
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); //mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
mDuration = 300; mDuration = 250;
mHandler.start((int) mDuration); mHandler.start((int) mDuration);
} }
public synchronized void animateZoom(float scale) { public synchronized void animateZoom(float scale) {
mStartScale = mMapScale; mStartScale = mAbsScale;
mEndScale = mMapScale * scale; mEndScale = mAbsScale * scale - mAbsScale;
//mScroller.fling(0, 0, velocityX, velocityY, minX, maxX, minY, maxY);
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); //mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
mDuration = 300; mDuration = 300;
mHandler.start((int) mDuration); mHandler.start((int) mDuration);
} }
//private float mScrollX, mScrollY;
public void updateAnimation() { public void updateAnimation() {
//scroll(); //scroll();
} }
synchronized boolean scroll(double div) { synchronized boolean scroll() {
if (mScroller.isFinished()) { if (mScroller.isFinished()) {
return false; return false;
} }
int x = mScrollX; //mScroller.getCurrX();
int y = mScrollY; //mScroller.getCurrY();
mScroller.computeScrollOffset(); mScroller.computeScrollOffset();
int mx = mScroller.getCurrX() - x; double dx = mScroller.getCurrX();
int my = mScroller.getCurrY() - y; double dy = mScroller.getCurrY();
mx *= div;
my *= div;
if (mx >= 1 || my >= 1 || mx <= -1 || my <= -1) { if (mAnimFling) {
moveMap(mx, my); int mx = (int) (dx - mScrollX);
int my = (int) (dy - mScrollY);
//mMapView.redrawMap(true); if (mx >= 1 || my >= 1 || mx <= -1 || my <= -1) {
mScrollX = mScroller.getCurrX(); moveMap(mx, my);
mScrollY = mScroller.getCurrY(); mScrollX = dx;
mScrollY = dy;
}
} }
else
moveAbs(dx, dy);
return true; return true;
} }
public synchronized void animateTo(float dx, float dy, float duration) { public synchronized void animateTo(float dx, float dy, float duration) {
applyRotation(dx, dy); applyRotation(dx, dy);
//mEndX = mRealX - mMovePoint.x;
//mEndY = mRealY - mMovePoint.y;
//mStartX = mRealX;
//mStartY = mRealY;
mDuration = duration; mDuration = duration;
mHandler.start((int) mDuration); mHandler.start((int) mDuration);
} }
void onTick(long millisLeft) { void onTick(long millisLeft) {
boolean changed = false; boolean changed = false;
double div = 1;
if (mStartScale != 0) { if (mAnimScale) {
double adv = millisLeft / mDuration; float adv = (1.0f - millisLeft / mDuration);
mMapScale = (adv * mStartScale) + (mEndScale * (1.0 - adv)); adv = mDecInterpolator.getInterpolation(adv);
div = mMapScale / mStartScale;
//adv *= adv;
mAbsScale = mStartScale + (mEndScale * (Math.pow(2, adv)-1));
//div = mAbsScale / mStartScale;
if (mAnimMove)
moveAbs(mStartX + mEndX * adv, mStartY + mEndY * adv);
updatePosition(); updatePosition();
changed = true; changed = true;
} }
if (scroll(div)) if (scroll())
changed = true; changed = true;
if (changed) if (changed)
@ -812,10 +843,18 @@ public class MapViewPosition {
} }
void onFinish() { void onFinish() {
//setMapPosition(mEndX, mEndY); if (!mAnimFling && !mScroller.isFinished())
moveAbs(mScroller.getFinalX(), mScroller.getFinalY());
if (mStartScale != 0) {
mAbsScale = mStartScale + mEndScale;
updatePosition();
mStartScale = 0;
}
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); //mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mMapView.redrawMap(true); mMapView.redrawMap(true);
mStartScale = 0;
} }
/** /**