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