split Viewport modifiers into ViewController
This commit is contained in:
parent
46878c81b7
commit
91d1e7b1a6
@ -22,7 +22,7 @@ import org.oscim.event.Gesture;
|
||||
import org.oscim.event.GestureListener;
|
||||
import org.oscim.event.MotionEvent;
|
||||
import org.oscim.map.Map;
|
||||
import org.oscim.map.Viewport;
|
||||
import org.oscim.map.ViewController;
|
||||
import org.oscim.utils.FastMath;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -74,12 +74,12 @@ public class MapEventLayer extends Layer implements Map.InputListener, GestureLi
|
||||
/** 100 ms since start of move to reduce fling scroll */
|
||||
protected static final float FLING_THREHSHOLD = 100;
|
||||
|
||||
private final Viewport mViewport;
|
||||
//private final Viewport mViewport;
|
||||
private final VelocityTracker mTracker;
|
||||
|
||||
public MapEventLayer(Map map) {
|
||||
super(map);
|
||||
mViewport = map.viewport();
|
||||
//mViewport = map.viewport();
|
||||
mTracker = new VelocityTracker();
|
||||
}
|
||||
|
||||
@ -173,6 +173,7 @@ public class MapEventLayer extends Layer implements Map.InputListener, GestureLi
|
||||
}
|
||||
|
||||
private boolean onActionMove(MotionEvent e) {
|
||||
ViewController mViewport = mMap.viewport();
|
||||
float x1 = e.getX(0);
|
||||
float y1 = e.getY(0);
|
||||
|
||||
|
@ -196,7 +196,7 @@ public class Animator {
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
Viewport v = mMap.viewport();
|
||||
ViewController v = mMap.viewport();
|
||||
|
||||
synchronized (v) {
|
||||
/* cancel animation when position was changed since last
|
||||
@ -252,7 +252,7 @@ public class Animator {
|
||||
}
|
||||
}
|
||||
|
||||
private void doScale(Viewport v, float adv) {
|
||||
private void doScale(ViewController v, float adv) {
|
||||
double newScale;
|
||||
|
||||
newScale = mStartPos.scale + (mDeltaPos.scale * adv);
|
||||
|
@ -42,7 +42,7 @@ public abstract class Map {
|
||||
/**
|
||||
* Listener interface for map update notifications.
|
||||
* Layers implementing this interface they will be automatically
|
||||
* regiseter when the layer is added to the map and unregistered when
|
||||
* register when the layer is added to the map and unregistered when
|
||||
* the layer is removed.
|
||||
*/
|
||||
public interface UpdateListener {
|
||||
@ -52,7 +52,7 @@ public abstract class Map {
|
||||
/**
|
||||
* Listener interface for input events.
|
||||
* Layers implementing this interface they will be automatically
|
||||
* regiseter when the layer is added to the map and unregistered when
|
||||
* register when the layer is added to the map and unregistered when
|
||||
* the layer is removed.
|
||||
*/
|
||||
public interface InputListener {
|
||||
@ -60,7 +60,7 @@ public abstract class Map {
|
||||
}
|
||||
|
||||
private final Layers mLayers;
|
||||
private final Viewport mViewport;
|
||||
private final ViewController mViewport;
|
||||
private final Animator mAnimator;
|
||||
|
||||
private final MapPosition mMapPosition;
|
||||
@ -80,7 +80,7 @@ public abstract class Map {
|
||||
protected boolean mClearMap = true;
|
||||
|
||||
public Map() {
|
||||
mViewport = new Viewport(this);
|
||||
mViewport = new ViewController(this);
|
||||
mAnimator = new Animator(this, mViewport);
|
||||
|
||||
mLayers = new Layers(this);
|
||||
@ -230,7 +230,7 @@ public abstract class Map {
|
||||
/**
|
||||
* @return Viewport instance
|
||||
*/
|
||||
public Viewport viewport() {
|
||||
public ViewController viewport() {
|
||||
return mViewport;
|
||||
}
|
||||
|
||||
|
206
vtm/src/org/oscim/map/ViewController.java
Normal file
206
vtm/src/org/oscim/map/ViewController.java
Normal file
@ -0,0 +1,206 @@
|
||||
package org.oscim.map;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Point;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.GLMatrix;
|
||||
import org.oscim.utils.FastMath;
|
||||
|
||||
public class ViewController extends Viewport {
|
||||
|
||||
ViewController(Map map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
public synchronized void setScreenSize(int width, int height) {
|
||||
mHeight = height;
|
||||
mWidth = width;
|
||||
|
||||
/* setup projection matrix:
|
||||
* 0. scale to window coordinates
|
||||
* 1. translate to VIEW_DISTANCE
|
||||
* 2. apply projection
|
||||
* setup inverse projection:
|
||||
* 0. invert projection
|
||||
* 1. invert translate to VIEW_DISTANCE */
|
||||
|
||||
float ratio = (mHeight / mWidth) * VIEW_SCALE;
|
||||
float[] tmp = new float[16];
|
||||
|
||||
GLMatrix.frustumM(tmp, 0, -VIEW_SCALE, VIEW_SCALE,
|
||||
ratio, -ratio, VIEW_NEAR, VIEW_FAR);
|
||||
|
||||
mProjMatrix.set(tmp);
|
||||
mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE);
|
||||
mProjMatrix.multiplyRhs(mTmpMatrix);
|
||||
|
||||
/* set inverse projection matrix (without scaling) */
|
||||
mProjMatrix.get(tmp);
|
||||
GLMatrix.invertM(tmp, 0, tmp, 0);
|
||||
mProjMatrixI.set(tmp);
|
||||
|
||||
mProjMatrixUnscaled.copy(mProjMatrix);
|
||||
|
||||
/* scale to window coordinates */
|
||||
mTmpMatrix.setScale(1 / mWidth, 1 / mWidth, 1 / mWidth);
|
||||
mProjMatrix.multiplyRhs(mTmpMatrix);
|
||||
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves this Viewport by the given amount of pixels.
|
||||
*
|
||||
* @param mx the amount of pixels to move the map horizontally.
|
||||
* @param my the amount of pixels to move the map vertically.
|
||||
*/
|
||||
public synchronized void moveMap(float mx, float my) {
|
||||
Point p = applyRotation(mx, my);
|
||||
double tileScale = mPos.scale * Tile.SIZE;
|
||||
moveTo(mPos.x - p.x / tileScale, mPos.y - p.y / tileScale);
|
||||
}
|
||||
|
||||
/* used by MapAnimator */
|
||||
void moveTo(double x, double y) {
|
||||
mPos.x = x;
|
||||
mPos.y = y;
|
||||
|
||||
// clamp latitude
|
||||
mPos.y = FastMath.clamp(mPos.y, 0, 1);
|
||||
|
||||
// wrap longitude
|
||||
while (mPos.x > 1)
|
||||
mPos.x -= 1;
|
||||
while (mPos.x < 0)
|
||||
mPos.x += 1;
|
||||
}
|
||||
|
||||
private Point applyRotation(double mx, double my) {
|
||||
if (mPos.angle == 0) {
|
||||
mMovePoint.x = mx;
|
||||
mMovePoint.y = my;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale map by scale width center at pivot in pixel relative to
|
||||
* screen center. Map scale is clamp to MIN_SCALE and MAX_SCALE.
|
||||
*
|
||||
* @param scale
|
||||
* @param pivotX
|
||||
* @param pivotY
|
||||
* @return true if scale was changed
|
||||
*/
|
||||
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||
// just sanitize input
|
||||
//scale = FastMath.clamp(scale, 0.5f, 2);
|
||||
if (scale < 0.000001)
|
||||
return false;
|
||||
|
||||
double newScale = mPos.scale * scale;
|
||||
|
||||
newScale = FastMath.clamp(newScale, MIN_SCALE, MAX_SCALE);
|
||||
|
||||
if (newScale == mPos.scale)
|
||||
return false;
|
||||
|
||||
scale = (float) (newScale / mPos.scale);
|
||||
|
||||
mPos.scale = newScale;
|
||||
|
||||
if (pivotX != 0 || pivotY != 0)
|
||||
moveMap(pivotX * (1.0f - scale),
|
||||
pivotY * (1.0f - scale));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate map by radians around pivot. Pivot is in pixel relative
|
||||
* to screen center.
|
||||
*
|
||||
* @param radians
|
||||
* @param pivotX
|
||||
* @param pivotY
|
||||
*/
|
||||
public synchronized void rotateMap(double radians, float pivotX, float pivotY) {
|
||||
|
||||
double rsin = Math.sin(radians);
|
||||
double rcos = Math.cos(radians);
|
||||
|
||||
float x = (float) (pivotX - pivotX * rcos + pivotY * rsin);
|
||||
float y = (float) (pivotY - pivotX * rsin - pivotY * rcos);
|
||||
|
||||
moveMap(x, y);
|
||||
|
||||
setRotation(mPos.angle + Math.toDegrees(radians));
|
||||
}
|
||||
|
||||
public synchronized void setRotation(double degree) {
|
||||
while (degree > 360)
|
||||
degree -= 360;
|
||||
while (degree < 0)
|
||||
degree += 360;
|
||||
|
||||
mPos.angle = (float) degree;
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
public synchronized boolean tiltMap(float move) {
|
||||
return setTilt(mPos.tilt + move);
|
||||
}
|
||||
|
||||
public synchronized boolean setTilt(float tilt) {
|
||||
tilt = FastMath.clamp(tilt, 0, MAX_TILT);
|
||||
if (tilt == mPos.tilt)
|
||||
return false;
|
||||
mPos.tilt = tilt;
|
||||
updateMatrix();
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void setMapPosition(MapPosition mapPosition) {
|
||||
mPos.scale = FastMath.clamp(mapPosition.scale, MIN_SCALE, MAX_SCALE);
|
||||
mPos.x = mapPosition.x;
|
||||
mPos.y = mapPosition.y;
|
||||
mPos.tilt = mapPosition.tilt;
|
||||
mPos.angle = mapPosition.angle;
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
private void updateMatrix() {
|
||||
/* - view matrix:
|
||||
* 0. apply rotate
|
||||
* 1. apply tilt */
|
||||
|
||||
mRotMatrix.setRotation(mPos.angle, 0, 0, 1);
|
||||
mTmpMatrix.setRotation(mPos.tilt, 1, 0, 0);
|
||||
|
||||
/* apply first rotation, then tilt */
|
||||
mRotMatrix.multiplyLhs(mTmpMatrix);
|
||||
|
||||
mViewMatrix.copy(mRotMatrix);
|
||||
|
||||
mVPMatrix.multiplyMM(mProjMatrix, mViewMatrix);
|
||||
|
||||
/* inverse projection matrix: */
|
||||
/* invert scale */
|
||||
mUnprojMatrix.setScale(mWidth, mWidth, 1);
|
||||
|
||||
/* invert rotation and tilt */
|
||||
mTmpMatrix.transposeM(mRotMatrix);
|
||||
|
||||
/* (AB)^-1 = B^-1*A^-1, invert scale, tilt and rotation */
|
||||
mTmpMatrix.multiplyLhs(mUnprojMatrix);
|
||||
|
||||
/* (AB)^-1 = B^-1*A^-1, invert projection */
|
||||
mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixI);
|
||||
}
|
||||
}
|
@ -44,26 +44,26 @@ public class Viewport {
|
||||
|
||||
public final static float MAX_TILT = 65;
|
||||
|
||||
private final MapPosition mPos = new MapPosition();
|
||||
protected final MapPosition mPos = new MapPosition();
|
||||
|
||||
private final GLMatrix mProjMatrix = new GLMatrix();
|
||||
private final GLMatrix mProjMatrixUnscaled = new GLMatrix();
|
||||
private final GLMatrix mProjMatrixI = new GLMatrix();
|
||||
private final GLMatrix mRotMatrix = new GLMatrix();
|
||||
private final GLMatrix mViewMatrix = new GLMatrix();
|
||||
private final GLMatrix mVPMatrix = new GLMatrix();
|
||||
private final GLMatrix mUnprojMatrix = new GLMatrix();
|
||||
private final GLMatrix mTmpMatrix = new GLMatrix();
|
||||
protected final GLMatrix mProjMatrix = new GLMatrix();
|
||||
protected final GLMatrix mProjMatrixUnscaled = new GLMatrix();
|
||||
protected final GLMatrix mProjMatrixI = new GLMatrix();
|
||||
protected final GLMatrix mRotMatrix = new GLMatrix();
|
||||
protected final GLMatrix mViewMatrix = new GLMatrix();
|
||||
protected final GLMatrix mVPMatrix = new GLMatrix();
|
||||
protected final GLMatrix mUnprojMatrix = new GLMatrix();
|
||||
protected final GLMatrix mTmpMatrix = new GLMatrix();
|
||||
|
||||
/* temporary vars: only use in synchronized functions! */
|
||||
private final Point mMovePoint = new Point();
|
||||
private final float[] mv = new float[4];
|
||||
private final float[] mu = new float[4];
|
||||
private final float[] mViewCoords = new float[8];
|
||||
protected final Point mMovePoint = new Point();
|
||||
protected final float[] mv = new float[4];
|
||||
protected final float[] mu = new float[4];
|
||||
protected final float[] mViewCoords = new float[8];
|
||||
|
||||
private final Box mMapBBox = new Box();
|
||||
protected final Box mMapBBox = new Box();
|
||||
|
||||
private float mHeight, mWidth;
|
||||
protected float mHeight, mWidth;
|
||||
|
||||
public final static float VIEW_DISTANCE = 3.0f;
|
||||
public final static float VIEW_NEAR = 1;
|
||||
@ -79,42 +79,6 @@ public class Viewport {
|
||||
mPos.tilt = 0;
|
||||
}
|
||||
|
||||
public synchronized void setScreenSize(int width, int height) {
|
||||
mHeight = height;
|
||||
mWidth = width;
|
||||
|
||||
/* setup projection matrix:
|
||||
* 0. scale to window coordinates
|
||||
* 1. translate to VIEW_DISTANCE
|
||||
* 2. apply projection
|
||||
* setup inverse projection:
|
||||
* 0. invert projection
|
||||
* 1. invert translate to VIEW_DISTANCE */
|
||||
|
||||
float ratio = (mHeight / mWidth) * VIEW_SCALE;
|
||||
float[] tmp = new float[16];
|
||||
|
||||
GLMatrix.frustumM(tmp, 0, -VIEW_SCALE, VIEW_SCALE,
|
||||
ratio, -ratio, VIEW_NEAR, VIEW_FAR);
|
||||
|
||||
mProjMatrix.set(tmp);
|
||||
mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE);
|
||||
mProjMatrix.multiplyRhs(mTmpMatrix);
|
||||
|
||||
/* set inverse projection matrix (without scaling) */
|
||||
mProjMatrix.get(tmp);
|
||||
GLMatrix.invertM(tmp, 0, tmp, 0);
|
||||
mProjMatrixI.set(tmp);
|
||||
|
||||
mProjMatrixUnscaled.copy(mProjMatrix);
|
||||
|
||||
/* scale to window coordinates */
|
||||
mTmpMatrix.setScale(1 / mWidth, 1 / mWidth, 1 / mWidth);
|
||||
mProjMatrix.multiplyRhs(mTmpMatrix);
|
||||
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current MapPosition.
|
||||
*
|
||||
@ -194,7 +158,7 @@ public class Viewport {
|
||||
/* Get Z-value of the map-plane for a point on screen -
|
||||
* calculate the intersection of a ray from camera origin
|
||||
* and the map plane */
|
||||
private float getDepth(float y) {
|
||||
protected float getDepth(float y) {
|
||||
if (y == 0)
|
||||
return 0;
|
||||
|
||||
@ -224,7 +188,7 @@ public class Viewport {
|
||||
return mv[2];
|
||||
}
|
||||
|
||||
private void unproject(float x, float y, float z, float[] coords, int position) {
|
||||
protected void unproject(float x, float y, float z, float[] coords, int position) {
|
||||
mv[0] = x;
|
||||
mv[1] = y;
|
||||
mv[2] = z;
|
||||
@ -375,165 +339,4 @@ public class Viewport {
|
||||
out.x = (mv[0] * (mWidth / 2));
|
||||
out.y = -(mv[1] * (mHeight / 2));
|
||||
}
|
||||
|
||||
private void updateMatrix() {
|
||||
/* - view matrix:
|
||||
* 0. apply rotate
|
||||
* 1. apply tilt */
|
||||
|
||||
mRotMatrix.setRotation(mPos.angle, 0, 0, 1);
|
||||
mTmpMatrix.setRotation(mPos.tilt, 1, 0, 0);
|
||||
|
||||
/* apply first rotation, then tilt */
|
||||
mRotMatrix.multiplyLhs(mTmpMatrix);
|
||||
|
||||
mViewMatrix.copy(mRotMatrix);
|
||||
|
||||
mVPMatrix.multiplyMM(mProjMatrix, mViewMatrix);
|
||||
|
||||
/* inverse projection matrix: */
|
||||
/* invert scale */
|
||||
mUnprojMatrix.setScale(mWidth, mWidth, 1);
|
||||
|
||||
/* invert rotation and tilt */
|
||||
mTmpMatrix.transposeM(mRotMatrix);
|
||||
|
||||
/* (AB)^-1 = B^-1*A^-1, invert scale, tilt and rotation */
|
||||
mTmpMatrix.multiplyLhs(mUnprojMatrix);
|
||||
|
||||
/* (AB)^-1 = B^-1*A^-1, invert projection */
|
||||
mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves this Viewport by the given amount of pixels.
|
||||
*
|
||||
* @param mx the amount of pixels to move the map horizontally.
|
||||
* @param my the amount of pixels to move the map vertically.
|
||||
*/
|
||||
public synchronized void moveMap(float mx, float my) {
|
||||
Point p = applyRotation(mx, my);
|
||||
double tileScale = mPos.scale * Tile.SIZE;
|
||||
moveTo(mPos.x - p.x / tileScale, mPos.y - p.y / tileScale);
|
||||
}
|
||||
|
||||
/* used by MapAnimator */
|
||||
void moveTo(double x, double y) {
|
||||
mPos.x = x;
|
||||
mPos.y = y;
|
||||
|
||||
// clamp latitude
|
||||
mPos.y = FastMath.clamp(mPos.y, 0, 1);
|
||||
|
||||
// wrap longitude
|
||||
while (mPos.x > 1)
|
||||
mPos.x -= 1;
|
||||
while (mPos.x < 0)
|
||||
mPos.x += 1;
|
||||
}
|
||||
|
||||
private Point applyRotation(double mx, double my) {
|
||||
if (mPos.angle == 0) {
|
||||
mMovePoint.x = mx;
|
||||
mMovePoint.y = my;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale map by scale width center at pivot in pixel relative to
|
||||
* screen center. Map scale is clamp to MIN_SCALE and MAX_SCALE.
|
||||
*
|
||||
* @param scale
|
||||
* @param pivotX
|
||||
* @param pivotY
|
||||
* @return true if scale was changed
|
||||
*/
|
||||
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||
// just sanitize input
|
||||
//scale = FastMath.clamp(scale, 0.5f, 2);
|
||||
if (scale < 0.000001)
|
||||
return false;
|
||||
|
||||
double newScale = mPos.scale * scale;
|
||||
|
||||
newScale = FastMath.clamp(newScale, MIN_SCALE, MAX_SCALE);
|
||||
|
||||
if (newScale == mPos.scale)
|
||||
return false;
|
||||
|
||||
scale = (float) (newScale / mPos.scale);
|
||||
|
||||
mPos.scale = newScale;
|
||||
|
||||
if (pivotX != 0 || pivotY != 0)
|
||||
moveMap(pivotX * (1.0f - scale),
|
||||
pivotY * (1.0f - scale));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate map by radians around pivot. Pivot is in pixel relative
|
||||
* to screen center.
|
||||
*
|
||||
* @param radians
|
||||
* @param pivotX
|
||||
* @param pivotY
|
||||
*/
|
||||
public synchronized void rotateMap(double radians, float pivotX, float pivotY) {
|
||||
|
||||
double rsin = Math.sin(radians);
|
||||
double rcos = Math.cos(radians);
|
||||
|
||||
float x = (float) (pivotX - pivotX * rcos + pivotY * rsin);
|
||||
float y = (float) (pivotY - pivotX * rsin - pivotY * rcos);
|
||||
|
||||
moveMap(x, y);
|
||||
|
||||
setRotation(mPos.angle + Math.toDegrees(radians));
|
||||
}
|
||||
|
||||
public synchronized void setRotation(double degree) {
|
||||
while (degree > 360)
|
||||
degree -= 360;
|
||||
while (degree < 0)
|
||||
degree += 360;
|
||||
|
||||
mPos.angle = (float) degree;
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
public synchronized boolean tiltMap(float move) {
|
||||
return setTilt(mPos.tilt + move);
|
||||
}
|
||||
|
||||
public synchronized boolean setTilt(float tilt) {
|
||||
tilt = FastMath.clamp(tilt, 0, MAX_TILT);
|
||||
if (tilt == mPos.tilt)
|
||||
return false;
|
||||
mPos.tilt = tilt;
|
||||
updateMatrix();
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void setMapPosition(MapPosition mapPosition) {
|
||||
mPos.scale = FastMath.clamp(mapPosition.scale, MIN_SCALE, MAX_SCALE);
|
||||
mPos.x = mapPosition.x;
|
||||
mPos.y = mapPosition.y;
|
||||
mPos.tilt = mapPosition.tilt;
|
||||
mPos.angle = mapPosition.angle;
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
synchronized void setPos(double x, double y) {
|
||||
mPos.x = x;
|
||||
mPos.y = y;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user