diff --git a/DataExtractionOSM/src/com/osmand/ToDoConstants.java b/DataExtractionOSM/src/com/osmand/ToDoConstants.java index a6823d5ace..409f88b306 100644 --- a/DataExtractionOSM/src/com/osmand/ToDoConstants.java +++ b/DataExtractionOSM/src/com/osmand/ToDoConstants.java @@ -27,6 +27,10 @@ public class ToDoConstants { // 42. Revise UI (icons/layouts). Support different devices. Add inactive/focus(!) icon versions. +// 37. Get rid of exit button (!). Think about when notification should go & how clear resources if it is necessary +// DONE : +// TODO : add to app settings preference (Refresh indexes). + // 32. Introduce POI predefined filters (car filter(other-fuel, transportation-car_wash, show-car) and others) // DONE : back end (POI filter object, save, delete, read) // TODO : activity to create/edit new index, activity to read both user defined/osm standard, add actions to remove/create @@ -36,19 +40,24 @@ public class ToDoConstants { // DONE: Load transport routes in swing. // TODO: Create transport index, create transport activity - -// 37. Get rid of exit button (!). Think about when notification should go & how clear resources if it is necessary -// DONE : -// TODO : add to app settings preference (Refresh indexes). + // 34. Suppport navigation for calculated route (example of get route from internet is in swing app). // IDEA : Victor have ideas - // FUTURE RELEASES + // FUTURE RELEASES + // 48. Enable change favourite point (for example fav - "car") means last point you left car. It is not static point. // 43. Enable poi filter by name (?) + // 44. Show gps status (possibly open existing gps-compass app (free) or suggest to install it - no sense to write own activity) + // 45. Get clear settings. Move that setting on top settings screen. + // That setting should rule all activities that use internet. It should ask whenever internet is used + // (would you like to use internet for that operation - if using internet is not checked). + // Internet using now for : edit POI osm, show osm bugs layer, download tiles. // 40. Support simple vector road rendering (require new index file) (?) // 26. Show the whole street on map (when it is chosen in search activity). Possibly extend that story to show layer with streets. (?) + // 46. Implement downloading strategy for tiles (do not load 17 zoom, load only 16 for example) - try to scale 15 zoom for 17 (?) + // 47. Internet connectivity could be checked before trying to use // BUGS Android // 5. Improvement : Implement caching files existing on FS, implement specific method in RM diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index d7ba33bec3..7911f250ed 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,5 +1,7 @@ + Use internet to calculate route + Use online routing Input osm password User password Specify osm settings: show bugs, osm login diff --git a/OsmAnd/res/xml/settings_pref.xml b/OsmAnd/res/xml/settings_pref.xml index 16932d00d1..64f353b332 100644 --- a/OsmAnd/res/xml/settings_pref.xml +++ b/OsmAnd/res/xml/settings_pref.xml @@ -4,7 +4,7 @@ - + diff --git a/OsmAnd/src/com/osmand/AmenityIndexRepository.java b/OsmAnd/src/com/osmand/AmenityIndexRepository.java index 6b91f26aed..127ac7b409 100644 --- a/OsmAnd/src/com/osmand/AmenityIndexRepository.java +++ b/OsmAnd/src/com/osmand/AmenityIndexRepository.java @@ -167,6 +167,8 @@ public class AmenityIndexRepository { db = SQLiteDatabase.openOrCreateDatabase(file, null); name = file.getName().substring(0, file.getName().indexOf('.')); if(db.getVersion() != IndexConstants.POI_TABLE_VERSION){ + db.close(); + db = null; return false; } diff --git a/OsmAnd/src/com/osmand/OsmandSettings.java b/OsmAnd/src/com/osmand/OsmandSettings.java index 5c61be4aea..fa59cab2c2 100644 --- a/OsmAnd/src/com/osmand/OsmandSettings.java +++ b/OsmAnd/src/com/osmand/OsmandSettings.java @@ -47,6 +47,14 @@ public class OsmandSettings { 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 settings_pref.xml preference name + public static final String USE_INTERNET_TO_CALCULATE_ROUTE = "use_internet_to_calculate_route"; + + public static boolean isUsingInternetToCalculateRoute(Context ctx) { + SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); + return prefs.getBoolean(USE_INTERNET_TO_CALCULATE_ROUTE, false); + } // this value string is synchronized with settings_pref.xml preference name public static final String SHOW_POI_OVER_MAP = "show_poi_over_map"; diff --git a/OsmAnd/src/com/osmand/RegionAddressRepository.java b/OsmAnd/src/com/osmand/RegionAddressRepository.java index 93b1c32a07..bf9735856e 100644 --- a/OsmAnd/src/com/osmand/RegionAddressRepository.java +++ b/OsmAnd/src/com/osmand/RegionAddressRepository.java @@ -51,6 +51,8 @@ public class RegionAddressRepository { db = SQLiteDatabase.openOrCreateDatabase(file, null); name = file.getName().substring(0, file.getName().indexOf('.')); if(db.getVersion() != IndexConstants.ADDRESS_TABLE_VERSION){ + db.close(); + db = null; return false; } diff --git a/OsmAnd/src/com/osmand/activities/MainMenuActivity.java b/OsmAnd/src/com/osmand/activities/MainMenuActivity.java index efe67158a8..4c70062593 100644 --- a/OsmAnd/src/com/osmand/activities/MainMenuActivity.java +++ b/OsmAnd/src/com/osmand/activities/MainMenuActivity.java @@ -53,7 +53,6 @@ public class MainMenuActivity extends Activity { public void startApplication(){ if(!applicationAlreadyStarted){ - // TODO exception!!! has leaked window ? final ProgressDialog dlg = ProgressDialog.show(this, "Loading data", "Reading indices...", true); final ProgressDialogImplementation impl = new ProgressDialogImplementation(dlg); impl.setRunnable("Initializing app", new Runnable(){ @@ -63,6 +62,12 @@ public class MainMenuActivity extends Activity { List warnings = new ArrayList(); warnings.addAll(ResourceManager.getResourceManager().indexingPoi(impl)); warnings.addAll(ResourceManager.getResourceManager().indexingAddresses(impl)); + SavingTrackHelper helper = new SavingTrackHelper(MainMenuActivity.this); + if (helper.hasDataToSave()) { + impl.startTask("Saving gpx tracks to SD...", -1); + helper.saveDataToGpx(); + } + helper.close(); showWarnings(warnings); } finally { dlg.dismiss(); @@ -90,9 +95,6 @@ public class MainMenuActivity extends Activity { getPreferences(MODE_WORLD_READABLE).edit().putLong(EXCEPTION_FILE_SIZE, 0).commit(); } } - SavingTrackHelper helper = new SavingTrackHelper(this); - helper.saveDataToGpx(); - helper.close(); } } diff --git a/OsmAnd/src/com/osmand/activities/MapActivity.java b/OsmAnd/src/com/osmand/activities/MapActivity.java index 661a653dba..fd9a253b31 100644 --- a/OsmAnd/src/com/osmand/activities/MapActivity.java +++ b/OsmAnd/src/com/osmand/activities/MapActivity.java @@ -49,6 +49,7 @@ import com.osmand.views.OsmandMapTileView; import com.osmand.views.POIMapLayer; import com.osmand.views.PointLocationLayer; import com.osmand.views.PointNavigationLayer; +import com.osmand.views.RouteLayer; public class MapActivity extends Activity implements LocationListener, IMapLocationListener, SensorEventListener { @@ -65,6 +66,8 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat private MapInfoLayer mapInfoLayer; private OsmBugsLayer osmBugsLayer; private SavingTrackHelper savingTrackHelper; + private RoutingHelper routingHelper; + private RouteLayer routeLayer; private WakeLock wakeLock; private boolean sensorRegistered = false; @@ -73,6 +76,8 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat + + private boolean isMapLinkedToLocation(){ return OsmandSettings.isMapSyncToGpsLocation(this); } @@ -99,11 +104,18 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat mapView.addLayer(mapInfoLayer); osmBugsLayer = new OsmBugsLayer(this); savingTrackHelper = new SavingTrackHelper(this); + routingHelper = new RoutingHelper(this); + routeLayer = new RouteLayer(routingHelper); + mapView.addLayer(routeLayer); locationLayer.setAppMode(OsmandSettings.getApplicationMode(this)); LatLon pointToNavigate = OsmandSettings.getPointToNavigate(this); + if(OsmandSettings.isUsingInternetToCalculateRoute(this)){ + routingHelper.setAppMode(OsmandSettings.getApplicationMode(this)); + routingHelper.setFinalLocation(pointToNavigate); + } navigationLayer.setPointToNavigate(pointToNavigate); SharedPreferences prefs = getSharedPreferences(OsmandSettings.SHARED_PREFERENCES_NAME, MODE_WORLD_READABLE); @@ -220,6 +232,8 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat MapTileDownloader.getInstance().removeDownloaderCallback(mapView); } + + public void setLocation(Location location){ // show point view only if gps enabled @@ -242,11 +256,13 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat } } Log.d(LogUtil.TAG, "Location changed"); - // TODO delete - if(locationLayer.getLastKnownLocation() != null){ + // TODO delete !!! (only for test purposes) + if(!location.hasSpeed() && locationLayer.getLastKnownLocation() != null){ location.setSpeed(location.distanceTo(locationLayer.getLastKnownLocation())); } + locationLayer.setLastKnownLocation(location); + routingHelper.setCurrentLocation(location); if (location != null) { if (isMapLinkedToLocation()) { if(OsmandSettings.isAutoZoomEnabled(this) && location.hasSpeed()){ @@ -291,6 +307,11 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat } else { OsmandSettings.clearPointToNavigate(this); } + routingHelper.setFinalLocation(point); + // TODO do it more clear + if(routingHelper.getLastFixedLocation() != null){ + routingHelper.setCurrentLocation(routingHelper.getLastFixedLocation()); + } navigationLayer.setPointToNavigate(point); updateNavigateToPointMenu(); } @@ -306,6 +327,10 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat public LatLon getPointToNavigate(){ return navigationLayer.getPointToNavigate(); } + + public RoutingHelper getRoutingHelper() { + return routingHelper; + } @Override @@ -434,6 +459,10 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat locationChanged(lat, lon, this); } + public OsmandMapTileView getMapView() { + return mapView; + } + @Override public void onSensorChanged(SensorEvent event) { // Attention : sensor produces a lot of events & can hang the system @@ -514,7 +543,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat } else if(which == 3){ osmBugsLayer.openBug(MapActivity.this, getLayoutInflater(), mapView, latitude, longitude); } else if(which == 4){ - EditingPOIActivity activity = new EditingPOIActivity(MapActivity.this, mapView); + EditingPOIActivity activity = new EditingPOIActivity(MapActivity.this); activity.showCreateDialog(latitude, longitude); } } diff --git a/OsmAnd/src/com/osmand/activities/RoutingHelper.java b/OsmAnd/src/com/osmand/activities/RoutingHelper.java new file mode 100644 index 0000000000..de71333d16 --- /dev/null +++ b/OsmAnd/src/com/osmand/activities/RoutingHelper.java @@ -0,0 +1,440 @@ +package com.osmand.activities; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import android.location.Location; +import android.util.FloatMath; +import android.widget.Toast; + +import com.osmand.LogUtil; +import com.osmand.OsmandSettings.ApplicationMode; +import com.osmand.osm.LatLon; +import com.osmand.osm.MapUtils; + +public class RoutingHelper { + + private static final org.apache.commons.logging.Log log = LogUtil.getLog(RoutingHelper.class); + + private final MapActivity activity; + + private List routeNodes = new ArrayList(); + private int[] listDistance = null; + private int currentRoute = 0; + + + private LatLon finalLocation; + private Location lastFixedLocation; + private Thread currentRunningJob; + private long lastTimeEvaluatedRoute = 0; + private int evalWaitInterval = 3000; + + private ApplicationMode mode; + + + // TEST CODE +// private static List testRoute = new ArrayList(); +// private static void addTestLocation(double lat, double lon){ +// Location l = new Location("p"); +// l.setLatitude(lat); +// l.setLongitude(lon); +// testRoute.add(l); +// } +// static { +// addTestLocation(53.83330108605482, 27.590844306640605); +// addTestLocation(53.83319978227928, 27.580802116088847); +// addTestLocation(53.83319978227928, 27.57196155517576); +// addTestLocation(53.833149130299624, 27.563893470458964); +// addTestLocation(53.8330984782587, 27.55651203124998); +// addTestLocation(53.83340238958535, 27.551448020629863); +// addTestLocation(53.834263459701916, 27.543208274536113); +// addTestLocation(53.835428408740796, 27.53325191467283); +// addTestLocation(53.83598554682643, 27.531964454345683); +// addTestLocation(53.83654267750025, 27.532221946411113); +// addTestLocation(53.836441381565386, 27.533166083984355); +// addTestLocation(53.8341621582541, 27.53325191467283); +// addTestLocation(53.83016055507444, 27.533595237426738); +// addTestLocation(53.82696912916281, 27.533938560180644); +// addTestLocation(53.8255506396008, 27.53376689880369); +// addTestLocation(53.82119354992355, 27.531706962280253); +// addTestLocation(53.817646747077355, 27.53050533264158); +// addTestLocation(53.81156581517512, 27.529389533691386); +// addTestLocation(53.81404896894648, 27.5300761791992); +// addTestLocation(53.80994408432531, 27.529217872314433); +// addTestLocation(53.8062949605079, 27.529217872314433); +// addTestLocation(53.80203724791403, 27.529132041625957); +// addTestLocation(53.794838702875424, 27.52878871887205); +// addTestLocation(53.79052912343052, 27.52758708923338); +// addTestLocation(53.77922071028288, 27.524497184448222); +// addTestLocation(53.76714827905046, 27.520978126220683); +// addTestLocation(53.756138036056214, 27.515914115600566); +// addTestLocation(53.75121547304873, 27.51385417907713); +// addTestLocation(53.74745972778275, 27.513425025634746); +// addTestLocation(53.74284071585075, 27.51402584045408); +// addTestLocation(53.738373496098994, 27.514884147338847); +// addTestLocation(53.735175081196715, 27.516257438354472); +// addTestLocation(53.711966594109235, 27.519604835205058); +// addTestLocation(53.70769930787764, 27.520463142089824); +// addTestLocation(53.69992563864831, 27.52381053894041); +// addTestLocation(53.69728328030487, 27.521235618286113); +// } + // END TEST CODE + + + public RoutingHelper(MapActivity activity){ + this.activity = activity; + + } + + public void setFinalLocation(LatLon finalLocation){ + this.finalLocation = finalLocation; + } + + public void setAppMode(ApplicationMode mode){ + this.mode = mode; + } + + public ApplicationMode getAppMode() { + return mode; + } + + public LatLon getFinalLocation() { + return finalLocation; + } + + + + public boolean finishAtLocation(Location currentLocation) { + Location lastPoint = routeNodes.get(routeNodes.size() - 1); + if(currentRoute > routeNodes.size() - 3 && currentLocation.distanceTo(lastPoint) < 50){ + if(lastFixedLocation != null && lastFixedLocation.distanceTo(lastPoint) < 50){ + // TODO mark as finished + showMessage("You arrived at destination point"); + currentRoute = routeNodes.size() - 1; + } + lastFixedLocation = currentLocation; + // ??? even if you go away from place you can't navigate once time +// finalLocation = null + return true; + } + return false; + } + + public Location getLastFixedLocation() { + return lastFixedLocation; + } + + + public void setCurrentLocation(Location currentLocation) { + if(finalLocation == null || currentLocation == null){ + return; + } + boolean calculateRoute = false; + synchronized (this) { + if(routeNodes.isEmpty() || routeNodes.size() <= currentRoute){ + calculateRoute = true; + } else { + // 1. try to mark passed route (move forward) + float dist = currentLocation.distanceTo(routeNodes.get(currentRoute)); + while(currentRoute + 1 < routeNodes.size()){ + float newDist = currentLocation.distanceTo(routeNodes.get(currentRoute + 1)); + if (newDist < dist) { + // that node already passed + currentRoute++; + dist = newDist; + } else { + break; + } + } + // 2. check if destination found + if(finishAtLocation(currentLocation)){ + return; + } + + // 3. check if closest location already passed + if(currentRoute + 1 < routeNodes.size()){ + float bearing = routeNodes.get(currentRoute).bearingTo(routeNodes.get(currentRoute + 1)); + float bearingMovement = currentLocation.bearingTo(routeNodes.get(currentRoute)); + if(Math.abs(bearing - bearingMovement) > 130 && Math.abs(bearing - bearingMovement) < 230){ + currentRoute++; + } + } + // 4. evaluate distance to the route and reevaluate if needed + if(currentRoute > 0){ + float bearing = routeNodes.get(currentRoute - 1).bearingTo(routeNodes.get(currentRoute)); + float bearingMovement = currentLocation.bearingTo(routeNodes.get(currentRoute)); + float d = Math.abs(currentLocation.distanceTo(routeNodes.get(currentRoute)) * FloatMath.sin((bearingMovement - bearing)*3.14f/180f)); + if(d > 50) { + log.info("Recalculate route, because correlation : " + d); + calculateRoute = true; + } + } + + // 5. also check bearing by summing distance + if(!calculateRoute){ + float d = currentLocation.distanceTo(routeNodes.get(currentRoute)); + if (d > 80) { + if (currentRoute > 0) { + // possibly that case is not needed (often it is covered by 4.) + float f1 = currentLocation.distanceTo(routeNodes.get(currentRoute - 1)) + d; + float c = routeNodes.get(currentRoute - 1).distanceTo(routeNodes.get(currentRoute)); + if (c * 2 < d + f1) { + log.info("Recalculate route, because too far from points : " + d + " " + f1 + " >> " + c); + calculateRoute = true; + } + } else { + // that case is needed + log.info("Recalculate route, because too far from start : " + d); + calculateRoute = true; + } + } + } + + // 5. Also bearing could be checked (is it same direction) +// float bearing; +// if(currentLocation.hasBearing()){ +// bearing = currentLocation.getBearing(); +// } else if(lastFixedLocation != null){ +// bearing = lastFixedLocation.bearingTo(currentLocation); +// } +// bearingRoute = currentLocation.bearingTo(routeNodes.get(currentRoute)); +// if (Math.abs(bearing - bearingRoute) > 60f && 360 - Math.abs(bearing - bearingRoute) > 60f) { +// something wrong however it could be starting movement +// } + } + } + + lastFixedLocation = currentLocation; + if(calculateRoute){ + calculateRoute(lastFixedLocation, finalLocation); + } + } + + private void setNewRoute(List locations){ + routeNodes = locations; + listDistance = new int[locations.size()]; + if (!locations.isEmpty()) { + listDistance[locations.size() - 1] = 0; + for (int i = locations.size() - 1; i > 0; i--) { + listDistance[i - 1] = (int) locations.get(i - 1).distanceTo(locations.get(i)); + listDistance[i - 1] += listDistance[i]; + } + } + currentRoute = 0; + } + + public int getDistance(){ + if(listDistance != null && currentRoute < listDistance.length){ + return listDistance[currentRoute]; + } + return 0; + } + + public void calculateRoute(final Location start, final LatLon end){ + if(currentRunningJob == null){ + // do not evaluate very often + if (System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) { + synchronized (this) { + currentRunningJob = new Thread(new Runnable() { + @Override + public void run() { + RouteCalculationResult res = calculateRouteImpl(start, end); + synchronized (RoutingHelper.this) { + if (res.isCalculated()) { + setNewRoute(res.list); + // reset error wait interval + evalWaitInterval = 3000; + } else { + evalWaitInterval = evalWaitInterval * 3 / 2; + if(evalWaitInterval > 120000){ + evalWaitInterval = 120000; + } + } + currentRunningJob = null; + } + if(res.isCalculated()){ + showMessage("New route is calculated distance : " + MapUtils.getFormattedDistance(sumDistance(res.list))); + // be aware that is non ui thread + activity.getMapView().refreshMap(); + } else { + if(res.errorMessage != null){ + showMessage("Error calculating route : " + res.errorMessage); + } else if(res.list == null){ + showMessage("Error occurred while calculating route"); + } else { + showMessage("Empty route is calculated"); + } + } + lastTimeEvaluatedRoute = System.currentTimeMillis(); + } + }, "Calculating route"); + currentRunningJob.start(); + } + } + } + } + + private int sumDistance(List locations) { + int d = 0; + if (locations.size() > 1) { + for (int i = 1; i < locations.size(); i++) { + d += locations.get(i - 1).distanceTo(locations.get(i)); + } + } + return d; + } + + private void showMessage(final String msg){ + activity.runOnUiThread(new Runnable(){ + @Override + public void run() { + Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show(); + } + }); + } + + public boolean hasPointsToShow(){ + return finalLocation != null && !routeNodes.isEmpty(); + } + + + public synchronized void fillLocationsToShow(double topLatitude, double leftLongitude, double bottomLatitude,double rightLongitude, List l){ + l.clear(); + boolean previousVisible = false; + if(lastFixedLocation != null){ + if(leftLongitude <= lastFixedLocation.getLongitude() && lastFixedLocation.getLongitude() <= rightLongitude && + bottomLatitude <= lastFixedLocation.getLatitude() && lastFixedLocation.getLatitude() <= topLatitude){ + l.add(lastFixedLocation); + previousVisible = true; + } + } + + for(int i=currentRoute; i currentRoute) { + l.add(0, ls); + previousVisible = true; + } else if(lastFixedLocation != null){ + l.add(0, ls); + } + previousVisible = true; + } else if(previousVisible){ + l.add(ls); + previousVisible = false; + // do not continue make method more efficient (because it calls in UI thread) + // this break also has logical sense ! + break; + } + } + } + + + private static class RouteCalculationResult { + public List list; + public String errorMessage; + public RouteCalculationResult( List list, String errorMessage) { + this.errorMessage = errorMessage; + this.list = list; + } + public boolean isCalculated(){ + return list != null && !list.isEmpty(); + } + + } + + private RouteCalculationResult calculateRouteImpl(Location start, LatLon end){ + long time = System.currentTimeMillis(); + if (start != null && end != null) { + List res = new ArrayList(); + if(log.isInfoEnabled()){ + log.info("Start finding route from " + start + " to " + end); + } + try { + StringBuilder uri = new StringBuilder(); + uri.append("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml"); + uri.append("&flat=").append(start.getLatitude()); + uri.append("&flon=").append(start.getLongitude()); + uri.append("&tlat=").append(end.getLatitude()); + uri.append("&tlon=").append(end.getLongitude()); + if(ApplicationMode.PEDESTRIAN== mode){ + uri.append("&v=foot") ; + } else if(ApplicationMode.BICYCLE == mode){ + uri.append("&v=bicycle") ; + } else { + uri.append("&v=motorcar"); + } + uri.append("&fast=1").append("&layer=mapnik"); + + URL url = new URL(uri.toString()); + URLConnection connection = url.openConnection(); + DocumentBuilder dom = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = dom.parse(new InputSource(new InputStreamReader(connection.getInputStream()))); + NodeList list = doc.getElementsByTagName("coordinates"); + for(int i=0; i 100) || (Math.abs(((float) dist - oldDist)/oldDist) < 0.01))){ return false; } return true; @@ -96,10 +96,17 @@ public class MapInfoLayer implements OsmandMapLayer { @Override public void onDraw(Canvas canvas) { if(map.getPointToNavigate() != null){ - Location.distanceBetween(view.getLatitude(), view.getLongitude(), map.getPointToNavigate().getLatitude(), - map.getPointToNavigate().getLongitude(), calculations); - if(distChanged(cachedMeters, (int)calculations[0])){ - cachedMeters = (int)calculations[0]; + int d = 0; + if(map.getRoutingHelper().getFinalLocation() != null){ + d = map.getRoutingHelper().getDistance(); + } + if (d == 0) { + Location.distanceBetween(view.getLatitude(), view.getLongitude(), map.getPointToNavigate().getLatitude(), map + .getPointToNavigate().getLongitude(), calculations); + d = (int) calculations[0]; + } + if(distChanged(cachedMeters, d)){ + cachedMeters = d; if(cachedMeters <= 20){ cachedMeters = 0; cachedDistString = null; @@ -128,7 +135,7 @@ public class MapInfoLayer implements OsmandMapLayer { // draw speed if(map.getLastKnownLocation() != null && map.getLastKnownLocation().hasSpeed()){ if(Math.abs(map.getLastKnownLocation().getSpeed() - cachedSpeed) > .3f){ - cachedSpeed = (int) map.getLastKnownLocation().getSpeed(); + cachedSpeed = map.getLastKnownLocation().getSpeed(); cachedSpeedString = ((int) (cachedSpeed * 3.6f)) + " km/h"; float right = paintBlack.measureText(cachedSpeedString) + 8 + boundsForSpeed.left; boundsForSpeed.right = boundsForDist.right = Math.max(right, boundsForDist.right); diff --git a/OsmAnd/src/com/osmand/views/PointLocationLayer.java b/OsmAnd/src/com/osmand/views/PointLocationLayer.java index dc8330ad39..02e895672c 100644 --- a/OsmAnd/src/com/osmand/views/PointLocationLayer.java +++ b/OsmAnd/src/com/osmand/views/PointLocationLayer.java @@ -153,8 +153,8 @@ public class PointLocationLayer implements OsmandMapLayer { } public void setLastKnownLocation(Location lastKnownLocation) { - this.lastKnownLocation = lastKnownLocation; boolean redraw = isLocationVisible(this.lastKnownLocation) || isLocationVisible(lastKnownLocation); + this.lastKnownLocation = lastKnownLocation; if (redraw) { view.refreshMap(); } diff --git a/OsmAnd/src/com/osmand/views/RouteLayer.java b/OsmAnd/src/com/osmand/views/RouteLayer.java new file mode 100644 index 0000000000..b8af9c0925 --- /dev/null +++ b/OsmAnd/src/com/osmand/views/RouteLayer.java @@ -0,0 +1,110 @@ +package com.osmand.views; + +import java.util.ArrayList; +import java.util.List; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PointF; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Paint.Style; +import android.location.Location; +import android.util.Log; + +import com.osmand.LogUtil; +import com.osmand.activities.RoutingHelper; +import com.osmand.osm.MapUtils; + +public class RouteLayer implements OsmandMapLayer { + + private OsmandMapTileView view; + + private final RoutingHelper helper; + private Rect boundsRect; + private RectF tileRect; + private List points = new ArrayList(); + private Paint paint; + + private Path path; + + public RouteLayer(RoutingHelper helper){ + this.helper = helper; + } + + + private void initUI() { + boundsRect = new Rect(0, 0, view.getWidth(), view.getHeight()); + tileRect = new RectF(); + paint = new Paint(); + paint.setColor(Color.GRAY); + paint.setStyle(Style.STROKE); + paint.setStrokeWidth(14); + paint.setAlpha(150); + paint.setAntiAlias(true); + path = new Path(); + } + + public void initLayer(OsmandMapTileView view) { + this.view = view; + initUI(); + } + + + @Override + public void onDraw(Canvas canvas) { + if (helper.hasPointsToShow()) { + long time = System.currentTimeMillis(); + boundsRect = new Rect(0, 0, view.getWidth(), view.getHeight()); + view.calculateTileRectangle(boundsRect, 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); + helper.fillLocationsToShow(topLatitude, leftLongitude, bottomLatitude, rightLongitude, points); + if((System.currentTimeMillis() - time) > 40){ + Log.e(LogUtil.TAG, "Calculate route layer " + (System.currentTimeMillis() - time)); + } + if (points.size() > 0) { + int px = view.getMapXForPoint(points.get(0).getLongitude()); + int py = view.getMapYForPoint(points.get(0).getLatitude()); + path.reset(); + path.moveTo(px, py); + for (Location o : points) { + int x = view.getMapXForPoint(o.getLongitude()); + int y = view.getMapYForPoint(o.getLatitude()); + path.lineTo(x, y); + } + canvas.drawPath(path, paint); + } + } + } + + + + @Override + public void destroyLayer() { + + } + @Override + public boolean drawInScreenPixels() { + return false; + } + + @Override + public boolean onLongPressEvent(PointF point) { + return false; + } + + @Override + public boolean onTouchEvent(PointF point) { + return false; + } + + + + +}