From 4de363414de6e569fa070ac1f9ab07158f73191d Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sat, 29 May 2010 08:04:41 +0000 Subject: [PATCH] Implement positioning on the bottom (fixing bugs) git-svn-id: https://osmand.googlecode.com/svn/trunk@94 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8 --- .../src/com/osmand/ToDoConstants.java | 16 +- OsmAnd/res/values/strings.xml | 2 + OsmAnd/res/xml/settings_pref.xml | 2 + .../com/osmand/AmenityIndexRepository.java | 2 +- OsmAnd/src/com/osmand/OsmandSettings.java | 22 +- .../com/osmand/activities/MapActivity.java | 10 +- .../osmand/activities/SettingsActivity.java | 11 + .../com/osmand/views/OsmandMapTileView.java | 191 ++++++++++++------ OsmAnd/src/com/osmand/views/POIMapLayer.java | 59 +++--- .../com/osmand/views/PointLocationLayer.java | 13 +- .../osmand/views/PointNavigationLayer.java | 15 +- 11 files changed, 221 insertions(+), 122 deletions(-) diff --git a/DataExtractionOSM/src/com/osmand/ToDoConstants.java b/DataExtractionOSM/src/com/osmand/ToDoConstants.java index e61b530ce2..d9c6304bf4 100644 --- a/DataExtractionOSM/src/com/osmand/ToDoConstants.java +++ b/DataExtractionOSM/src/com/osmand/ToDoConstants.java @@ -21,16 +21,12 @@ public class ToDoConstants { // 24. Implement ResourceManager, load cities/streets/buildings on Low memory (clear previous all addresses cities). // 5. Search for city/streets/buildings -// 15. Investigate interruption of any long running operation & implement where it is needed -// 17. Enable go to location by specifying coordinates +// 15. Investigate interruption of any long running operation & implement where it is needed // 11. Print out additional info speed, altitude, number of satellites // 19. Show how map is rotated where north/south on map (do not consider compass) -// 23. Implement moving point from center to bottom (for rotating map) - // 21. Implement zooming tile (if tile doesn't exist local, we can zoom in previous tile). - // 8. Enable change POI directly on map (requires OSM login) // 16. Support open street bugs api. // 20. Implement save track/route to gpx (?) @@ -46,6 +42,8 @@ public class ToDoConstants { // (for example reset navigate to point, reset link map with location). It should be reset after user call exit. // 7. Implement search amenities by type (!). // Rewrite search activity in order to limit amenities not to all types. + // 8. Introduce activity search by location (unify with existing dialog) + // 9. When all features will be ready we can remove show location from context menu // TODO SWING: // 1. Download tiles without using dir tiles @@ -53,12 +51,16 @@ public class ToDoConstants { // 5. Implement supress warning for duplicate id // 6. Implement renaming/deleting street/building/city // 7. Implement saving bundle of tiles in different folder + // DONE ANDROID : -// 18. Implement go to point -// 2. Showing compass on the map : use device compass if exists(?) +// 23. Implement moving point from center to bottom (for rotating map) +// 17. Enable go to location by specifying coordinates // 9. Configure file log & see log from file (when exception happened to see from device) +// 2. Showing compass on the map : use device compass if exists(?) +// 18. Implement go to point + // DONE SWING diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 1e696bd29c..c1bb1c9f3d 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,5 +1,7 @@ + Choose postion on the map + Position on the map Specify point Show aspect of vew based on compass Show aspect of view diff --git a/OsmAnd/res/xml/settings_pref.xml b/OsmAnd/res/xml/settings_pref.xml index 69faa58729..7b83190f72 100644 --- a/OsmAnd/res/xml/settings_pref.xml +++ b/OsmAnd/res/xml/settings_pref.xml @@ -7,6 +7,8 @@ + + diff --git a/OsmAnd/src/com/osmand/AmenityIndexRepository.java b/OsmAnd/src/com/osmand/AmenityIndexRepository.java index c7374fe8f9..33ee51a9a1 100644 --- a/OsmAnd/src/com/osmand/AmenityIndexRepository.java +++ b/OsmAnd/src/com/osmand/AmenityIndexRepository.java @@ -82,7 +82,7 @@ public class AmenityIndexRepository { cBottomLatitude = bottomLatitude - (topLatitude -bottomLatitude); cLeftLongitude = leftLongitude - (rightLongitude - leftLongitude); cRightLongitude = rightLongitude + (rightLongitude - leftLongitude); - searchAmenities(topLatitude, leftLongitude, bottomLatitude, rightLongitude, -1, cachedAmenities); + searchAmenities(cTopLatitude, cLeftLongitude, cBottomLatitude, cRightLongitude, -1, cachedAmenities); checkCachedAmenities(topLatitude, leftLongitude, bottomLatitude, rightLongitude, toFill); } diff --git a/OsmAnd/src/com/osmand/OsmandSettings.java b/OsmAnd/src/com/osmand/OsmandSettings.java index eca8706ad3..dcf833290b 100644 --- a/OsmAnd/src/com/osmand/OsmandSettings.java +++ b/OsmAnd/src/com/osmand/OsmandSettings.java @@ -15,36 +15,46 @@ public class OsmandSettings { // These settings are stored in SharedPreferences public static final String SHARED_PREFERENCES_NAME = "com.osmand.settings"; + + public static final int CENTER_CONSTANT = 0; + public static final int BOTTOM_CONSTANT = 1; - // this value string is synchronized with android.xml preference name + // this value string is synchronized with settings_pref.xml preference name public static final String USE_INTERNET_TO_DOWNLOAD_TILES = "use_internet_to_download_tiles"; public static boolean isUsingInternetToDownloadTiles(Context ctx){ SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); return prefs.getBoolean(USE_INTERNET_TO_DOWNLOAD_TILES, true); } - // this value string is synchronized with android.xml preference name + // this value string is synchronized with settings_pref.xml preference name public static final String SHOW_POI_OVER_MAP = "show_poi_over_map"; public static boolean isShowingPoiOverMap(Context ctx){ SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); return prefs.getBoolean(SHOW_POI_OVER_MAP, false); } - // this value string is synchronized with android.xml preference name + // this value string is synchronized with settings_pref.xml preference name public static final String SHOW_VIEW_ANGLE = "show_view_angle"; public static boolean isShowingViewAngle(Context ctx){ SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); return prefs.getBoolean(SHOW_VIEW_ANGLE, true); } - // this value string is synchronized with android.xml preference name + // this value string is synchronized with settings_pref.xml preference name public static final String ROTATE_MAP_TO_BEARING = "rotate_map_to_bearing"; public static boolean isRotateMapToBearing(Context ctx){ SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); return prefs.getBoolean(ROTATE_MAP_TO_BEARING, false); } - // this value string is synchronized with android.xml preference name + // this value string is synchronized with settings_pref.xml preference name + public static final String POSITION_ON_MAP = "position_on_map"; + public static int getPositionOnMap(Context ctx){ + SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); + return prefs.getInt(POSITION_ON_MAP, CENTER_CONSTANT); + } + + // this value string is synchronized with settings_pref.xml preference name public static final String MAP_VIEW_3D = "map_view_3d"; public static boolean isMapView3D(Context ctx){ SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); @@ -52,7 +62,7 @@ public class OsmandSettings { } - // this value string is synchronized with android.xml preference name + // this value string is synchronized with settings_pref.xml preference name public static final String MAP_TILE_SOURCES = "map_tile_sources"; public static ITileSource getMapTileSource(Context ctx){ SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); diff --git a/OsmAnd/src/com/osmand/activities/MapActivity.java b/OsmAnd/src/com/osmand/activities/MapActivity.java index 07ca01edc4..d53dba676f 100644 --- a/OsmAnd/src/com/osmand/activities/MapActivity.java +++ b/OsmAnd/src/com/osmand/activities/MapActivity.java @@ -162,6 +162,10 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat } public void setLocation(Location location){ + if(location != null){ + location.setSpeed(30); + location.setBearing(90); + } // Do very strange manipulation to call redraw only once // show point view only if gps enabled @@ -191,7 +195,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat mapView.setLatLon(location.getLatitude(), location.getLongitude()); } } else { - mapView.prepareImage(); + mapView.refreshMap(); if(backToLocation.getVisibility() != View.VISIBLE){ backToLocation.setVisibility(View.VISIBLE); } @@ -265,6 +269,8 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat if(!OsmandSettings.isRotateMapToBearing(this)){ mapView.setRotate(0); } + mapView.setMapPosition(OsmandSettings.getPositionOnMap(this)); + if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(this)){ if(OsmandSettings.isShowingPoiOverMap(this)){ @@ -360,7 +366,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat Message m = Message.obtain(sensorHandler, new Runnable(){ @Override public void run() { - mapView.prepareImage(); + mapView.refreshMap(); } }); m.what = 1; diff --git a/OsmAnd/src/com/osmand/activities/SettingsActivity.java b/OsmAnd/src/com/osmand/activities/SettingsActivity.java index c19a266dea..0e46cfdf77 100644 --- a/OsmAnd/src/com/osmand/activities/SettingsActivity.java +++ b/OsmAnd/src/com/osmand/activities/SettingsActivity.java @@ -25,6 +25,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference private ListPreference tileSourcePreference; private CheckBoxPreference rotateMapToBearing; private CheckBoxPreference showViewAngle; + private ListPreference positionOnMap; @Override public void onCreate(Bundle savedInstanceState) { @@ -40,6 +41,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference showViewAngle =(CheckBoxPreference) screen.findPreference(OsmandSettings.SHOW_VIEW_ANGLE); showViewAngle.setOnPreferenceChangeListener(this); + positionOnMap =(ListPreference) screen.findPreference(OsmandSettings.POSITION_ON_MAP); + positionOnMap.setOnPreferenceChangeListener(this); tileSourcePreference =(ListPreference) screen.findPreference(OsmandSettings.MAP_TILE_SOURCES); tileSourcePreference.setOnPreferenceChangeListener(this); @@ -53,6 +56,11 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference showPoiOnMap.setChecked(OsmandSettings.isShowingPoiOverMap(this)); rotateMapToBearing.setChecked(OsmandSettings.isRotateMapToBearing(this)); showViewAngle.setChecked(OsmandSettings.isShowingViewAngle(this)); + String[] e = new String[] { "Center", "Bottom" }; + positionOnMap.setEntryValues(e); + positionOnMap.setEntries(e); + positionOnMap.setValueIndex(OsmandSettings.getPositionOnMap(this)); + List list = TileSourceManager.getKnownSourceTemplates(); String[] entries = new String[list.size()]; @@ -84,6 +92,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference } else if(preference == showViewAngle){ edit.putBoolean(OsmandSettings.SHOW_VIEW_ANGLE, (Boolean) newValue); edit.commit(); + } else if(preference == positionOnMap){ + edit.putInt(OsmandSettings.POSITION_ON_MAP, positionOnMap.findIndexOfValue((String) newValue)); + edit.commit(); } else if (preference == tileSourcePreference) { edit.putString(OsmandSettings.MAP_TILE_SOURCES, (String) newValue); edit.commit(); diff --git a/OsmAnd/src/com/osmand/views/OsmandMapTileView.java b/OsmAnd/src/com/osmand/views/OsmandMapTileView.java index f5d64dcb67..6d376350e6 100644 --- a/OsmAnd/src/com/osmand/views/OsmandMapTileView.java +++ b/OsmAnd/src/com/osmand/views/OsmandMapTileView.java @@ -52,6 +52,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall private float rotate = 0; + private int mapPosition; + // name of source map private ITileSource map = null; @@ -71,6 +73,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall Paint paintBlack; Paint paintBitmap; + @@ -118,12 +121,12 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - prepareImage(); + refreshMap(); } @Override public void surfaceCreated(SurfaceHolder holder) { - prepareImage(); + refreshMap(); } @Override @@ -165,7 +168,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall if (map == null || (map.getMaximumZoomSupported() >= zoom && map.getMinimumZoomSupported() <= zoom)) { animatedDraggingThread.stopDragging(); this.zoom = zoom; - prepareImage(); + refreshMap(); } } @@ -174,7 +177,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall if (dif > 2 || dif < -2) { this.rotate = rotate; animatedDraggingThread.stopDragging(); - prepareImage(); + refreshMap(); } } @@ -183,7 +186,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall this.rotate = rotate; this.latitude = latitude; this.longitude = longitude; - prepareImage(); + refreshMap(); } public float getRotate() { @@ -202,14 +205,14 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall if(map.getMinimumZoomSupported() > this.zoom){ zoom = map.getMinimumZoomSupported(); } - prepareImage(); + refreshMap(); } public void setLatLon(double latitude, double longitude){ animatedDraggingThread.stopDragging(); this.latitude = latitude; this.longitude = longitude; - prepareImage(); + refreshMap(); } public double getLatitude() { @@ -238,13 +241,12 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall //////////////////////////////// DRAWING MAP PART ///////////////////////////////////////////// - protected void drawEmptyTile(Canvas cvs, int x, int y){ + protected void drawEmptyTile(Canvas cvs, float x, float y){ int tileDiv = getTileSize() / emptyTileDivisor; for (int k1 = 0; k1 < emptyTileDivisor; k1++) { - for (int k2 = 0; k2 < emptyTileDivisor; k2++) { - int xk = x + tileDiv* k1; - int yk = y + tileDiv* k2; + float xk = x + tileDiv* k1; + float yk = y + tileDiv* k2; if ((k1 + k2) % 2 == 0) { cvs.drawRect(xk, yk, xk + tileDiv, yk + tileDiv, paintGrayFill); } else { @@ -254,16 +256,31 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall } } + public int getCenterPointX(){ + return getWidth() / 2; + } + + public int getCenterPointY(){ + if(mapPosition == OsmandSettings.BOTTOM_CONSTANT){ + return 3 * getHeight() / 4; + } + return getHeight() / 2; + } + + public void setMapPosition(int type){ + this.mapPosition = type; + } + private void drawOverMap(Canvas canvas){ - canvas.drawCircle(getWidth() / 2, getHeight() / 2, 3, paintBlack); - canvas.drawCircle(getWidth() / 2, getHeight() / 2, 6, paintBlack); + canvas.drawCircle(getCenterPointX(), getCenterPointY(), 3, paintBlack); + canvas.drawCircle(getCenterPointX(), getCenterPointY(), 6, paintBlack); for(OsmandMapLayer layer : layers){ layer.onDraw(canvas); } } - protected void calculateTileRectangle(RectF pixRect, float cx, float cy, RectF tileRect){ + protected void calculateTileRectangle(Rect pixRect, float cx, float cy, float ctilex, float ctiley, RectF tileRect){ float x1 = calcDiffTileX(pixRect.left - cx, pixRect.top - cy); float x2 = calcDiffTileX(pixRect.left - cx, pixRect.bottom - cy); float x3 = calcDiffTileX(pixRect.right - cx, pixRect.top - cy); @@ -272,24 +289,42 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall float y2 = calcDiffTileY(pixRect.left - cx, pixRect.bottom - cy); float y3 = calcDiffTileY(pixRect.right - cx, pixRect.top - cy); float y4 = calcDiffTileY(pixRect.right - cx, pixRect.bottom - cy); - float l = Math.min(Math.min(x1, x2), Math.min(x3, x4)) + getXTile(); - float r = Math.max(Math.max(x1, x2), Math.max(x3, x4)) + getXTile(); - float t = Math.min(Math.min(y1, y2), Math.min(y3, y4)) + getYTile(); - float b = Math.max(Math.max(y1, y2), Math.max(y3, y4)) + getYTile(); + float l = Math.min(Math.min(x1, x2), Math.min(x3, x4)) + ctilex; + float r = Math.max(Math.max(x1, x2), Math.max(x3, x4)) + ctilex; + float t = Math.min(Math.min(y1, y2), Math.min(y3, y4)) + ctiley; + float b = Math.max(Math.max(y1, y2), Math.max(y3, y4)) + ctiley; tileRect.set(l, t, r, b); } + protected void calculatePixelRectangle(Rect pixelRect, float cx, float cy, float ctilex, float ctiley, RectF tileRect){ + float x1 = calcDiffPixelX(tileRect.left - ctilex, tileRect.top - ctiley); + float x2 = calcDiffPixelX(tileRect.left - ctilex, tileRect.bottom - ctiley); + float x3 = calcDiffPixelX(tileRect.right - ctilex, tileRect.top - ctiley); + float x4 = calcDiffPixelX(tileRect.right - ctilex, tileRect.bottom - ctiley); + float y1 = calcDiffPixelY(tileRect.left - ctilex, tileRect.top - ctiley); + float y2 = calcDiffPixelY(tileRect.left - ctilex, tileRect.bottom - ctiley); + float y3 = calcDiffPixelY(tileRect.right - ctilex, tileRect.top - ctiley); + float y4 = calcDiffPixelY(tileRect.right - ctilex, tileRect.bottom - ctiley); + int l = (int) (Math.min(Math.min(x1, x2), Math.min(x3, x4)) + cx); + int r = (int) (Math.max(Math.max(x1, x2), Math.max(x3, x4)) + cx); + int t = (int) (Math.min(Math.min(y1, y2), Math.min(y3, y4)) + cy); + int b = (int) (Math.max(Math.max(y1, y2), Math.max(y3, y4)) + cy); + pixelRect.set(l, t, r, b); + } + // used only to save space & reuse protected RectF tilesRect = new RectF(); - protected RectF boundsRect = new RectF(); + protected Rect boundsRect = new Rect(); - public void prepareImage() { + public void refreshMap() { if (OsmandSettings.isUsingInternetToDownloadTiles(getContext())) { MapTileDownloader.getInstance().refuseAllPreviousRequests(); } int tileSize = getTileSize(); float tileX = getXTile(); float tileY = getYTile(); + float w = getCenterPointX(); + float h = getCenterPointY(); SurfaceHolder holder = getHolder(); synchronized (holder) { @@ -297,11 +332,10 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall if (canvas != null) { ResourceManager mgr = ResourceManager.getResourceManager(); boolean useInternet = OsmandSettings.isUsingInternetToDownloadTiles(getContext()); - float w = getWidth() / 2; - float h = getHeight() / 2; + canvas.rotate(rotate, w , h); boundsRect.set(0, 0, getWidth(), getHeight()); - calculateTileRectangle(boundsRect, w, h, tilesRect); + calculateTileRectangle(boundsRect, w, h, tileX, tileY, tilesRect); try { int left = (int) FloatMath.floor(tilesRect.left); int top = (int) FloatMath.floor(tilesRect.top); @@ -329,37 +363,42 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall public void tileDownloaded(DownloadRequest request) { - // TODO estimate bounds for rotated map - if(request == null || rotate != 0){ + if (request == null) { // we don't know exact images were changed - prepareImage(); + refreshMap(); return; } - int xTileLeft = (int) Math.floor(getXTile() - getWidth() / (2d * getTileSize())); - int yTileUp = (int) Math.floor(getYTile() - getHeight() / (2d * getTileSize())); - int startingX = (int) ((xTileLeft - getXTile()) * getTileSize() + getWidth() / 2); - int startingY = (int) ((yTileUp - getYTile()) * getTileSize() + getHeight() / 2); - int i = (request.xTile - xTileLeft) * getTileSize() + startingX; - int j = (request.yTile - yTileUp) * getTileSize() + startingY; - if (request.zoom == this.zoom && - (i + getTileSize() >= 0 && i < getWidth()) && (j + getTileSize() >= 0 && j < getHeight())) { - SurfaceHolder holder = getHolder(); - synchronized (holder) { - Canvas canvas = holder.lockCanvas(new Rect(i, j, getTileSize() + i, getTileSize() + j)); - if (canvas != null) { - canvas.rotate(rotate,getWidth()/2, getHeight()/2); - try { - ResourceManager mgr = ResourceManager.getResourceManager(); - Bitmap bmp = mgr.getTileImageForMapSync(map, request.xTile, request.yTile, zoom, false); - if (bmp == null) { - drawEmptyTile(canvas, i, j); - } else { - canvas.drawBitmap(bmp, i, j, null); - } - drawOverMap(canvas); - } finally { - holder.unlockCanvasAndPost(canvas); + if (request.zoom != this.zoom) { + return; + } + float w = getCenterPointX(); + float h = getCenterPointY(); + float tileX = getXTile(); + float tileY = getYTile(); + + SurfaceHolder holder = getHolder(); + synchronized (holder) { + tilesRect.set(request.xTile, request.yTile, request.xTile + 1, request.yTile + 1); + calculatePixelRectangle(boundsRect, w, h, tileX, tileY, tilesRect); + if(boundsRect.left > getWidth() || boundsRect.right < 0 || boundsRect.bottom < 0 || boundsRect.top > getHeight()){ + return; + } + Canvas canvas = holder.lockCanvas(boundsRect); + if (canvas != null) { + canvas.rotate(rotate, w , h); + try { + ResourceManager mgr = ResourceManager.getResourceManager(); + Bitmap bmp = mgr.getTileImageForMapSync(map, request.xTile, request.yTile, zoom, false); + float x = (request.xTile - getXTile()) * getTileSize() + w; + float y = (request.yTile - getYTile()) * getTileSize() + h; + if (bmp == null) { + drawEmptyTile(canvas, x, y); + } else { + canvas.drawBitmap(bmp, x, y, null); } + drawOverMap(canvas); + } finally { + holder.unlockCanvasAndPost(canvas); } } } @@ -378,15 +417,49 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall return (FloatMath.cos(rad) * dx + FloatMath.sin(rad) * dy) / getTileSize(); } - - public boolean isPointOnTheMap(double latitude, double longitude){ - int cx = getWidth()/2; - int cy = getHeight()/2; - int dx = MapUtils.getPixelShiftX(zoom, longitude, this.longitude, getTileSize()); - int dy = MapUtils.getPixelShiftY(zoom, latitude, this.latitude , getTileSize()); + public float calcDiffPixelY(float dTileX, float dTileY){ float rad = (float) Math.toRadians(rotate); - int newX = (int) (dx * FloatMath.cos(rad) - dy * FloatMath.sin(rad) + cx); - int newY = (int) (dx * FloatMath.sin(rad) + dy * FloatMath.cos(rad) + cy); + return (FloatMath.sin(rad) * dTileX + FloatMath.cos(rad) * dTileY) * getTileSize(); + } + + public float calcDiffPixelX(float dTileX, float dTileY){ + float rad = (float) Math.toRadians(rotate); + return (FloatMath.cos(rad) * dTileX - FloatMath.sin(rad) * dTileY) * getTileSize(); + } + + /** + * These methods do not consider rotating + */ + public int getMapXForPoint(double longitude){ + double tileX = MapUtils.getTileNumberX(zoom, longitude); + return (int) ((tileX - getXTile()) * getTileSize() + getCenterPointX()); + } + public int getMapYForPoint(double latitude){ + double tileY = MapUtils.getTileNumberY(zoom, latitude); + return (int) ((tileY - getYTile()) * getTileSize() + getCenterPointY()); + } + + public int getRotatedMapXForPoint(double latitude, double longitude){ + int cx = getCenterPointX(); + double xTile = MapUtils.getTileNumberX(zoom, longitude); + double yTile = MapUtils.getTileNumberY(zoom, latitude); + return (int) (calcDiffPixelX((float) (xTile - getXTile()), (float) (yTile - getYTile())) + cx); + } + public int getRotatedMapYForPoint(double latitude, double longitude){ + int cy = getCenterPointY(); + double xTile = MapUtils.getTileNumberX(zoom, longitude); + double yTile = MapUtils.getTileNumberY(zoom, latitude); + return (int) (calcDiffPixelY((float) (xTile - getXTile()), (float) (yTile - getYTile())) + cy); + } + + + public boolean isPointOnTheRotatedMap(double latitude, double longitude){ + int cx = getCenterPointX(); + int cy = getCenterPointY(); + double xTile = MapUtils.getTileNumberX(zoom, longitude); + double yTile = MapUtils.getTileNumberY(zoom, latitude); + int newX = (int) (calcDiffPixelX((float) (xTile - getXTile()), (float) (yTile - getYTile())) + cx); + int newY = (int) (calcDiffPixelY((float) (xTile - getXTile()), (float) (yTile - getYTile())) + cy); if(newX >= 0 && newX <= getWidth() && newY >=0 && newY <= getHeight()){ return true; } @@ -402,7 +475,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall this.latitude = MapUtils.getLatitudeFromTile(zoom, getYTile() + fy); this.longitude = MapUtils.getLongitudeFromTile(zoom, getXTile() + fx); - prepareImage(); + refreshMap(); if(locationListener != null){ locationListener.locationChanged(latitude, longitude, this); } diff --git a/OsmAnd/src/com/osmand/views/POIMapLayer.java b/OsmAnd/src/com/osmand/views/POIMapLayer.java index bc641724d6..3139736005 100644 --- a/OsmAnd/src/com/osmand/views/POIMapLayer.java +++ b/OsmAnd/src/com/osmand/views/POIMapLayer.java @@ -6,6 +6,8 @@ import java.util.List; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; import android.view.MotionEvent; import android.widget.Toast; @@ -24,29 +26,27 @@ public class POIMapLayer implements OsmandMapLayer { - // TODO optimize all evaluations @Override public boolean onTouchEvent(MotionEvent event) { - if(event.getAction() == MotionEvent.ACTION_DOWN && objects != null) { - double tileNumberX = MapUtils.getTileNumberX(view.getZoom(), view.getLongitude()); - double tileNumberY = MapUtils.getTileNumberY(view.getZoom(), view.getLatitude()); - double xTileLeft = tileNumberX - view.getWidth() / (2d * getTileSize()); - double yTileUp = tileNumberY - view.getHeight() / (2d * getTileSize()); + if (event.getAction() == MotionEvent.ACTION_DOWN && objects != null) { int ex = (int) event.getX(); int ey = (int) event.getY(); int radius = getRadiusPoi(view.getZoom()) * 3 / 2; - for(Amenity n : objects){ - double tileX = MapUtils.getTileNumberX(view.getZoom(), n.getLocation().getLongitude()); - int x = (int) ((tileX - xTileLeft) * getTileSize()); - double tileY = MapUtils.getTileNumberY(view.getZoom(), n.getLocation().getLatitude()); - int y = (int) ((tileY - yTileUp) * getTileSize()); - if(Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius){ - Toast.makeText(view.getContext(), n.getSimpleFormat(), Toast.LENGTH_SHORT).show(); - return true; + try { + for (int i = 0; i < objects.size(); i++) { + Amenity n = objects.get(i); + int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); + int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); + if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { + Toast.makeText(view.getContext(), n.getSimpleFormat(), Toast.LENGTH_SHORT).show(); + return true; + } } + } catch (IndexOutOfBoundsException e) { + // that's really rare case, but is much efficient than introduce synchronized block } - } -// return super.onTouchEvent(event); + } + // return super.onTouchEvent(event); return false; } @@ -64,6 +64,7 @@ public class POIMapLayer implements OsmandMapLayer { pointAltUI.setAlpha(150); pointAltUI.setAntiAlias(true); resourceManager = ResourceManager.getResourceManager(); + pixRect.set(0, 0, view.getWidth(), view.getHeight()); } public int getRadiusPoi(int zoom){ @@ -74,27 +75,25 @@ public class POIMapLayer implements OsmandMapLayer { } } + Rect pixRect = new Rect(); + RectF tileRect = new RectF(); + @Override public void onDraw(Canvas canvas) { if (view.getZoom() >= 15) { - double tileNumberX = MapUtils.getTileNumberX(view.getZoom(), view.getLongitude()); - double tileNumberY = MapUtils.getTileNumberY(view.getZoom(), view.getLatitude()); - double xTileLeft = tileNumberX - view.getWidth() / (2d * getTileSize()); - double xTileRight = tileNumberX + view.getWidth() / (2d * getTileSize()); - double yTileUp = tileNumberY - view.getHeight() / (2d * getTileSize()); - double yTileDown = tileNumberY + view.getHeight() / (2d * getTileSize()); - double topLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), yTileUp); - double leftLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), xTileLeft); - double bottomLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), yTileDown); - double rightLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), xTileRight); + pixRect.set(0, 0, view.getWidth(), view.getHeight()); + view.calculateTileRectangle(pixRect, view.getCenterPointX(), + view.getCenterPointY(), view.getXTile(), view.getYTile(), tileRect); + double topLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.top); + double leftLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.left); + double bottomLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.bottom); + double rightLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.right); objects.clear(); resourceManager.searchAmenitiesAsync(topLatitude, leftLongitude, bottomLatitude, rightLongitude, objects); for (Amenity o : objects) { - double tileX = MapUtils.getTileNumberX(view.getZoom(), o.getLocation().getLongitude()); - int x = (int) ((tileX - xTileLeft) * getTileSize()); - double tileY = MapUtils.getTileNumberY(view.getZoom(), o.getLocation().getLatitude()); - int y = (int) ((tileY - yTileUp) * getTileSize()); + int x = view.getMapXForPoint(o.getLocation().getLongitude()); + int y = view.getMapYForPoint(o.getLocation().getLatitude()); canvas.drawCircle(x, y, getRadiusPoi(view.getZoom()), pointAltUI); } diff --git a/OsmAnd/src/com/osmand/views/PointLocationLayer.java b/OsmAnd/src/com/osmand/views/PointLocationLayer.java index edcd5d7601..f564572819 100644 --- a/OsmAnd/src/com/osmand/views/PointLocationLayer.java +++ b/OsmAnd/src/com/osmand/views/PointLocationLayer.java @@ -71,14 +71,11 @@ public class PointLocationLayer implements OsmandMapLayer { return new RectF(locationX - rad, locationY - rad, locationX + rad, locationY + rad); } - // TODO simplify calculation if possible @Override public void onDraw(Canvas canvas) { if (isLocationVisible(lastKnownLocation)) { - int locationX = MapUtils.getPixelShiftX(view.getZoom(), lastKnownLocation.getLongitude(), view.getLongitude(), - view.getTileSize()) + view.getWidth() / 2; - int locationY = MapUtils.getPixelShiftY(view.getZoom(), - lastKnownLocation.getLatitude(), view.getLatitude(), view.getTileSize()) + view.getHeight() / 2; + int locationX = view.getMapXForPoint(lastKnownLocation.getLongitude()); + int locationY = view.getMapYForPoint(lastKnownLocation.getLatitude()); int radius = MapUtils.getLengthXFromMeters(view.getZoom(), view.getLatitude(), view.getLongitude(), lastKnownLocation .getAccuracy(), view.getTileSize(), view.getWidth()); @@ -124,7 +121,7 @@ public class PointLocationLayer implements OsmandMapLayer { if(l == null || view == null){ return false; } - return view.isPointOnTheMap(l.getLatitude(), l.getLongitude()); + return view.isPointOnTheRotatedMap(l.getLatitude(), l.getLongitude()); } @@ -135,7 +132,7 @@ public class PointLocationLayer implements OsmandMapLayer { public void setHeading(Float heading, boolean doNotRedraw){ this.heading = heading; if(!doNotRedraw && isLocationVisible(this.lastKnownLocation)){ - view.prepareImage(); + view.refreshMap(); } } @@ -148,7 +145,7 @@ public class PointLocationLayer implements OsmandMapLayer { if (!doNotRedraw) { boolean redraw = isLocationVisible(this.lastKnownLocation) || isLocationVisible(lastKnownLocation); if (redraw) { - view.prepareImage(); + view.refreshMap(); } } } diff --git a/OsmAnd/src/com/osmand/views/PointNavigationLayer.java b/OsmAnd/src/com/osmand/views/PointNavigationLayer.java index 0f99e87a3a..2e29017f33 100644 --- a/OsmAnd/src/com/osmand/views/PointNavigationLayer.java +++ b/OsmAnd/src/com/osmand/views/PointNavigationLayer.java @@ -10,7 +10,6 @@ import android.location.Location; import android.view.MotionEvent; import com.osmand.osm.LatLon; -import com.osmand.osm.MapUtils; public class PointNavigationLayer implements OsmandMapLayer { protected final static int RADIUS = 10; @@ -52,10 +51,8 @@ public class PointNavigationLayer implements OsmandMapLayer { return; } if (isLocationVisible()) { - int locationX = MapUtils.getPixelShiftX(view.getZoom(), pointToNavigate.getLongitude(), view.getLongitude(), - view.getTileSize()) + view.getWidth() / 2; - int locationY = MapUtils.getPixelShiftY(view.getZoom(), - pointToNavigate.getLatitude(), view.getLatitude(), view.getTileSize()) + view.getHeight() / 2; + int locationX = view.getMapXForPoint(pointToNavigate.getLongitude()); + int locationY = view.getMapYForPoint(pointToNavigate.getLatitude()); canvas.drawCircle(locationX, locationY, RADIUS, point); } else { @@ -72,8 +69,8 @@ public class PointNavigationLayer implements OsmandMapLayer { m.reset(); m.postScale(RADIUS * 2, RADIUS * 2); m.postTranslate(0, -radiusBearing); - m.postTranslate(view.getWidth() / 2, view.getHeight() / 2); - m.postRotate(bearing, view.getWidth() / 2, view.getHeight() / 2); + m.postTranslate(view.getCenterPointX(), view.getCenterPointY()); + m.postRotate(bearing, view.getCenterPointX(), view.getCenterPointY()); pathForDirection.transform(m); canvas.drawPath(pathForDirection, point); } @@ -83,7 +80,7 @@ public class PointNavigationLayer implements OsmandMapLayer { if(pointToNavigate == null || view == null){ return false; } - return view.isPointOnTheMap(pointToNavigate.getLatitude(), pointToNavigate.getLongitude()); + return view.isPointOnTheRotatedMap(pointToNavigate.getLatitude(), pointToNavigate.getLongitude()); } @@ -93,7 +90,7 @@ public class PointNavigationLayer implements OsmandMapLayer { public void setPointToNavigate(LatLon pointToNavigate) { this.pointToNavigate = pointToNavigate; - view.prepareImage(); + view.refreshMap(); } @Override