start implementing following directions
git-svn-id: https://osmand.googlecode.com/svn/trunk@204 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
ecc99d0dde
commit
497bd6bf3e
5 changed files with 500 additions and 160 deletions
|
@ -76,6 +76,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
|
|||
|
||||
private boolean providerSupportsBearing = false;
|
||||
private boolean providerSupportsSpeed = false;
|
||||
private String currentLocationProvider = null;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
private OsmandMapTileView mapView;
|
||||
|
@ -462,15 +463,24 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
|
|||
if(LocationProvider.OUT_OF_SERVICE == status){
|
||||
setLocation(null);
|
||||
}
|
||||
service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
|
||||
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
|
||||
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
|
||||
if(!isRunningOnEmulator() && service.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
|
||||
if(!Algoritms.objectEquals(currentLocationProvider, LocationManager.NETWORK_PROVIDER)){
|
||||
currentLocationProvider = LocationManager.NETWORK_PROVIDER;
|
||||
service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
|
||||
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
|
||||
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
|
||||
}
|
||||
}
|
||||
} else if (LocationProvider.AVAILABLE == status) {
|
||||
service.removeUpdates(this);
|
||||
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
|
||||
prov = service.getProvider(LocationManager.GPS_PROVIDER);
|
||||
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
|
||||
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
|
||||
if(!Algoritms.objectEquals(currentLocationProvider, LocationManager.GPS_PROVIDER)){
|
||||
currentLocationProvider = LocationManager.GPS_PROVIDER;
|
||||
service.removeUpdates(this);
|
||||
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
|
||||
prov = service.getProvider(LocationManager.GPS_PROVIDER);
|
||||
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
|
||||
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
266
OsmAnd/src/com/osmand/activities/RouteProvider.java
Normal file
266
OsmAnd/src/com/osmand/activities/RouteProvider.java
Normal file
|
@ -0,0 +1,266 @@
|
|||
package com.osmand.activities;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.FactoryConfigurationError;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
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 com.osmand.LogUtil;
|
||||
import com.osmand.OsmandSettings.ApplicationMode;
|
||||
import com.osmand.activities.RoutingHelper.RouteDirectionInfo;
|
||||
import com.osmand.activities.RoutingHelper.TurnType;
|
||||
import com.osmand.osm.LatLon;
|
||||
|
||||
public class RouteProvider {
|
||||
private static final org.apache.commons.logging.Log log = LogUtil.getLog(RouteProvider.class);
|
||||
|
||||
public RouteProvider(){
|
||||
}
|
||||
|
||||
|
||||
public static class RouteCalculationResult {
|
||||
private final List<Location> locations;
|
||||
private final List<RouteDirectionInfo> directions;
|
||||
private final String errorMessage;
|
||||
private int[] listDistance = null;
|
||||
|
||||
public RouteCalculationResult(String errorMessage) {
|
||||
this(null, null, errorMessage);
|
||||
}
|
||||
public RouteCalculationResult(List<Location> list, List<RouteDirectionInfo> directions, String errorMessage) {
|
||||
this.directions = directions;
|
||||
this.errorMessage = errorMessage;
|
||||
this.locations = list;
|
||||
if (list != null) {
|
||||
prepareResult();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Location> getLocations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
public List<RouteDirectionInfo> getDirections() {
|
||||
return directions;
|
||||
}
|
||||
|
||||
public int[] getListDistance() {
|
||||
return listDistance;
|
||||
}
|
||||
|
||||
private void prepareResult() {
|
||||
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];
|
||||
}
|
||||
}
|
||||
if(directions != null){
|
||||
int sum =0;
|
||||
for(int i=directions.size() - 1; i>=0; i--){
|
||||
directions.get(i).afterLeftTime = sum;
|
||||
sum += directions.get(i).expectedTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean isCalculated(){
|
||||
return locations != null && !locations.isEmpty();
|
||||
}
|
||||
|
||||
public String getErrorMessage(){
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, ApplicationMode mode){
|
||||
long time = System.currentTimeMillis();
|
||||
if (start != null && end != null) {
|
||||
if(log.isInfoEnabled()){
|
||||
log.info("Start finding route from " + start + " to " + end); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
try {
|
||||
// RouteCalculationResult res = findYOURSRoute(start, end, mode);
|
||||
RouteCalculationResult res = findCloudMadeRoute(start, end, mode);
|
||||
if(log.isInfoEnabled() && res.locations != null){
|
||||
log.info("Finding route contained " + res.locations.size() + " points for " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
}
|
||||
return res;
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to find route ", e); //$NON-NLS-1$
|
||||
} catch (ParserConfigurationException e) {
|
||||
log.error("Failed to find route ", e); //$NON-NLS-1$
|
||||
} catch (SAXException e) {
|
||||
log.error("Failed to find route ", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
return new RouteCalculationResult(null);
|
||||
}
|
||||
|
||||
|
||||
protected RouteCalculationResult findYOURSRoute(Location start, LatLon end, ApplicationMode mode) throws MalformedURLException, IOException,
|
||||
ParserConfigurationException, FactoryConfigurationError, SAXException {
|
||||
List<Location> res = new ArrayList<Location>();
|
||||
StringBuilder uri = new StringBuilder();
|
||||
uri.append("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml"); //$NON-NLS-1$
|
||||
uri.append("&flat=").append(start.getLatitude()); //$NON-NLS-1$
|
||||
uri.append("&flon=").append(start.getLongitude()); //$NON-NLS-1$
|
||||
uri.append("&tlat=").append(end.getLatitude()); //$NON-NLS-1$
|
||||
uri.append("&tlon=").append(end.getLongitude()); //$NON-NLS-1$
|
||||
if(ApplicationMode.PEDESTRIAN == mode){
|
||||
uri.append("&v=foot") ; //$NON-NLS-1$
|
||||
} else if(ApplicationMode.BICYCLE == mode){
|
||||
uri.append("&v=bicycle") ; //$NON-NLS-1$
|
||||
} else {
|
||||
uri.append("&v=motorcar"); //$NON-NLS-1$
|
||||
}
|
||||
uri.append("&fast=1").append("&layer=mapnik"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
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"); //$NON-NLS-1$
|
||||
for(int i=0; i<list.getLength(); i++){
|
||||
Node item = list.item(i);
|
||||
String str = item.getFirstChild().getNodeValue();
|
||||
if(str == null){
|
||||
continue;
|
||||
}
|
||||
int st = 0;
|
||||
int next = 0;
|
||||
while((next = str.indexOf('\n', st)) != -1){
|
||||
String coordinate = str.substring(st, next + 1);
|
||||
int s = coordinate.indexOf(',');
|
||||
if (s != -1) {
|
||||
try {
|
||||
double lon = Double.parseDouble(coordinate.substring(0, s));
|
||||
double lat = Double.parseDouble(coordinate.substring(s + 1));
|
||||
Location l = new Location("router"); //$NON-NLS-1$
|
||||
l.setLatitude(lat);
|
||||
l.setLongitude(lon);
|
||||
res.add(l);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
st = next + 1;
|
||||
}
|
||||
}
|
||||
if(list.getLength() == 0){
|
||||
if(doc.getChildNodes().getLength() == 1){
|
||||
Node item = doc.getChildNodes().item(0);
|
||||
return new RouteCalculationResult(item.getNodeValue());
|
||||
|
||||
}
|
||||
}
|
||||
return new RouteCalculationResult(res, null, null);
|
||||
}
|
||||
|
||||
|
||||
protected RouteCalculationResult findCloudMadeRoute(Location start, LatLon end, ApplicationMode mode) throws MalformedURLException, IOException,
|
||||
ParserConfigurationException, FactoryConfigurationError, SAXException {
|
||||
List<Location> res = new ArrayList<Location>();
|
||||
List<RouteDirectionInfo> directions = null;
|
||||
StringBuilder uri = new StringBuilder();
|
||||
// possibly hide that API key because it is privacy of osmand
|
||||
uri.append("http://routes.cloudmade.com/A6421860EBB04234AB5EF2D049F2CD8F/api/0.3/"); //$NON-NLS-1$
|
||||
uri.append(start.getLatitude()+"").append(","); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
uri.append(start.getLongitude()+"").append(","); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
uri.append(end.getLatitude()+"").append(","); //$NON-NLS-1$//$NON-NLS-2$
|
||||
uri.append(end.getLongitude()+"").append("/"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
if (ApplicationMode.PEDESTRIAN == mode) {
|
||||
uri.append("foot.gpx"); //$NON-NLS-1$
|
||||
} else if (ApplicationMode.BICYCLE == mode) {
|
||||
uri.append("bicycle.gpx"); //$NON-NLS-1$
|
||||
} else {
|
||||
uri.append("car.gpx"); //$NON-NLS-1$
|
||||
}
|
||||
uri.append("?lang=").append(Locale.getDefault().getLanguage()); //$NON-NLS-1$
|
||||
|
||||
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())));
|
||||
// TODO how to find that error occurred ? API gpx doesn't say nothing
|
||||
NodeList list = doc.getElementsByTagName("wpt"); //$NON-NLS-1$
|
||||
for (int i = 0; i < list.getLength(); i++) {
|
||||
Element item = (Element) list.item(i);
|
||||
try {
|
||||
Location l = new Location("router"); //$NON-NLS-1$
|
||||
l.setLatitude(Double.parseDouble(item.getAttribute("lat"))); //$NON-NLS-1$
|
||||
l.setLongitude(Double.parseDouble(item.getAttribute("lon"))); //$NON-NLS-1$
|
||||
res.add(l);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
list = doc.getElementsByTagName("rtept"); //$NON-NLS-1$
|
||||
if(list.getLength() > 0){
|
||||
directions = new ArrayList<RouteDirectionInfo>();
|
||||
}
|
||||
for (int i = 0; i < list.getLength(); i++) {
|
||||
Element item = (Element) list.item(i);
|
||||
try {
|
||||
RouteDirectionInfo dirInfo = new RouteDirectionInfo();
|
||||
dirInfo.descriptionRoute = getContentFromNode(item, "desc"); //$NON-NLS-1$
|
||||
String stime = getContentFromNode(item, "time"); //$NON-NLS-1$
|
||||
if(stime != null){
|
||||
dirInfo.expectedTime = Integer.parseInt(stime);
|
||||
}
|
||||
String sturn = getContentFromNode(item, "turn-angle"); //$NON-NLS-1$
|
||||
if(sturn != null){
|
||||
dirInfo.turnAngle = (float) Double.parseDouble(sturn);
|
||||
}
|
||||
String stype = getContentFromNode(item, "turn"); //$NON-NLS-1$
|
||||
if(stype != null){
|
||||
dirInfo.turnType = TurnType.valueOf(stype.toUpperCase());
|
||||
} else {
|
||||
dirInfo.turnType = TurnType.C;
|
||||
}
|
||||
int offset = Integer.parseInt(getContentFromNode(item, "offset")); //$NON-NLS-1$
|
||||
dirInfo.routePointOffset = offset;
|
||||
directions.add(dirInfo);
|
||||
} catch (NumberFormatException e) {
|
||||
log.info("Exception", e); //$NON-NLS-1$
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.info("Exception", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return new RouteCalculationResult(res, directions, null);
|
||||
}
|
||||
|
||||
private String getContentFromNode(Element item, String tagName){
|
||||
NodeList list = item.getElementsByTagName(tagName);
|
||||
if(list.getLength() > 0){
|
||||
return list.item(0).getFirstChild().getNodeValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +1,8 @@
|
|||
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;
|
||||
|
@ -24,6 +10,7 @@ import android.widget.Toast;
|
|||
import com.osmand.LogUtil;
|
||||
import com.osmand.R;
|
||||
import com.osmand.OsmandSettings.ApplicationMode;
|
||||
import com.osmand.activities.RouteProvider.RouteCalculationResult;
|
||||
import com.osmand.osm.LatLon;
|
||||
import com.osmand.osm.MapUtils;
|
||||
|
||||
|
@ -34,8 +21,14 @@ public class RoutingHelper {
|
|||
// activity to show messages & refresh map when route is calculated
|
||||
private MapActivity activity;
|
||||
|
||||
// instead of this properties RouteCalculationResult could be used
|
||||
private List<Location> routeNodes = new ArrayList<Location>();
|
||||
private List<RouteDirectionInfo> directionInfo = null;
|
||||
private int[] listDistance = null;
|
||||
|
||||
// Note always currentRoute > get(currentDirectionInfo).routeOffset,
|
||||
// but currentRoute <= get(currentDirectionInfo+1).routeOffset
|
||||
private int currentDirectionInfo = 0;
|
||||
private int currentRoute = 0;
|
||||
|
||||
|
||||
|
@ -47,6 +40,8 @@ public class RoutingHelper {
|
|||
|
||||
private ApplicationMode mode;
|
||||
|
||||
private RouteProvider provider = new RouteProvider();
|
||||
|
||||
|
||||
// TEST CODE
|
||||
// private static List<Location> testRoute = new ArrayList<Location>();
|
||||
|
@ -80,6 +75,7 @@ public class RoutingHelper {
|
|||
this.finalLocation = finalLocation;
|
||||
this.routeNodes.clear();
|
||||
listDistance = null;
|
||||
directionInfo = null;
|
||||
evalWaitInterval = 3000;
|
||||
// to update route
|
||||
setCurrentLocation(currentLocation);
|
||||
|
@ -114,7 +110,7 @@ public class RoutingHelper {
|
|||
if(activity != null){
|
||||
showMessage(activity.getString(R.string.arrived_at_destination));
|
||||
}
|
||||
currentRoute = routeNodes.size() - 1;
|
||||
updateCurrentRoute(routeNodes.size() - 1);
|
||||
// clear final location to prevent all time showing message
|
||||
finalLocation = null;
|
||||
}
|
||||
|
@ -128,6 +124,17 @@ public class RoutingHelper {
|
|||
return lastFixedLocation;
|
||||
}
|
||||
|
||||
private void updateCurrentRoute(int currentRoute){
|
||||
this.currentRoute = currentRoute;
|
||||
if(directionInfo != null){
|
||||
while(currentDirectionInfo < directionInfo.size() - 1 &&
|
||||
directionInfo.get(currentDirectionInfo + 1).routePointOffset < currentRoute){
|
||||
currentDirectionInfo ++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setCurrentLocation(Location currentLocation) {
|
||||
if(finalLocation == null || currentLocation == null){
|
||||
|
@ -138,13 +145,15 @@ public class RoutingHelper {
|
|||
if(routeNodes.isEmpty() || routeNodes.size() <= currentRoute){
|
||||
calculateRoute = true;
|
||||
} else {
|
||||
// Check whether user follow by route in correct direction
|
||||
|
||||
// 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++;
|
||||
updateCurrentRoute(currentRoute + 1);
|
||||
dist = newDist;
|
||||
} else {
|
||||
break;
|
||||
|
@ -160,7 +169,7 @@ public class RoutingHelper {
|
|||
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++;
|
||||
updateCurrentRoute(currentRoute + 1);
|
||||
}
|
||||
}
|
||||
// 4. evaluate distance to the route and reevaluate if needed
|
||||
|
@ -214,16 +223,11 @@ public class RoutingHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private void setNewRoute(List<Location> 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];
|
||||
}
|
||||
}
|
||||
private void setNewRoute(RouteCalculationResult res){
|
||||
routeNodes = res.getLocations();
|
||||
directionInfo = res.getDirections();
|
||||
listDistance = res.getListDistance();
|
||||
currentDirectionInfo = 0;
|
||||
currentRoute = 0;
|
||||
}
|
||||
|
||||
|
@ -237,6 +241,46 @@ public class RoutingHelper {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public RouteDirectionInfo getNextRouteDirectionInfo(){
|
||||
if(directionInfo != null && currentDirectionInfo < directionInfo.size() - 1){
|
||||
return directionInfo.get(currentDirectionInfo + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getDistanceToNextRouteDirection() {
|
||||
if (directionInfo != null && currentDirectionInfo < directionInfo.size()) {
|
||||
int dist = listDistance[currentRoute];
|
||||
if (currentDirectionInfo < directionInfo.size() - 1) {
|
||||
dist -= listDistance[directionInfo.get(currentDirectionInfo + 1).routePointOffset];
|
||||
}
|
||||
if(lastFixedLocation != null){
|
||||
dist += lastFixedLocation.distanceTo(routeNodes.get(currentRoute));
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public synchronized int getLeftTime(){
|
||||
if(directionInfo != null && currentDirectionInfo < directionInfo.size()){
|
||||
int t = directionInfo.get(currentDirectionInfo).afterLeftTime;
|
||||
int e = directionInfo.get(currentDirectionInfo).expectedTime;
|
||||
if (e > 0) {
|
||||
int passedDist = listDistance[directionInfo.get(currentDirectionInfo).routePointOffset] - listDistance[currentRoute];
|
||||
int wholeDist = listDistance[directionInfo.get(currentDirectionInfo).routePointOffset];
|
||||
if (currentDirectionInfo < directionInfo.size() - 1) {
|
||||
wholeDist -= listDistance[directionInfo.get(currentDirectionInfo + 1).routePointOffset];
|
||||
}
|
||||
if (wholeDist > 0) {
|
||||
t = (int) (t + ((float)e) * (1 - (float) passedDist / (float) wholeDist));
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void calculateRoute(final Location start, final LatLon end){
|
||||
if(currentRunningJob == null){
|
||||
// do not evaluate very often
|
||||
|
@ -245,10 +289,10 @@ public class RoutingHelper {
|
|||
currentRunningJob = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
RouteCalculationResult res = calculateRouteImpl(start, end);
|
||||
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode);
|
||||
synchronized (RoutingHelper.this) {
|
||||
if (res.isCalculated()) {
|
||||
setNewRoute(res.list);
|
||||
setNewRoute(res);
|
||||
// reset error wait interval
|
||||
evalWaitInterval = 3000;
|
||||
} else {
|
||||
|
@ -261,13 +305,15 @@ public class RoutingHelper {
|
|||
}
|
||||
if (activity != null) {
|
||||
if (res.isCalculated()) {
|
||||
showMessage(activity.getString(R.string.new_route_calculated_dist) + MapUtils.getFormattedDistance(sumDistance(res.list)));
|
||||
int[] dist = res.getListDistance();
|
||||
int l = dist != null && dist.length > 0 ? dist[0] : 0;
|
||||
showMessage(activity.getString(R.string.new_route_calculated_dist) + MapUtils.getFormattedDistance(l));
|
||||
// be aware that is non ui thread
|
||||
activity.getMapView().refreshMap();
|
||||
} else {
|
||||
if (res.errorMessage != null) {
|
||||
showMessage(activity.getString(R.string.error_calculating_route) + res.errorMessage);
|
||||
} else if (res.list == null) {
|
||||
if (res.getErrorMessage() != null) {
|
||||
showMessage(activity.getString(R.string.error_calculating_route) + res.getErrorMessage());
|
||||
} else if (res.getLocations() == null) {
|
||||
showMessage(activity.getString(R.string.error_calculating_route_occured));
|
||||
} else {
|
||||
showMessage(activity.getString(R.string.empty_route_calculated));
|
||||
|
@ -283,16 +329,6 @@ public class RoutingHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private int sumDistance(List<Location> 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){
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
|
@ -344,95 +380,30 @@ public class RoutingHelper {
|
|||
}
|
||||
|
||||
|
||||
private static class RouteCalculationResult {
|
||||
public List<Location> list;
|
||||
public String errorMessage;
|
||||
public RouteCalculationResult( List<Location> list, String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
this.list = list;
|
||||
}
|
||||
public boolean isCalculated(){
|
||||
return list != null && !list.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public static enum TurnType {
|
||||
C , // continue (go straight)
|
||||
TL, // turn left
|
||||
TSLL, // turn slight left
|
||||
TSHL, // turn sharp left
|
||||
TR, // turn right
|
||||
TSLR, // turn slight right
|
||||
TSHR, // turn sharp right
|
||||
TU, // U-turn
|
||||
|
||||
// TODO Exit3...
|
||||
}
|
||||
|
||||
private RouteCalculationResult calculateRouteImpl(Location start, LatLon end){
|
||||
long time = System.currentTimeMillis();
|
||||
if (start != null && end != null) {
|
||||
List<Location> res = new ArrayList<Location>();
|
||||
if(log.isInfoEnabled()){
|
||||
log.info("Start finding route from " + start + " to " + end); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
try {
|
||||
StringBuilder uri = new StringBuilder();
|
||||
uri.append("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml"); //$NON-NLS-1$
|
||||
uri.append("&flat=").append(start.getLatitude()); //$NON-NLS-1$
|
||||
uri.append("&flon=").append(start.getLongitude()); //$NON-NLS-1$
|
||||
uri.append("&tlat=").append(end.getLatitude()); //$NON-NLS-1$
|
||||
uri.append("&tlon=").append(end.getLongitude()); //$NON-NLS-1$
|
||||
if(ApplicationMode.PEDESTRIAN== mode){
|
||||
uri.append("&v=foot") ; //$NON-NLS-1$
|
||||
} else if(ApplicationMode.BICYCLE == mode){
|
||||
uri.append("&v=bicycle") ; //$NON-NLS-1$
|
||||
} else {
|
||||
uri.append("&v=motorcar"); //$NON-NLS-1$
|
||||
}
|
||||
uri.append("&fast=1").append("&layer=mapnik"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
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"); //$NON-NLS-1$
|
||||
for(int i=0; i<list.getLength(); i++){
|
||||
Node item = list.item(i);
|
||||
String str = item.getFirstChild().getNodeValue();
|
||||
if(str == null){
|
||||
continue;
|
||||
}
|
||||
int st = 0;
|
||||
int next = 0;
|
||||
while((next = str.indexOf('\n', st)) != -1){
|
||||
String coordinate = str.substring(st, next + 1);
|
||||
int s = coordinate.indexOf(',');
|
||||
if (s != -1) {
|
||||
try {
|
||||
double lon = Double.parseDouble(coordinate.substring(0, s));
|
||||
double lat = Double.parseDouble(coordinate.substring(s + 1));
|
||||
Location l = new Location("router"); //$NON-NLS-1$
|
||||
l.setLatitude(lat);
|
||||
l.setLongitude(lon);
|
||||
res.add(l);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
st = next + 1;
|
||||
}
|
||||
}
|
||||
if(list.getLength() == 0){
|
||||
if(doc.getChildNodes().getLength() == 1){
|
||||
Node item = doc.getChildNodes().item(0);
|
||||
return new RouteCalculationResult(null, item.getNodeValue());
|
||||
|
||||
}
|
||||
}
|
||||
if(log.isInfoEnabled()){
|
||||
log.info("Finding route contained " + res.size() + " points for " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
}
|
||||
|
||||
return new RouteCalculationResult(res, null);
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to find route ", e); //$NON-NLS-1$
|
||||
} catch (ParserConfigurationException e) {
|
||||
log.error("Failed to find route ", e); //$NON-NLS-1$
|
||||
} catch (SAXException e) {
|
||||
log.error("Failed to find route ", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
return new RouteCalculationResult(null, null);
|
||||
public static class RouteDirectionInfo {
|
||||
public String descriptionRoute;
|
||||
public int expectedTime;
|
||||
public float turnAngle;
|
||||
public TurnType turnType;
|
||||
public int routePointOffset;
|
||||
public int afterLeftTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -8,33 +8,46 @@ import android.graphics.PointF;
|
|||
import android.graphics.RectF;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.location.Location;
|
||||
import android.text.format.DateFormat;
|
||||
|
||||
import com.osmand.Messages;
|
||||
import com.osmand.activities.MapActivity;
|
||||
import com.osmand.activities.RoutingHelper.RouteDirectionInfo;
|
||||
import com.osmand.activities.RoutingHelper.TurnType;
|
||||
import com.osmand.osm.MapUtils;
|
||||
|
||||
public class MapInfoLayer implements OsmandMapLayer {
|
||||
|
||||
|
||||
private OsmandMapTileView view;
|
||||
private boolean showMiniMap = false;
|
||||
private final MapActivity map;
|
||||
private final RouteLayer routeLayer;
|
||||
|
||||
private Paint paintBlack;
|
||||
private Paint paintMiniRoute;
|
||||
|
||||
|
||||
private Path pathForCompass;
|
||||
private Path pathForCompass2;
|
||||
private Path pathForTurn;
|
||||
|
||||
private Paint paintBlack;
|
||||
private Paint paintMiniRoute;
|
||||
private Paint fillBlack;
|
||||
private Paint fillRed;
|
||||
private Paint paintAlphaGray;
|
||||
private Paint paintRouteDirection;
|
||||
|
||||
private RectF boundsForCompass;
|
||||
private RectF boundsForZoom;
|
||||
private RectF boundsForDist;
|
||||
private RectF boundsForMiniRoute;
|
||||
private RectF boundsForLeftTime;
|
||||
private RectF boundsForSpeed;
|
||||
private Paint paintAlphaGray;
|
||||
|
||||
|
||||
|
||||
private String cachedLeftTimeString = null;
|
||||
private long cachedLeftTime = 0;
|
||||
private float[] calculations = new float[1];
|
||||
private String cachedDistString = null;
|
||||
private int cachedMeters = 0;
|
||||
|
@ -66,6 +79,11 @@ public class MapInfoLayer implements OsmandMapLayer {
|
|||
paintAlphaGray.setColor(Color.LTGRAY);
|
||||
paintAlphaGray.setAlpha(180); // do not make very transparent (to hide route)
|
||||
|
||||
paintRouteDirection = new Paint();
|
||||
paintRouteDirection.setStyle(Style.FILL_AND_STROKE);
|
||||
paintRouteDirection.setColor(Color.rgb(100, 0, 255));
|
||||
paintRouteDirection.setAntiAlias(true);
|
||||
|
||||
fillBlack = new Paint();
|
||||
fillBlack.setStyle(Style.FILL_AND_STROKE);
|
||||
fillBlack.setColor(Color.BLACK);
|
||||
|
@ -86,8 +104,10 @@ public class MapInfoLayer implements OsmandMapLayer {
|
|||
boundsForDist = new RectF(35, 0, 110, 32);
|
||||
boundsForZoom = new RectF(0, 32, 35, 64);
|
||||
boundsForSpeed = new RectF(35, 32, 110, 64);
|
||||
|
||||
boundsForMiniRoute = new RectF(0, 64, 96, 196);
|
||||
boundsForLeftTime = new RectF(0, 0, 75, 32);
|
||||
|
||||
|
||||
centerMiniRouteX = 48;
|
||||
centerMiniRouteY= 160;
|
||||
scaleMiniRoute = 0.15f;
|
||||
|
@ -103,6 +123,8 @@ public class MapInfoLayer implements OsmandMapLayer {
|
|||
pathForCompass2.lineTo(22f, 15.5f);
|
||||
pathForCompass2.lineTo(15.5f, 2f);
|
||||
pathForCompass2.lineTo(9, 15);
|
||||
|
||||
pathForTurn = new Path();
|
||||
}
|
||||
|
||||
public boolean distChanged(int oldDist, int dist){
|
||||
|
@ -174,23 +196,9 @@ public class MapInfoLayer implements OsmandMapLayer {
|
|||
canvas.drawText(cachedDistString, boundsForDist.left + 15, boundsForDist.bottom - 9, paintBlack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(routeLayer != null && !routeLayer.getPath().isEmpty()){
|
||||
canvas.save();
|
||||
canvas.clipRect(boundsForMiniRoute);
|
||||
canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintAlphaGray);
|
||||
canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintBlack);
|
||||
|
||||
canvas.translate(centerMiniRouteX - view.getCenterPointX(), centerMiniRouteY - view.getCenterPointY());
|
||||
canvas.scale(scaleMiniRoute, scaleMiniRoute, view.getCenterPointX(), view.getCenterPointY());
|
||||
canvas.rotate(view.getRotate(), view.getCenterPointX(), view.getCenterPointY());
|
||||
|
||||
canvas.drawCircle(view.getCenterPointX(), view.getCenterPointY(), 3/scaleMiniRoute, fillBlack);
|
||||
canvas.drawPath(routeLayer.getPath(), paintMiniRoute);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
// draw route information
|
||||
drawRouteInfo(canvas);
|
||||
|
||||
// draw compass the last because it use rotating
|
||||
canvas.drawRoundRect(boundsForCompass, 3, 3, paintAlphaGray);
|
||||
|
@ -198,9 +206,85 @@ public class MapInfoLayer implements OsmandMapLayer {
|
|||
canvas.rotate(view.getRotate(), 15, 15);
|
||||
canvas.drawPath(pathForCompass2, fillRed);
|
||||
canvas.drawPath(pathForCompass, fillBlack);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void calcTurnPath(TurnType turnType){
|
||||
pathForTurn.reset();
|
||||
// if(turnType == TurnType.C){
|
||||
int c = (int) ((boundsForMiniRoute.right - boundsForMiniRoute.left) /2 + boundsForMiniRoute.left);
|
||||
pathForTurn.moveTo(c + 8, boundsForMiniRoute.bottom - 32);
|
||||
pathForTurn.lineTo(c + 8, boundsForMiniRoute.top + 32);
|
||||
pathForTurn.lineTo(c + 20, boundsForMiniRoute.top + 32);
|
||||
pathForTurn.lineTo(c, boundsForMiniRoute.top + 5);
|
||||
pathForTurn.lineTo(c - 20, boundsForMiniRoute.top + 32);
|
||||
pathForTurn.lineTo(c - 8, boundsForMiniRoute.top + 32);
|
||||
pathForTurn.lineTo(c - 8, boundsForMiniRoute.bottom - 32);
|
||||
pathForTurn.close();
|
||||
// }
|
||||
}
|
||||
|
||||
private void drawRouteInfo(Canvas canvas) {
|
||||
if(routeLayer != null && routeLayer.getHelper().isRouterEnabled()){
|
||||
if (showMiniMap) {
|
||||
if (!routeLayer.getPath().isEmpty()) {
|
||||
canvas.save();
|
||||
canvas.clipRect(boundsForMiniRoute);
|
||||
canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintAlphaGray);
|
||||
canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintBlack);
|
||||
canvas.translate(centerMiniRouteX - view.getCenterPointX(), centerMiniRouteY - view.getCenterPointY());
|
||||
canvas.scale(scaleMiniRoute, scaleMiniRoute, view.getCenterPointX(), view.getCenterPointY());
|
||||
canvas.rotate(view.getRotate(), view.getCenterPointX(), view.getCenterPointY());
|
||||
canvas.drawCircle(view.getCenterPointX(), view.getCenterPointY(), 3 / scaleMiniRoute, fillBlack);
|
||||
canvas.drawPath(routeLayer.getPath(), paintMiniRoute);
|
||||
canvas.restore();
|
||||
}
|
||||
} else {
|
||||
int d = routeLayer.getHelper().getDistanceToNextRouteDirection();
|
||||
if(d > 0){
|
||||
canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintAlphaGray);
|
||||
canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintBlack);
|
||||
RouteDirectionInfo next = routeLayer.getHelper().getNextRouteDirectionInfo();
|
||||
if(next != null){
|
||||
calcTurnPath(next.turnType);
|
||||
canvas.drawPath(pathForTurn, paintRouteDirection);
|
||||
canvas.drawPath(pathForTurn, paintBlack);
|
||||
canvas.drawText(MapUtils.getFormattedDistance(d),
|
||||
boundsForMiniRoute.left + 10, boundsForMiniRoute.bottom - 9, paintBlack);
|
||||
}
|
||||
} else {
|
||||
// TEST
|
||||
// canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintAlphaGray);
|
||||
// canvas.drawRoundRect(boundsForMiniRoute, 3, 3, paintBlack);
|
||||
// calcTurnPath(TurnType.C);
|
||||
// canvas.drawPath(pathForTurn, paintRouteDirection);
|
||||
// canvas.drawPath(pathForTurn, paintBlack);
|
||||
// canvas.drawText(MapUtils.getFormattedDistance(300),
|
||||
// boundsForMiniRoute.left + 10, boundsForMiniRoute.bottom - 9, paintBlack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int time = routeLayer.getHelper().getLeftTime() * 1000;
|
||||
if(time == 0){
|
||||
cachedLeftTime = 0;
|
||||
cachedLeftTimeString = null;
|
||||
} else {
|
||||
if(Math.abs(System.currentTimeMillis() + time - cachedLeftTime) > 30000){
|
||||
cachedLeftTime = System.currentTimeMillis() + time;
|
||||
cachedLeftTimeString = DateFormat.format("k:mm", cachedLeftTime).toString(); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
if(cachedLeftTimeString != null) {
|
||||
int w = (int) (boundsForLeftTime.right - boundsForLeftTime.left);
|
||||
boundsForLeftTime.right = view.getWidth();
|
||||
boundsForLeftTime.left = view.getWidth() - w;
|
||||
canvas.drawRoundRect(boundsForLeftTime, 3, 3, paintAlphaGray);
|
||||
canvas.drawRoundRect(boundsForLeftTime, 3, 3, paintBlack);
|
||||
canvas.drawText(cachedLeftTimeString, boundsForLeftTime.left + 5, boundsForLeftTime.bottom - 9, paintBlack);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -220,6 +304,11 @@ public class MapInfoLayer implements OsmandMapLayer {
|
|||
|
||||
@Override
|
||||
public boolean onTouchEvent(PointF point) {
|
||||
if(boundsForMiniRoute.contains(point.x, point.y) && routeLayer != null && routeLayer.getHelper().isRouterEnabled()){
|
||||
showMiniMap = !showMiniMap;
|
||||
view.refreshMap();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,10 @@ public class RouteLayer implements OsmandMapLayer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RoutingHelper getHelper() {
|
||||
return helper;
|
||||
}
|
||||
|
||||
|
||||
// to show further direction
|
||||
|
|
Loading…
Reference in a new issue