start implementing following directions

git-svn-id: https://osmand.googlecode.com/svn/trunk@204 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-06-24 21:19:51 +00:00
parent ecc99d0dde
commit 497bd6bf3e
5 changed files with 500 additions and 160 deletions

View file

@ -76,6 +76,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
private boolean providerSupportsBearing = false; private boolean providerSupportsBearing = false;
private boolean providerSupportsSpeed = false; private boolean providerSupportsSpeed = false;
private String currentLocationProvider = null;
/** Called when the activity is first created. */ /** Called when the activity is first created. */
private OsmandMapTileView mapView; private OsmandMapTileView mapView;
@ -462,15 +463,24 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
if(LocationProvider.OUT_OF_SERVICE == status){ if(LocationProvider.OUT_OF_SERVICE == status){
setLocation(null); setLocation(null);
} }
service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this); if(!isRunningOnEmulator() && service.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator(); if(!Algoritms.objectEquals(currentLocationProvider, LocationManager.NETWORK_PROVIDER)){
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator(); 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) { } else if (LocationProvider.AVAILABLE == status) {
service.removeUpdates(this); if(!Algoritms.objectEquals(currentLocationProvider, LocationManager.GPS_PROVIDER)){
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this); currentLocationProvider = LocationManager.GPS_PROVIDER;
prov = service.getProvider(LocationManager.GPS_PROVIDER); service.removeUpdates(this);
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator(); service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator(); prov = service.getProvider(LocationManager.GPS_PROVIDER);
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
}
} }
} }
} }

View 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;
}
}

View file

@ -1,22 +1,8 @@
package com.osmand.activities; 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.ArrayList;
import java.util.List; 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.location.Location;
import android.util.FloatMath; import android.util.FloatMath;
import android.widget.Toast; import android.widget.Toast;
@ -24,6 +10,7 @@ import android.widget.Toast;
import com.osmand.LogUtil; import com.osmand.LogUtil;
import com.osmand.R; import com.osmand.R;
import com.osmand.OsmandSettings.ApplicationMode; import com.osmand.OsmandSettings.ApplicationMode;
import com.osmand.activities.RouteProvider.RouteCalculationResult;
import com.osmand.osm.LatLon; import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils; import com.osmand.osm.MapUtils;
@ -34,8 +21,14 @@ public class RoutingHelper {
// activity to show messages & refresh map when route is calculated // activity to show messages & refresh map when route is calculated
private MapActivity activity; private MapActivity activity;
// instead of this properties RouteCalculationResult could be used
private List<Location> routeNodes = new ArrayList<Location>(); private List<Location> routeNodes = new ArrayList<Location>();
private List<RouteDirectionInfo> directionInfo = null;
private int[] listDistance = 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; private int currentRoute = 0;
@ -47,6 +40,8 @@ public class RoutingHelper {
private ApplicationMode mode; private ApplicationMode mode;
private RouteProvider provider = new RouteProvider();
// TEST CODE // TEST CODE
// private static List<Location> testRoute = new ArrayList<Location>(); // private static List<Location> testRoute = new ArrayList<Location>();
@ -80,6 +75,7 @@ public class RoutingHelper {
this.finalLocation = finalLocation; this.finalLocation = finalLocation;
this.routeNodes.clear(); this.routeNodes.clear();
listDistance = null; listDistance = null;
directionInfo = null;
evalWaitInterval = 3000; evalWaitInterval = 3000;
// to update route // to update route
setCurrentLocation(currentLocation); setCurrentLocation(currentLocation);
@ -114,7 +110,7 @@ public class RoutingHelper {
if(activity != null){ if(activity != null){
showMessage(activity.getString(R.string.arrived_at_destination)); 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 // clear final location to prevent all time showing message
finalLocation = null; finalLocation = null;
} }
@ -128,6 +124,17 @@ public class RoutingHelper {
return lastFixedLocation; 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) { public void setCurrentLocation(Location currentLocation) {
if(finalLocation == null || currentLocation == null){ if(finalLocation == null || currentLocation == null){
@ -138,13 +145,15 @@ public class RoutingHelper {
if(routeNodes.isEmpty() || routeNodes.size() <= currentRoute){ if(routeNodes.isEmpty() || routeNodes.size() <= currentRoute){
calculateRoute = true; calculateRoute = true;
} else { } else {
// Check whether user follow by route in correct direction
// 1. try to mark passed route (move forward) // 1. try to mark passed route (move forward)
float dist = currentLocation.distanceTo(routeNodes.get(currentRoute)); float dist = currentLocation.distanceTo(routeNodes.get(currentRoute));
while(currentRoute + 1 < routeNodes.size()){ while(currentRoute + 1 < routeNodes.size()){
float newDist = currentLocation.distanceTo(routeNodes.get(currentRoute + 1)); float newDist = currentLocation.distanceTo(routeNodes.get(currentRoute + 1));
if (newDist < dist) { if (newDist < dist) {
// that node already passed // that node already passed
currentRoute++; updateCurrentRoute(currentRoute + 1);
dist = newDist; dist = newDist;
} else { } else {
break; break;
@ -160,7 +169,7 @@ public class RoutingHelper {
float bearing = routeNodes.get(currentRoute).bearingTo(routeNodes.get(currentRoute + 1)); float bearing = routeNodes.get(currentRoute).bearingTo(routeNodes.get(currentRoute + 1));
float bearingMovement = currentLocation.bearingTo(routeNodes.get(currentRoute)); float bearingMovement = currentLocation.bearingTo(routeNodes.get(currentRoute));
if(Math.abs(bearing - bearingMovement) > 130 && Math.abs(bearing - bearingMovement) < 230){ 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 // 4. evaluate distance to the route and reevaluate if needed
@ -214,16 +223,11 @@ public class RoutingHelper {
} }
} }
private void setNewRoute(List<Location> locations){ private void setNewRoute(RouteCalculationResult res){
routeNodes = locations; routeNodes = res.getLocations();
listDistance = new int[locations.size()]; directionInfo = res.getDirections();
if (!locations.isEmpty()) { listDistance = res.getListDistance();
listDistance[locations.size() - 1] = 0; currentDirectionInfo = 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; currentRoute = 0;
} }
@ -237,6 +241,46 @@ public class RoutingHelper {
return 0; 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){ public void calculateRoute(final Location start, final LatLon end){
if(currentRunningJob == null){ if(currentRunningJob == null){
// do not evaluate very often // do not evaluate very often
@ -245,10 +289,10 @@ public class RoutingHelper {
currentRunningJob = new Thread(new Runnable() { currentRunningJob = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
RouteCalculationResult res = calculateRouteImpl(start, end); RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode);
synchronized (RoutingHelper.this) { synchronized (RoutingHelper.this) {
if (res.isCalculated()) { if (res.isCalculated()) {
setNewRoute(res.list); setNewRoute(res);
// reset error wait interval // reset error wait interval
evalWaitInterval = 3000; evalWaitInterval = 3000;
} else { } else {
@ -261,13 +305,15 @@ public class RoutingHelper {
} }
if (activity != null) { if (activity != null) {
if (res.isCalculated()) { 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 // be aware that is non ui thread
activity.getMapView().refreshMap(); activity.getMapView().refreshMap();
} else { } else {
if (res.errorMessage != null) { if (res.getErrorMessage() != null) {
showMessage(activity.getString(R.string.error_calculating_route) + res.errorMessage); showMessage(activity.getString(R.string.error_calculating_route) + res.getErrorMessage());
} else if (res.list == null) { } else if (res.getLocations() == null) {
showMessage(activity.getString(R.string.error_calculating_route_occured)); showMessage(activity.getString(R.string.error_calculating_route_occured));
} else { } else {
showMessage(activity.getString(R.string.empty_route_calculated)); 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){ private void showMessage(final String msg){
if (activity != null) { if (activity != null) {
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@ -344,93 +380,28 @@ 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){ public static class RouteDirectionInfo {
long time = System.currentTimeMillis(); public String descriptionRoute;
if (start != null && end != null) { public int expectedTime;
List<Location> res = new ArrayList<Location>(); public float turnAngle;
if(log.isInfoEnabled()){ public TurnType turnType;
log.info("Start finding route from " + start + " to " + end); //$NON-NLS-1$ //$NON-NLS-2$ public int routePointOffset;
} public int afterLeftTime;
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);
} }

View file

@ -8,33 +8,46 @@ import android.graphics.PointF;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.location.Location; import android.location.Location;
import android.text.format.DateFormat;
import com.osmand.Messages; import com.osmand.Messages;
import com.osmand.activities.MapActivity; import com.osmand.activities.MapActivity;
import com.osmand.activities.RoutingHelper.RouteDirectionInfo;
import com.osmand.activities.RoutingHelper.TurnType;
import com.osmand.osm.MapUtils; import com.osmand.osm.MapUtils;
public class MapInfoLayer implements OsmandMapLayer { public class MapInfoLayer implements OsmandMapLayer {
private OsmandMapTileView view; private OsmandMapTileView view;
private boolean showMiniMap = false;
private final MapActivity map; private final MapActivity map;
private final RouteLayer routeLayer; private final RouteLayer routeLayer;
private Paint paintBlack;
private Paint paintMiniRoute;
private Path pathForCompass; private Path pathForCompass;
private Path pathForCompass2; private Path pathForCompass2;
private Path pathForTurn;
private Paint paintBlack;
private Paint paintMiniRoute;
private Paint fillBlack; private Paint fillBlack;
private Paint fillRed; private Paint fillRed;
private Paint paintAlphaGray;
private Paint paintRouteDirection;
private RectF boundsForCompass; private RectF boundsForCompass;
private RectF boundsForZoom; private RectF boundsForZoom;
private RectF boundsForDist; private RectF boundsForDist;
private RectF boundsForMiniRoute; private RectF boundsForMiniRoute;
private RectF boundsForLeftTime;
private RectF boundsForSpeed; private RectF boundsForSpeed;
private Paint paintAlphaGray;
private String cachedLeftTimeString = null;
private long cachedLeftTime = 0;
private float[] calculations = new float[1]; private float[] calculations = new float[1];
private String cachedDistString = null; private String cachedDistString = null;
private int cachedMeters = 0; private int cachedMeters = 0;
@ -66,6 +79,11 @@ public class MapInfoLayer implements OsmandMapLayer {
paintAlphaGray.setColor(Color.LTGRAY); paintAlphaGray.setColor(Color.LTGRAY);
paintAlphaGray.setAlpha(180); // do not make very transparent (to hide route) 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 = new Paint();
fillBlack.setStyle(Style.FILL_AND_STROKE); fillBlack.setStyle(Style.FILL_AND_STROKE);
fillBlack.setColor(Color.BLACK); fillBlack.setColor(Color.BLACK);
@ -86,8 +104,10 @@ public class MapInfoLayer implements OsmandMapLayer {
boundsForDist = new RectF(35, 0, 110, 32); boundsForDist = new RectF(35, 0, 110, 32);
boundsForZoom = new RectF(0, 32, 35, 64); boundsForZoom = new RectF(0, 32, 35, 64);
boundsForSpeed = new RectF(35, 32, 110, 64); boundsForSpeed = new RectF(35, 32, 110, 64);
boundsForMiniRoute = new RectF(0, 64, 96, 196); boundsForMiniRoute = new RectF(0, 64, 96, 196);
boundsForLeftTime = new RectF(0, 0, 75, 32);
centerMiniRouteX = 48; centerMiniRouteX = 48;
centerMiniRouteY= 160; centerMiniRouteY= 160;
scaleMiniRoute = 0.15f; scaleMiniRoute = 0.15f;
@ -103,6 +123,8 @@ public class MapInfoLayer implements OsmandMapLayer {
pathForCompass2.lineTo(22f, 15.5f); pathForCompass2.lineTo(22f, 15.5f);
pathForCompass2.lineTo(15.5f, 2f); pathForCompass2.lineTo(15.5f, 2f);
pathForCompass2.lineTo(9, 15); pathForCompass2.lineTo(9, 15);
pathForTurn = new Path();
} }
public boolean distChanged(int oldDist, int dist){ public boolean distChanged(int oldDist, int dist){
@ -175,22 +197,8 @@ public class MapInfoLayer implements OsmandMapLayer {
} }
// draw route information
drawRouteInfo(canvas);
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 compass the last because it use rotating // draw compass the last because it use rotating
canvas.drawRoundRect(boundsForCompass, 3, 3, paintAlphaGray); canvas.drawRoundRect(boundsForCompass, 3, 3, paintAlphaGray);
@ -198,9 +206,85 @@ public class MapInfoLayer implements OsmandMapLayer {
canvas.rotate(view.getRotate(), 15, 15); canvas.rotate(view.getRotate(), 15, 15);
canvas.drawPath(pathForCompass2, fillRed); canvas.drawPath(pathForCompass2, fillRed);
canvas.drawPath(pathForCompass, fillBlack); 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 @Override
public boolean onTouchEvent(PointF point) { 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; return false;
} }

View file

@ -97,6 +97,10 @@ public class RouteLayer implements OsmandMapLayer {
} }
} }
public RoutingHelper getHelper() {
return helper;
}
// to show further direction // to show further direction
public Path getPath() { public Path getPath() {