fix MapAnimator.animateTo()

- cleanups
This commit is contained in:
Hannes Janetzek 2013-09-19 21:29:38 +02:00
parent f6bb944907
commit 0107ade039
2 changed files with 56 additions and 75 deletions

View File

@ -19,6 +19,11 @@ public class MapAnimator {
mMap = map;
}
private final int ANIM_NONE = 0;
private final int ANIM_MOVE = 1 << 1;
private final int ANIM_SCALE = 1 << 2;
private final int ANIM_FLING = 1 << 3;
private final Map mMap;
private final Viewport mViewport;
@ -35,19 +40,17 @@ public class MapAnimator {
private float mDuration = 500;
private long mAnimEnd = -1;
private boolean mAnimMove;
private boolean mAnimFling;
private boolean mAnimScale;
private int mState = ANIM_NONE;
public synchronized void animateTo(BoundingBox bbox) {
// TODO for large distatance first scale out, then in
// calculate the maximum scale at which the bbox is completely visible
double dx = Math.abs(MercatorProjection.longitudeToX(bbox.getMaxLongitude())
- MercatorProjection.longitudeToX(bbox.getMinLongitude()));
- MercatorProjection.longitudeToX(bbox.getMinLongitude()));
double dy = Math.abs(MercatorProjection.latitudeToY(bbox.getMinLatitude())
- MercatorProjection.latitudeToY(bbox.getMaxLatitude()));
- MercatorProjection.latitudeToY(bbox.getMaxLatitude()));
double zx = mMap.getWidth() / (dx * Tile.SIZE);
double zy = mMap.getHeight() / (dy * Tile.SIZE);
@ -57,12 +60,12 @@ public class MapAnimator {
}
public synchronized void animateTo(long duration, GeoPoint geoPoint, double scale,
boolean relative) {
boolean relative) {
mViewport.getMapPosition(mPos);
if (relative) {
if (mAnimEnd > 0 && mAnimScale)
if (mAnimEnd > 0 && (mState & ANIM_SCALE) != 0)
scale = mDeltaPos.scale * scale;
else
scale = mPos.scale * scale;
@ -86,9 +89,7 @@ public class MapAnimator {
mDeltaPos.x -= mStartPos.x;
mDeltaPos.y -= mStartPos.y;
mAnimMove = true;
mAnimScale = true;
mAnimFling = false;
mState = ANIM_MOVE | ANIM_SCALE;
animStart(duration);
}
@ -97,7 +98,7 @@ public class MapAnimator {
mViewport.getMapPosition(mPos);
if (mAnimEnd > 0 && mAnimScale)
if (mAnimEnd > 0 && (mState & ANIM_SCALE) != 0)
scale = mDeltaPos.scale * scale;
else
scale = mPos.scale * scale;
@ -109,16 +110,13 @@ public class MapAnimator {
mScaleBy = mPos.scale * scale - mPos.scale;
mStartPos.scale = mPos.scale;
mStartPos.angle = mPos.angle;
mPivot.x = pivotX;
mPivot.y = pivotY;
mAnimScale = true;
mAnimFling = false;
mAnimMove = false;
mState = ANIM_SCALE;
animStart(duration);
}
@ -128,7 +126,7 @@ public class MapAnimator {
}
public synchronized void animateFling(int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY) {
int minX, int maxX, int minY, int maxY) {
if (velocityX * velocityX + velocityY * velocityY < 2048)
return;
@ -147,54 +145,28 @@ public class MapAnimator {
FastMath.clamp(mVelocity.x, minX, maxX);
FastMath.clamp(mVelocity.y, minY, maxY);
mAnimFling = true;
mAnimMove = false;
mAnimScale = false;
mState = ANIM_FLING;
animStart(duration);
}
private void animStart(float duration) {
mDuration = duration;
mAnimEnd = System.currentTimeMillis() + (long) duration;
mMap.render();
}
private void animCancel() {
mAnimEnd = -1;
mAnimScale = false;
mAnimFling = false;
mAnimMove = false;
mState = ANIM_NONE;
mPivot.x = 0;
mPivot.y = 0;
}
private boolean fling(float adv) {
synchronized (mViewport) {
adv = (float) Math.sqrt(adv);
double dx = mVelocity.x * adv;
double dy = mVelocity.y * adv;
if (dx == 0 && dy == 0)
return false;
mViewport.moveMap((float) (dx - mScroll.x), (float) (dy - mScroll.y));
mScroll.x = dx;
mScroll.y = dy;
}
return true;
}
/**
* called by GLRenderer at begin of each frame.
*/
public void updateAnimation() {
if (mAnimEnd < 0)
if (mState == ANIM_NONE)
return;
long millisLeft = mAnimEnd - System.currentTimeMillis();
@ -210,17 +182,18 @@ public class MapAnimator {
if (millisLeft <= 0) {
// set final position
if (mAnimMove && !mAnimFling)
mViewport.moveInternal(mStartPos.x + mDeltaPos.x, mStartPos.y + mDeltaPos.y);
if ((mState & ANIM_MOVE) != 0)
mViewport.moveInternal(mStartPos.x + mDeltaPos.x,
mStartPos.y + mDeltaPos.y);
if (mAnimScale) {
if ((mState & ANIM_SCALE) != 0) {
if (mScaleBy > 0)
doScale(mStartPos.scale + (mScaleBy - 1));
else
doScale(mStartPos.scale + mScaleBy);
}
mMap.updateMap(true);
mMap.updateMap(true);
animCancel();
return;
}
@ -229,7 +202,7 @@ public class MapAnimator {
float adv = (1.0f - millisLeft / mDuration);
if (mAnimScale) {
if ((mState & ANIM_SCALE) != 0) {
if (mScaleBy > 0)
doScale(mStartPos.scale + (mScaleBy * (Math.pow(2, adv) - 1)));
else
@ -238,11 +211,9 @@ public class MapAnimator {
changed = true;
}
if (mAnimMove) {
mViewport.moveInternal(
mStartPos.x + mDeltaPos.x * adv,
mStartPos.y + mDeltaPos.y * adv);
if ((mState & ANIM_MOVE) != 0) {
mViewport.moveInternal(mStartPos.x + mDeltaPos.x * adv,
mStartPos.y + mDeltaPos.y * adv);
changed = true;
}
@ -251,12 +222,22 @@ public class MapAnimator {
// updateMatrix();
//}
if (mAnimFling && fling(adv))
changed = true;
if ((mState & ANIM_FLING) != 0) {
adv = (float) Math.sqrt(adv);
double dx = mVelocity.x * adv;
double dy = mVelocity.y * adv;
if ((dx - mScroll.x) != 0 || (dy - mScroll.y) != 0) {
mViewport.moveMap((float) (dx - mScroll.x), (float) (dy - mScroll.y));
mScroll.x = dx;
mScroll.y = dy;
changed = true;
}
}
// continue animation
if (changed) {
// inform other layers that position has changed
// render and inform layers that position has changed
mMap.updateMap(true);
} else {
// just render next frame
@ -269,6 +250,7 @@ public class MapAnimator {
}
private void doScale(double newScale) {
mViewport.scaleMap((float) (newScale / mPos.scale), (float)mPivot.x, (float)mPivot.y);
mViewport.scaleMap((float) (newScale / mPos.scale),
(float) mPivot.x, (float) mPivot.y);
}
}

View File

@ -82,7 +82,7 @@ public class Viewport {
float[] tmp = new float[16];
Matrix4.frustumM(tmp, 0, -s, s,
aspect * s, -aspect * s, VIEW_NEAR, VIEW_FAR);
aspect * s, -aspect * s, VIEW_NEAR, VIEW_FAR);
mProjMatrix.set(tmp);
mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE);
@ -107,10 +107,10 @@ public class Viewport {
public synchronized boolean getMapPosition(MapPosition pos) {
boolean changed = (pos.scale != mPos.scale
|| pos.x != mPos.x
|| pos.y != mPos.y
|| pos.angle != mPos.angle
|| pos.tilt != mPos.tilt);
|| pos.x != mPos.x
|| pos.y != mPos.y
|| pos.angle != mPos.angle
|| pos.tilt != mPos.tilt);
pos.angle = mPos.angle;
pos.tilt = mPos.tilt;
@ -295,8 +295,8 @@ public class Viewport {
public synchronized GeoPoint fromScreenPoint(float x, float y) {
fromScreenPoint(x, y, mMovePoint);
return new GeoPoint(
MercatorProjection.toLatitude(mMovePoint.y),
MercatorProjection.toLongitude(mMovePoint.x));
MercatorProjection.toLatitude(mMovePoint.y),
MercatorProjection.toLongitude(mMovePoint.x));
}
/**
@ -423,19 +423,18 @@ public class Viewport {
Point p = applyRotation(mx, my);
double tileScale = mPos.scale * Tile.SIZE;
moveBy(p.x / tileScale, p.y / tileScale);
moveTo(mPos.x - p.x / tileScale, mPos.y - p.y / tileScale);
}
/* used by MapAnimator */
void moveInternal(double mx, double my) {
Point p = applyRotation(mx, my);
moveBy(p.x, p.y);
moveTo(p.x, p.y);
}
/* used by MapAnimator */
void moveBy(double mx, double my) {
mPos.x -= mx;
mPos.y -= my;
private void moveTo(double x, double y) {
mPos.x = x;
mPos.y = y;
// clamp latitude
mPos.y = FastMath.clamp(mPos.y, 0, 1);
@ -447,7 +446,7 @@ public class Viewport {
mPos.x += 1;
}
Point applyRotation(double mx, double my) {
private Point applyRotation(double mx, double my) {
if (mPos.angle == 0) {
mMovePoint.x = mx;
mMovePoint.y = my;
@ -489,7 +488,7 @@ public class Viewport {
if (pivotX != 0 || pivotY != 0)
moveMap(pivotX * (1.0f - scale),
pivotY * (1.0f - scale));
pivotY * (1.0f - scale));
return true;
}