implement rotating map

git-svn-id: https://osmand.googlecode.com/svn/trunk@78 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-05-23 20:59:55 +00:00
parent 891a38e697
commit 56befb372c
11 changed files with 199 additions and 74 deletions

View file

@ -19,36 +19,51 @@ public class ToDoConstants {
*/ */
public int DESCRIBE_ABOUT_AUTHORS = 8; public int DESCRIBE_ABOUT_AUTHORS = 8;
// 0. Minimize memory used for index & improve time for read index // TODO ANDROID
//// TODO for releasing version // 0. Minimize memory used for index & improve time for reading index
// 1. POI SEARCH NEAR TO YOU // 1. POI search near to map location (show categories & type). First cut. (implement incremental search)
// 2. FIX BACK TO your location & gps & point of view (may be compass) // 3. Revise osmand UI. Preparing new icons.
// 3. Revise UI icons/layout // 2. Showing compass on the map : use device compass if exists(?)
// 5. Enable city/streets/buildings index // 5. Search for city/streets/buildings
// 7. Search for city/streets/buildings! // 9. Config file log & see log from file (when exception happened to see from device)
// 8. Enable change POI directly on map // 11. Print out additional info speed, altitude, number of satellites
// 9. Log to see when exception occurred (android) // 8. Enable change POI directly on map (requires OSM login)
// 10. Specify auto-rotating map (compass). // 13. Save point as favourite & introduce favourite points dialog
// 11. Print out additional info speed, altitude, number of satellites // 14. Show zoom level on map
// 12. Show point where are you going (the arrow not the point) // 15. Investigate interruption of any long running operation & implement where it is needed
// 13. Save point as favorite // 16. Support open street bugs api.
// 14. Show zoom level directly on map // 17. Enable go to location specifying coordinates
// 15. Investigate interruption of progress (is it available & how to support it) // 18. Implement go to point
// ------------------- // 19. Show how map is rotated where north/south on map (do not consider compass)
// 20. Implement save track/route to gpx (?)
// BUGS Androd : // FIXME Bugs Androd :
// 0. FIX TODO for partial loading rotated map
// 1. When firstly run osmand navigation (from notification bar) show map & go to menu shows desktop. // 1. When firstly run osmand navigation (from notification bar) show map & go to menu shows desktop.
// No chance to close application // No chance to close application
// 3. Fix progress information (loading indices) for android version
// 4. Fix when POI selected & enable button backToLocation
// TODO SWING:
// 1. download tiles without using dir tiles
// 2. Config file log & see log from file
// 3. Reinvent index mechanism (save in zip file with tile indexes, save city/town addresses separately, read partially !)
// 4. Invent different file extensions for poi.index, address.index,...
// Max letter :
// 1. Fix bug 1
// 2. Create for each screen activity
// 3. Implement incremental search (reduce first time display to 10 & depth 2)
// 4. Improve navigate back/forward between screens
// 5. Implement exit confirmation
/// SWING version : // DONE ANDROID :
// TODO : // 12. Show information of where are you going (the arrow on the map)
// 1. Accept amenity as way // 10. Specify auto-rotating map (bearing of your direction)
// 1. Fix TODO in files
// DONE SWING
// 3. download tiles without using dir tiles
// 4. Config file log & see log from file
// 5. Reinvent index mechanism (save in zip file with tile indexes, save city/town addresses separately, read partially !)
// 6. Invent different file extensions for poi.index, address.index,...
} }

View file

@ -88,7 +88,7 @@ public class DataTileManager<T> {
if(isEmpty()){ if(isEmpty()){
return Collections.emptyList(); return Collections.emptyList();
} }
int dp = 1; int dp = 0;
List<T> l = null; List<T> l = null;
while (l == null || l.isEmpty()) { while (l == null || l.isEmpty()) {
l = getClosestObjects(latitude, longitude, dp, dp + defaultStep); l = getClosestObjects(latitude, longitude, dp, dp + defaultStep);
@ -106,8 +106,10 @@ public class DataTileManager<T> {
int tileY = (int) MapUtils.getTileNumberY(zoom, latitude); int tileY = (int) MapUtils.getTileNumberY(zoom, latitude);
List<T> result = new ArrayList<T>(); List<T> result = new ArrayList<T>();
if(startDepth <= 0){
putObjects(tileX, tileY, result); putObjects(tileX, tileY, result);
startDepth = 1;
}
// that's very difficult way visiting node : // that's very difficult way visiting node :
// similar to visit by spiral // similar to visit by spiral

View file

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<ImageView android:id="@+id/icon" android:layout_width="20px" <ImageView android:id="@+id/icon" android:layout_width="25px"
android:paddingLeft="2px" android:paddingRight="2px" android:paddingLeft="2px" android:paddingRight="2px"
android:paddingTop="2px" android:layout_height="fill_parent"/> android:paddingTop="2px" android:layout_height="fill_parent"/>
<TextView android:id="@+id/label" android:layout_width="wrap_content" <TextView android:id="@+id/label" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:textSize="20px" /> android:layout_height="wrap_content" android:textSize="25px" />
</LinearLayout> </LinearLayout>

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="rotate_map_to_bearing_descr">Rotate map to bearing of your direction</string>
<string name="rotate_map_to_bearing">Rotate map</string>
<string name="show_poi_over_map_description">Show POI on map</string> <string name="show_poi_over_map_description">Show POI on map</string>
<string name="show_poi_over_map">Show POI</string> <string name="show_poi_over_map">Show POI</string>
<string name="map_tile_source_descr">Choose the source of tiles:</string> <string name="map_tile_source_descr">Choose the source of tiles:</string>

View file

@ -5,6 +5,7 @@
<CheckBoxPreference android:key="use_internet_to_download_tiles" android:title="@string/use_internet" android:summary="@string/use_internet_to_download_tile"></CheckBoxPreference> <CheckBoxPreference android:key="use_internet_to_download_tiles" android:title="@string/use_internet" android:summary="@string/use_internet_to_download_tile"></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="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>
</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

@ -30,6 +30,13 @@ public class OsmandSettings {
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
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 android.xml preference name
public static final String MAP_TILE_SOURCES = "map_tile_sources"; public static final String MAP_TILE_SOURCES = "map_tile_sources";

View file

@ -135,16 +135,22 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
} }
public void setLocation(Location location){ public void setLocation(Location location){
locationLayer.setLastKnownLocation(location); // Do very strange manipulation to call redraw only once
locationLayer.setLastKnownLocation(location, true);
if (location != null) { if (location != null) {
if (linkLocationWithMap) { if (linkLocationWithMap) {
mapView.setLatLon(location.getLatitude(), location.getLongitude()); if (location.hasBearing() && OsmandSettings.isRotateMapToBearing(this)) {
} mapView.setRotateWithLocation(-location.getBearing(), location.getLatitude(), location.getLongitude());
} else {
mapView.setLatLon(location.getLatitude(), location.getLongitude());
}
} else {
mapView.prepareImage();
}
} else { } else {
if(!linkLocationWithMap){ if (!linkLocationWithMap) {
backToLocation.setVisibility(View.VISIBLE); backToLocation.setVisibility(View.VISIBLE);
} }
} }
} }
@ -191,6 +197,9 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
if(mapView.getMap() != OsmandSettings.getMapTileSource(this)){ if(mapView.getMap() != OsmandSettings.getMapTileSource(this)){
mapView.setMap(OsmandSettings.getMapTileSource(this)); mapView.setMap(OsmandSettings.getMapTileSource(this));
} }
if(!OsmandSettings.isRotateMapToBearing(this)){
mapView.setRotate(0);
}
if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(this)){ if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(this)){
if(OsmandSettings.isShowingPoiOverMap(this)){ if(OsmandSettings.isShowingPoiOverMap(this)){
mapView.addLayer(poiMapLayer); mapView.addLayer(poiMapLayer);

View file

@ -112,6 +112,12 @@ public class SearchActivity extends ListActivity {
AmenityAdapter(Object list) { AmenityAdapter(Object list) {
super(SearchActivity.this, R.layout.searchlist, (List<?>) list); super(SearchActivity.this, R.layout.searchlist, (List<?>) list);
} }
@Override
public int getCount() {
int c = super.getCount();
return c > 20 ? 20 : c;
}
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater(); LayoutInflater inflater = getLayoutInflater();

View file

@ -23,6 +23,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private CheckBoxPreference showPoiOnMap; private CheckBoxPreference showPoiOnMap;
private CheckBoxPreference useInternetToDownloadTiles; private CheckBoxPreference useInternetToDownloadTiles;
private ListPreference tileSourcePreference; private ListPreference tileSourcePreference;
private CheckBoxPreference rotateMapToBearing;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -33,6 +34,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
useInternetToDownloadTiles.setOnPreferenceChangeListener(this); useInternetToDownloadTiles.setOnPreferenceChangeListener(this);
showPoiOnMap =(CheckBoxPreference) screen.findPreference(OsmandSettings.SHOW_POI_OVER_MAP); showPoiOnMap =(CheckBoxPreference) screen.findPreference(OsmandSettings.SHOW_POI_OVER_MAP);
showPoiOnMap.setOnPreferenceChangeListener(this); showPoiOnMap.setOnPreferenceChangeListener(this);
rotateMapToBearing =(CheckBoxPreference) screen.findPreference(OsmandSettings.ROTATE_MAP_TO_BEARING);
rotateMapToBearing.setOnPreferenceChangeListener(this);
tileSourcePreference =(ListPreference) screen.findPreference(OsmandSettings.MAP_TILE_SOURCES); tileSourcePreference =(ListPreference) screen.findPreference(OsmandSettings.MAP_TILE_SOURCES);
tileSourcePreference.setOnPreferenceChangeListener(this); tileSourcePreference.setOnPreferenceChangeListener(this);
@ -45,6 +48,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
super.onResume(); super.onResume();
useInternetToDownloadTiles.setChecked(OsmandSettings.isUsingInternetToDownloadTiles(this)); useInternetToDownloadTiles.setChecked(OsmandSettings.isUsingInternetToDownloadTiles(this));
showPoiOnMap.setChecked(OsmandSettings.isShowingPoiOverMap(this)); showPoiOnMap.setChecked(OsmandSettings.isShowingPoiOverMap(this));
rotateMapToBearing.setChecked(OsmandSettings.isRotateMapToBearing(this));
List<TileSourceTemplate> list = TileSourceManager.getKnownSourceTemplates(); List<TileSourceTemplate> list = TileSourceManager.getKnownSourceTemplates();
String[] entries = new String[list.size()]; String[] entries = new String[list.size()];
@ -70,6 +74,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
} else if(preference == useInternetToDownloadTiles){ } else if(preference == useInternetToDownloadTiles){
edit.putBoolean(OsmandSettings.USE_INTERNET_TO_DOWNLOAD_TILES, (Boolean) newValue); edit.putBoolean(OsmandSettings.USE_INTERNET_TO_DOWNLOAD_TILES, (Boolean) newValue);
edit.commit(); edit.commit();
} else if(preference == rotateMapToBearing){
edit.putBoolean(OsmandSettings.ROTATE_MAP_TO_BEARING, (Boolean) 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

@ -13,8 +13,10 @@ import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
@ -48,6 +50,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
private double latitude = 0d; private double latitude = 0d;
private float rotate = 0;
// name of source map // name of source map
private ITileSource map = null; private ITileSource map = null;
@ -65,6 +69,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
Paint paintGrayFill; Paint paintGrayFill;
Paint paintWhiteFill; Paint paintWhiteFill;
Paint paintBlack; Paint paintBlack;
Paint paintBitmap;
@ -84,14 +89,21 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
paintGrayFill = new Paint(); paintGrayFill = new Paint();
paintGrayFill.setColor(Color.GRAY); paintGrayFill.setColor(Color.GRAY);
paintGrayFill.setStyle(Style.FILL); paintGrayFill.setStyle(Style.FILL);
// when map rotate
paintGrayFill.setAntiAlias(true);
paintWhiteFill = new Paint(); paintWhiteFill = new Paint();
paintWhiteFill.setColor(Color.WHITE); paintWhiteFill.setColor(Color.WHITE);
paintWhiteFill.setStyle(Style.FILL); paintWhiteFill.setStyle(Style.FILL);
// when map rotate
paintWhiteFill.setAntiAlias(true);
paintBlack = new Paint(); paintBlack = new Paint();
paintBlack.setStyle(Style.STROKE); paintBlack.setStyle(Style.STROKE);
paintBlack.setColor(Color.BLACK); paintBlack.setColor(Color.BLACK);
paintBitmap = new Paint();
paintBitmap.setFilterBitmap(true);
setClickable(true); setClickable(true);
getHolder().addCallback(this); getHolder().addCallback(this);
@ -140,12 +152,12 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
public double getXTile(){ public float getXTile(){
return MapUtils.getTileNumberX(zoom, longitude); return (float) MapUtils.getTileNumberX(zoom, longitude);
} }
public double getYTile(){ public float getYTile(){
return MapUtils.getTileNumberY(zoom, latitude); return (float) MapUtils.getTileNumberY(zoom, latitude);
} }
@ -157,6 +169,27 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
} }
public void setRotate(float rotate) {
float dif = this.rotate - rotate;
if (dif > 2 || dif < -2) {
this.rotate = rotate;
animatedDraggingThread.stopDragging();
prepareImage();
}
}
public void setRotateWithLocation(float rotate, double latitude, double longitude){
animatedDraggingThread.stopDragging();
this.rotate = rotate;
this.latitude = latitude;
this.longitude = longitude;
prepareImage();
}
public float getRotate() {
return rotate;
}
public ITileSource getMap() { public ITileSource getMap() {
return map; return map;
} }
@ -230,33 +263,59 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
} }
} }
protected void calculateTileRectangle(RectF pixRect, float cx, float cy, 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);
float x4 = calcDiffTileX(pixRect.right - cx, pixRect.bottom - cy);
float y1 = calcDiffTileY(pixRect.left - cx, pixRect.top - cy);
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();
tileRect.set(l, t, r, b);
}
// used only to save space & reuse
protected RectF tilesRect = new RectF();
protected RectF boundsRect = new RectF();
public void prepareImage() { public void prepareImage() {
if (OsmandSettings.isUsingInternetToDownloadTiles(getContext())) { if (OsmandSettings.isUsingInternetToDownloadTiles(getContext())) {
MapTileDownloader.getInstance().refuseAllPreviousRequests(); MapTileDownloader.getInstance().refuseAllPreviousRequests();
} }
int width = getWidth();
int height = getHeight();
int tileSize = getTileSize(); int tileSize = getTileSize();
float tileX = getXTile();
int xTileLeft = (int) Math.floor(getXTile() - width / (2d * getTileSize())); float tileY = getYTile();
int yTileUp = (int) Math.floor(getYTile() - height / (2d * getTileSize()));
int startingX = (int) ((xTileLeft - getXTile()) * getTileSize() + getWidth() / 2);
int startingY = (int) ((yTileUp - getYTile()) * getTileSize() + getHeight() / 2);
SurfaceHolder holder = getHolder(); SurfaceHolder holder = getHolder();
synchronized (holder) { synchronized (holder) {
Canvas canvas = holder.lockCanvas(); Canvas canvas = holder.lockCanvas();
if (canvas != null) { if (canvas != null) {
// canvas.rotate(45); 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);
try { try {
for (int i = 0; i * tileSize + startingX < width; i++) { int left = (int) FloatMath.floor(tilesRect.left);
for (int j = 0; j * tileSize + startingY < height; j++) { int top = (int) FloatMath.floor(tilesRect.top);
ResourceManager mgr = ResourceManager.getResourceManager(); int width = (int) (FloatMath.ceil(tilesRect.right) - left);
Bitmap bmp = mgr.getTileImageForMapAsync(map, xTileLeft + i, yTileUp + j, zoom, OsmandSettings.isUsingInternetToDownloadTiles(getContext())); int height = (int) (FloatMath.ceil(tilesRect.bottom) - top);
for (int i = 0; i <width; i++) {
for (int j = 0; j< height; j++) {
float x1 = (i + left - tileX) * tileSize + w;
float y1 = (j + top - tileY) * tileSize + h;
Bitmap bmp = mgr.getTileImageForMapAsync(map, left + i, top + j, zoom, useInternet);
if (bmp == null) { if (bmp == null) {
drawEmptyTile(canvas, i * tileSize + startingX, j * tileSize + startingY); drawEmptyTile(canvas, (int) x1, (int) y1);
} else { } else {
canvas.drawBitmap(bmp, i * tileSize + startingX, j * tileSize + startingY, null); canvas.drawBitmap(bmp, x1, y1, paintBitmap);
} }
} }
} }
@ -270,7 +329,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public void tileDownloaded(DownloadRequest request) { public void tileDownloaded(DownloadRequest request) {
if(request == null){ // TODO estimate bounds for rotated map
if(request == null || rotate != 0){
// we don't know exact images were changed // we don't know exact images were changed
prepareImage(); prepareImage();
return; return;
@ -285,10 +345,9 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
(i + getTileSize() >= 0 && i < getWidth()) && (j + getTileSize() >= 0 && j < getHeight())) { (i + getTileSize() >= 0 && i < getWidth()) && (j + getTileSize() >= 0 && j < getHeight())) {
SurfaceHolder holder = getHolder(); SurfaceHolder holder = getHolder();
synchronized (holder) { synchronized (holder) {
// TODO
Canvas canvas = holder.lockCanvas(new Rect(i, j, getTileSize() + i, getTileSize() + j)); Canvas canvas = holder.lockCanvas(new Rect(i, j, getTileSize() + i, getTileSize() + j));
if (canvas != null) { if (canvas != null) {
// canvas.rotate(45); canvas.rotate(rotate,getWidth()/2, getHeight()/2);
try { try {
ResourceManager mgr = ResourceManager.getResourceManager(); ResourceManager mgr = ResourceManager.getResourceManager();
Bitmap bmp = mgr.getTileImageForMapSync(map, request.xTile, request.yTile, zoom, false); Bitmap bmp = mgr.getTileImageForMapSync(map, request.xTile, request.yTile, zoom, false);
@ -309,14 +368,26 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
/////////////////////////////////// DRAGGING PART /////////////////////////////////////// /////////////////////////////////// DRAGGING PART ///////////////////////////////////////
public float calcDiffTileY(float dx, float dy){
float rad = (float) Math.toRadians(rotate);
return (-FloatMath.sin(rad) * dx + FloatMath.cos(rad) * dy) / getTileSize();
}
public float calcDiffTileX(float dx, float dy){
float rad = (float) Math.toRadians(rotate);
return (FloatMath.cos(rad) * dx + FloatMath.sin(rad) * dy) / getTileSize();
}
@Override @Override
public void dragTo(float fromX, float fromY, float toX, float toY){ public void dragTo(float fromX, float fromY, float toX, float toY){
float dx = (fromX - toX)/getTileSize(); float dx = (fromX - toX) ;
float dy = (fromY - toY)/getTileSize(); float dy = (fromY - toY);
this.latitude = MapUtils.getLatitudeFromTile(zoom, getYTile() + dy); float fy = calcDiffTileY(dx, dy);
this.longitude = MapUtils.getLongitudeFromTile(zoom, getXTile() + dx); float fx = calcDiffTileX(dx, dy);
this.latitude = MapUtils.getLatitudeFromTile(zoom, getYTile() + fy);
this.longitude = MapUtils.getLongitudeFromTile(zoom, getXTile() + fx);
prepareImage(); prepareImage();
if(locationListener != null){ if(locationListener != null){
locationListener.locationChanged(latitude, longitude, this); locationListener.locationChanged(latitude, longitude, this);

View file

@ -7,6 +7,7 @@ import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.location.Location; import android.location.Location;
import android.util.FloatMath;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.osmand.osm.MapUtils; import com.osmand.osm.MapUtils;
@ -52,6 +53,7 @@ public class PointLocationLayer implements OsmandMapLayer {
} }
// TODO simplify calculation if possible
@Override @Override
public void onDraw(Canvas canvas) { public void onDraw(Canvas canvas) {
if (isLocationVisible(lastKnownLocation)) { if (isLocationVisible(lastKnownLocation)) {
@ -62,9 +64,7 @@ public class PointLocationLayer implements OsmandMapLayer {
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());
if (locationX >= 0 && locationY >= 0) { canvas.drawCircle(locationX, locationY, RADIUS, location);
canvas.drawCircle(locationX, locationY, RADIUS, location);
}
if (radius > RADIUS) { if (radius > RADIUS) {
canvas.drawCircle(locationX, locationY, radius, area); canvas.drawCircle(locationX, locationY, radius, area);
} }
@ -103,12 +103,15 @@ public class PointLocationLayer implements OsmandMapLayer {
if(l == null || view == null){ if(l == null || view == null){
return false; return false;
} }
int newX = MapUtils.getPixelShiftX(view.getZoom(), int cx = view.getWidth()/2;
l.getLongitude(), view.getLongitude(), view.getTileSize()) + int cy = view.getHeight()/2;
view.getWidth()/2; int dx = MapUtils.getPixelShiftX(view.getZoom(),
int newY = MapUtils.getPixelShiftY(view.getZoom(), l.getLongitude(), view.getLongitude(), view.getTileSize());
l.getLatitude(), view.getLatitude() , view.getTileSize()) + int dy = MapUtils.getPixelShiftY(view.getZoom(),
view.getHeight()/2; l.getLatitude(), view.getLatitude() , view.getTileSize());
float rad = (float) Math.toRadians(view.getRotate());
int newX = (int) (dx * FloatMath.cos(rad) - dy * FloatMath.sin(rad) + cx);
int newY = (int) (dx * FloatMath.sin(rad) + dy * FloatMath.cos(rad) + cy);
int radius = MapUtils.getLengthXFromMeters(view.getZoom(), view.getLatitude(), view.getLongitude(), int radius = MapUtils.getLengthXFromMeters(view.getZoom(), view.getLatitude(), view.getLongitude(),
l.getAccuracy(), view.getTileSize(), view.getWidth()); l.getAccuracy(), view.getTileSize(), view.getWidth());
if(newX >= 0 && newX <= view.getWidth() && newY >=0 && newY <= view.getHeight()){ if(newX >= 0 && newX <= view.getWidth() && newY >=0 && newY <= view.getHeight()){
@ -127,11 +130,13 @@ public class PointLocationLayer implements OsmandMapLayer {
return lastKnownLocation; return lastKnownLocation;
} }
public void setLastKnownLocation(Location lastKnownLocation) { public void setLastKnownLocation(Location lastKnownLocation, boolean doNotRedraw) {
boolean redraw = isLocationVisible(this.lastKnownLocation) || isLocationVisible(lastKnownLocation);
this.lastKnownLocation = lastKnownLocation; this.lastKnownLocation = lastKnownLocation;
if(redraw){ if (!doNotRedraw) {
view.prepareImage(); boolean redraw = isLocationVisible(this.lastKnownLocation) || isLocationVisible(lastKnownLocation);
if (redraw) {
view.prepareImage();
}
} }
} }