avoid zoom-level relative calculation
This commit is contained in:
parent
c14d101aef
commit
5230aee091
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.oscim.core;
|
||||
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@ -74,6 +75,11 @@ public class GeoPoint implements Parcelable, Comparable<GeoPoint> {
|
||||
this(latitudeE6 / CONVERSION_FACTOR, longitudeE6 / CONVERSION_FACTOR);
|
||||
}
|
||||
|
||||
public void project(Point2D out) {
|
||||
out.x = MercatorProjection.longitudeToX(this.longitudeE6 / CONVERSION_FACTOR);
|
||||
out.y = MercatorProjection.latitudeToY(this.latitudeE6 / CONVERSION_FACTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GeoPoint geoPoint) {
|
||||
if (this.longitudeE6 > geoPoint.longitudeE6) {
|
||||
|
@ -27,6 +27,7 @@ public class MapPosition {
|
||||
public float angle;
|
||||
public float tilt;
|
||||
|
||||
// map center in tile coordinates of current zoom-level
|
||||
public double x;
|
||||
public double y;
|
||||
|
||||
@ -40,21 +41,6 @@ public class MapPosition {
|
||||
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
||||
}
|
||||
|
||||
// public Point geopointToMap(GeoPoint in, Point reuse) {
|
||||
// Point out = reuse == null ? new Point() : reuse;
|
||||
// out.x = (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(), zoomLevel) - x);
|
||||
// out.y = (int) (MercatorProjection.latitudeToPixelY(in.getLatitude(), zoomLevel) - y);
|
||||
//
|
||||
// return out;
|
||||
// }
|
||||
|
||||
// public void geopointToMap(GeoPoint in, float[] out, int pos) {
|
||||
// out[pos * 2 + 0] =
|
||||
// (float) (MercatorProjection.longitudeToPixelX(in.getLongitude(), zoomLevel) - x);
|
||||
// out[pos * 2 + 1] =
|
||||
// (float) (MercatorProjection.latitudeToPixelY(in.getLatitude(), zoomLevel) - y);
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param geoPoint
|
||||
* the map position.
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.oscim.core;
|
||||
|
||||
import android.graphics.Point;
|
||||
|
||||
/**
|
||||
* An implementation of the spherical Mercator projection.
|
||||
@ -197,6 +196,13 @@ public final class MercatorProjection {
|
||||
return 360 * ((pixelX / ((long) Tile.TILE_SIZE << zoomLevel)) - 0.5);
|
||||
}
|
||||
|
||||
public static double toLongitude(double pixelX) {
|
||||
return 360 * (pixelX - 0.5);
|
||||
}
|
||||
|
||||
public static double toLongitude(double pixelX, double scale) {
|
||||
return 360 * ((pixelX / scale) - 0.5);
|
||||
}
|
||||
/**
|
||||
* Converts a pixel X coordinate to the tile X number.
|
||||
*
|
||||
@ -226,6 +232,15 @@ public final class MercatorProjection {
|
||||
return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
||||
}
|
||||
|
||||
public static double toLatitude(double pixelY) {
|
||||
double y = 0.5 - pixelY;
|
||||
return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
||||
}
|
||||
|
||||
public static double toLatitude(double pixelY, double scale) {
|
||||
double y = 0.5 - pixelY / scale;
|
||||
return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
||||
}
|
||||
/**
|
||||
* Converts a pixel Y coordinate to the tile Y number.
|
||||
*
|
||||
@ -272,12 +287,14 @@ public final class MercatorProjection {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public static Point projectPoint(GeoPoint geopoint, byte z, Point reuse) {
|
||||
Point out = reuse == null ? new Point() : reuse;
|
||||
// public static Point projectPoint(GeoPoint geopoint, byte z, Point reuse) {
|
||||
// Point out = reuse == null ? new Point() : reuse;
|
||||
//
|
||||
// out.x = (int) MercatorProjection.longitudeToPixelX(geopoint.getLongitude(), z);
|
||||
// out.y = (int) MercatorProjection.latitudeToPixelY(geopoint.getLatitude(), z);
|
||||
//
|
||||
// return out;
|
||||
// }
|
||||
|
||||
out.x = (int) MercatorProjection.longitudeToPixelX(geopoint.getLongitude(), z);
|
||||
out.y = (int) MercatorProjection.latitudeToPixelY(geopoint.getLatitude(), z);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ package org.oscim.overlay;
|
||||
import java.util.List;
|
||||
|
||||
import org.oscim.app.R;
|
||||
import org.oscim.core.MercatorProjection;
|
||||
import org.oscim.view.MapView;
|
||||
import org.oscim.view.MapViewPosition;
|
||||
|
||||
@ -34,7 +33,6 @@ public class ItemizedIconOverlay<Item extends OverlayItem> extends ItemizedOverl
|
||||
protected final List<Item> mItemList;
|
||||
protected OnItemGestureListener<Item> mOnItemGestureListener;
|
||||
private int mDrawnItemsLimit = Integer.MAX_VALUE;
|
||||
private final Point mTouchScreenPoint = new Point();
|
||||
|
||||
private final Point mItemPoint = new Point();
|
||||
|
||||
@ -181,32 +179,29 @@ public class ItemizedIconOverlay<Item extends OverlayItem> extends ItemizedOverl
|
||||
* ..
|
||||
* @return true if event is handled false otherwise
|
||||
*/
|
||||
private boolean activateSelectedItems(final MotionEvent event,
|
||||
final ActiveItem task) {
|
||||
final int eventX = (int) event.getX();
|
||||
final int eventY = (int) event.getY();
|
||||
private boolean activateSelectedItems(MotionEvent event, ActiveItem task) {
|
||||
int eventX = (int) event.getX() - mMapView.getWidth()/2;
|
||||
int eventY = (int) event.getY() - mMapView.getHeight()/2;
|
||||
MapViewPosition mapViewPosition = mMapView.getMapViewPosition();
|
||||
|
||||
byte z = mapViewPosition.getMapPosition().zoomLevel;
|
||||
|
||||
mapViewPosition.getScreenPointOnMap(eventX, eventY, mTouchScreenPoint);
|
||||
|
||||
int nearest = -1;
|
||||
double dist = Double.MAX_VALUE;
|
||||
|
||||
// TODO use intermediate projection and bounding box test
|
||||
for (int i = 0; i < this.mItemList.size(); ++i) {
|
||||
final Item item = getItem(i);
|
||||
for (int i = 0; i < this.mItemList.size(); i++) {
|
||||
Item item = getItem(i);
|
||||
|
||||
// final Drawable marker = (item.getMarker(0) == null) ? this.mDefaultMarker : item
|
||||
// .getMarker(0);
|
||||
MercatorProjection.projectPoint(item.getPoint(), z, mItemPoint);
|
||||
|
||||
float dx = mItemPoint.x - mTouchScreenPoint.x;
|
||||
float dy = mItemPoint.y - mTouchScreenPoint.y;
|
||||
double d = Math.sqrt(dx * dx + dy * dy);
|
||||
mapViewPosition.project(item.getPoint(), mItemPoint);
|
||||
|
||||
if (d < 50) {
|
||||
int dx = mItemPoint.x - eventX;
|
||||
int dy = mItemPoint.y - eventY;
|
||||
double d = dx * dx + dy * dy;
|
||||
|
||||
// squared dist: 50*50 pixel
|
||||
if (d < 2500) {
|
||||
if (d < dist) {
|
||||
dist = d;
|
||||
nearest = i;
|
||||
|
@ -180,12 +180,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mMapViewPosition = mapView.getMapViewPosition();
|
||||
mMapPosition = new MapPosition();
|
||||
|
||||
//Matrix.setIdentityM(mMVPMatrix, 0);
|
||||
mMatrices = new Matrices();
|
||||
|
||||
// add half pixel to tile clip/fill coordinates to avoid rounding issues
|
||||
short min = -4;
|
||||
short max = (short) ((Tile.TILE_SIZE << 3) + 4);
|
||||
short min = 0;
|
||||
short max = (short) ((Tile.TILE_SIZE * COORD_SCALE));
|
||||
mFillCoords = new short[8];
|
||||
mFillCoords[0] = min;
|
||||
mFillCoords[1] = max;
|
||||
@ -329,7 +327,40 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
private static Object tilelock = new Object();
|
||||
|
||||
static void draw() {
|
||||
private static void updateTileVisibility() {
|
||||
float[] coords = mTileCoords;
|
||||
MapPosition pos = mMapPosition;
|
||||
MapTile[] tiles = mDrawTiles.tiles;
|
||||
// lock tiles while updating isVisible state
|
||||
synchronized (GLRenderer.tilelock) {
|
||||
|
||||
for (int i = 0; i < mDrawTiles.cnt; i++)
|
||||
tiles[i].isVisible = false;
|
||||
|
||||
// relative zoom-level, 'tiles' could not have been updated after
|
||||
// zoom-level changed.
|
||||
byte z = tiles[0].zoomLevel;
|
||||
float div = FastMath.pow(z - pos.zoomLevel);
|
||||
|
||||
// transform screen coordinates to tile coordinates
|
||||
float scale = pos.scale / div;
|
||||
float px = (float) pos.x * div;
|
||||
float py = (float) pos.y * div;
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
coords[i + 0] = (px + coords[i + 0] / scale) / Tile.TILE_SIZE;
|
||||
coords[i + 1] = (py + coords[i + 1] / scale) / Tile.TILE_SIZE;
|
||||
}
|
||||
|
||||
// count placeholder tiles
|
||||
mHolderCount = 0;
|
||||
|
||||
// check visibile tiles
|
||||
mScanBox.scan(coords, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static void draw() {
|
||||
long start = 0;
|
||||
|
||||
if (MapView.debugFrameTime)
|
||||
@ -374,46 +405,25 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// get current MapPosition, set mTileCoords (mapping of screen to model
|
||||
// coordinates)
|
||||
MapPosition pos = mMapPosition;
|
||||
float[] coords = mTileCoords;
|
||||
boolean changed;
|
||||
boolean positionChanged;
|
||||
|
||||
synchronized (mMapViewPosition) {
|
||||
changed = mMapViewPosition.getMapPosition(pos);
|
||||
mMapViewPosition.getMapViewProjection(coords);
|
||||
mMapViewPosition.updateAnimation();
|
||||
|
||||
positionChanged = mMapViewPosition.getMapPosition(pos);
|
||||
|
||||
if (positionChanged)
|
||||
mMapViewPosition.getMapViewProjection(mTileCoords);
|
||||
|
||||
mMapViewPosition.getMatrix(mMatrices.view, null, mMatrices.viewproj);
|
||||
|
||||
}
|
||||
|
||||
int tileCnt = mDrawTiles.cnt;
|
||||
MapTile[] tiles = mDrawTiles.tiles;
|
||||
|
||||
if (changed) {
|
||||
// lock tiles while updating isVisible state
|
||||
synchronized (GLRenderer.tilelock) {
|
||||
|
||||
for (int i = 0; i < tileCnt; i++)
|
||||
tiles[i].isVisible = false;
|
||||
|
||||
// relative zoom-level, 'tiles' could not have been updated after
|
||||
// zoom-level changed.
|
||||
byte z = tiles[0].zoomLevel;
|
||||
float div = FastMath.pow(z - pos.zoomLevel);
|
||||
|
||||
// transform screen coordinates to tile coordinates
|
||||
float scale = pos.scale / div;
|
||||
float px = (float) pos.x * div;
|
||||
float py = (float) pos.y * div;
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
coords[i + 0] = (px + coords[i + 0] / scale) / Tile.TILE_SIZE;
|
||||
coords[i + 1] = (py + coords[i + 1] / scale) / Tile.TILE_SIZE;
|
||||
}
|
||||
|
||||
// count placeholder tiles
|
||||
mHolderCount = 0;
|
||||
|
||||
// check visibile tiles
|
||||
mScanBox.scan(coords, z);
|
||||
}
|
||||
}
|
||||
if (positionChanged)
|
||||
updateTileVisibility();
|
||||
|
||||
tileCnt += mHolderCount;
|
||||
|
||||
@ -466,7 +476,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
List<RenderOverlay> overlays = mMapView.getOverlayManager().getRenderLayers();
|
||||
|
||||
for (int i = 0, n = overlays.size(); i < n; i++)
|
||||
overlays.get(i).update(mMapPosition, changed, tilesChanged);
|
||||
overlays.get(i).update(mMapPosition, positionChanged, tilesChanged);
|
||||
|
||||
/* draw base layer */
|
||||
BaseMap.draw(tiles, tileCnt, pos, mMatrices);
|
||||
|
@ -14,6 +14,8 @@
|
||||
*/
|
||||
package org.oscim.utils;
|
||||
|
||||
import org.oscim.core.Point2D;
|
||||
|
||||
import android.graphics.Point;
|
||||
|
||||
/**
|
||||
@ -169,18 +171,13 @@ public final class GeometryUtils {
|
||||
return Math.abs((P.x - A.x) * (B.y - A.y) - (P.y - A.y) * (B.x - A.x)) / normalLength;
|
||||
}
|
||||
|
||||
public static final class Point2D {
|
||||
public double x;
|
||||
public double y;
|
||||
}
|
||||
|
||||
// from libosmscout-render
|
||||
public static byte calcLinesIntersect(
|
||||
double ax1, double ay1,
|
||||
double ax2, double ay2,
|
||||
double bx1, double by1,
|
||||
double bx2, double by2,
|
||||
GeometryUtils.Point2D point)
|
||||
Point2D point)
|
||||
{
|
||||
double ua_numr = (bx2 - bx1) * (ay1 - by1) - (by2 - by1) * (ax1 - bx1);
|
||||
double ub_numr = (ax2 - ax1) * (ay1 - by1) - (ay2 - ay1) * (ax1 - bx1);
|
||||
|
@ -78,7 +78,7 @@ public class MapView extends RelativeLayout {
|
||||
private final MapViewPosition mMapViewPosition;
|
||||
private final MapPosition mMapPosition;
|
||||
|
||||
private final MapZoomControls mMapZoomControls;
|
||||
//private final MapZoomControls mMapZoomControls;
|
||||
|
||||
private final TouchHandler mTouchEventHandler;
|
||||
private final Compass mCompass;
|
||||
@ -86,7 +86,7 @@ public class MapView extends RelativeLayout {
|
||||
private final TileManager mTileManager;
|
||||
private final OverlayManager mOverlayManager;
|
||||
|
||||
private final GLView mGLView;
|
||||
final GLView mGLView;
|
||||
private final JobQueue mJobQueue;
|
||||
|
||||
// TODO use 1 download and 1 generator thread instead
|
||||
@ -161,7 +161,6 @@ public class MapView extends RelativeLayout {
|
||||
mTileManager = new TileManager(this);
|
||||
|
||||
mGLView = new GLView(context, this);
|
||||
|
||||
mMapWorkers = new MapWorker[mNumMapWorkers];
|
||||
|
||||
mDebugSettings = new DebugSettings();
|
||||
@ -186,8 +185,8 @@ public class MapView extends RelativeLayout {
|
||||
|
||||
addView(mGLView, params);
|
||||
|
||||
mMapZoomControls = new MapZoomControls(mapActivity, this);
|
||||
mMapZoomControls.setShowMapZoomControls(true);
|
||||
//mMapZoomControls = new MapZoomControls(mapActivity, this);
|
||||
//mMapZoomControls.setShowMapZoomControls(true);
|
||||
mRotationEnabled = true;
|
||||
|
||||
//mOverlayManager.add(new GenericOverlay(this, new GridOverlay(this)));
|
||||
@ -277,8 +276,6 @@ public class MapView extends RelativeLayout {
|
||||
return mRotationEnabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calculates all necessary tiles and adds jobs accordingly.
|
||||
*
|
||||
@ -303,8 +300,6 @@ public class MapView extends RelativeLayout {
|
||||
|
||||
boolean changed = mMapViewPosition.getMapPosition(mMapPosition);
|
||||
|
||||
//Log.d(TAG, "redraw " + changed + " " + forceRedraw);
|
||||
|
||||
// required when not changed?
|
||||
if (AndroidUtils.currentThreadIsUiThread())
|
||||
mOverlayManager.onUpdate(mMapPosition, changed);
|
||||
@ -505,7 +500,6 @@ public class MapView extends RelativeLayout {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void destroy() {
|
||||
for (MapWorker mapWorker : mMapWorkers) {
|
||||
mapWorker.pause();
|
||||
@ -580,14 +574,6 @@ public class MapView extends RelativeLayout {
|
||||
return true;
|
||||
}
|
||||
|
||||
// byte limitZoomLevel(byte zoom) {
|
||||
// if (mMapZoomControls == null)
|
||||
// return zoom;
|
||||
//
|
||||
// return (byte) Math.max(Math.min(zoom, getMaximumPossibleZoomLevel()),
|
||||
// mMapZoomControls.getZoomLevelMin());
|
||||
// }
|
||||
|
||||
/**
|
||||
* Sets the center and zoom level of this MapView and triggers a redraw.
|
||||
*
|
||||
@ -598,6 +584,7 @@ public class MapView extends RelativeLayout {
|
||||
Log.d(TAG, "setMapCenter "
|
||||
+ " lat: " + mapPosition.lat
|
||||
+ " lon: " + mapPosition.lon);
|
||||
|
||||
mMapViewPosition.setMapCenter(mapPosition);
|
||||
redrawMap(true);
|
||||
}
|
||||
@ -609,10 +596,9 @@ public class MapView extends RelativeLayout {
|
||||
* the new center point of the map.
|
||||
*/
|
||||
public void setCenter(GeoPoint geoPoint) {
|
||||
MapPosition mapPosition = new MapPosition(geoPoint,
|
||||
mMapViewPosition.getZoomLevel(), 1);
|
||||
|
||||
setMapCenter(mapPosition);
|
||||
mMapViewPosition.setMapCenter(geoPoint);
|
||||
redrawMap(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -687,27 +673,4 @@ public class MapView extends RelativeLayout {
|
||||
public GeoPoint getCenter() {
|
||||
return new GeoPoint(mMapPosition.lat, mMapPosition.lon);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Sets the visibility of the zoom controls.
|
||||
// *
|
||||
// * @param showZoomControls
|
||||
// * true if the zoom controls should be visible, false otherwise.
|
||||
// */
|
||||
// public void setBuiltInZoomControls(boolean showZoomControls) {
|
||||
// mMapZoomControls.setShowMapZoomControls(showZoomControls);
|
||||
//
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Sets the text scale for the map rendering. Has no effect in downloading
|
||||
// mode.
|
||||
// *
|
||||
// * @param textScale
|
||||
// * the new text scale for the map rendering.
|
||||
// */
|
||||
// public void setTextScale(float textScale) {
|
||||
// mJobParameters = new JobParameters(mJobParameters.theme, textScale);
|
||||
// clearAndRedrawMapView();
|
||||
// }
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ import org.oscim.core.BoundingBox;
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.MercatorProjection;
|
||||
import org.oscim.core.Point2D;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.utils.FastMath;
|
||||
import org.oscim.utils.GeometryUtils.Point2D;
|
||||
import org.oscim.utils.GlUtils;
|
||||
|
||||
import android.graphics.Point;
|
||||
@ -32,6 +32,7 @@ import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.widget.Scroller;
|
||||
|
||||
/**
|
||||
* A MapPosition stores the latitude and longitude coordinate of a MapView
|
||||
@ -39,11 +40,13 @@ import android.util.Log;
|
||||
*/
|
||||
|
||||
public class MapViewPosition {
|
||||
//private static final String TAG = MapViewPosition.class.getName();
|
||||
private static final String TAG = MapViewPosition.class.getName();
|
||||
|
||||
public final static int MAX_ZOOMLEVEL = 17;
|
||||
public final static int MIN_ZOOMLEVEL = 2;
|
||||
public final static int MAX_END_SCALE = 8;
|
||||
public final static double MAX_SCALE = ((1 << MAX_ZOOMLEVEL) * MAX_END_SCALE);
|
||||
public final static double MIN_SCALE = (1 << MIN_ZOOMLEVEL);
|
||||
|
||||
private final static float MAX_ANGLE = 65;
|
||||
|
||||
@ -51,31 +54,39 @@ public class MapViewPosition {
|
||||
|
||||
private double mLatitude;
|
||||
private double mLongitude;
|
||||
private byte mZoomLevel;
|
||||
// 1.0 - 2.0 scale per level
|
||||
private float mScale;
|
||||
// 2^mZoomLevel * mScale;
|
||||
private float mMapScale;
|
||||
|
||||
private double mMapScale;
|
||||
|
||||
// mMapScale * Tile.TILE_SIZE
|
||||
// i.e. size of tile 0/0/0 at current scale in pixel
|
||||
private double mTileScale;
|
||||
|
||||
private float mRotation;
|
||||
public float mTilt;
|
||||
|
||||
// private static final int REF_ZOOM = 20;
|
||||
private double mPosX;
|
||||
private double mPosY;
|
||||
// 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 Scroller mScroller;
|
||||
|
||||
MapViewPosition(MapView mapView) {
|
||||
mMapView = mapView;
|
||||
mLatitude = Double.NaN;
|
||||
mLongitude = Double.NaN;
|
||||
mZoomLevel = -1;
|
||||
mScale = 1;
|
||||
mRotation = 0.0f;
|
||||
mTilt = 0;
|
||||
mMapScale = 1;
|
||||
|
||||
mHandler = new AnimationHandler(this);
|
||||
mScroller = new Scroller(mapView.getContext());
|
||||
}
|
||||
|
||||
private final float[] mProjMatrix = new float[16];
|
||||
@ -88,8 +99,8 @@ public class MapViewPosition {
|
||||
|
||||
// temporary vars: only use in synchronized functions!
|
||||
private final Point2D mMovePoint = new Point2D();
|
||||
private final float[] mv = { 0, 0, 0, 1 };
|
||||
private final float[] mu = { 0, 0, 0, 1 };
|
||||
private final float[] mv = new float[4];
|
||||
private final float[] mu = new float[4];
|
||||
private final float[] mBBoxCoords = new float[8];
|
||||
|
||||
private float mHeight, mWidth;
|
||||
@ -118,38 +129,46 @@ public class MapViewPosition {
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
public synchronized boolean getMapPosition(final MapPosition mapPosition) {
|
||||
// if (!isValid())
|
||||
// return false;
|
||||
/**
|
||||
* Get the current MapPosition
|
||||
*
|
||||
* @param pos MapPosition object to be updated
|
||||
* @return true if current position is different from 'pos'.
|
||||
*/
|
||||
public synchronized boolean getMapPosition(MapPosition pos) {
|
||||
|
||||
if (mapPosition.lat == mLatitude
|
||||
&& mapPosition.lon == mLongitude
|
||||
&& mapPosition.zoomLevel == mZoomLevel
|
||||
&& mapPosition.scale == mScale
|
||||
&& mapPosition.angle == mRotation
|
||||
&& mapPosition.tilt == mTilt)
|
||||
updateTileScale();
|
||||
|
||||
if (pos.lat == mLatitude
|
||||
&& pos.lon == mLongitude
|
||||
&& pos.zoomLevel == mZoomLevel
|
||||
&& pos.scale == mScale
|
||||
&& pos.angle == mRotation
|
||||
&& pos.tilt == mTilt)
|
||||
return false;
|
||||
|
||||
byte z = mZoomLevel;
|
||||
|
||||
mapPosition.lat = mLatitude;
|
||||
mapPosition.lon = mLongitude;
|
||||
mapPosition.angle = mRotation;
|
||||
mapPosition.tilt = mTilt;
|
||||
mapPosition.scale = mScale;
|
||||
mapPosition.zoomLevel = z;
|
||||
pos.lat = mLatitude;
|
||||
pos.lon = mLongitude;
|
||||
pos.angle = mRotation;
|
||||
pos.tilt = mTilt;
|
||||
|
||||
mapPosition.x = mPosX;
|
||||
mapPosition.y = mPosY;
|
||||
// for tiling
|
||||
pos.scale = mScale;
|
||||
pos.zoomLevel = z;
|
||||
|
||||
pos.x = mAbsX * (Tile.TILE_SIZE << mZoomLevel);
|
||||
pos.y = mAbsY * (Tile.TILE_SIZE << mZoomLevel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a copy of current matrices
|
||||
* Get a copy of current matrices
|
||||
*
|
||||
* @param view ...
|
||||
* @param proj ...
|
||||
* @param view view Matrix
|
||||
* @param proj projection Matrix
|
||||
* @param vp view and projection
|
||||
*/
|
||||
public synchronized void getMatrix(float[] view, float[] proj, float[] vp) {
|
||||
@ -163,21 +182,33 @@ public class MapViewPosition {
|
||||
System.arraycopy(mVPMatrix, 0, vp, 0, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inverse projection of the viewport, i.e. the
|
||||
* coordinates with z==0 that will be projected exactly
|
||||
* to screen corners by current view-projection-matrix.
|
||||
*
|
||||
* @param box float[8] will be set.
|
||||
*/
|
||||
public synchronized void getMapViewProjection(float[] box) {
|
||||
float t = getZ(1);
|
||||
float t2 = getZ(-1);
|
||||
|
||||
unproject(1, -1, t, box, 0); // top-right
|
||||
unproject(-1, -1, t, box, 2); // top-left
|
||||
unproject(-1, 1, t2, box, 4); // bottom-left
|
||||
unproject(1, 1, t2, box, 6); // bottom-right
|
||||
// top-right
|
||||
unproject(1, -1, t, box, 0);
|
||||
// top-left
|
||||
unproject(-1, -1, t, box, 2);
|
||||
// bottom-left
|
||||
unproject(-1, 1, t2, box, 4);
|
||||
// bottom-right
|
||||
unproject(1, 1, t2, box, 6);
|
||||
}
|
||||
|
||||
// get the z-value of the map-plane for a point on screen
|
||||
/*
|
||||
* 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 getZ(float y) {
|
||||
// calculate the intersection of a ray from
|
||||
// camera origin and the map plane
|
||||
|
||||
// origin is moved by VIEW_DISTANCE
|
||||
double cx = VIEW_DISTANCE;
|
||||
// 'height' of the ray
|
||||
@ -208,11 +239,9 @@ public class MapViewPosition {
|
||||
|
||||
Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0);
|
||||
|
||||
if (mv[3] != 0) {
|
||||
coords[position + 0] = mv[0] / mv[3];
|
||||
coords[position + 1] = mv[1] / mv[3];
|
||||
}
|
||||
}
|
||||
|
||||
/** @return the current center point of the MapView. */
|
||||
public synchronized GeoPoint getMapCenter() {
|
||||
@ -227,20 +256,11 @@ public class MapViewPosition {
|
||||
if (!isValid()) {
|
||||
return null;
|
||||
}
|
||||
updateTileScale();
|
||||
|
||||
return new MapPosition(mLatitude, mLongitude, mZoomLevel, mScale, mRotation);
|
||||
}
|
||||
|
||||
/** @return the current zoom level of the MapView. */
|
||||
public synchronized byte getZoomLevel() {
|
||||
return mZoomLevel;
|
||||
}
|
||||
|
||||
/** @return the current scale of the MapView. */
|
||||
public synchronized float getScale() {
|
||||
return mScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
@ -253,96 +273,106 @@ public class MapViewPosition {
|
||||
float t = getZ(1);
|
||||
float t2 = getZ(-1);
|
||||
|
||||
unproject(1, -1, t, coords, 0); // top-right
|
||||
unproject(-1, -1, t, coords, 2); // top-left
|
||||
unproject(-1, 1, t2, coords, 4); // bottom-left
|
||||
unproject(1, 1, t2, coords, 6); // bottom-right
|
||||
unproject(1, -1, t, coords, 0);
|
||||
unproject(-1, -1, t, coords, 2);
|
||||
unproject(-1, 1, t2, coords, 4);
|
||||
unproject(1, 1, t2, coords, 6);
|
||||
|
||||
byte z = mZoomLevel;
|
||||
double dx, dy;
|
||||
double minLat = 0, minLon = 0, maxLat = 0, maxLon = 0, lon, lat;
|
||||
double minX = Double.MAX_VALUE;
|
||||
double minY = Double.MAX_VALUE;
|
||||
|
||||
double maxX = Double.MIN_VALUE;
|
||||
double maxY = Double.MIN_VALUE;
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
dx = mRealX - coords[i + 0];
|
||||
dy = mRealY - coords[i + 1];
|
||||
|
||||
dx = mPosX - coords[i + 0] / mScale;
|
||||
dy = mPosY - coords[i + 1] / mScale;
|
||||
|
||||
lon = MercatorProjection.pixelXToLongitude(dx, z);
|
||||
lat = MercatorProjection.pixelYToLatitude(dy, z);
|
||||
if (i == 0) {
|
||||
minLon = maxLon = lon;
|
||||
minLat = maxLat = lat;
|
||||
} else {
|
||||
if (lat > maxLat)
|
||||
maxLat = lat;
|
||||
else if (lat < minLat)
|
||||
minLat = lat;
|
||||
|
||||
if (lon > maxLon)
|
||||
maxLon = lon;
|
||||
else if (lon < minLon)
|
||||
minLon = lon;
|
||||
}
|
||||
minX = Math.min(minX, dx);
|
||||
maxX = Math.max(maxX, dx);
|
||||
minY = Math.min(minY, dy);
|
||||
maxY = Math.max(maxY, dy);
|
||||
}
|
||||
|
||||
BoundingBox bbox = new BoundingBox(minLat, minLon, maxLat, maxLon);
|
||||
minX = MercatorProjection.toLongitude(minX, mTileScale);
|
||||
maxX = MercatorProjection.toLongitude(maxX, mTileScale);
|
||||
minY = MercatorProjection.toLatitude(minY, mTileScale);
|
||||
maxY = MercatorProjection.toLatitude(maxY, mTileScale);
|
||||
|
||||
Log.d(">>>", "getScreenBoundingBox " + bbox);
|
||||
// yea, this is upside down..
|
||||
BoundingBox bbox = new BoundingBox(maxY, minX, minY, maxX);
|
||||
|
||||
Log.d(TAG, "getScreenBoundingBox " + bbox);
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* for x,y in screen coordinates get the point on the map in map-tile
|
||||
* coordinates
|
||||
* For x, y in screen coordinates set Point to map-tile
|
||||
* coordinates at returned scale.
|
||||
*
|
||||
* @param x ...
|
||||
* @param y ...
|
||||
* @param reuse ...
|
||||
* @return ...
|
||||
* @param x screen coordinate
|
||||
* @param y screen coordinate
|
||||
* @param out Point coords will be set
|
||||
* @return current map scale
|
||||
*/
|
||||
public synchronized Point getScreenPointOnMap(float x, float y, Point reuse) {
|
||||
Point out = reuse == null ? new Point() : reuse;
|
||||
public synchronized float getScreenPointOnMap(float x, float y, Point2D out) {
|
||||
|
||||
float mx = ((mWidth / 2) - x) / (mWidth / 2);
|
||||
float my = ((mHeight / 2) - y) / (mHeight / 2);
|
||||
// scale to -1..1
|
||||
float mx = 1 - (x / mWidth * 2);
|
||||
float my = 1 - (y / mHeight * 2);
|
||||
|
||||
unproject(-mx, my, getZ(-my), mu, 0);
|
||||
|
||||
out.x = (int) (mPosX + mu[0] / mScale);
|
||||
out.y = (int) (mPosY + mu[1] / mScale);
|
||||
//Log.d(TAG, "getScreenPointOnMap " + reuse);
|
||||
out.x = mRealX + mu[0];
|
||||
out.y = mRealY + mu[1];
|
||||
|
||||
return out;
|
||||
return (float) mMapScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the GeoPoint for x,y in screen coordinates
|
||||
* Get the GeoPoint for x,y in screen coordinates.
|
||||
* (only used by MapEventsOverlay currently)
|
||||
*
|
||||
* @param x screen pixel x
|
||||
* @param y screen pixel y
|
||||
* @param x screen coordinate
|
||||
* @param y screen coordinate
|
||||
* @return the corresponding GeoPoint
|
||||
*/
|
||||
public synchronized GeoPoint fromScreenPixels(float x, float y) {
|
||||
float mx = ((mWidth / 2) - x) / (mWidth / 2);
|
||||
float my = ((mHeight / 2) - y) / (mHeight / 2);
|
||||
// scale to -1..1
|
||||
float mx = 1 - (x / mWidth * 2);
|
||||
float my = 1 - (y / mHeight * 2);
|
||||
|
||||
unproject(-mx, my, getZ(-my), mu, 0);
|
||||
|
||||
double dx = mPosX + mu[0] / mScale;
|
||||
double dy = mPosY + mu[1] / mScale;
|
||||
double dx = mRealX + mu[0];
|
||||
double dy = mRealY + mu[1];
|
||||
dx /= mMapScale * Tile.TILE_SIZE;
|
||||
dy /= mMapScale * Tile.TILE_SIZE;
|
||||
|
||||
if (dx > 1) {
|
||||
while (dx > 1)
|
||||
dx -= 1;
|
||||
} else {
|
||||
while (dx < 0)
|
||||
dx += 1;
|
||||
}
|
||||
|
||||
if (dy > 1)
|
||||
dy = 1;
|
||||
else if (dy < 0)
|
||||
dy = 0;
|
||||
|
||||
GeoPoint p = new GeoPoint(
|
||||
MercatorProjection.pixelYToLatitude(dy, mZoomLevel),
|
||||
MercatorProjection.pixelXToLongitude(dx, mZoomLevel));
|
||||
|
||||
//Log.d(TAG, "fromScreenPixels " + p);
|
||||
MercatorProjection.toLatitude(dy),
|
||||
MercatorProjection.toLongitude(dx));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the screen pixel for a GeoPoint
|
||||
* Get the screen pixel for a GeoPoint
|
||||
*
|
||||
* @param geoPoint ...
|
||||
* @param reuse ...
|
||||
@ -351,40 +381,24 @@ public class MapViewPosition {
|
||||
public synchronized Point project(GeoPoint geoPoint, Point reuse) {
|
||||
Point out = reuse == null ? new Point() : reuse;
|
||||
|
||||
double x = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(),
|
||||
mZoomLevel);
|
||||
double y = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(),
|
||||
mZoomLevel);
|
||||
double x = MercatorProjection.longitudeToX(geoPoint.getLongitude()) * mTileScale;
|
||||
double y = MercatorProjection.latitudeToY(geoPoint.getLatitude()) * mTileScale;
|
||||
|
||||
mv[0] = (float) (x - mRealX);
|
||||
mv[1] = (float) (y - mRealY);
|
||||
|
||||
mv[0] = (float) (x - mPosX) * mScale;
|
||||
mv[1] = (float) (y - mPosY) * mScale;
|
||||
mv[2] = 0;
|
||||
mv[3] = 1;
|
||||
|
||||
Matrix.multiplyMV(mv, 0, mVPMatrix, 0, mv, 0);
|
||||
|
||||
out.x = (int) (mv[0] / mv[3] * mWidth / 2);
|
||||
out.y = (int) (mv[1] / mv[3] * mHeight / 2);
|
||||
// positive direction is down and right;
|
||||
out.x = (int) ((mv[0] / mv[3]) * (mWidth / 2));
|
||||
out.y = (int) -((mv[1] / mv[3]) * (mHeight / 2));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// public static Point project(float x, float y, float[] matrix, float[] tmpVec, Point reuse) {
|
||||
// Point out = reuse == null ? new Point() : reuse;
|
||||
//
|
||||
// tmpVec[0] = x;
|
||||
// tmpVec[1] = y;
|
||||
// tmpVec[2] = 0;
|
||||
// tmpVec[3] = 1;
|
||||
//
|
||||
// Matrix.multiplyMV(tmpVec, 0, matrix, 0, tmpVec, 0);
|
||||
//
|
||||
// out.x = (int) (tmpVec[0] / tmpVec[3] * mWidth / 2);
|
||||
// out.y = (int) (tmpVec[1] / tmpVec[3] * mHeight / 2);
|
||||
//
|
||||
// return out;
|
||||
// }
|
||||
|
||||
private void updateMatrix() {
|
||||
// --- view matrix
|
||||
// 1. scale to window coordinates
|
||||
@ -449,6 +463,10 @@ public class MapViewPosition {
|
||||
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.
|
||||
*
|
||||
@ -456,75 +474,88 @@ public class MapViewPosition {
|
||||
* @param my the amount of pixels to move the map vertically.
|
||||
*/
|
||||
public synchronized void moveMap(float mx, float my) {
|
||||
Point2D p = getMove(mx, my);
|
||||
// stop animation
|
||||
mHandler.cancel();
|
||||
|
||||
mLatitude = MercatorProjection.pixelYToLatitude(mPosY - p.y, mZoomLevel);
|
||||
mLatitude = MercatorProjection.limitLatitude(mLatitude);
|
||||
Point2D p = applyRotation(mx, my);
|
||||
|
||||
mLongitude = MercatorProjection.pixelXToLongitude(mPosX - p.x, mZoomLevel);
|
||||
mLongitude = MercatorProjection.wrapLongitude(mLongitude);
|
||||
move(p.x, p.y);
|
||||
}
|
||||
|
||||
private synchronized void move(double mx, double my) {
|
||||
mAbsX = (mRealX - mx) / mTileScale;
|
||||
mAbsY = (mRealY - my) / mTileScale;
|
||||
|
||||
// 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 Point2D getMove(float mx, float my) {
|
||||
double dx = mx / mScale;
|
||||
double dy = my / mScale;
|
||||
private Point2D applyRotation(float mx, float my) {
|
||||
|
||||
if (mMapView.mRotationEnabled || mMapView.mCompassEnabled) {
|
||||
double rad = Math.toRadians(mRotation);
|
||||
double rcos = Math.cos(rad);
|
||||
double rsin = Math.sin(rad);
|
||||
double x = dx * rcos + dy * rsin;
|
||||
double y = dx * -rsin + dy * rcos;
|
||||
dx = x;
|
||||
dy = y;
|
||||
float x = (float) (mx * rcos + my * rsin);
|
||||
float y = (float) (mx * -rsin + my * rcos);
|
||||
mx = x;
|
||||
my = y;
|
||||
}
|
||||
|
||||
mMovePoint.x = dx;
|
||||
mMovePoint.y = dy;
|
||||
mMovePoint.x = mx;
|
||||
mMovePoint.y = my;
|
||||
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 ...
|
||||
* @param scale map by this factor
|
||||
* @param pivotX ...
|
||||
* @param pivotY ...
|
||||
* @return true if scale was changed
|
||||
*/
|
||||
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||
// stop animation
|
||||
mHandler.cancel();
|
||||
|
||||
// sanitize input
|
||||
// just sanitize input
|
||||
scale = FastMath.clamp(scale, 0.5f, 2);
|
||||
|
||||
float newScale = mMapScale * scale;
|
||||
double newScale = mMapScale * scale;
|
||||
|
||||
int z = FastMath.log2((int) newScale);
|
||||
newScale = FastMath.clamp(newScale, MIN_SCALE, MAX_SCALE);
|
||||
|
||||
if (z < MIN_ZOOMLEVEL || (z >= MAX_ZOOMLEVEL && mScale >= 8))
|
||||
if (newScale == mMapScale)
|
||||
return false;
|
||||
|
||||
if (z > MAX_ZOOMLEVEL) {
|
||||
// z17 shows everything, just increase scaling
|
||||
// need to fix this for ScanBox
|
||||
if (mScale * scale > 4)
|
||||
return false;
|
||||
scale = (float) (newScale / mMapScale);
|
||||
|
||||
mScale *= scale;
|
||||
mMapScale = newScale;
|
||||
} else {
|
||||
mZoomLevel = (byte) z;
|
||||
updatePosition();
|
||||
|
||||
mScale = newScale / (1 << z);
|
||||
mMapScale = newScale;
|
||||
}
|
||||
|
||||
if (pivotX != 0 || pivotY != 0)
|
||||
moveMap(pivotX * (1.0f - scale),
|
||||
pivotY * (1.0f - scale));
|
||||
else
|
||||
updatePosition();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -532,14 +563,21 @@ public class MapViewPosition {
|
||||
/**
|
||||
* rotate map around pivot cx,cy
|
||||
*
|
||||
* @param angle ...
|
||||
* @param radians ...
|
||||
* @param cx ...
|
||||
* @param cy ...
|
||||
*/
|
||||
public synchronized void rotateMap(float angle, float cx, float cy) {
|
||||
moveMap(cx, cy);
|
||||
public synchronized void rotateMap(double radians, float cx, float cy) {
|
||||
|
||||
mRotation += angle;
|
||||
double rsin = Math.sin(radians);
|
||||
double rcos = Math.cos(radians);
|
||||
|
||||
float x = (float) (cx * rcos + cy * -rsin - cx);
|
||||
float y = (float) (cx * rsin + cy * rcos - cy);
|
||||
|
||||
moveMap(x, y);
|
||||
|
||||
mRotation += Math.toDegrees(radians);
|
||||
|
||||
updateMatrix();
|
||||
}
|
||||
@ -567,6 +605,9 @@ public class MapViewPosition {
|
||||
private void setMapCenter(double latitude, double longitude) {
|
||||
mLatitude = MercatorProjection.limitLatitude(latitude);
|
||||
mLongitude = MercatorProjection.limitLongitude(longitude);
|
||||
mAbsX = MercatorProjection.longitudeToX(mLongitude);
|
||||
mAbsY = MercatorProjection.latitudeToY(mLatitude);
|
||||
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
@ -575,33 +616,42 @@ public class MapViewPosition {
|
||||
}
|
||||
|
||||
synchronized void setMapCenter(MapPosition mapPosition) {
|
||||
//mZoomLevel = mMapView.limitZoomLevel(mapPosition.zoomLevel);
|
||||
setZoomLevelLimit(mapPosition.zoomLevel);
|
||||
mMapScale = 1 << mZoomLevel;
|
||||
//mMapScale = 1 << mZoomLevel;
|
||||
|
||||
setMapCenter(mapPosition.lat, mapPosition.lon);
|
||||
}
|
||||
|
||||
synchronized void setZoomLevel(byte zoomLevel) {
|
||||
//mZoomLevel = mMapView.limitZoomLevel(zoomLevel);
|
||||
setZoomLevelLimit(zoomLevel);
|
||||
mMapScale = 1 << mZoomLevel;
|
||||
mScale = 1;
|
||||
//mMapScale = 1 << mZoomLevel;
|
||||
//mScale = 1;
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
private void setZoomLevelLimit(byte zoomLevel) {
|
||||
mZoomLevel = (byte)FastMath.clamp(zoomLevel, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
||||
mMapScale = 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() {
|
||||
mPosX = MercatorProjection.longitudeToPixelX(mLongitude, mZoomLevel);
|
||||
mPosY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel);
|
||||
mTileScale = mMapScale * Tile.TILE_SIZE;
|
||||
|
||||
mRealX = mAbsX * mTileScale;
|
||||
mRealY = mAbsY * mTileScale;
|
||||
}
|
||||
|
||||
private double mStartX;
|
||||
private double mStartY;
|
||||
private double mEndX;
|
||||
private double mEndY;
|
||||
private int mScrollX;
|
||||
private int mScrollY;
|
||||
|
||||
private double mStartScale;
|
||||
private double mEndScale;
|
||||
|
||||
private float mDuration = 500;
|
||||
|
||||
public synchronized void animateTo(BoundingBox bbox) {
|
||||
@ -610,6 +660,7 @@ public class MapViewPosition {
|
||||
double dy = MercatorProjection.latitudeToY(bbox.getMinLatitude())
|
||||
- MercatorProjection.latitudeToY(bbox.getMaxLatitude());
|
||||
|
||||
|
||||
double log4 = Math.log(4);
|
||||
|
||||
double zx = -log4 * Math.log(dx) + (mWidth / Tile.TILE_SIZE);
|
||||
@ -617,80 +668,160 @@ public class MapViewPosition {
|
||||
|
||||
double z = Math.min(zx, zy);
|
||||
|
||||
setZoomLevelLimit((byte) Math.floor(z));
|
||||
double newScale = Math.pow(2, z);
|
||||
|
||||
mScale = FastMath.clamp((float) (1 + (z - mZoomLevel)), 1, MAX_END_SCALE);
|
||||
//double newScale = (1 << (int)Math.floor(z));
|
||||
|
||||
mMapScale = (1 << mZoomLevel) * mScale;
|
||||
//Log.d(TAG, "zoom: " + bbox + " " + zx + " " + zy + " / " + mScale + " " + mZoomLevel);
|
||||
setMapCenter(bbox.getCenterPoint());
|
||||
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);
|
||||
mEndScale = mMapScale * scale;
|
||||
mStartScale = mMapScale;
|
||||
|
||||
//mMapScale = newScale;
|
||||
//updatePosition();
|
||||
//
|
||||
// // reset rotation/tilt
|
||||
// mTilt = 0;
|
||||
// mRotation = 0;
|
||||
// updateMatrix();
|
||||
//
|
||||
// GeoPoint geoPoint = bbox.getCenterPoint();
|
||||
// mEndX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mZoomLevel);
|
||||
// mEndY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mZoomLevel);
|
||||
// mStartX = mPosX;
|
||||
// mStartY = mPosY;
|
||||
//
|
||||
// mDuration = 300;
|
||||
// mHandler.start((int) mDuration);
|
||||
|
||||
// ----- 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
|
||||
mTilt = 0;
|
||||
mRotation = 0;
|
||||
updateMatrix();
|
||||
|
||||
GeoPoint geoPoint = bbox.getCenterPoint();
|
||||
|
||||
//mStartScale = mMapScale;
|
||||
|
||||
double mx = MercatorProjection.longitudeToX(geoPoint.getLongitude()) * mTileScale;
|
||||
double my = MercatorProjection.latitudeToY(geoPoint.getLatitude()) * mTileScale;
|
||||
mx = mRealX - mx;
|
||||
my = mRealY - my;
|
||||
|
||||
mScrollX = 0;
|
||||
mScrollY = 0;
|
||||
mDuration = 500;
|
||||
|
||||
mScroller.startScroll(0, 0, (int) mx, (int) my, (int)mDuration);
|
||||
|
||||
mHandler.start((int) mDuration);
|
||||
}
|
||||
|
||||
public synchronized void animateTo(GeoPoint geoPoint) {
|
||||
//MercatorProjection.projectPoint(geoPoint, mZoomLevel, mTmpPoint);
|
||||
|
||||
mEndX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mZoomLevel);
|
||||
mEndY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mZoomLevel);
|
||||
mStartX = mPosX;
|
||||
mStartY = mPosY;
|
||||
//mEndX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mZoomLevel);
|
||||
//mEndY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mZoomLevel);
|
||||
//mStartX = mPosX;
|
||||
//mStartY = mPosY;
|
||||
mDuration = 300;
|
||||
mHandler.start((int) mDuration);
|
||||
}
|
||||
|
||||
public synchronized void animateFling(int velocityX, int velocityY,
|
||||
int minX, int maxX, int minY, int maxY) {
|
||||
|
||||
mScrollX = 0;
|
||||
mScrollY = 0;
|
||||
|
||||
mScroller.fling(0, 0, velocityX, velocityY, minX, maxX, minY, maxY);
|
||||
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
|
||||
|
||||
mDuration = 300;
|
||||
mHandler.start((int) mDuration);
|
||||
}
|
||||
|
||||
public synchronized void animateZoom(float scale) {
|
||||
mStartScale = mMapScale;
|
||||
mEndScale = mMapScale * scale;
|
||||
|
||||
//mScroller.fling(0, 0, velocityX, velocityY, minX, maxX, minY, maxY);
|
||||
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
|
||||
|
||||
mDuration = 300;
|
||||
mHandler.start((int) mDuration);
|
||||
}
|
||||
|
||||
//private float mScrollX, mScrollY;
|
||||
|
||||
public void updateAnimation() {
|
||||
//scroll();
|
||||
}
|
||||
|
||||
synchronized boolean scroll(double div) {
|
||||
if (mScroller.isFinished()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = mScrollX; //mScroller.getCurrX();
|
||||
int y = mScrollY; //mScroller.getCurrY();
|
||||
|
||||
mScroller.computeScrollOffset();
|
||||
|
||||
int mx = mScroller.getCurrX() - x;
|
||||
int my = mScroller.getCurrY() - y;
|
||||
mx *= div;
|
||||
my *= div;
|
||||
|
||||
if (mx >= 1 || my >= 1 || mx <= -1 || my <= -1) {
|
||||
moveMap(mx, my);
|
||||
|
||||
//mMapView.redrawMap(true);
|
||||
mScrollX = mScroller.getCurrX();
|
||||
mScrollY = mScroller.getCurrY();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void animateTo(float dx, float dy, float duration) {
|
||||
getMove(dx, dy);
|
||||
applyRotation(dx, dy);
|
||||
|
||||
mEndX = mPosX - mMovePoint.x;
|
||||
mEndY = mPosY - mMovePoint.y;
|
||||
//mEndX = mRealX - mMovePoint.x;
|
||||
//mEndY = mRealY - mMovePoint.y;
|
||||
|
||||
mStartX = mPosX;
|
||||
mStartY = mPosY;
|
||||
//mStartX = mRealX;
|
||||
//mStartY = mRealY;
|
||||
|
||||
mDuration = duration;
|
||||
mHandler.start((int) mDuration);
|
||||
}
|
||||
|
||||
synchronized void setMapPosition(double x, double y) {
|
||||
|
||||
mLatitude = MercatorProjection.pixelYToLatitude(y, mZoomLevel);
|
||||
mLatitude = MercatorProjection.limitLatitude(mLatitude);
|
||||
|
||||
mLongitude = MercatorProjection.pixelXToLongitude(x, mZoomLevel);
|
||||
mLongitude = MercatorProjection.wrapLongitude(mLongitude);
|
||||
void onTick(long millisLeft) {
|
||||
boolean changed = false;
|
||||
double div = 1;
|
||||
if (mStartScale != 0) {
|
||||
double adv = millisLeft / mDuration;
|
||||
mMapScale = (adv * mStartScale) + (mEndScale * (1.0 - adv));
|
||||
div = mMapScale / mStartScale;
|
||||
|
||||
updatePosition();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void onTick(long millisLeft) {
|
||||
double adv = millisLeft / mDuration;
|
||||
double mx = (mStartX + (mEndX - mStartX) * (1.0 - adv));
|
||||
double my = (mStartY + (mEndY - mStartY) * (1.0 - adv));
|
||||
setMapPosition(mx, my);
|
||||
if (scroll(div))
|
||||
changed = true;
|
||||
|
||||
if (changed)
|
||||
mMapView.redrawMap(true);
|
||||
}
|
||||
|
||||
void onFinish() {
|
||||
setMapPosition(mEndX, mEndY);
|
||||
//setMapPosition(mEndX, mEndY);
|
||||
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
||||
mMapView.redrawMap(true);
|
||||
mStartScale = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* below is borrowed from CountDownTimer class:
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*/
|
||||
static class AnimationHandler extends Handler {
|
||||
private final WeakReference<MapViewPosition> mMapViewPosition;
|
||||
private static final int MSG = 1;
|
||||
|
@ -1,358 +1,358 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view;
|
||||
|
||||
import org.oscim.generator.TileGenerator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.ZoomControls;
|
||||
|
||||
/**
|
||||
* A MapZoomControls instance displays buttons for zooming in and out in a map.
|
||||
*/
|
||||
public class MapZoomControls {
|
||||
private static class ZoomControlsHideHandler extends Handler {
|
||||
private final ZoomControls mZoomControls;
|
||||
|
||||
ZoomControlsHideHandler(ZoomControls zoomControls) {
|
||||
super();
|
||||
mZoomControls = zoomControls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
mZoomControls.hide();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ZoomInClickListener implements View.OnClickListener {
|
||||
private final MapZoomControls mMapZoomControls;
|
||||
|
||||
ZoomInClickListener(MapZoomControls mapZoomControls) {
|
||||
mMapZoomControls = mapZoomControls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
// if (MapView.testRegionZoom)
|
||||
// mMapView.mRegionLookup.updateRegion(1, null);
|
||||
// else
|
||||
// MapZoomControls.this.zoom((byte) 1);
|
||||
mMapZoomControls.zoom((byte) 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ZoomOutClickListener implements View.OnClickListener {
|
||||
private final MapZoomControls mMapZoomControls;
|
||||
|
||||
ZoomOutClickListener(MapZoomControls mapZoomControls) {
|
||||
mMapZoomControls = mapZoomControls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
// if (MapView.testRegionZoom)
|
||||
// mMapView.mRegionLookup.updateRegion(-1, null);
|
||||
// else
|
||||
mMapZoomControls.zoom((byte) -1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default {@link Gravity} of the zoom controls.
|
||||
*/
|
||||
private static final int DEFAULT_ZOOM_CONTROLS_GRAVITY = Gravity.BOTTOM
|
||||
| Gravity.RIGHT;
|
||||
|
||||
/**
|
||||
* Default maximum zoom level.
|
||||
*/
|
||||
private static final byte DEFAULT_ZOOM_LEVEL_MAX = 18;
|
||||
|
||||
/**
|
||||
* Default minimum zoom level.
|
||||
*/
|
||||
private static final byte DEFAULT_ZOOM_LEVEL_MIN = 1;
|
||||
|
||||
/**
|
||||
* Message code for the handler to hide the zoom controls.
|
||||
*/
|
||||
private static final int MSG_ZOOM_CONTROLS_HIDE = 0;
|
||||
|
||||
/**
|
||||
* Horizontal padding for the zoom controls.
|
||||
*/
|
||||
private static final int ZOOM_CONTROLS_HORIZONTAL_PADDING = 5;
|
||||
|
||||
/**
|
||||
* Delay in milliseconds after which the zoom controls disappear.
|
||||
*/
|
||||
private static final long ZOOM_CONTROLS_TIMEOUT = ViewConfiguration
|
||||
.getZoomControlsTimeout();
|
||||
|
||||
private boolean mGravityChanged;
|
||||
private boolean mShowMapZoomControls;
|
||||
private final ZoomControls mZoomControls;
|
||||
private int mZoomControlsGravity;
|
||||
private final Handler mZoomControlsHideHandler;
|
||||
private byte mZoomLevelMax;
|
||||
private byte mZoomLevelMin;
|
||||
private final MapView mMapView;
|
||||
|
||||
MapZoomControls(Context context, final MapView mapView) {
|
||||
mMapView = mapView;
|
||||
mZoomControls = new ZoomControls(context);
|
||||
mShowMapZoomControls = true;
|
||||
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
||||
mZoomLevelMin = DEFAULT_ZOOM_LEVEL_MIN;
|
||||
// if (!MapView.testRegionZoom)
|
||||
mZoomControls.setVisibility(View.GONE);
|
||||
mZoomControlsGravity = DEFAULT_ZOOM_CONTROLS_GRAVITY;
|
||||
|
||||
mZoomControls.setOnZoomInClickListener(new ZoomInClickListener(this));
|
||||
mZoomControls.setOnZoomOutClickListener(new ZoomOutClickListener(this));
|
||||
mZoomControlsHideHandler = new ZoomControlsHideHandler(mZoomControls);
|
||||
|
||||
int wrapContent = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
LayoutParams layoutParams = new LayoutParams(wrapContent, wrapContent);
|
||||
mapView.addView(mZoomControls, layoutParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms in or out by the given amount of zoom levels.
|
||||
*
|
||||
* @param zoomLevelDiff
|
||||
* the difference to the current zoom level.
|
||||
* @return true if the zoom level was changed, false otherwise.
|
||||
*/
|
||||
boolean zoom(byte zoomLevelDiff) {
|
||||
MapViewPosition mapViewPosition = mMapView.getMapViewPosition();
|
||||
int z = mapViewPosition.getZoomLevel() + zoomLevelDiff;
|
||||
if (zoomLevelDiff > 0) {
|
||||
// check if zoom in is possible
|
||||
if (z > mZoomLevelMax) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (zoomLevelDiff < 0) {
|
||||
// check if zoom out is possible
|
||||
if (z < getZoomLevelMin()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mapViewPosition.setZoomLevel((byte) z);
|
||||
mMapView.redrawMap(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current gravity for the placing of the zoom controls.
|
||||
* @see Gravity
|
||||
*/
|
||||
public int getZoomControlsGravity() {
|
||||
return mZoomControlsGravity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum zoom level of the map.
|
||||
*/
|
||||
public byte getZoomLevelMax() {
|
||||
return mZoomLevelMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the minimum zoom level of the map.
|
||||
*/
|
||||
public byte getZoomLevelMin() {
|
||||
return mZoomLevelMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the zoom controls are visible, false otherwise.
|
||||
*/
|
||||
public boolean isShowMapZoomControls() {
|
||||
return mShowMapZoomControls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param show
|
||||
* true if the zoom controls should be visible, false otherwise.
|
||||
*/
|
||||
public void setShowMapZoomControls(boolean show) {
|
||||
mShowMapZoomControls = show;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gravity for the placing of the zoom controls. Supported values
|
||||
* are {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL},
|
||||
* {@link Gravity#BOTTOM}, {@link Gravity#LEFT},
|
||||
* {@link Gravity#CENTER_HORIZONTAL} and {@link Gravity#RIGHT}.
|
||||
*
|
||||
* @param zoomControlsGravity
|
||||
* a combination of {@link Gravity} constants describing the
|
||||
* desired placement.
|
||||
*/
|
||||
public void setZoomControlsGravity(int zoomControlsGravity) {
|
||||
if (mZoomControlsGravity != zoomControlsGravity) {
|
||||
mZoomControlsGravity = zoomControlsGravity;
|
||||
mGravityChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum zoom level of the map.
|
||||
* <p>
|
||||
* The maximum possible zoom level of the MapView depends also on the
|
||||
* current {@link TileGenerator}. For example, downloading map tiles may
|
||||
* only be possible up to a certain zoom level. Setting a higher maximum
|
||||
* zoom level has no effect in this case.
|
||||
*
|
||||
* @param zoomLevelMax
|
||||
* the maximum zoom level.
|
||||
* @throws IllegalArgumentException
|
||||
* if the maximum zoom level is smaller than the current minimum
|
||||
* zoom level.
|
||||
*/
|
||||
public void setZoomLevelMax(byte zoomLevelMax) {
|
||||
if (zoomLevelMax < mZoomLevelMin) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
mZoomLevelMax = zoomLevelMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum zoom level of the map.
|
||||
*
|
||||
* @param zoomLevelMin
|
||||
* the minimum zoom level.
|
||||
* @throws IllegalArgumentException
|
||||
* if the minimum zoom level is larger than the current maximum
|
||||
* zoom level.
|
||||
*/
|
||||
public void setZoomLevelMin(byte zoomLevelMin) {
|
||||
if (zoomLevelMin > mZoomLevelMax) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
mZoomLevelMin = zoomLevelMin;
|
||||
}
|
||||
|
||||
private int calculatePositionLeft(int left, int right, int zoomControlsWidth) {
|
||||
int gravity = mZoomControlsGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
|
||||
switch (gravity) {
|
||||
case Gravity.LEFT:
|
||||
return ZOOM_CONTROLS_HORIZONTAL_PADDING;
|
||||
|
||||
case Gravity.CENTER_HORIZONTAL:
|
||||
return (right - left - zoomControlsWidth) / 2;
|
||||
|
||||
case Gravity.RIGHT:
|
||||
return right - left - zoomControlsWidth
|
||||
- ZOOM_CONTROLS_HORIZONTAL_PADDING;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown horizontal gravity: " + gravity);
|
||||
}
|
||||
|
||||
private int calculatePositionTop(int top, int bottom, int zoomControlsHeight) {
|
||||
int gravity = mZoomControlsGravity & Gravity.VERTICAL_GRAVITY_MASK;
|
||||
switch (gravity) {
|
||||
case Gravity.TOP:
|
||||
return 0;
|
||||
|
||||
case Gravity.CENTER_VERTICAL:
|
||||
return (bottom - top - zoomControlsHeight) / 2;
|
||||
|
||||
case Gravity.BOTTOM:
|
||||
return bottom - top - zoomControlsHeight;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown vertical gravity: " + gravity);
|
||||
}
|
||||
|
||||
private void showZoomControls() {
|
||||
mZoomControlsHideHandler.removeMessages(MSG_ZOOM_CONTROLS_HIDE);
|
||||
if (mZoomControls.getVisibility() != View.VISIBLE) {
|
||||
mZoomControls.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void showZoomControlsWithTimeout() {
|
||||
showZoomControls();
|
||||
mZoomControlsHideHandler.sendEmptyMessageDelayed(MSG_ZOOM_CONTROLS_HIDE,
|
||||
ZOOM_CONTROLS_TIMEOUT);
|
||||
}
|
||||
|
||||
int getMeasuredHeight() {
|
||||
return mZoomControls.getMeasuredHeight();
|
||||
}
|
||||
|
||||
int getMeasuredWidth() {
|
||||
return mZoomControls.getMeasuredWidth();
|
||||
}
|
||||
|
||||
void measure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
mZoomControls.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (!changed && !mGravityChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
int zoomControlsWidth = mZoomControls.getMeasuredWidth();
|
||||
int zoomControlsHeight = mZoomControls.getMeasuredHeight();
|
||||
|
||||
int positionLeft = calculatePositionLeft(left, right, zoomControlsWidth);
|
||||
int positionTop = calculatePositionTop(top, bottom, zoomControlsHeight);
|
||||
int positionRight = positionLeft + zoomControlsWidth;
|
||||
int positionBottom = positionTop + zoomControlsHeight;
|
||||
|
||||
mZoomControls.layout(positionLeft, positionTop, positionRight, positionBottom);
|
||||
mGravityChanged = false;
|
||||
}
|
||||
|
||||
void onMapViewTouchEvent(int action) {
|
||||
if (mShowMapZoomControls) {
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
showZoomControls();
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
showZoomControlsWithTimeout();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
showZoomControlsWithTimeout();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onZoomLevelChange(int zoomLevel) {
|
||||
boolean zoomInEnabled = zoomLevel < mZoomLevelMax;
|
||||
boolean zoomOutEnabled = zoomLevel > mZoomLevelMin;
|
||||
|
||||
mZoomControls.setIsZoomInEnabled(zoomInEnabled);
|
||||
mZoomControls.setIsZoomOutEnabled(zoomOutEnabled);
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * Copyright 2010, 2011, 2012 mapsforge.org
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify it under the
|
||||
// * terms of the GNU Lesser General Public License as published by the Free Software
|
||||
// * Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
// * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU Lesser General Public License along with
|
||||
// * this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// */
|
||||
//package org.oscim.view;
|
||||
//
|
||||
//import org.oscim.generator.TileGenerator;
|
||||
//
|
||||
//import android.content.Context;
|
||||
//import android.os.Handler;
|
||||
//import android.os.Message;
|
||||
//import android.view.Gravity;
|
||||
//import android.view.MotionEvent;
|
||||
//import android.view.View;
|
||||
//import android.view.ViewConfiguration;
|
||||
//import android.view.ViewGroup.LayoutParams;
|
||||
//import android.widget.ZoomControls;
|
||||
//
|
||||
///**
|
||||
// * A MapZoomControls instance displays buttons for zooming in and out in a map.
|
||||
// */
|
||||
//public class MapZoomControls {
|
||||
// private static class ZoomControlsHideHandler extends Handler {
|
||||
// private final ZoomControls mZoomControls;
|
||||
//
|
||||
// ZoomControlsHideHandler(ZoomControls zoomControls) {
|
||||
// super();
|
||||
// mZoomControls = zoomControls;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void handleMessage(Message message) {
|
||||
// mZoomControls.hide();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static class ZoomInClickListener implements View.OnClickListener {
|
||||
// private final MapZoomControls mMapZoomControls;
|
||||
//
|
||||
// ZoomInClickListener(MapZoomControls mapZoomControls) {
|
||||
// mMapZoomControls = mapZoomControls;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onClick(View view) {
|
||||
// // if (MapView.testRegionZoom)
|
||||
// // mMapView.mRegionLookup.updateRegion(1, null);
|
||||
// // else
|
||||
// // MapZoomControls.this.zoom((byte) 1);
|
||||
// mMapZoomControls.zoom((byte) 1);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static class ZoomOutClickListener implements View.OnClickListener {
|
||||
// private final MapZoomControls mMapZoomControls;
|
||||
//
|
||||
// ZoomOutClickListener(MapZoomControls mapZoomControls) {
|
||||
// mMapZoomControls = mapZoomControls;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onClick(View view) {
|
||||
// // if (MapView.testRegionZoom)
|
||||
// // mMapView.mRegionLookup.updateRegion(-1, null);
|
||||
// // else
|
||||
// mMapZoomControls.zoom((byte) -1);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Default {@link Gravity} of the zoom controls.
|
||||
// */
|
||||
// private static final int DEFAULT_ZOOM_CONTROLS_GRAVITY = Gravity.BOTTOM
|
||||
// | Gravity.RIGHT;
|
||||
//
|
||||
// /**
|
||||
// * Default maximum zoom level.
|
||||
// */
|
||||
// private static final byte DEFAULT_ZOOM_LEVEL_MAX = 18;
|
||||
//
|
||||
// /**
|
||||
// * Default minimum zoom level.
|
||||
// */
|
||||
// private static final byte DEFAULT_ZOOM_LEVEL_MIN = 1;
|
||||
//
|
||||
// /**
|
||||
// * Message code for the handler to hide the zoom controls.
|
||||
// */
|
||||
// private static final int MSG_ZOOM_CONTROLS_HIDE = 0;
|
||||
//
|
||||
// /**
|
||||
// * Horizontal padding for the zoom controls.
|
||||
// */
|
||||
// private static final int ZOOM_CONTROLS_HORIZONTAL_PADDING = 5;
|
||||
//
|
||||
// /**
|
||||
// * Delay in milliseconds after which the zoom controls disappear.
|
||||
// */
|
||||
// private static final long ZOOM_CONTROLS_TIMEOUT = ViewConfiguration
|
||||
// .getZoomControlsTimeout();
|
||||
//
|
||||
// private boolean mGravityChanged;
|
||||
// private boolean mShowMapZoomControls;
|
||||
// private final ZoomControls mZoomControls;
|
||||
// private int mZoomControlsGravity;
|
||||
// private final Handler mZoomControlsHideHandler;
|
||||
// private byte mZoomLevelMax;
|
||||
// private byte mZoomLevelMin;
|
||||
// private final MapView mMapView;
|
||||
//
|
||||
// MapZoomControls(Context context, final MapView mapView) {
|
||||
// mMapView = mapView;
|
||||
// mZoomControls = new ZoomControls(context);
|
||||
// mShowMapZoomControls = true;
|
||||
// mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
||||
// mZoomLevelMin = DEFAULT_ZOOM_LEVEL_MIN;
|
||||
// // if (!MapView.testRegionZoom)
|
||||
// mZoomControls.setVisibility(View.GONE);
|
||||
// mZoomControlsGravity = DEFAULT_ZOOM_CONTROLS_GRAVITY;
|
||||
//
|
||||
// mZoomControls.setOnZoomInClickListener(new ZoomInClickListener(this));
|
||||
// mZoomControls.setOnZoomOutClickListener(new ZoomOutClickListener(this));
|
||||
// mZoomControlsHideHandler = new ZoomControlsHideHandler(mZoomControls);
|
||||
//
|
||||
// int wrapContent = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
// LayoutParams layoutParams = new LayoutParams(wrapContent, wrapContent);
|
||||
// mapView.addView(mZoomControls, layoutParams);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Zooms in or out by the given amount of zoom levels.
|
||||
// *
|
||||
// * @param zoomLevelDiff
|
||||
// * the difference to the current zoom level.
|
||||
// * @return true if the zoom level was changed, false otherwise.
|
||||
// */
|
||||
// boolean zoom(byte zoomLevelDiff) {
|
||||
// MapViewPosition mapViewPosition = mMapView.getMapViewPosition();
|
||||
// int z = mapViewPosition.getZoomLevel() + zoomLevelDiff;
|
||||
// if (zoomLevelDiff > 0) {
|
||||
// // check if zoom in is possible
|
||||
// if (z > mZoomLevelMax) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// } else if (zoomLevelDiff < 0) {
|
||||
// // check if zoom out is possible
|
||||
// if (z < getZoomLevelMin()) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// mapViewPosition.setZoomLevel((byte) z);
|
||||
// mMapView.redrawMap(true);
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the current gravity for the placing of the zoom controls.
|
||||
// * @see Gravity
|
||||
// */
|
||||
// public int getZoomControlsGravity() {
|
||||
// return mZoomControlsGravity;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the maximum zoom level of the map.
|
||||
// */
|
||||
// public byte getZoomLevelMax() {
|
||||
// return mZoomLevelMax;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the minimum zoom level of the map.
|
||||
// */
|
||||
// public byte getZoomLevelMin() {
|
||||
// return mZoomLevelMin;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return true if the zoom controls are visible, false otherwise.
|
||||
// */
|
||||
// public boolean isShowMapZoomControls() {
|
||||
// return mShowMapZoomControls;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param show
|
||||
// * true if the zoom controls should be visible, false otherwise.
|
||||
// */
|
||||
// public void setShowMapZoomControls(boolean show) {
|
||||
// mShowMapZoomControls = show;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Sets the gravity for the placing of the zoom controls. Supported values
|
||||
// * are {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL},
|
||||
// * {@link Gravity#BOTTOM}, {@link Gravity#LEFT},
|
||||
// * {@link Gravity#CENTER_HORIZONTAL} and {@link Gravity#RIGHT}.
|
||||
// *
|
||||
// * @param zoomControlsGravity
|
||||
// * a combination of {@link Gravity} constants describing the
|
||||
// * desired placement.
|
||||
// */
|
||||
// public void setZoomControlsGravity(int zoomControlsGravity) {
|
||||
// if (mZoomControlsGravity != zoomControlsGravity) {
|
||||
// mZoomControlsGravity = zoomControlsGravity;
|
||||
// mGravityChanged = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Sets the maximum zoom level of the map.
|
||||
// * <p>
|
||||
// * The maximum possible zoom level of the MapView depends also on the
|
||||
// * current {@link TileGenerator}. For example, downloading map tiles may
|
||||
// * only be possible up to a certain zoom level. Setting a higher maximum
|
||||
// * zoom level has no effect in this case.
|
||||
// *
|
||||
// * @param zoomLevelMax
|
||||
// * the maximum zoom level.
|
||||
// * @throws IllegalArgumentException
|
||||
// * if the maximum zoom level is smaller than the current minimum
|
||||
// * zoom level.
|
||||
// */
|
||||
// public void setZoomLevelMax(byte zoomLevelMax) {
|
||||
// if (zoomLevelMax < mZoomLevelMin) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// mZoomLevelMax = zoomLevelMax;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Sets the minimum zoom level of the map.
|
||||
// *
|
||||
// * @param zoomLevelMin
|
||||
// * the minimum zoom level.
|
||||
// * @throws IllegalArgumentException
|
||||
// * if the minimum zoom level is larger than the current maximum
|
||||
// * zoom level.
|
||||
// */
|
||||
// public void setZoomLevelMin(byte zoomLevelMin) {
|
||||
// if (zoomLevelMin > mZoomLevelMax) {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
// mZoomLevelMin = zoomLevelMin;
|
||||
// }
|
||||
//
|
||||
// private int calculatePositionLeft(int left, int right, int zoomControlsWidth) {
|
||||
// int gravity = mZoomControlsGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
|
||||
// switch (gravity) {
|
||||
// case Gravity.LEFT:
|
||||
// return ZOOM_CONTROLS_HORIZONTAL_PADDING;
|
||||
//
|
||||
// case Gravity.CENTER_HORIZONTAL:
|
||||
// return (right - left - zoomControlsWidth) / 2;
|
||||
//
|
||||
// case Gravity.RIGHT:
|
||||
// return right - left - zoomControlsWidth
|
||||
// - ZOOM_CONTROLS_HORIZONTAL_PADDING;
|
||||
// }
|
||||
//
|
||||
// throw new IllegalArgumentException("unknown horizontal gravity: " + gravity);
|
||||
// }
|
||||
//
|
||||
// private int calculatePositionTop(int top, int bottom, int zoomControlsHeight) {
|
||||
// int gravity = mZoomControlsGravity & Gravity.VERTICAL_GRAVITY_MASK;
|
||||
// switch (gravity) {
|
||||
// case Gravity.TOP:
|
||||
// return 0;
|
||||
//
|
||||
// case Gravity.CENTER_VERTICAL:
|
||||
// return (bottom - top - zoomControlsHeight) / 2;
|
||||
//
|
||||
// case Gravity.BOTTOM:
|
||||
// return bottom - top - zoomControlsHeight;
|
||||
// }
|
||||
//
|
||||
// throw new IllegalArgumentException("unknown vertical gravity: " + gravity);
|
||||
// }
|
||||
//
|
||||
// private void showZoomControls() {
|
||||
// mZoomControlsHideHandler.removeMessages(MSG_ZOOM_CONTROLS_HIDE);
|
||||
// if (mZoomControls.getVisibility() != View.VISIBLE) {
|
||||
// mZoomControls.show();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void showZoomControlsWithTimeout() {
|
||||
// showZoomControls();
|
||||
// mZoomControlsHideHandler.sendEmptyMessageDelayed(MSG_ZOOM_CONTROLS_HIDE,
|
||||
// ZOOM_CONTROLS_TIMEOUT);
|
||||
// }
|
||||
//
|
||||
// int getMeasuredHeight() {
|
||||
// return mZoomControls.getMeasuredHeight();
|
||||
// }
|
||||
//
|
||||
// int getMeasuredWidth() {
|
||||
// return mZoomControls.getMeasuredWidth();
|
||||
// }
|
||||
//
|
||||
// void measure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// mZoomControls.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
// }
|
||||
//
|
||||
// void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
// if (!changed && !mGravityChanged) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// int zoomControlsWidth = mZoomControls.getMeasuredWidth();
|
||||
// int zoomControlsHeight = mZoomControls.getMeasuredHeight();
|
||||
//
|
||||
// int positionLeft = calculatePositionLeft(left, right, zoomControlsWidth);
|
||||
// int positionTop = calculatePositionTop(top, bottom, zoomControlsHeight);
|
||||
// int positionRight = positionLeft + zoomControlsWidth;
|
||||
// int positionBottom = positionTop + zoomControlsHeight;
|
||||
//
|
||||
// mZoomControls.layout(positionLeft, positionTop, positionRight, positionBottom);
|
||||
// mGravityChanged = false;
|
||||
// }
|
||||
//
|
||||
// void onMapViewTouchEvent(int action) {
|
||||
// if (mShowMapZoomControls) {
|
||||
// switch (action) {
|
||||
// case MotionEvent.ACTION_DOWN:
|
||||
// showZoomControls();
|
||||
// break;
|
||||
// case MotionEvent.ACTION_CANCEL:
|
||||
// showZoomControlsWithTimeout();
|
||||
// break;
|
||||
// case MotionEvent.ACTION_UP:
|
||||
// showZoomControlsWithTimeout();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void onZoomLevelChange(int zoomLevel) {
|
||||
// boolean zoomInEnabled = zoomLevel < mZoomLevelMax;
|
||||
// boolean zoomOutEnabled = zoomLevel > mZoomLevelMin;
|
||||
//
|
||||
// mZoomControls.setIsZoomInEnabled(zoomInEnabled);
|
||||
// mZoomControls.setIsZoomOutEnabled(zoomOutEnabled);
|
||||
// }
|
||||
//}
|
||||
|
@ -20,14 +20,11 @@ import org.oscim.core.Tile;
|
||||
import org.oscim.overlay.OverlayManager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.CountDownTimer;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.OnDoubleTapListener;
|
||||
import android.view.GestureDetector.OnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.Scroller;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
@ -40,18 +37,19 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
|
||||
private static final String TAG = TouchHandler.class.getName();
|
||||
|
||||
private static final boolean debug = false;
|
||||
|
||||
private final MapView mMapView;
|
||||
private final MapViewPosition mMapPosition;
|
||||
private final OverlayManager mOverlayManager;
|
||||
|
||||
private final DecelerateInterpolator mInterpolator;
|
||||
private boolean mBeginScale;
|
||||
private float mSumScale;
|
||||
private float mSumRotate;
|
||||
|
||||
private boolean mBeginScale;
|
||||
private boolean mBeginRotate;
|
||||
private boolean mBeginTilt;
|
||||
private boolean mLongPress;
|
||||
private boolean mDoubleTap;
|
||||
|
||||
private float mPrevX;
|
||||
private float mPrevY;
|
||||
@ -60,16 +58,17 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
private float mPrevY2;
|
||||
|
||||
private double mAngle;
|
||||
private double mPrevPinchWidth;
|
||||
|
||||
private float mFocusX;
|
||||
private float mFocusY;
|
||||
|
||||
private final GestureDetector mGestureDetector;
|
||||
|
||||
private static final float SCALE_DURATION = 500;
|
||||
protected static final int JUMP_THRESHOLD = 100;
|
||||
protected static final double PINCH_ZOOM_THRESHOLD = 5;
|
||||
protected static final double PINCH_ROTATE_THRESHOLD = 0.02;
|
||||
protected static final float PINCH_TILT_THRESHOLD = 1f;
|
||||
protected int mPrevPointerCount = 0;
|
||||
protected double mPrevPinchWidth = -1;
|
||||
|
||||
/**
|
||||
* @param context
|
||||
@ -83,8 +82,6 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
mOverlayManager = mapView.getOverlayManager();
|
||||
mGestureDetector = new GestureDetector(context, this);
|
||||
mGestureDetector.setOnDoubleTapListener(this);
|
||||
mInterpolator = new DecelerateInterpolator(2f);
|
||||
mScroller = new Scroller(mMapView.getContext(), mInterpolator);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,8 +125,7 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
}
|
||||
|
||||
private boolean onActionCancel() {
|
||||
//mPointerId1 = INVALID_POINTER_ID;
|
||||
mLongPress = true;
|
||||
mDoubleTap = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -143,8 +139,14 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
float width = mMapView.getWidth();
|
||||
float height = mMapView.getHeight();
|
||||
|
||||
// return if detect a new gesture, as indicated by a large jump
|
||||
if (Math.abs(mx) > JUMP_THRESHOLD || Math.abs(my) > JUMP_THRESHOLD)
|
||||
return true;
|
||||
|
||||
// double-tap + hold
|
||||
if (mLongPress) {
|
||||
if (mDoubleTap) {
|
||||
if (debug)
|
||||
Log.d(TAG, "tap scale: " + mx + " " + my);
|
||||
mMapPosition.scaleMap(1 - my / (height / 5), 0, 0);
|
||||
mMapView.redrawMap(true);
|
||||
|
||||
@ -239,12 +241,7 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
mSumRotate += da;
|
||||
|
||||
if (Math.abs(da) > 0.001) {
|
||||
double rsin = Math.sin(r);
|
||||
double rcos = Math.cos(r);
|
||||
float x = (float) (mFocusX * rcos + mFocusY * -rsin - mFocusX);
|
||||
float y = (float) (mFocusX * rsin + mFocusY * rcos - mFocusY);
|
||||
|
||||
mMapPosition.rotateMap((float) Math.toDegrees(da), x, y);
|
||||
mMapPosition.rotateMap(da, mFocusX, mFocusY);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@ -265,60 +262,59 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
return true;
|
||||
}
|
||||
|
||||
private int mMulti = 0;
|
||||
private int mMulti;
|
||||
private boolean mWasMulti;
|
||||
|
||||
private boolean onActionPointerDown(MotionEvent event) {
|
||||
private void updateMulti(MotionEvent e) {
|
||||
int cnt = e.getPointerCount();
|
||||
|
||||
mMulti++;
|
||||
mWasMulti = true;
|
||||
mSumScale = 1;
|
||||
if (cnt == 2) {
|
||||
mPrevX = e.getX(0);
|
||||
mPrevY = e.getY(0);
|
||||
|
||||
if (mMulti == 1) {
|
||||
mPrevX2 = event.getX(1);
|
||||
mPrevY2 = event.getY(1);
|
||||
mPrevX2 = e.getX(1);
|
||||
mPrevY2 = e.getY(1);
|
||||
double dx = mPrevX - mPrevX2;
|
||||
double dy = mPrevY - mPrevY2;
|
||||
|
||||
mAngle = Math.atan2(dy, dx);
|
||||
mPrevPinchWidth = Math.sqrt(dx * dx + dy * dy);
|
||||
mSumScale = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean onActionPointerDown(MotionEvent e) {
|
||||
|
||||
mMulti++;
|
||||
mWasMulti = true;
|
||||
|
||||
updateMulti(e);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean onActionPointerUp(MotionEvent e) {
|
||||
|
||||
int cnt = e.getPointerCount();
|
||||
|
||||
if (cnt >= 2) {
|
||||
mPrevX = e.getX(0);
|
||||
mPrevY = e.getY(0);
|
||||
|
||||
mPrevX2 = e.getX(1);
|
||||
mPrevY2 = e.getY(1);
|
||||
|
||||
double dx = mPrevX - mPrevX2;
|
||||
double dy = mPrevY - mPrevY2;
|
||||
mAngle = Math.atan2(dy, dx);
|
||||
|
||||
mPrevPinchWidth = Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
updateMulti(e);
|
||||
mMulti--;
|
||||
|
||||
mLongPress = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean onActionDown(MotionEvent e) {
|
||||
mPrevX = e.getX();
|
||||
mPrevY = e.getY();
|
||||
private void printState(String action) {
|
||||
Log.d(TAG, action
|
||||
+ " " + mDoubleTap
|
||||
+ " " + mBeginScale
|
||||
+ " " + mBeginRotate
|
||||
+ " " + mBeginTilt);
|
||||
}
|
||||
|
||||
mBeginRotate = false;
|
||||
mBeginTilt = false;
|
||||
mBeginScale = false;
|
||||
private boolean onActionDown(MotionEvent e) {
|
||||
mPrevX = e.getX(0);
|
||||
mPrevY = e.getY(0);
|
||||
|
||||
if (debug)
|
||||
printState("onActionDown");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -330,19 +326,22 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
*/
|
||||
private boolean onActionUp(MotionEvent event) {
|
||||
|
||||
mLongPress = false;
|
||||
mMulti = 0;
|
||||
mPrevPinchWidth = -1;
|
||||
mPrevPointerCount = 0;
|
||||
if (debug)
|
||||
printState("onActionUp");
|
||||
|
||||
mBeginRotate = false;
|
||||
mBeginTilt = false;
|
||||
mBeginScale = false;
|
||||
mDoubleTap = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************* GestureListener *******************/
|
||||
|
||||
private final Scroller mScroller;
|
||||
private float mScrollX, mScrollY;
|
||||
private boolean fling = false;
|
||||
//private final Scroller mScroller;
|
||||
//private float mScrollX, mScrollY;
|
||||
// private boolean fling = false;
|
||||
|
||||
@Override
|
||||
public void onShowPress(MotionEvent e) {
|
||||
@ -356,37 +355,22 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent e) {
|
||||
if (fling) {
|
||||
mScroller.forceFinished(true);
|
||||
if (debug)
|
||||
printState("onDown");
|
||||
|
||||
if (mTimer != null) {
|
||||
mTimer.cancel();
|
||||
mTimer = null;
|
||||
}
|
||||
fling = false;
|
||||
}
|
||||
// if (fling) {
|
||||
// mScroller.forceFinished(true);
|
||||
//
|
||||
// if (mTimer != null) {
|
||||
// mTimer.cancel();
|
||||
// mTimer = null;
|
||||
// }
|
||||
// fling = false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean scroll() {
|
||||
if (mScroller.isFinished()) {
|
||||
return false;
|
||||
}
|
||||
mScroller.computeScrollOffset();
|
||||
|
||||
float moveX = mScroller.getCurrX() - mScrollX;
|
||||
float moveY = mScroller.getCurrY() - mScrollY;
|
||||
|
||||
if (moveX >= 1 || moveY >= 1 || moveX <= -1 || moveY <= -1) {
|
||||
mMapPosition.moveMap(moveX, moveY);
|
||||
mMapView.redrawMap(true);
|
||||
mScrollX = mScroller.getCurrX();
|
||||
mScrollY = mScroller.getCurrY();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX,
|
||||
final float distanceY) {
|
||||
@ -396,6 +380,8 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
}
|
||||
|
||||
if (mMulti == 0) {
|
||||
if (debug)
|
||||
printState("onScroll " + distanceX + " " + distanceY);
|
||||
mMapPosition.moveMap(-distanceX, -distanceY);
|
||||
mMapView.redrawMap(true);
|
||||
}
|
||||
@ -412,13 +398,6 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
|
||||
int w = Tile.TILE_SIZE * 6;
|
||||
int h = Tile.TILE_SIZE * 6;
|
||||
mScrollX = 0;
|
||||
mScrollY = 0;
|
||||
|
||||
if (mTimer != null) {
|
||||
mTimer.cancel();
|
||||
mTimer = null;
|
||||
}
|
||||
|
||||
if (mMapView.enablePagedFling) {
|
||||
|
||||
@ -436,28 +415,16 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
mMapPosition.animateTo(vx * move, vy * move, 250);
|
||||
} else {
|
||||
float s = (300 / mMapView.dpi) / 2;
|
||||
mScroller.fling(0, 0, Math.round(velocityX * s),
|
||||
Math.round(velocityY * s),
|
||||
-w, w, -h, h);
|
||||
|
||||
mTimer = new CountDownTimer(1000, 16) {
|
||||
@Override
|
||||
public void onTick(long tick) {
|
||||
scroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
}
|
||||
}.start();
|
||||
fling = true;
|
||||
mMapPosition.animateFling(Math.round(velocityX * s), Math.round(velocityY * s), -w, w, -h, h);
|
||||
// fling = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongPress(MotionEvent e) {
|
||||
if (mLongPress)
|
||||
if (mDoubleTap)
|
||||
return;
|
||||
|
||||
if (mOverlayManager.onLongPress(e)) {
|
||||
@ -470,28 +437,6 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
// }
|
||||
}
|
||||
|
||||
boolean scale2(long tick) {
|
||||
|
||||
fling = true;
|
||||
if (mPrevScale >= 1)
|
||||
return false;
|
||||
|
||||
float adv = (SCALE_DURATION - tick) / SCALE_DURATION;
|
||||
adv = mInterpolator.getInterpolation(adv);
|
||||
float scale = adv - mPrevScale;
|
||||
mPrevScale += scale;
|
||||
scale *= 0.75;
|
||||
scale += 1;
|
||||
adv += 1;
|
||||
|
||||
if (scale > 1) {
|
||||
mMapPosition.scaleMap(scale, mScrollX / adv, mScrollY / adv);
|
||||
mMapView.redrawMap(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************* DoubleTapListener ****************/
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
@ -503,7 +448,11 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
if (mOverlayManager.onDoubleTap(e))
|
||||
return true;
|
||||
|
||||
mLongPress = true;
|
||||
//mDoubleTap = true;
|
||||
mMapPosition.animateZoom(2);
|
||||
|
||||
if (debug)
|
||||
printState("onDoubleTap");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -514,13 +463,12 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
||||
}
|
||||
|
||||
// /******************* ScaleListener *******************/
|
||||
private float mPrevScale;
|
||||
private CountDownTimer mTimer;
|
||||
boolean mZooutOut;
|
||||
//private float mPrevScale;
|
||||
//private CountDownTimer mTimer;
|
||||
//boolean mZooutOut;
|
||||
// private float mCenterX;
|
||||
// private float mCenterY;
|
||||
private float mFocusX;
|
||||
private float mFocusY;
|
||||
|
||||
// private long mTimeStart;
|
||||
// private long mTimeEnd;
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user