Implement positioning on the bottom (fixing bugs)

git-svn-id: https://osmand.googlecode.com/svn/trunk@94 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-05-29 08:04:41 +00:00
parent 2ec7068197
commit 4de363414d
11 changed files with 221 additions and 122 deletions

View file

@ -21,16 +21,12 @@ public class ToDoConstants {
// 24. Implement ResourceManager, load cities/streets/buildings on Low memory (clear previous all addresses cities). // 24. Implement ResourceManager, load cities/streets/buildings on Low memory (clear previous all addresses cities).
// 5. Search for city/streets/buildings // 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 // 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) // 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). // 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) // 8. Enable change POI directly on map (requires OSM login)
// 16. Support open street bugs api. // 16. Support open street bugs api.
// 20. Implement save track/route to gpx (?) // 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. // (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 (!). // 7. Implement search amenities by type (!).
// Rewrite search activity in order to limit amenities not to all types. // 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: // TODO SWING:
// 1. Download tiles without using dir tiles // 1. Download tiles without using dir tiles
@ -55,10 +53,14 @@ public class ToDoConstants {
// 7. Implement saving bundle of tiles in different folder // 7. Implement saving bundle of tiles in different folder
// DONE ANDROID : // DONE ANDROID :
// 18. Implement go to point // 23. Implement moving point from center to bottom (for rotating map)
// 2. Showing compass on the map : use device compass if exists(?) // 17. Enable go to location by specifying coordinates
// 9. Configure file log & see log from file (when exception happened to see from device) // 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 // DONE SWING

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="position_on_map_descr">Choose postion on the map</string>
<string name="position_on_map">Position on the map</string>
<string name="map_specify_point">Specify point</string> <string name="map_specify_point">Specify point</string>
<string name="show_view_angle_descr">Show aspect of vew based on compass</string> <string name="show_view_angle_descr">Show aspect of vew based on compass</string>
<string name="show_view_angle">Show aspect of view</string> <string name="show_view_angle">Show aspect of view</string>

View file

@ -7,6 +7,8 @@
<CheckBoxPreference android:key="show_poi_over_map" android:title="@string/show_poi_over_map" android:summary="@string/show_poi_over_map_description"></CheckBoxPreference> <CheckBoxPreference android:key="show_poi_over_map" android:title="@string/show_poi_over_map" android:summary="@string/show_poi_over_map_description"></CheckBoxPreference>
<CheckBoxPreference android:key="rotate_map_to_bearing" android:title="@string/rotate_map_to_bearing" android:summary="@string/rotate_map_to_bearing_descr"></CheckBoxPreference> <CheckBoxPreference android:key="rotate_map_to_bearing" android:title="@string/rotate_map_to_bearing" android:summary="@string/rotate_map_to_bearing_descr"></CheckBoxPreference>
<CheckBoxPreference android:key="show_view_angle" android:title="@string/show_view_angle" android:summary="@string/show_view_angle_descr"></CheckBoxPreference> <CheckBoxPreference android:key="show_view_angle" android:title="@string/show_view_angle" android:summary="@string/show_view_angle_descr"></CheckBoxPreference>
<ListPreference android:key="position_on_map" android:title="@string/position_on_map" android:summary="@string/position_on_map_descr"></ListPreference>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/map_source"><ListPreference android:title="@string/map_tile_source" android:summary="@string/map_tile_source_descr" android:key="map_tile_sources"></ListPreference> <PreferenceCategory android:title="@string/map_source"><ListPreference android:title="@string/map_tile_source" android:summary="@string/map_tile_source_descr" android:key="map_tile_sources"></ListPreference>
</PreferenceCategory> </PreferenceCategory>

View file

@ -82,7 +82,7 @@ public class AmenityIndexRepository {
cBottomLatitude = bottomLatitude - (topLatitude -bottomLatitude); cBottomLatitude = bottomLatitude - (topLatitude -bottomLatitude);
cLeftLongitude = leftLongitude - (rightLongitude - leftLongitude); cLeftLongitude = leftLongitude - (rightLongitude - leftLongitude);
cRightLongitude = rightLongitude + (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); checkCachedAmenities(topLatitude, leftLongitude, bottomLatitude, rightLongitude, toFill);
} }

View file

@ -16,35 +16,45 @@ public class OsmandSettings {
// These settings are stored in SharedPreferences // These settings are stored in SharedPreferences
public static final String SHARED_PREFERENCES_NAME = "com.osmand.settings"; public static final String SHARED_PREFERENCES_NAME = "com.osmand.settings";
// this value string is synchronized with android.xml preference name public static final int CENTER_CONSTANT = 0;
public static final int BOTTOM_CONSTANT = 1;
// 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 final String USE_INTERNET_TO_DOWNLOAD_TILES = "use_internet_to_download_tiles";
public static boolean isUsingInternetToDownloadTiles(Context ctx){ public static boolean isUsingInternetToDownloadTiles(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getBoolean(USE_INTERNET_TO_DOWNLOAD_TILES, true); 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 final String SHOW_POI_OVER_MAP = "show_poi_over_map";
public static boolean isShowingPoiOverMap(Context ctx){ public static boolean isShowingPoiOverMap(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getBoolean(SHOW_POI_OVER_MAP, false); 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 final String SHOW_VIEW_ANGLE = "show_view_angle";
public static boolean isShowingViewAngle(Context ctx){ public static boolean isShowingViewAngle(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getBoolean(SHOW_VIEW_ANGLE, true); 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 final String ROTATE_MAP_TO_BEARING = "rotate_map_to_bearing";
public static boolean isRotateMapToBearing(Context ctx){ public static boolean isRotateMapToBearing(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getBoolean(ROTATE_MAP_TO_BEARING, false); 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 final String MAP_VIEW_3D = "map_view_3d";
public static boolean isMapView3D(Context ctx){ public static boolean isMapView3D(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); 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 final String MAP_TILE_SOURCES = "map_tile_sources";
public static ITileSource getMapTileSource(Context ctx){ public static ITileSource getMapTileSource(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);

View file

@ -162,6 +162,10 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
} }
public void setLocation(Location location){ public void setLocation(Location location){
if(location != null){
location.setSpeed(30);
location.setBearing(90);
}
// Do very strange manipulation to call redraw only once // Do very strange manipulation to call redraw only once
// show point view only if gps enabled // 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()); mapView.setLatLon(location.getLatitude(), location.getLongitude());
} }
} else { } else {
mapView.prepareImage(); mapView.refreshMap();
if(backToLocation.getVisibility() != View.VISIBLE){ if(backToLocation.getVisibility() != View.VISIBLE){
backToLocation.setVisibility(View.VISIBLE); backToLocation.setVisibility(View.VISIBLE);
} }
@ -265,6 +269,8 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
if(!OsmandSettings.isRotateMapToBearing(this)){ if(!OsmandSettings.isRotateMapToBearing(this)){
mapView.setRotate(0); mapView.setRotate(0);
} }
mapView.setMapPosition(OsmandSettings.getPositionOnMap(this));
if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(this)){ if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(this)){
if(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(){ Message m = Message.obtain(sensorHandler, new Runnable(){
@Override @Override
public void run() { public void run() {
mapView.prepareImage(); mapView.refreshMap();
} }
}); });
m.what = 1; m.what = 1;

View file

@ -25,6 +25,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private ListPreference tileSourcePreference; private ListPreference tileSourcePreference;
private CheckBoxPreference rotateMapToBearing; private CheckBoxPreference rotateMapToBearing;
private CheckBoxPreference showViewAngle; private CheckBoxPreference showViewAngle;
private ListPreference positionOnMap;
@Override @Override
public void onCreate(Bundle savedInstanceState) { 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 =(CheckBoxPreference) screen.findPreference(OsmandSettings.SHOW_VIEW_ANGLE);
showViewAngle.setOnPreferenceChangeListener(this); showViewAngle.setOnPreferenceChangeListener(this);
positionOnMap =(ListPreference) screen.findPreference(OsmandSettings.POSITION_ON_MAP);
positionOnMap.setOnPreferenceChangeListener(this);
tileSourcePreference =(ListPreference) screen.findPreference(OsmandSettings.MAP_TILE_SOURCES); tileSourcePreference =(ListPreference) screen.findPreference(OsmandSettings.MAP_TILE_SOURCES);
tileSourcePreference.setOnPreferenceChangeListener(this); tileSourcePreference.setOnPreferenceChangeListener(this);
@ -53,6 +56,11 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
showPoiOnMap.setChecked(OsmandSettings.isShowingPoiOverMap(this)); showPoiOnMap.setChecked(OsmandSettings.isShowingPoiOverMap(this));
rotateMapToBearing.setChecked(OsmandSettings.isRotateMapToBearing(this)); rotateMapToBearing.setChecked(OsmandSettings.isRotateMapToBearing(this));
showViewAngle.setChecked(OsmandSettings.isShowingViewAngle(this)); showViewAngle.setChecked(OsmandSettings.isShowingViewAngle(this));
String[] e = new String[] { "Center", "Bottom" };
positionOnMap.setEntryValues(e);
positionOnMap.setEntries(e);
positionOnMap.setValueIndex(OsmandSettings.getPositionOnMap(this));
List<TileSourceTemplate> list = TileSourceManager.getKnownSourceTemplates(); List<TileSourceTemplate> list = TileSourceManager.getKnownSourceTemplates();
String[] entries = new String[list.size()]; String[] entries = new String[list.size()];
@ -84,6 +92,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
} else if(preference == showViewAngle){ } else if(preference == showViewAngle){
edit.putBoolean(OsmandSettings.SHOW_VIEW_ANGLE, (Boolean) newValue); edit.putBoolean(OsmandSettings.SHOW_VIEW_ANGLE, (Boolean) newValue);
edit.commit(); edit.commit();
} else if(preference == positionOnMap){
edit.putInt(OsmandSettings.POSITION_ON_MAP, positionOnMap.findIndexOfValue((String) newValue));
edit.commit();
} else if (preference == tileSourcePreference) { } else if (preference == tileSourcePreference) {
edit.putString(OsmandSettings.MAP_TILE_SOURCES, (String) newValue); edit.putString(OsmandSettings.MAP_TILE_SOURCES, (String) newValue);
edit.commit(); edit.commit();

View file

@ -52,6 +52,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
private float rotate = 0; private float rotate = 0;
private int mapPosition;
// name of source map // name of source map
private ITileSource map = null; private ITileSource map = null;
@ -74,6 +76,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public OsmandMapTileView(Context context, AttributeSet attrs) { public OsmandMapTileView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
initView(); initView();
@ -118,12 +121,12 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
@Override @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
prepareImage(); refreshMap();
} }
@Override @Override
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
prepareImage(); refreshMap();
} }
@Override @Override
@ -165,7 +168,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
if (map == null || (map.getMaximumZoomSupported() >= zoom && map.getMinimumZoomSupported() <= zoom)) { if (map == null || (map.getMaximumZoomSupported() >= zoom && map.getMinimumZoomSupported() <= zoom)) {
animatedDraggingThread.stopDragging(); animatedDraggingThread.stopDragging();
this.zoom = zoom; this.zoom = zoom;
prepareImage(); refreshMap();
} }
} }
@ -174,7 +177,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
if (dif > 2 || dif < -2) { if (dif > 2 || dif < -2) {
this.rotate = rotate; this.rotate = rotate;
animatedDraggingThread.stopDragging(); animatedDraggingThread.stopDragging();
prepareImage(); refreshMap();
} }
} }
@ -183,7 +186,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
this.rotate = rotate; this.rotate = rotate;
this.latitude = latitude; this.latitude = latitude;
this.longitude = longitude; this.longitude = longitude;
prepareImage(); refreshMap();
} }
public float getRotate() { public float getRotate() {
@ -202,14 +205,14 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
if(map.getMinimumZoomSupported() > this.zoom){ if(map.getMinimumZoomSupported() > this.zoom){
zoom = map.getMinimumZoomSupported(); zoom = map.getMinimumZoomSupported();
} }
prepareImage(); refreshMap();
} }
public void setLatLon(double latitude, double longitude){ public void setLatLon(double latitude, double longitude){
animatedDraggingThread.stopDragging(); animatedDraggingThread.stopDragging();
this.latitude = latitude; this.latitude = latitude;
this.longitude = longitude; this.longitude = longitude;
prepareImage(); refreshMap();
} }
public double getLatitude() { public double getLatitude() {
@ -238,13 +241,12 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
//////////////////////////////// DRAWING MAP PART ///////////////////////////////////////////// //////////////////////////////// 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; int tileDiv = getTileSize() / emptyTileDivisor;
for (int k1 = 0; k1 < emptyTileDivisor; k1++) { for (int k1 = 0; k1 < emptyTileDivisor; k1++) {
for (int k2 = 0; k2 < emptyTileDivisor; k2++) { for (int k2 = 0; k2 < emptyTileDivisor; k2++) {
int xk = x + tileDiv* k1; float xk = x + tileDiv* k1;
int yk = y + tileDiv* k2; float yk = y + tileDiv* k2;
if ((k1 + k2) % 2 == 0) { if ((k1 + k2) % 2 == 0) {
cvs.drawRect(xk, yk, xk + tileDiv, yk + tileDiv, paintGrayFill); cvs.drawRect(xk, yk, xk + tileDiv, yk + tileDiv, paintGrayFill);
} else { } 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){ private void drawOverMap(Canvas canvas){
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 3, paintBlack); canvas.drawCircle(getCenterPointX(), getCenterPointY(), 3, paintBlack);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 6, paintBlack); canvas.drawCircle(getCenterPointX(), getCenterPointY(), 6, paintBlack);
for(OsmandMapLayer layer : layers){ for(OsmandMapLayer layer : layers){
layer.onDraw(canvas); 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 x1 = calcDiffTileX(pixRect.left - cx, pixRect.top - cy);
float x2 = calcDiffTileX(pixRect.left - cx, pixRect.bottom - cy); float x2 = calcDiffTileX(pixRect.left - cx, pixRect.bottom - cy);
float x3 = calcDiffTileX(pixRect.right - cx, pixRect.top - 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 y2 = calcDiffTileY(pixRect.left - cx, pixRect.bottom - cy);
float y3 = calcDiffTileY(pixRect.right - cx, pixRect.top - cy); float y3 = calcDiffTileY(pixRect.right - cx, pixRect.top - cy);
float y4 = calcDiffTileY(pixRect.right - cx, pixRect.bottom - cy); float y4 = calcDiffTileY(pixRect.right - cx, pixRect.bottom - cy);
float l = Math.min(Math.min(x1, x2), Math.min(x3, x4)) + getXTile(); 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)) + getXTile(); 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)) + getYTile(); 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)) + getYTile(); float b = Math.max(Math.max(y1, y2), Math.max(y3, y4)) + ctiley;
tileRect.set(l, t, r, b); 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 // used only to save space & reuse
protected RectF tilesRect = new RectF(); 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())) { if (OsmandSettings.isUsingInternetToDownloadTiles(getContext())) {
MapTileDownloader.getInstance().refuseAllPreviousRequests(); MapTileDownloader.getInstance().refuseAllPreviousRequests();
} }
int tileSize = getTileSize(); int tileSize = getTileSize();
float tileX = getXTile(); float tileX = getXTile();
float tileY = getYTile(); float tileY = getYTile();
float w = getCenterPointX();
float h = getCenterPointY();
SurfaceHolder holder = getHolder(); SurfaceHolder holder = getHolder();
synchronized (holder) { synchronized (holder) {
@ -297,11 +332,10 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
if (canvas != null) { if (canvas != null) {
ResourceManager mgr = ResourceManager.getResourceManager(); ResourceManager mgr = ResourceManager.getResourceManager();
boolean useInternet = OsmandSettings.isUsingInternetToDownloadTiles(getContext()); boolean useInternet = OsmandSettings.isUsingInternetToDownloadTiles(getContext());
float w = getWidth() / 2;
float h = getHeight() / 2;
canvas.rotate(rotate, w , h); canvas.rotate(rotate, w , h);
boundsRect.set(0, 0, getWidth(), getHeight()); boundsRect.set(0, 0, getWidth(), getHeight());
calculateTileRectangle(boundsRect, w, h, tilesRect); calculateTileRectangle(boundsRect, w, h, tileX, tileY, tilesRect);
try { try {
int left = (int) FloatMath.floor(tilesRect.left); int left = (int) FloatMath.floor(tilesRect.left);
int top = (int) FloatMath.floor(tilesRect.top); int top = (int) FloatMath.floor(tilesRect.top);
@ -329,37 +363,42 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public void tileDownloaded(DownloadRequest request) { public void tileDownloaded(DownloadRequest request) {
// TODO estimate bounds for rotated map if (request == null) {
if(request == null || rotate != 0){
// we don't know exact images were changed // we don't know exact images were changed
prepareImage(); refreshMap();
return; return;
} }
int xTileLeft = (int) Math.floor(getXTile() - getWidth() / (2d * getTileSize())); if (request.zoom != this.zoom) {
int yTileUp = (int) Math.floor(getYTile() - getHeight() / (2d * getTileSize())); return;
int startingX = (int) ((xTileLeft - getXTile()) * getTileSize() + getWidth() / 2); }
int startingY = (int) ((yTileUp - getYTile()) * getTileSize() + getHeight() / 2); float w = getCenterPointX();
int i = (request.xTile - xTileLeft) * getTileSize() + startingX; float h = getCenterPointY();
int j = (request.yTile - yTileUp) * getTileSize() + startingY; float tileX = getXTile();
if (request.zoom == this.zoom && float tileY = getYTile();
(i + getTileSize() >= 0 && i < getWidth()) && (j + getTileSize() >= 0 && j < getHeight())) {
SurfaceHolder holder = getHolder(); SurfaceHolder holder = getHolder();
synchronized (holder) { synchronized (holder) {
Canvas canvas = holder.lockCanvas(new Rect(i, j, getTileSize() + i, getTileSize() + j)); tilesRect.set(request.xTile, request.yTile, request.xTile + 1, request.yTile + 1);
if (canvas != null) { calculatePixelRectangle(boundsRect, w, h, tileX, tileY, tilesRect);
canvas.rotate(rotate,getWidth()/2, getHeight()/2); if(boundsRect.left > getWidth() || boundsRect.right < 0 || boundsRect.bottom < 0 || boundsRect.top > getHeight()){
try { return;
ResourceManager mgr = ResourceManager.getResourceManager(); }
Bitmap bmp = mgr.getTileImageForMapSync(map, request.xTile, request.yTile, zoom, false); Canvas canvas = holder.lockCanvas(boundsRect);
if (bmp == null) { if (canvas != null) {
drawEmptyTile(canvas, i, j); canvas.rotate(rotate, w , h);
} else { try {
canvas.drawBitmap(bmp, i, j, null); ResourceManager mgr = ResourceManager.getResourceManager();
} Bitmap bmp = mgr.getTileImageForMapSync(map, request.xTile, request.yTile, zoom, false);
drawOverMap(canvas); float x = (request.xTile - getXTile()) * getTileSize() + w;
} finally { float y = (request.yTile - getYTile()) * getTileSize() + h;
holder.unlockCanvasAndPost(canvas); 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(); return (FloatMath.cos(rad) * dx + FloatMath.sin(rad) * dy) / getTileSize();
} }
public float calcDiffPixelY(float dTileX, float dTileY){
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());
float rad = (float) Math.toRadians(rotate); float rad = (float) Math.toRadians(rotate);
int newX = (int) (dx * FloatMath.cos(rad) - dy * FloatMath.sin(rad) + cx); return (FloatMath.sin(rad) * dTileX + FloatMath.cos(rad) * dTileY) * getTileSize();
int newY = (int) (dx * FloatMath.sin(rad) + dy * FloatMath.cos(rad) + cy); }
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()){ if(newX >= 0 && newX <= getWidth() && newY >=0 && newY <= getHeight()){
return true; return true;
} }
@ -402,7 +475,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
this.latitude = MapUtils.getLatitudeFromTile(zoom, getYTile() + fy); this.latitude = MapUtils.getLatitudeFromTile(zoom, getYTile() + fy);
this.longitude = MapUtils.getLongitudeFromTile(zoom, getXTile() + fx); this.longitude = MapUtils.getLongitudeFromTile(zoom, getXTile() + fx);
prepareImage(); refreshMap();
if(locationListener != null){ if(locationListener != null){
locationListener.locationChanged(latitude, longitude, this); locationListener.locationChanged(latitude, longitude, this);
} }

View file

@ -6,6 +6,8 @@ import java.util.List;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.widget.Toast; import android.widget.Toast;
@ -24,29 +26,27 @@ public class POIMapLayer implements OsmandMapLayer {
// TODO optimize all evaluations
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN && objects != null) { 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());
int ex = (int) event.getX(); int ex = (int) event.getX();
int ey = (int) event.getY(); int ey = (int) event.getY();
int radius = getRadiusPoi(view.getZoom()) * 3 / 2; int radius = getRadiusPoi(view.getZoom()) * 3 / 2;
for(Amenity n : objects){ try {
double tileX = MapUtils.getTileNumberX(view.getZoom(), n.getLocation().getLongitude()); for (int i = 0; i < objects.size(); i++) {
int x = (int) ((tileX - xTileLeft) * getTileSize()); Amenity n = objects.get(i);
double tileY = MapUtils.getTileNumberY(view.getZoom(), n.getLocation().getLatitude()); int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
int y = (int) ((tileY - yTileUp) * getTileSize()); int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
if(Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius){ if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
Toast.makeText(view.getContext(), n.getSimpleFormat(), Toast.LENGTH_SHORT).show(); Toast.makeText(view.getContext(), n.getSimpleFormat(), Toast.LENGTH_SHORT).show();
return true; 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; return false;
} }
@ -64,6 +64,7 @@ public class POIMapLayer implements OsmandMapLayer {
pointAltUI.setAlpha(150); pointAltUI.setAlpha(150);
pointAltUI.setAntiAlias(true); pointAltUI.setAntiAlias(true);
resourceManager = ResourceManager.getResourceManager(); resourceManager = ResourceManager.getResourceManager();
pixRect.set(0, 0, view.getWidth(), view.getHeight());
} }
public int getRadiusPoi(int zoom){ public int getRadiusPoi(int zoom){
@ -74,27 +75,25 @@ public class POIMapLayer implements OsmandMapLayer {
} }
} }
Rect pixRect = new Rect();
RectF tileRect = new RectF();
@Override @Override
public void onDraw(Canvas canvas) { public void onDraw(Canvas canvas) {
if (view.getZoom() >= 15) { if (view.getZoom() >= 15) {
double tileNumberX = MapUtils.getTileNumberX(view.getZoom(), view.getLongitude()); pixRect.set(0, 0, view.getWidth(), view.getHeight());
double tileNumberY = MapUtils.getTileNumberY(view.getZoom(), view.getLatitude()); view.calculateTileRectangle(pixRect, view.getCenterPointX(),
double xTileLeft = tileNumberX - view.getWidth() / (2d * getTileSize()); view.getCenterPointY(), view.getXTile(), view.getYTile(), tileRect);
double xTileRight = tileNumberX + view.getWidth() / (2d * getTileSize()); double topLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.top);
double yTileUp = tileNumberY - view.getHeight() / (2d * getTileSize()); double leftLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.left);
double yTileDown = tileNumberY + view.getHeight() / (2d * getTileSize()); double bottomLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.bottom);
double topLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), yTileUp); double rightLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.right);
double leftLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), xTileLeft);
double bottomLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), yTileDown);
double rightLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), xTileRight);
objects.clear(); objects.clear();
resourceManager.searchAmenitiesAsync(topLatitude, leftLongitude, bottomLatitude, rightLongitude, objects); resourceManager.searchAmenitiesAsync(topLatitude, leftLongitude, bottomLatitude, rightLongitude, objects);
for (Amenity o : objects) { for (Amenity o : objects) {
double tileX = MapUtils.getTileNumberX(view.getZoom(), o.getLocation().getLongitude()); int x = view.getMapXForPoint(o.getLocation().getLongitude());
int x = (int) ((tileX - xTileLeft) * getTileSize()); int y = view.getMapYForPoint(o.getLocation().getLatitude());
double tileY = MapUtils.getTileNumberY(view.getZoom(), o.getLocation().getLatitude());
int y = (int) ((tileY - yTileUp) * getTileSize());
canvas.drawCircle(x, y, getRadiusPoi(view.getZoom()), pointAltUI); canvas.drawCircle(x, y, getRadiusPoi(view.getZoom()), pointAltUI);
} }

View file

@ -71,14 +71,11 @@ public class PointLocationLayer implements OsmandMapLayer {
return new RectF(locationX - rad, locationY - rad, locationX + rad, locationY + rad); return new RectF(locationX - rad, locationY - rad, locationX + rad, locationY + rad);
} }
// TODO simplify calculation if possible
@Override @Override
public void onDraw(Canvas canvas) { public void onDraw(Canvas canvas) {
if (isLocationVisible(lastKnownLocation)) { if (isLocationVisible(lastKnownLocation)) {
int locationX = MapUtils.getPixelShiftX(view.getZoom(), lastKnownLocation.getLongitude(), view.getLongitude(), int locationX = view.getMapXForPoint(lastKnownLocation.getLongitude());
view.getTileSize()) + view.getWidth() / 2; int locationY = view.getMapYForPoint(lastKnownLocation.getLatitude());
int locationY = MapUtils.getPixelShiftY(view.getZoom(),
lastKnownLocation.getLatitude(), view.getLatitude(), view.getTileSize()) + view.getHeight() / 2;
int radius = MapUtils.getLengthXFromMeters(view.getZoom(), view.getLatitude(), view.getLongitude(), lastKnownLocation int radius = MapUtils.getLengthXFromMeters(view.getZoom(), view.getLatitude(), view.getLongitude(), lastKnownLocation
.getAccuracy(), view.getTileSize(), view.getWidth()); .getAccuracy(), view.getTileSize(), view.getWidth());
@ -124,7 +121,7 @@ public class PointLocationLayer implements OsmandMapLayer {
if(l == null || view == null){ if(l == null || view == null){
return false; 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){ public void setHeading(Float heading, boolean doNotRedraw){
this.heading = heading; this.heading = heading;
if(!doNotRedraw && isLocationVisible(this.lastKnownLocation)){ if(!doNotRedraw && isLocationVisible(this.lastKnownLocation)){
view.prepareImage(); view.refreshMap();
} }
} }
@ -148,7 +145,7 @@ public class PointLocationLayer implements OsmandMapLayer {
if (!doNotRedraw) { if (!doNotRedraw) {
boolean redraw = isLocationVisible(this.lastKnownLocation) || isLocationVisible(lastKnownLocation); boolean redraw = isLocationVisible(this.lastKnownLocation) || isLocationVisible(lastKnownLocation);
if (redraw) { if (redraw) {
view.prepareImage(); view.refreshMap();
} }
} }
} }

View file

@ -10,7 +10,6 @@ import android.location.Location;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.osmand.osm.LatLon; import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils;
public class PointNavigationLayer implements OsmandMapLayer { public class PointNavigationLayer implements OsmandMapLayer {
protected final static int RADIUS = 10; protected final static int RADIUS = 10;
@ -52,10 +51,8 @@ public class PointNavigationLayer implements OsmandMapLayer {
return; return;
} }
if (isLocationVisible()) { if (isLocationVisible()) {
int locationX = MapUtils.getPixelShiftX(view.getZoom(), pointToNavigate.getLongitude(), view.getLongitude(), int locationX = view.getMapXForPoint(pointToNavigate.getLongitude());
view.getTileSize()) + view.getWidth() / 2; int locationY = view.getMapYForPoint(pointToNavigate.getLatitude());
int locationY = MapUtils.getPixelShiftY(view.getZoom(),
pointToNavigate.getLatitude(), view.getLatitude(), view.getTileSize()) + view.getHeight() / 2;
canvas.drawCircle(locationX, locationY, RADIUS, point); canvas.drawCircle(locationX, locationY, RADIUS, point);
} else { } else {
@ -72,8 +69,8 @@ public class PointNavigationLayer implements OsmandMapLayer {
m.reset(); m.reset();
m.postScale(RADIUS * 2, RADIUS * 2); m.postScale(RADIUS * 2, RADIUS * 2);
m.postTranslate(0, -radiusBearing); m.postTranslate(0, -radiusBearing);
m.postTranslate(view.getWidth() / 2, view.getHeight() / 2); m.postTranslate(view.getCenterPointX(), view.getCenterPointY());
m.postRotate(bearing, view.getWidth() / 2, view.getHeight() / 2); m.postRotate(bearing, view.getCenterPointX(), view.getCenterPointY());
pathForDirection.transform(m); pathForDirection.transform(m);
canvas.drawPath(pathForDirection, point); canvas.drawPath(pathForDirection, point);
} }
@ -83,7 +80,7 @@ public class PointNavigationLayer implements OsmandMapLayer {
if(pointToNavigate == null || view == null){ if(pointToNavigate == null || view == null){
return false; 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) { public void setPointToNavigate(LatLon pointToNavigate) {
this.pointToNavigate = pointToNavigate; this.pointToNavigate = pointToNavigate;
view.prepareImage(); view.refreshMap();
} }
@Override @Override