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:
parent
246fd40f7a
commit
6b39c95905
@ -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 (mAnimFling) {
|
||||||
|
int mx = (int) (dx - mScrollX);
|
||||||
|
int my = (int) (dy - mScrollY);
|
||||||
|
|
||||||
if (mx >= 1 || my >= 1 || mx <= -1 || my <= -1) {
|
if (mx >= 1 || my >= 1 || mx <= -1 || my <= -1) {
|
||||||
moveMap(mx, my);
|
moveMap(mx, my);
|
||||||
|
mScrollX = dx;
|
||||||
//mMapView.redrawMap(true);
|
mScrollY = dy;
|
||||||
mScrollX = mScroller.getCurrX();
|
|
||||||
mScrollY = mScroller.getCurrY();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
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,12 +843,20 @@ public class MapViewPosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onFinish() {
|
void onFinish() {
|
||||||
//setMapPosition(mEndX, mEndY);
|
if (!mAnimFling && !mScroller.isFinished())
|
||||||
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
moveAbs(mScroller.getFinalX(), mScroller.getFinalY());
|
||||||
mMapView.redrawMap(true);
|
|
||||||
|
if (mStartScale != 0) {
|
||||||
|
mAbsScale = mStartScale + mEndScale;
|
||||||
|
updatePosition();
|
||||||
mStartScale = 0;
|
mStartScale = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
||||||
|
|
||||||
|
mMapView.redrawMap(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* below is borrowed from CountDownTimer class:
|
* below is borrowed from CountDownTimer class:
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user