refactor: extract animation stuff from Viewport into MapAnimator
This commit is contained in:
parent
51c2c5d62a
commit
eb1e8b63c5
@ -237,9 +237,9 @@ public class SearchBox {
|
|||||||
if (b.maxLatitudeE6 - b.minLatitudeE6 < 100 &&
|
if (b.maxLatitudeE6 - b.minLatitudeE6 < 100 &&
|
||||||
b.maxLongitudeE6 - b.minLongitudeE6 < 100)
|
b.maxLongitudeE6 - b.minLongitudeE6 < 100)
|
||||||
// for small bbox use zoom=16 to get an overview
|
// for small bbox use zoom=16 to get an overview
|
||||||
map.getViewport().animateTo(500, b.getCenterPoint(), 1 << 16, false);
|
map.getAnimator().animateTo(500, b.getCenterPoint(), 1 << 16, false);
|
||||||
else
|
else
|
||||||
map.getViewport().animateTo(b);
|
map.getAnimator().animateTo(b);
|
||||||
if (d instanceof NominatimData && ((NominatimData) d).getWkt() != null) {
|
if (d instanceof NominatimData && ((NominatimData) d).getWkt() != null) {
|
||||||
String wkt = ((NominatimData) d).getWkt();
|
String wkt = ((NominatimData) d).getWkt();
|
||||||
|
|
||||||
|
@ -365,12 +365,12 @@ public class GdxMap implements ApplicationListener {
|
|||||||
|
|
||||||
if (amount > 0) {
|
if (amount > 0) {
|
||||||
|
|
||||||
mMapPosition.animateZoom(150, 0.8f, 0, 0);
|
mMap.getAnimator().animateZoom(150, 0.8f, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
float fx = mPosX - mMap.getWidth() / 2;
|
float fx = mPosX - mMap.getWidth() / 2;
|
||||||
float fy = mPosY - mMap.getHeight() / 2;
|
float fy = mPosY - mMap.getHeight() / 2;
|
||||||
|
|
||||||
mMapPosition.animateZoom(150, 1.25f, fx, fy);
|
mMap.getAnimator().animateZoom(150, 1.25f, fx, fy);
|
||||||
}
|
}
|
||||||
mMap.updateMap(false);
|
mMap.updateMap(false);
|
||||||
|
|
||||||
@ -438,7 +438,7 @@ public class GdxMap implements ApplicationListener {
|
|||||||
//Log.d("", "fling " + button + " " + velocityX + "/" + velocityY);
|
//Log.d("", "fling " + button + " " + velocityX + "/" + velocityY);
|
||||||
if (mayFling && button == Buttons.LEFT) {
|
if (mayFling && button == Buttons.LEFT) {
|
||||||
int m = Tile.SIZE * 4;
|
int m = Tile.SIZE * 4;
|
||||||
mMapPosition.animateFling((int) velocityX, (int) velocityY, -m, m, -m, m);
|
mMap.getAnimator().animateFling((int) velocityX, (int) velocityY, -m, m, -m, m);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -299,7 +299,7 @@ public class MapEventLayer extends InputLayer {
|
|||||||
int w = Tile.SIZE * 3;
|
int w = Tile.SIZE * 3;
|
||||||
int h = Tile.SIZE * 3;
|
int h = Tile.SIZE * 3;
|
||||||
|
|
||||||
mMapPosition.animateFling(
|
mMap.getAnimator().animateFling(
|
||||||
Math.round(velocityX),
|
Math.round(velocityX),
|
||||||
Math.round(velocityY),
|
Math.round(velocityY),
|
||||||
-w, w, -h, h);
|
-w, w, -h, h);
|
||||||
|
@ -294,8 +294,7 @@ public class GLRenderer {
|
|||||||
MapPosition pos = mMapPosition;
|
MapPosition pos = mMapPosition;
|
||||||
|
|
||||||
synchronized (mViewport) {
|
synchronized (mViewport) {
|
||||||
// update MapPosition
|
mMap.getAnimator().updateAnimation();
|
||||||
mViewport.updateAnimation();
|
|
||||||
|
|
||||||
// get current MapPosition
|
// get current MapPosition
|
||||||
changed = mViewport.getMapPosition(pos);
|
changed = mViewport.getMapPosition(pos);
|
||||||
|
@ -35,6 +35,8 @@ public abstract class Map {
|
|||||||
|
|
||||||
private final Layers mLayers;
|
private final Layers mLayers;
|
||||||
private final Viewport mViewport;
|
private final Viewport mViewport;
|
||||||
|
private final MapAnimator mAnimator;
|
||||||
|
|
||||||
private final MapPosition mMapPosition;
|
private final MapPosition mMapPosition;
|
||||||
private final AsyncExecutor mAsyncExecutor;
|
private final AsyncExecutor mAsyncExecutor;
|
||||||
|
|
||||||
@ -49,11 +51,12 @@ public abstract class Map {
|
|||||||
public Map() {
|
public Map() {
|
||||||
|
|
||||||
mViewport = new Viewport(this);
|
mViewport = new Viewport(this);
|
||||||
|
mAnimator = new MapAnimator(this, mViewport);
|
||||||
|
|
||||||
mMapPosition = new MapPosition();
|
mMapPosition = new MapPosition();
|
||||||
mLayers = new Layers();
|
mLayers = new Layers();
|
||||||
mAsyncExecutor = new AsyncExecutor(2);
|
mAsyncExecutor = new AsyncExecutor(2);
|
||||||
|
|
||||||
// FIXME!
|
|
||||||
mDebugSettings = new DebugSettings();
|
mDebugSettings = new DebugSettings();
|
||||||
MapTileLoader.setDebugSettings(mDebugSettings);
|
MapTileLoader.setDebugSettings(mDebugSettings);
|
||||||
|
|
||||||
@ -216,4 +219,8 @@ public abstract class Map {
|
|||||||
public BoundingBox getBoundingBox() {
|
public BoundingBox getBoundingBox() {
|
||||||
return mViewport.getViewBox();
|
return mViewport.getViewBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MapAnimator getAnimator() {
|
||||||
|
return mAnimator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
274
vtm/src/org/oscim/view/MapAnimator.java
Normal file
274
vtm/src/org/oscim/view/MapAnimator.java
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
package org.oscim.view;
|
||||||
|
|
||||||
|
import org.oscim.core.BoundingBox;
|
||||||
|
import org.oscim.core.GeoPoint;
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.core.MercatorProjection;
|
||||||
|
import org.oscim.core.Point;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.utils.FastMath;
|
||||||
|
|
||||||
|
// TODO: rewrite
|
||||||
|
|
||||||
|
public class MapAnimator {
|
||||||
|
|
||||||
|
//private static final String TAG = MapAnimator.class.getName();
|
||||||
|
|
||||||
|
public MapAnimator(Map map, Viewport viewport) {
|
||||||
|
mViewport = viewport;
|
||||||
|
mMap = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map mMap;
|
||||||
|
private final Viewport mViewport;
|
||||||
|
|
||||||
|
private final MapPosition mPos = new MapPosition();
|
||||||
|
private final MapPosition mStartPos = new MapPosition();
|
||||||
|
private final MapPosition mDeltaPos = new MapPosition();
|
||||||
|
|
||||||
|
private final Point mScroll = new Point();
|
||||||
|
private final Point mPivot = new Point();
|
||||||
|
private final Point mVelocity = new Point();
|
||||||
|
|
||||||
|
private double mScaleBy;
|
||||||
|
|
||||||
|
private float mDuration = 500;
|
||||||
|
private long mAnimEnd = -1;
|
||||||
|
|
||||||
|
private boolean mAnimMove;
|
||||||
|
private boolean mAnimFling;
|
||||||
|
private boolean mAnimScale;
|
||||||
|
|
||||||
|
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()));
|
||||||
|
|
||||||
|
double dy = Math.abs(MercatorProjection.latitudeToY(bbox.getMinLatitude())
|
||||||
|
- MercatorProjection.latitudeToY(bbox.getMaxLatitude()));
|
||||||
|
|
||||||
|
double zx = mMap.getWidth() / (dx * Tile.SIZE);
|
||||||
|
double zy = mMap.getHeight() / (dy * Tile.SIZE);
|
||||||
|
double newScale = Math.min(zx, zy);
|
||||||
|
|
||||||
|
animateTo(500, bbox.getCenterPoint(), newScale, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void animateTo(long duration, GeoPoint geoPoint, double scale,
|
||||||
|
boolean relative) {
|
||||||
|
|
||||||
|
mViewport.getMapPosition(mPos);
|
||||||
|
|
||||||
|
if (relative) {
|
||||||
|
if (mAnimEnd > 0 && mAnimScale)
|
||||||
|
scale = mDeltaPos.scale * scale;
|
||||||
|
else
|
||||||
|
scale = mPos.scale * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale = FastMath.clamp(scale, Viewport.MIN_SCALE, Viewport.MAX_SCALE);
|
||||||
|
mDeltaPos.scale = scale;
|
||||||
|
|
||||||
|
scale = (float) (scale / mPos.scale);
|
||||||
|
|
||||||
|
mScaleBy = mPos.scale * scale - mPos.scale;
|
||||||
|
|
||||||
|
mStartPos.scale = mPos.scale;
|
||||||
|
mStartPos.angle = mPos.angle;
|
||||||
|
|
||||||
|
mStartPos.x = mPos.x;
|
||||||
|
mStartPos.y = mPos.y;
|
||||||
|
|
||||||
|
mDeltaPos.x = MercatorProjection.longitudeToX(geoPoint.getLongitude());
|
||||||
|
mDeltaPos.y = MercatorProjection.latitudeToY(geoPoint.getLatitude());
|
||||||
|
mDeltaPos.x -= mStartPos.x;
|
||||||
|
mDeltaPos.y -= mStartPos.y;
|
||||||
|
|
||||||
|
mAnimMove = true;
|
||||||
|
mAnimScale = true;
|
||||||
|
mAnimFling = false;
|
||||||
|
|
||||||
|
animStart(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void animateZoom(long duration, double scale, float pivotX, float pivotY) {
|
||||||
|
|
||||||
|
mViewport.getMapPosition(mPos);
|
||||||
|
|
||||||
|
if (mAnimEnd > 0 && mAnimScale)
|
||||||
|
scale = mDeltaPos.scale * scale;
|
||||||
|
else
|
||||||
|
scale = mPos.scale * scale;
|
||||||
|
|
||||||
|
scale = FastMath.clamp(scale, Viewport.MIN_SCALE, Viewport.MAX_SCALE);
|
||||||
|
mDeltaPos.scale = scale;
|
||||||
|
|
||||||
|
scale = (float) (scale / mPos.scale);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
animStart(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void animateTo(GeoPoint geoPoint) {
|
||||||
|
animateTo(300, geoPoint, 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void animateFling(int velocityX, int velocityY,
|
||||||
|
int minX, int maxX, int minY, int maxY) {
|
||||||
|
|
||||||
|
if (velocityX * velocityX + velocityY * velocityY < 2048)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mViewport.getMapPosition(mPos);
|
||||||
|
|
||||||
|
mScroll.x = 0;
|
||||||
|
mScroll.y = 0;
|
||||||
|
|
||||||
|
float duration = 500;
|
||||||
|
|
||||||
|
// pi times thumb..
|
||||||
|
float flingFactor = (duration / 2500);
|
||||||
|
mVelocity.x = velocityX * flingFactor;
|
||||||
|
mVelocity.y = velocityY * flingFactor;
|
||||||
|
FastMath.clamp(mVelocity.x, minX, maxX);
|
||||||
|
FastMath.clamp(mVelocity.y, minY, maxY);
|
||||||
|
|
||||||
|
mAnimFling = true;
|
||||||
|
mAnimMove = false;
|
||||||
|
mAnimScale = false;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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)
|
||||||
|
return;
|
||||||
|
|
||||||
|
long millisLeft = mAnimEnd - System.currentTimeMillis();
|
||||||
|
|
||||||
|
synchronized (mViewport) {
|
||||||
|
|
||||||
|
// cancel animation when position was changed since last
|
||||||
|
// update, i.e. when it was modified outside the animator.
|
||||||
|
if (mViewport.getMapPosition(mPos)) {
|
||||||
|
animCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (millisLeft <= 0) {
|
||||||
|
// set final position
|
||||||
|
if (mAnimMove && !mAnimFling)
|
||||||
|
mViewport.moveInternal(mStartPos.x + mDeltaPos.x, mStartPos.y + mDeltaPos.y);
|
||||||
|
|
||||||
|
if (mAnimScale) {
|
||||||
|
if (mScaleBy > 0)
|
||||||
|
doScale(mStartPos.scale + (mScaleBy - 1));
|
||||||
|
else
|
||||||
|
doScale(mStartPos.scale + mScaleBy);
|
||||||
|
}
|
||||||
|
mMap.updateMap(true);
|
||||||
|
|
||||||
|
animCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
float adv = (1.0f - millisLeft / mDuration);
|
||||||
|
|
||||||
|
if (mAnimScale) {
|
||||||
|
if (mScaleBy > 0)
|
||||||
|
doScale(mStartPos.scale + (mScaleBy * (Math.pow(2, adv) - 1)));
|
||||||
|
else
|
||||||
|
doScale(mStartPos.scale + (mScaleBy * adv));
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAnimMove) {
|
||||||
|
mViewport.moveInternal(
|
||||||
|
mStartPos.x + mDeltaPos.x * adv,
|
||||||
|
mStartPos.y + mDeltaPos.y * adv);
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (mAnimMove && mAnimScale) {
|
||||||
|
// mPos.angle = mStartPos.angle * (1 - adv);
|
||||||
|
// updateMatrix();
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (mAnimFling && fling(adv))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
// continue animation
|
||||||
|
if (changed) {
|
||||||
|
// inform other layers that position has changed
|
||||||
|
mMap.updateMap(true);
|
||||||
|
} else {
|
||||||
|
// just render next frame
|
||||||
|
mMap.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember current map position
|
||||||
|
mViewport.getMapPosition(mPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doScale(double newScale) {
|
||||||
|
mViewport.scaleMap((float) (newScale / mPos.scale), (float)mPivot.x, (float)mPivot.y);
|
||||||
|
}
|
||||||
|
}
|
@ -28,7 +28,6 @@ import org.oscim.utils.Matrix4;
|
|||||||
public class Viewport {
|
public class Viewport {
|
||||||
//private static final String TAG = Viewport.class.getName();
|
//private static final String TAG = Viewport.class.getName();
|
||||||
|
|
||||||
// needs to fit for int: 2 * 20 * Tile.SIZE
|
|
||||||
public final static int MAX_ZOOMLEVEL = 20;
|
public final static int MAX_ZOOMLEVEL = 20;
|
||||||
public final static int MIN_ZOOMLEVEL = 2;
|
public final static int MIN_ZOOMLEVEL = 2;
|
||||||
|
|
||||||
@ -37,24 +36,7 @@ public class Viewport {
|
|||||||
|
|
||||||
private final static float MAX_TILT = 65;
|
private final static float MAX_TILT = 65;
|
||||||
|
|
||||||
private final Map mMap;
|
private final MapPosition mPos = new MapPosition();
|
||||||
|
|
||||||
private double mAbsScale;
|
|
||||||
private double mAbsX;
|
|
||||||
private double mAbsY;
|
|
||||||
|
|
||||||
// mAbsScale * Tile.SIZE
|
|
||||||
// i.e. size of tile 0/0/0 at current scale in pixel
|
|
||||||
private double mCurScale;
|
|
||||||
|
|
||||||
// mAbsX * mCurScale
|
|
||||||
private double mCurX;
|
|
||||||
|
|
||||||
// mAbsY * mCurScale
|
|
||||||
private double mCurY;
|
|
||||||
|
|
||||||
private float mRotation;
|
|
||||||
private float mTilt;
|
|
||||||
|
|
||||||
private final Matrix4 mProjMatrix = new Matrix4();
|
private final Matrix4 mProjMatrix = new Matrix4();
|
||||||
private final Matrix4 mProjMatrixI = new Matrix4();
|
private final Matrix4 mProjMatrixI = new Matrix4();
|
||||||
@ -81,22 +63,13 @@ public class Viewport {
|
|||||||
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
||||||
|
|
||||||
Viewport(Map map) {
|
Viewport(Map map) {
|
||||||
mMap = map;
|
|
||||||
|
|
||||||
mAbsScale = 4;
|
mPos.scale = 4;
|
||||||
mAbsX = 0.5;
|
mPos.x = 0.5;
|
||||||
mAbsY = 0.5;
|
mPos.y = 0.5;
|
||||||
|
|
||||||
mRotation = 0;
|
mPos.angle = 0;
|
||||||
mTilt = 0;
|
mPos.tilt = 0;
|
||||||
|
|
||||||
updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePosition() {
|
|
||||||
mCurScale = mAbsScale * Tile.SIZE;
|
|
||||||
mCurX = mAbsX * mCurScale;
|
|
||||||
mCurY = mAbsY * mCurScale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setViewport(int width, int height) {
|
public void setViewport(int width, int height) {
|
||||||
@ -129,25 +102,23 @@ public class Viewport {
|
|||||||
*/
|
*/
|
||||||
public synchronized boolean getMapPosition(MapPosition pos) {
|
public synchronized boolean getMapPosition(MapPosition pos) {
|
||||||
|
|
||||||
int z = FastMath.log2((int) mAbsScale);
|
int z = FastMath.log2((int) mPos.scale);
|
||||||
//z = FastMath.clamp(z, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
|
||||||
//float scale = (float) (mAbsScale / (1 << z));
|
|
||||||
|
|
||||||
boolean changed = (pos.zoomLevel != z
|
boolean changed = (pos.zoomLevel != z
|
||||||
|| pos.x != mAbsX
|
|| pos.x != mPos.x
|
||||||
|| pos.y != mAbsY
|
|| pos.y != mPos.y
|
||||||
|| pos.scale != mAbsScale
|
|| pos.scale != mPos.scale
|
||||||
|| pos.angle != mRotation
|
|| pos.angle != mPos.angle
|
||||||
|| pos.tilt != mTilt);
|
|| pos.tilt != mPos.tilt);
|
||||||
|
|
||||||
pos.angle = mRotation;
|
pos.angle = mPos.angle;
|
||||||
pos.tilt = mTilt;
|
pos.tilt = mPos.tilt;
|
||||||
|
|
||||||
pos.x = mAbsX;
|
pos.x = mPos.x;
|
||||||
pos.y = mAbsY;
|
pos.y = mPos.y;
|
||||||
pos.scale = mAbsScale;
|
pos.scale = mPos.scale;
|
||||||
|
|
||||||
// for tiling
|
// handy for tiling
|
||||||
pos.zoomLevel = z;
|
pos.zoomLevel = z;
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
@ -212,7 +183,7 @@ public class Viewport {
|
|||||||
ua = 1;
|
ua = 1;
|
||||||
else {
|
else {
|
||||||
// tilt of the plane (center is kept on x = 0)
|
// tilt of the plane (center is kept on x = 0)
|
||||||
double t = Math.toRadians(mTilt);
|
double t = Math.toRadians(mPos.tilt);
|
||||||
double px = y * Math.sin(t);
|
double px = y * Math.sin(t);
|
||||||
double py = y * Math.cos(t);
|
double py = y * Math.cos(t);
|
||||||
ua = 1 + (px * ry) / (py * cx);
|
ua = 1 + (px * ry) / (py * cx);
|
||||||
@ -240,8 +211,8 @@ public class Viewport {
|
|||||||
|
|
||||||
/** @return the current center point of the MapView. */
|
/** @return the current center point of the MapView. */
|
||||||
public synchronized GeoPoint getMapCenter() {
|
public synchronized GeoPoint getMapCenter() {
|
||||||
return new GeoPoint(MercatorProjection.toLatitude(mAbsY),
|
return new GeoPoint(MercatorProjection.toLatitude(mPos.y),
|
||||||
MercatorProjection.toLongitude(mAbsX));
|
MercatorProjection.toLongitude(mPos.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -285,10 +256,15 @@ public class Viewport {
|
|||||||
box.maxY = Math.max(box.maxY, coords[i + 1]);
|
box.maxY = Math.max(box.maxY, coords[i + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
box.minX = (mCurX + box.minX) / mCurScale;
|
//updatePosition();
|
||||||
box.maxX = (mCurX + box.maxX) / mCurScale;
|
double cs = mPos.scale * Tile.SIZE;
|
||||||
box.minY = (mCurY + box.minY) / mCurScale;
|
double cx = mPos.x * cs;
|
||||||
box.maxY = (mCurY + box.maxY) / mCurScale;
|
double cy = mPos.y * cs;
|
||||||
|
|
||||||
|
box.minX = (cx + box.minX) / cs;
|
||||||
|
box.maxX = (cx + box.maxX) / cs;
|
||||||
|
box.minY = (cy + box.minY) / cs;
|
||||||
|
box.maxY = (cy + box.maxY) / cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,8 +287,8 @@ public class Viewport {
|
|||||||
out.y = mu[1];
|
out.y = mu[1];
|
||||||
|
|
||||||
if (scale != 0) {
|
if (scale != 0) {
|
||||||
out.x *= scale / mAbsScale;
|
out.x *= scale / mPos.scale;
|
||||||
out.y *= scale / mAbsScale;
|
out.y *= scale / mPos.scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,11 +320,15 @@ public class Viewport {
|
|||||||
|
|
||||||
unproject(-mx, my, getZ(-my), mu, 0);
|
unproject(-mx, my, getZ(-my), mu, 0);
|
||||||
|
|
||||||
double dx = mCurX + mu[0];
|
double cs = mPos.scale * Tile.SIZE;
|
||||||
double dy = mCurY + mu[1];
|
double cx = mPos.x * cs;
|
||||||
|
double cy = mPos.y * cs;
|
||||||
|
|
||||||
dx /= mCurScale;
|
double dx = cx + mu[0];
|
||||||
dy /= mCurScale;
|
double dy = cy + mu[1];
|
||||||
|
|
||||||
|
dx /= cs;
|
||||||
|
dy /= cs;
|
||||||
|
|
||||||
if (dx > 1) {
|
if (dx > 1) {
|
||||||
while (dx > 1)
|
while (dx > 1)
|
||||||
@ -386,8 +366,13 @@ public class Viewport {
|
|||||||
*/
|
*/
|
||||||
public synchronized void project(double x, double y, Point out) {
|
public synchronized void project(double x, double y, Point out) {
|
||||||
|
|
||||||
mv[0] = (float) (x * mCurScale - mCurX);
|
//updatePosition();
|
||||||
mv[1] = (float) (y * mCurScale - mCurY);
|
double cs = mPos.scale * Tile.SIZE;
|
||||||
|
double cx = mPos.x * cs;
|
||||||
|
double cy = mPos.y * cs;
|
||||||
|
|
||||||
|
mv[0] = (float) (x * cs - cx);
|
||||||
|
mv[1] = (float) (y * cs - cy);
|
||||||
|
|
||||||
mv[2] = 0;
|
mv[2] = 0;
|
||||||
mv[3] = 1;
|
mv[3] = 1;
|
||||||
@ -408,15 +393,15 @@ public class Viewport {
|
|||||||
// 4. translate to VIEW_DISTANCE
|
// 4. translate to VIEW_DISTANCE
|
||||||
// 5. apply projection
|
// 5. apply projection
|
||||||
|
|
||||||
while (mRotation > 360)
|
while (mPos.angle > 360)
|
||||||
mRotation -= 360;
|
mPos.angle -= 360;
|
||||||
while (mRotation < 0)
|
while (mPos.angle < 0)
|
||||||
mRotation += 360;
|
mPos.angle += 360;
|
||||||
|
|
||||||
mRotMatrix.setRotation(mRotation, 0, 0, 1);
|
mRotMatrix.setRotation(mPos.angle, 0, 0, 1);
|
||||||
|
|
||||||
// tilt map
|
// tilt map
|
||||||
mTmpMatrix.setRotation(mTilt, 1, 0, 0);
|
mTmpMatrix.setRotation(mPos.tilt, 1, 0, 0);
|
||||||
|
|
||||||
// apply first rotation, then tilt
|
// apply first rotation, then tilt
|
||||||
mRotMatrix.multiplyMM(mTmpMatrix, mRotMatrix);
|
mRotMatrix.multiplyMM(mTmpMatrix, mRotMatrix);
|
||||||
@ -450,35 +435,42 @@ public class Viewport {
|
|||||||
* @param my the amount of pixels to move the map vertically.
|
* @param my the amount of pixels to move the map vertically.
|
||||||
*/
|
*/
|
||||||
public synchronized void moveMap(float mx, float my) {
|
public synchronized void moveMap(float mx, float my) {
|
||||||
// stop animation
|
|
||||||
animCancel();
|
|
||||||
|
|
||||||
Point p = applyRotation(mx, my);
|
Point p = applyRotation(mx, my);
|
||||||
move(p.x, p.y);
|
double tileScale = mPos.scale * Tile.SIZE;
|
||||||
|
|
||||||
|
moveBy(p.x / tileScale, p.y / tileScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void move(double mx, double my) {
|
void moveInternal(double mx, double my){
|
||||||
mAbsX = (mCurX - mx) / mCurScale;
|
Point p = applyRotation(mx, my);
|
||||||
mAbsY = (mCurY - my) / mCurScale;
|
moveBy(p.x, p.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveBy(double mx, double my) {
|
||||||
|
mPos.x -= mx;
|
||||||
|
mPos.y -= my;
|
||||||
|
|
||||||
// clamp latitude
|
// clamp latitude
|
||||||
mAbsY = FastMath.clamp(mAbsY, 0, 1);
|
mPos.y = FastMath.clamp(mPos.y, 0, 1);
|
||||||
|
|
||||||
// wrap longitude
|
// wrap longitude
|
||||||
while (mAbsX > 1)
|
while (mPos.x > 1)
|
||||||
mAbsX -= 1;
|
mPos.x -= 1;
|
||||||
while (mAbsX < 0)
|
while (mPos.x < 0)
|
||||||
mAbsX += 1;
|
mPos.x += 1;
|
||||||
|
|
||||||
updatePosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Point applyRotation(float mx, float my) {
|
Point applyRotation(double mx, double my) {
|
||||||
double rad = Math.toRadians(mRotation);
|
if (mPos.angle == 0) {
|
||||||
double rcos = Math.cos(rad);
|
mMovePoint.x = mx;
|
||||||
double rsin = Math.sin(rad);
|
mMovePoint.y = my;
|
||||||
mMovePoint.x = mx * rcos + my * rsin;
|
} else {
|
||||||
mMovePoint.y = mx * -rsin + my * rcos;
|
double rad = Math.toRadians(mPos.angle);
|
||||||
|
double rcos = Math.cos(rad);
|
||||||
|
double rsin = Math.sin(rad);
|
||||||
|
mMovePoint.x = mx * rcos + my * rsin;
|
||||||
|
mMovePoint.y = mx * -rsin + my * rcos;
|
||||||
|
}
|
||||||
return mMovePoint;
|
return mMovePoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,28 +481,25 @@ public class Viewport {
|
|||||||
* @return true if scale was changed
|
* @return true if scale was changed
|
||||||
*/
|
*/
|
||||||
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||||
// stop animation
|
|
||||||
animCancel();
|
|
||||||
|
|
||||||
// just sanitize input
|
// just sanitize input
|
||||||
scale = FastMath.clamp(scale, 0.5f, 2);
|
//scale = FastMath.clamp(scale, 0.5f, 2);
|
||||||
|
if (scale < 0.000001)
|
||||||
|
return false;
|
||||||
|
|
||||||
double newScale = mAbsScale * scale;
|
double newScale = mPos.scale * scale;
|
||||||
|
|
||||||
newScale = FastMath.clamp(newScale, MIN_SCALE, MAX_SCALE);
|
newScale = FastMath.clamp(newScale, MIN_SCALE, MAX_SCALE);
|
||||||
|
|
||||||
if (newScale == mAbsScale)
|
if (newScale == mPos.scale)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
scale = (float) (newScale / mAbsScale);
|
scale = (float) (newScale / mPos.scale);
|
||||||
|
|
||||||
mAbsScale = newScale;
|
mPos.scale = newScale;
|
||||||
|
|
||||||
if (pivotX != 0 || pivotY != 0)
|
if (pivotX != 0 || pivotY != 0)
|
||||||
moveMap(pivotX * (1.0f - scale),
|
moveMap(pivotX * (1.0f - scale),
|
||||||
pivotY * (1.0f - scale));
|
pivotY * (1.0f - scale));
|
||||||
else
|
|
||||||
updatePosition();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -519,341 +508,64 @@ public class Viewport {
|
|||||||
* rotate map around pivot cx,cy
|
* rotate map around pivot cx,cy
|
||||||
*
|
*
|
||||||
* @param radians ...
|
* @param radians ...
|
||||||
* @param cx ...
|
* @param pivotX ...
|
||||||
* @param cy ...
|
* @param pivotY ...
|
||||||
*/
|
*/
|
||||||
public synchronized void rotateMap(double radians, float cx, float cy) {
|
public synchronized void rotateMap(double radians, float pivotX, float pivotY) {
|
||||||
|
|
||||||
double rsin = Math.sin(radians);
|
double rsin = Math.sin(radians);
|
||||||
double rcos = Math.cos(radians);
|
double rcos = Math.cos(radians);
|
||||||
|
|
||||||
float x = (float) (cx * rcos + cy * -rsin - cx);
|
float x = (float) (pivotX * rcos + pivotY * -rsin - pivotX);
|
||||||
float y = (float) (cx * rsin + cy * rcos - cy);
|
float y = (float) (pivotX * rsin + pivotY * rcos - pivotY);
|
||||||
|
|
||||||
moveMap(x, y);
|
moveMap(x, y);
|
||||||
|
|
||||||
mRotation += Math.toDegrees(radians);
|
mPos.angle += Math.toDegrees(radians);
|
||||||
|
|
||||||
updateMatrix();
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setRotation(float f) {
|
public synchronized void setRotation(float f) {
|
||||||
|
|
||||||
mRotation = f;
|
mPos.angle = f;
|
||||||
updateMatrix();
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean tiltMap(float move) {
|
public synchronized boolean tiltMap(float move) {
|
||||||
return setTilt(mTilt + move);
|
return setTilt(mPos.tilt + move);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean setTilt(float tilt) {
|
public synchronized boolean setTilt(float tilt) {
|
||||||
tilt = FastMath.clamp(tilt, 0, MAX_TILT);
|
tilt = FastMath.clamp(tilt, 0, MAX_TILT);
|
||||||
if (tilt == mTilt)
|
if (tilt == mPos.tilt)
|
||||||
return false;
|
return false;
|
||||||
mTilt = tilt;
|
mPos.tilt = tilt;
|
||||||
updateMatrix();
|
updateMatrix();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized float getTilt() {
|
public synchronized float getTilt() {
|
||||||
return mTilt;
|
return mPos.tilt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMapCenter(double latitude, double longitude) {
|
private void setMapCenter(double latitude, double longitude) {
|
||||||
latitude = MercatorProjection.limitLatitude(latitude);
|
latitude = MercatorProjection.limitLatitude(latitude);
|
||||||
longitude = MercatorProjection.limitLongitude(longitude);
|
longitude = MercatorProjection.limitLongitude(longitude);
|
||||||
mAbsX = MercatorProjection.longitudeToX(longitude);
|
mPos.x = MercatorProjection.longitudeToX(longitude);
|
||||||
mAbsY = MercatorProjection.latitudeToY(latitude);
|
mPos.y = MercatorProjection.latitudeToY(latitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setMapPosition(MapPosition mapPosition) {
|
public synchronized void setMapPosition(MapPosition mapPosition) {
|
||||||
mAbsScale = FastMath.clamp(mapPosition.scale, MIN_SCALE, MAX_SCALE);
|
mPos.scale = FastMath.clamp(mapPosition.scale, MIN_SCALE, MAX_SCALE);
|
||||||
mAbsX = mapPosition.x;
|
mPos.x = mapPosition.x;
|
||||||
mAbsY = mapPosition.y;
|
mPos.y = mapPosition.y;
|
||||||
mTilt = mapPosition.tilt;
|
mPos.tilt = mapPosition.tilt;
|
||||||
mRotation = mapPosition.angle;
|
mPos.angle = mapPosition.angle;
|
||||||
updatePosition();
|
|
||||||
updateMatrix();
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void setMapCenter(GeoPoint geoPoint) {
|
synchronized void setMapCenter(GeoPoint geoPoint) {
|
||||||
setMapCenter(geoPoint.getLatitude(), geoPoint.getLongitude());
|
setMapCenter(geoPoint.getLatitude(), geoPoint.getLongitude());
|
||||||
updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
// TODO move to MapAnimator
|
|
||||||
class AnimState {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private double mScrollX;
|
|
||||||
private double mScrollY;
|
|
||||||
private double mStartX;
|
|
||||||
private double mStartY;
|
|
||||||
private double mEndX;
|
|
||||||
private double mEndY;
|
|
||||||
|
|
||||||
private double mStartScale;
|
|
||||||
private double mEndScale;
|
|
||||||
private float mStartRotation;
|
|
||||||
|
|
||||||
private float mDuration = 500;
|
|
||||||
private long mAnimEnd = -1;
|
|
||||||
|
|
||||||
private boolean mAnimMove;
|
|
||||||
private boolean mAnimFling;
|
|
||||||
private boolean mAnimScale;
|
|
||||||
private boolean mAnimPivot;
|
|
||||||
private GeoPoint mEndPos;
|
|
||||||
private double mFinalScale;
|
|
||||||
|
|
||||||
public synchronized void animateTo(BoundingBox bbox) {
|
|
||||||
// calculate the maximum scale at which the bbox is completely visible
|
|
||||||
double dx = Math.abs(MercatorProjection.longitudeToX(bbox.getMaxLongitude())
|
|
||||||
- MercatorProjection.longitudeToX(bbox.getMinLongitude()));
|
|
||||||
|
|
||||||
double dy = Math.abs(MercatorProjection.latitudeToY(bbox.getMinLatitude())
|
|
||||||
- MercatorProjection.latitudeToY(bbox.getMaxLatitude()));
|
|
||||||
|
|
||||||
double zx = mWidth / (dx * Tile.SIZE);
|
|
||||||
double zy = mHeight / (dy * Tile.SIZE);
|
|
||||||
double newScale = Math.min(zx, zy);
|
|
||||||
|
|
||||||
//Log.d(TAG, "scale to " + bbox + " " + newScale + " " + mAbsScale
|
|
||||||
// + " " + FastMath.log2((int) newScale));
|
|
||||||
|
|
||||||
animateTo(500, bbox.getCenterPoint(), newScale, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void animateTo(long duration, GeoPoint geoPoint, double scale,
|
|
||||||
boolean relative) {
|
|
||||||
|
|
||||||
if (relative) {
|
|
||||||
if (mAnimEnd > 0 && mAnimScale)
|
|
||||||
scale = mFinalScale * scale;
|
|
||||||
else
|
|
||||||
scale = mAbsScale * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
scale = FastMath.clamp(scale, MIN_SCALE, MAX_SCALE);
|
|
||||||
mFinalScale = scale;
|
|
||||||
|
|
||||||
scale = (float) (scale / mAbsScale);
|
|
||||||
|
|
||||||
mEndScale = mAbsScale * scale - mAbsScale;
|
|
||||||
mStartScale = mAbsScale;
|
|
||||||
mStartRotation = mRotation;
|
|
||||||
|
|
||||||
mStartX = mAbsX;
|
|
||||||
mStartY = mAbsY;
|
|
||||||
|
|
||||||
mEndX = MercatorProjection.longitudeToX(geoPoint.getLongitude());
|
|
||||||
mEndY = MercatorProjection.latitudeToY(geoPoint.getLatitude());
|
|
||||||
mEndX -= mStartX;
|
|
||||||
mEndY -= mStartY;
|
|
||||||
mAnimMove = true;
|
|
||||||
mAnimScale = true;
|
|
||||||
mAnimFling = false;
|
|
||||||
|
|
||||||
mEndPos = geoPoint;
|
|
||||||
|
|
||||||
animStart(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void animateZoom(long duration, double scale, double pivotX, double pivotY) {
|
|
||||||
|
|
||||||
if (mAnimEnd > 0 && mAnimScale)
|
|
||||||
scale = mFinalScale * scale;
|
|
||||||
else
|
|
||||||
scale = mAbsScale * scale;
|
|
||||||
|
|
||||||
scale = FastMath.clamp(scale, MIN_SCALE, MAX_SCALE);
|
|
||||||
mFinalScale = scale;
|
|
||||||
|
|
||||||
scale = (float) (scale / mAbsScale);
|
|
||||||
|
|
||||||
mEndScale = mAbsScale * scale - mAbsScale;
|
|
||||||
mStartScale = mAbsScale;
|
|
||||||
mStartRotation = mRotation;
|
|
||||||
|
|
||||||
mScrollX = pivotX;
|
|
||||||
mScrollY = pivotY;
|
|
||||||
|
|
||||||
mAnimScale = true;
|
|
||||||
mAnimPivot = (pivotX != 0 || pivotY != 0);
|
|
||||||
|
|
||||||
mAnimFling = false;
|
|
||||||
mAnimMove = false;
|
|
||||||
|
|
||||||
animStart(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void animateTo(GeoPoint geoPoint) {
|
|
||||||
animateTo(300, geoPoint, 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void animStart(float duration) {
|
|
||||||
mDuration = duration;
|
|
||||||
|
|
||||||
mAnimEnd = System.currentTimeMillis() + (long) duration;
|
|
||||||
mMap.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void animCancel() {
|
|
||||||
mAnimEnd = -1;
|
|
||||||
mEndPos = null;
|
|
||||||
mAnimScale = false;
|
|
||||||
mAnimFling = false;
|
|
||||||
mAnimMove = false;
|
|
||||||
mAnimPivot = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized boolean fling(float adv) {
|
|
||||||
|
|
||||||
adv = (float) Math.sqrt(adv);
|
|
||||||
|
|
||||||
float dx = mVelocityX * adv;
|
|
||||||
float dy = mVelocityY * adv;
|
|
||||||
|
|
||||||
if (dx != 0 || dy != 0) {
|
|
||||||
Point p = applyRotation((float) (dx - mScrollX), (float) (dy - mScrollY));
|
|
||||||
move(p.x, p.y);
|
|
||||||
|
|
||||||
mScrollX = dx;
|
|
||||||
mScrollY = dy;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private float mVelocityX;
|
|
||||||
private float mVelocityY;
|
|
||||||
|
|
||||||
public synchronized void animateFling(int velocityX, int velocityY,
|
|
||||||
int minX, int maxX, int minY, int maxY) {
|
|
||||||
|
|
||||||
if (velocityX * velocityX + velocityY * velocityY < 2048)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mScrollX = 0;
|
|
||||||
mScrollY = 0;
|
|
||||||
|
|
||||||
float duration = 500;
|
|
||||||
|
|
||||||
// pi times thumb..
|
|
||||||
float flingFactor = (duration / 2500);
|
|
||||||
mVelocityX = velocityX * flingFactor;
|
|
||||||
mVelocityY = velocityY * flingFactor;
|
|
||||||
FastMath.clamp(mVelocityX, minX, maxX);
|
|
||||||
FastMath.clamp(mVelocityY, minY, maxY);
|
|
||||||
|
|
||||||
mAnimFling = true;
|
|
||||||
mAnimMove = false;
|
|
||||||
mAnimScale = false;
|
|
||||||
animStart(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* called by GLRenderer at begin of each frame.
|
|
||||||
*/
|
|
||||||
public void updateAnimation() {
|
|
||||||
if (mAnimEnd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
long millisLeft = mAnimEnd - System.currentTimeMillis();
|
|
||||||
|
|
||||||
if (millisLeft <= 0) {
|
|
||||||
// set final position
|
|
||||||
if (mAnimMove) {
|
|
||||||
if (mEndPos == null)
|
|
||||||
doMove(mStartX + mEndX, mStartY + mEndY);
|
|
||||||
else {
|
|
||||||
setMapCenter(mEndPos);
|
|
||||||
mEndPos = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAnimScale) {
|
|
||||||
doScale(mFinalScale);
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePosition();
|
|
||||||
mMap.updateMap(true);
|
|
||||||
|
|
||||||
animCancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean changed = false;
|
|
||||||
|
|
||||||
float adv = (1.0f - millisLeft / mDuration);
|
|
||||||
|
|
||||||
if (mAnimScale) {
|
|
||||||
if (mEndScale > 0)
|
|
||||||
doScale(mStartScale + (mEndScale * (Math.pow(2, adv) - 1)));
|
|
||||||
else
|
|
||||||
doScale(mStartScale + (mEndScale * adv));
|
|
||||||
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAnimMove) {
|
|
||||||
doMove(mStartX + mEndX * adv, mStartY + mEndY * adv);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAnimMove && mAnimScale) {
|
|
||||||
mRotation = mStartRotation * (1 - adv);
|
|
||||||
updateMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed) {
|
|
||||||
updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAnimFling && fling(adv))
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
// continue animation
|
|
||||||
if (changed) {
|
|
||||||
// inform other layers that position has changed
|
|
||||||
mMap.updateMap(true);
|
|
||||||
} else {
|
|
||||||
// just render next frame
|
|
||||||
mMap.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doScale(double newScale) {
|
|
||||||
double scale = mAbsScale;
|
|
||||||
|
|
||||||
mAbsScale = newScale;
|
|
||||||
|
|
||||||
if (mAnimPivot) {
|
|
||||||
scale = mAbsScale / scale;
|
|
||||||
|
|
||||||
Point p = applyRotation(
|
|
||||||
(float) (mScrollX * (1.0 - scale)),
|
|
||||||
(float) (mScrollY * (1.0 - scale)));
|
|
||||||
move(p.x, p.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doMove(double x, double y) {
|
|
||||||
mAbsX = x;
|
|
||||||
mAbsY = y;
|
|
||||||
|
|
||||||
// clamp latitude
|
|
||||||
mAbsY = FastMath.clamp(mAbsY, 0, 1);
|
|
||||||
|
|
||||||
// wrap longitude
|
|
||||||
while (mAbsX > 1)
|
|
||||||
mAbsX -= 1;
|
|
||||||
while (mAbsX < 0)
|
|
||||||
mAbsX += 1;
|
|
||||||
|
|
||||||
updatePosition();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user