fix small issues

add route information for YOURS (when only points are provided)

git-svn-id: https://osmand.googlecode.com/svn/trunk@302 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-07-08 12:01:58 +00:00
parent fa774610ad
commit f3ad1ac635
11 changed files with 221 additions and 29 deletions

View file

@ -16,9 +16,9 @@ public class ToDoConstants {
// TODO ANDROID
// 61. Provide route information for YOURS (calclate turns/angle/expected time).
// Fix some missing turns in CloudMade (for secondary roads wo name). Add them (if dist to prev/next turn > 150m) [dacha]
// 60. Audio guidance for routing
// 61. Provide route information for YOURS (calclate turns/angle/expected time) [done]
// Fix some missing turns in CloudMade (for secondary roads wo name). Add them (if dist to prev/next turn > 150m) [dacha] !
// 60. Audio guidance for routing !
// 43. Enable poi filter by name
// 58. Upload/Download zip-index from site & unzip them on phone
@ -29,15 +29,14 @@ public class ToDoConstants {
// 66. Transport routing (show next stop, total distance, show stop get out) (?).
// 64. Traffic information (?)
// 65. Intermediate points (?)
// 65. Intermediate points - for better control routing, to avoid traffic jam ...(?)
// 40. Support simple vector road rendering (require new index file) (?)
// 63. Support simple offline routing(require new index file) (?)
// FIXME BUGS Android
// 1. Fix bugs with test data (bug with follow turn / left time / add turn)
// 2. Improvement : Show stops in the transport route
// 3. Pinch zoom
// 1. Improvement : Show stops in the transport route
// 2. Pinch zoom !!!
// TODO swing
// 9. Fix issues with big files (such as netherlands) - save memory (!) - very slow due to transport index !

View file

@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.osmand" android:versionName="0.2.1" android:versionCode="4">
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:debuggable="false" android:name=".activities.OsmandApplication" android:description="@string/app_description">
android:debuggable="true" android:name=".activities.OsmandApplication" android:description="@string/app_description">
<activity android:name=".activities.MainMenuActivity"
android:label="@string/app_name">
<intent-filter>

View file

@ -1,5 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="route_tr">Поверните направо и двигайтесь</string>
<string name="route_tshr">Поверните резко направо и двигайтесь</string>
<string name="route_tslr">Поверните направо и двигайтесь</string>
<string name="route_tl">Поверните налево и двигайтесь</string>
<string name="route_tshl">Поверните резко налево и двигайтесь</string>
<string name="route_tsll">Поверните налево и двигайтесь</string>
<string name="route_tu">Выполните разворот и двигайтесь</string>
<string name="route_head">Двигайтесь</string>
<string name="first_time_continue">Продолжить</string>
<string name="first_time_download">Загрузить индексы</string>
<string name="first_time_msg">Спасибо за то, что выбрали OsmAnd. \n
@ -102,10 +110,10 @@
<string name="loading">Загрузка</string>
<string name="poi">POI</string>
<string name="error_occurred_saving_gpx">Ошибка во время сохранения пути в gpx</string>
<string name="error_calculating_route">Ошибка прокладки маршрута : </string>
<string name="error_calculating_route">Ошибка прокладки маршрута</string>
<string name="error_calculating_route_occured">Ошибка во время прокладки маршрута</string>
<string name="empty_route_calculated">Пустой путь рассчитан</string>
<string name="new_route_calculated_dist">Проложен новый путь, расстояние : </string>
<string name="new_route_calculated_dist">Проложен новый путь, расстояние</string>
<string name="arrived_at_destination">Вы прибыли в пункт назначения</string>
<string name="invalid_locations">Координаты неправильные</string>
<string name="go_back_to_osmand">Вернуться к OsmAnd карте</string>
@ -114,7 +122,7 @@
<string name="reading_indexes">Чтение индексов...</string>
<string name="previous_run_crashed">Предыдущий запуск приложения был неудачен. Лог файл в {0}. Пожалуйста откройте баг и присоедините лог файл.</string>
<string name="saving_gpx_tracks">Сохранение gpx путей на SD...</string>
<string name="finished_task">Окончен : </string>
<string name="finished_task">Окончен</string>
<string name="reload_indexes_descr">Перезагрузить индексы с SD</string>
<string name="reload_indexes">Обновить индексы</string>
<string name="download_indexes_descr">Загрузить индекс файлы из интернета</string>

View file

@ -1,5 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="route_tr">Turn right and go</string>
<string name="route_tshr">Turn sharply right and go</string>
<string name="route_tslr">Turn slightly right and go</string>
<string name="route_tl">Turn left and go</string>
<string name="route_tshl">Turn sharply left and go</string>
<string name="route_tsll">Turn slightly left and go</string>
<string name="route_tu">Make U-turn and go</string>
<string name="route_head">Head</string>
<string name="first_time_continue">Continue</string>
<string name="first_time_download">Download indexes</string>
<string name="first_time_msg">Thank you for choosing OsmAnd. \nTo be able to use all features of application you need index files, which you can download (Settings/Data) or prepare by yourself. After that you can use : search by address, search POI, search transport.</string>
@ -101,10 +109,10 @@ See osmand.googlecode.com.</string>
<string name="loading">Loading</string>
<string name="poi">POI</string>
<string name="error_occurred_saving_gpx">Error occurred while saving gpx</string>
<string name="error_calculating_route">Error calculating route : </string>
<string name="error_calculating_route">Error calculating route</string>
<string name="error_calculating_route_occured">Error occurred while calculating route</string>
<string name="empty_route_calculated">Empty route is calculated</string>
<string name="new_route_calculated_dist">New route is calculated, distance : </string>
<string name="new_route_calculated_dist">New route is calculated, distance</string>
<string name="arrived_at_destination">You arrived at destination point</string>
<string name="invalid_locations">Locations are invalid</string>
<string name="go_back_to_osmand">Go back to OsmAnd map</string>
@ -113,7 +121,7 @@ See osmand.googlecode.com.</string>
<string name="reading_indexes">Reading indices...</string>
<string name="previous_run_crashed">Previous application run was crashed. Log file is at {0}. Please raise the issue and attach log file.</string>
<string name="saving_gpx_tracks">Saving gpx tracks to SD...</string>
<string name="finished_task">Finished : </string>
<string name="finished_task">Finished</string>
<string name="reload_indexes_descr">Reload data indexes from SD</string>
<string name="reload_indexes">Reload indexes</string>
<string name="download_indexes_descr">Download indexes from internet</string>

View file

@ -108,7 +108,7 @@ public class ProgressDialogImplementation implements IProgress {
@Override
public void finishTask() {
if (taskName != null) {
message = context.getResources().getString(R.string.finished_task) + taskName;
message = context.getResources().getString(R.string.finished_task) +" : "+ taskName; //$NON-NLS-1$
mViewUpdateHandler.sendEmptyMessage(0);
}
work = -1;

View file

@ -194,10 +194,10 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
savingTrackHelper = new SavingTrackHelper(this);
locationLayer.setAppMode(OsmandSettings.getApplicationMode(this));
LatLon pointToNavigate = OsmandSettings.getPointToNavigate(this);
routingHelper.setAppMode(OsmandSettings.getApplicationMode(this));
if(!Algoritms.objectEquals(routingHelper.getFinalLocation(), pointToNavigate)){
// there is no way how to clear mode. Only user can do : clear point to navigate, exit from app & set up new point.
// that case help to not calculate route at all.
@ -566,6 +566,9 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
if(!OsmandSettings.isShowingViewAngle(this)){
locationLayer.setHeading(null);
}
locationLayer.setAppMode(OsmandSettings.getApplicationMode(this));
routingHelper.setAppMode(OsmandSettings.getApplicationMode(this));
poiMapLayer.setFilter(OsmandSettings.getPoiFilterForMap(this));
mapView.setMapPosition(OsmandSettings.getPositionOnMap(this));
SharedPreferences prefs = getSharedPreferences(OsmandSettings.SHARED_PREFERENCES_NAME, MODE_WORLD_READABLE);

View file

@ -21,13 +21,16 @@ import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.content.Context;
import android.location.Location;
import com.osmand.LogUtil;
import com.osmand.R;
import com.osmand.OsmandSettings.ApplicationMode;
import com.osmand.activities.RoutingHelper.RouteDirectionInfo;
import com.osmand.activities.RoutingHelper.TurnType;
import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils;
public class RouteProvider {
private static final org.apache.commons.logging.Log log = LogUtil.getLog(RouteProvider.class);
@ -49,7 +52,7 @@ public class RouteProvider {
public static class RouteCalculationResult {
private final List<Location> locations;
private final List<RouteDirectionInfo> directions;
private List<RouteDirectionInfo> directions;
private final String errorMessage;
private int[] listDistance = null;
@ -108,7 +111,7 @@ public class RouteProvider {
}
public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, ApplicationMode mode, RouteService type){
public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, ApplicationMode mode, RouteService type, Context ctx){
long time = System.currentTimeMillis();
if (start != null && end != null) {
if(log.isInfoEnabled()){
@ -118,8 +121,11 @@ public class RouteProvider {
RouteCalculationResult res;
if (type == RouteService.YOURS) {
res = findYOURSRoute(start, end, mode);
addMissingTurnsToRoute(res, mode, ctx);
} else {
res = findCloudMadeRoute(start, end, mode);
// for test purpose
addMissingTurnsToRoute(res, mode, ctx);
}
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$
@ -135,6 +141,150 @@ public class RouteProvider {
}
return new RouteCalculationResult(null);
}
protected String getString(Context ctx, int resId){
if(ctx == null){
return ""; //$NON-NLS-1$
}
return ctx.getString(resId);
}
protected void addMissingTurnsToRoute(RouteCalculationResult res, ApplicationMode mode, Context ctx){
if(!res.isCalculated()){
return;
}
// speed m/s
float speed = 1.5f;
int minDistanceForTurn = 5;
if(mode == ApplicationMode.CAR){
speed = 15.3f;
minDistanceForTurn = 25;
} else if(mode == ApplicationMode.BICYCLE){
speed = 5.5f;
minDistanceForTurn = 12;
}
List<RouteDirectionInfo> directions = new ArrayList<RouteDirectionInfo>();
int[] listDistance = res.getListDistance();
List<Location> locations = res.getLocations();
int previousLocation = 0;
int prevBearingLocation = 0;
RouteDirectionInfo previousInfo = new RouteDirectionInfo();
previousInfo.turnType = TurnType.valueOf(TurnType.C);
previousInfo.routePointOffset = 0;
previousInfo.descriptionRoute = getString(ctx, R.string.route_head);
directions.add(previousInfo);
int distForTurn = 0;
float previousBearing = 0;
int startTurnPoint = 0;
for (int i = 1; i < locations.size() - 1; i++) {
Location next = locations.get(i + 1);
Location current = locations.get(i);
float bearing = current.bearingTo(next);
// try to get close to current location if possible
while(prevBearingLocation < i - 1){
if(locations.get(prevBearingLocation + 1).distanceTo(current) > 70){
prevBearingLocation ++;
} else {
break;
}
}
if(distForTurn == 0){
// measure only after turn
previousBearing = locations.get(prevBearingLocation).bearingTo(current);
startTurnPoint = i;
}
TurnType type = null;
String description = null;
float delta = previousBearing - bearing;
while(delta < 0){
delta += 360;
}
while(delta > 360){
delta -= 360;
}
distForTurn += locations.get(i).distanceTo(locations.get(i + 1));
if (i < locations.size() - 1 && distForTurn < minDistanceForTurn) {
// For very smooth turn we try to accumulate whole distance
// simply skip that turn needed for situation
// 1) if you are going to have U-turn - not 2 left turns
// 2) if there is a small gap between roads (turn right and after 4m next turn left) - so the direction head
continue;
}
if(delta > 50 && delta < 310){
if(delta < 70){
type = TurnType.valueOf(TurnType.TSLL);
description = getString(ctx, R.string.route_tsll);
} else if(delta < 110){
type = TurnType.valueOf(TurnType.TL);
description = getString(ctx, R.string.route_tl);
} else if(delta < 125){
type = TurnType.valueOf(TurnType.TSHL);
description = getString(ctx, R.string.route_tshl);
} else if(delta < 225){
type = TurnType.valueOf(TurnType.TU);
description = getString(ctx, R.string.route_tu);
} else if(delta < 250){
description = getString(ctx, R.string.route_tshr);
type = TurnType.valueOf(TurnType.TSHR);
} else if(delta < 290){
description = getString(ctx, R.string.route_tr);
type = TurnType.valueOf(TurnType.TR);
} else {
description = getString(ctx, R.string.route_tslr);
type = TurnType.valueOf(TurnType.TSLR);
}
// calculate for previousRoute
previousInfo.distance = listDistance[previousLocation]- listDistance[i];
previousInfo.expectedTime = (int) (previousInfo.distance / speed);
previousInfo.descriptionRoute += " " + MapUtils.getFormattedDistance(previousInfo.distance); //$NON-NLS-1$
previousInfo = new RouteDirectionInfo();
previousInfo.turnType = type;
previousInfo.turnType.setTurnAngle(360 - delta);
previousInfo.descriptionRoute = description;
previousInfo.routePointOffset = startTurnPoint;
directions.add(previousInfo);
previousLocation = startTurnPoint;
prevBearingLocation = i; // for bearing using current location
}
// clear dist for turn
distForTurn = 0;
}
previousInfo.distance = listDistance[previousLocation];
previousInfo.expectedTime = (int) (previousInfo.distance / speed);
previousInfo.descriptionRoute += " " + MapUtils.getFormattedDistance(previousInfo.distance); //$NON-NLS-1$
int sum = 0;
for (int i = directions.size() - 1; i >= 0; i--) {
directions.get(i).afterLeftTime = sum;
sum += directions.get(i).expectedTime;
}
if(res.directions == null || res.directions.isEmpty()){
res.directions = new ArrayList<RouteDirectionInfo>(directions);
} else {
// TODO try to add missing turns
// res.directions = new ArrayList<RouteDirectionInfo>(directions);
}
}
protected RouteCalculationResult findYOURSRoute(Location start, LatLon end, ApplicationMode mode) throws MalformedURLException, IOException,

View file

@ -215,6 +215,21 @@ public class RoutingHelper {
updateCurrentRoute(currentRoute + 1);
}
}
// 3.5 check that we already pass very sharp turn by missing one point (so our turn is sharper than expected)
// instead of that rule possible could be introduced another if the dist < 5m mark the location as already passed
if(currentRoute + 2 < routeNodes.size()){
float bearing = routeNodes.get(currentRoute + 1).bearingTo(routeNodes.get(currentRoute + 2));
float bearingMovement = currentLocation.bearingTo(routeNodes.get(currentRoute + 1));
// only 15 degrees for that case because it wrong catches sharp turns
if(Math.abs(bearing - bearingMovement) > 165 && Math.abs(bearing - bearingMovement) < 195){
if(log.isDebugEnabled()){
log.debug("Processed point movement bearing 2 : "+bearingMovement +" bearing " + bearing); //$NON-NLS-1$ //$NON-NLS-2$
}
updateCurrentRoute(currentRoute + 2);
}
}
// 4. evaluate distance to the route and reevaluate if needed
if(currentRoute > 0){
float bearing = routeNodes.get(currentRoute - 1).bearingTo(routeNodes.get(currentRoute));
@ -350,7 +365,7 @@ public class RoutingHelper {
currentRunningJob = new Thread(new Runnable() {
@Override
public void run() {
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service);
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, activity);
synchronized (RoutingHelper.this) {
if (res.isCalculated()) {
setNewRoute(res);
@ -368,14 +383,14 @@ public class RoutingHelper {
if (res.isCalculated()) {
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));
showMessage(activity.getString(R.string.new_route_calculated_dist) +" : "+ MapUtils.getFormattedDistance(l)); //$NON-NLS-1$
if (activity instanceof MapActivity) {
// be aware that is non ui thread
((MapActivity) activity).getMapView().refreshMap();
}
} else {
if (res.getErrorMessage() != null) {
showMessage(activity.getString(R.string.error_calculating_route) + res.getErrorMessage());
showMessage(activity.getString(R.string.error_calculating_route)+" : " + res.getErrorMessage()); //$NON-NLS-1$
} else if (res.getLocations() == null) {
showMessage(activity.getString(R.string.error_calculating_route_occured));
} else {
@ -508,11 +523,18 @@ public class RoutingHelper {
public static class RouteDirectionInfo {
public String descriptionRoute = ""; //$NON-NLS-1$
// expected time after route point
public int expectedTime;
public TurnType turnType;
// location when you should action (turn or go ahead)
public int routePointOffset;
// calculated vars
// after action (for i.e. after turn to next turn)
public int afterLeftTime;
// distance after action (for i.e. after turn to next turn)
public int distance;
}

View file

@ -4,6 +4,7 @@
package com.osmand.activities;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.List;
import android.app.ListActivity;
@ -39,9 +40,6 @@ import com.osmand.views.MapInfoLayer;
*/
public class ShowRouteInfoActivity extends ListActivity {
@Override
public void onCreate(Bundle icicle) {
@ -50,7 +48,8 @@ public class ShowRouteInfoActivity extends ListActivity {
lv.setId(android.R.id.list);
TextView header = new TextView(this);
RoutingHelper helper = RoutingHelper.getInstance(this);
int time = helper.getLeftTime()* 1000;
Calendar c = Calendar.getInstance();
int time = helper.getLeftTime() * 1000 - c.getTimeZone().getOffset(0);
int dist = helper.getLeftDistance();
header.setText(MessageFormat.format(getString(R.string.route_general_information), MapUtils.getFormattedDistance(dist),
DateFormat.format("kk:mm", time))); //$NON-NLS-1$
@ -138,7 +137,7 @@ public class ShowRouteInfoActivity extends ListActivity {
if(model.expectedTime < 3600){
timeLabel.setText(DateFormat.format("mm:ss", model.expectedTime * 1000)); //$NON-NLS-1$
} else {
timeLabel.setText(DateFormat.format("k:mm:ss", model.expectedTime * 1000)); //$NON-NLS-1$
timeLabel.setText(DateFormat.format("kk:mm:ss", model.expectedTime * 1000)); //$NON-NLS-1$
}
return row;
}

View file

@ -1,5 +1,7 @@
package com.osmand.views;
import java.util.Calendar;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
@ -270,7 +272,8 @@ public class MapInfoLayer implements OsmandMapLayer {
}
if(Math.abs(toFindTime - cachedLeftTime) > 30000){
cachedLeftTime = toFindTime;
cachedLeftTimeString = DateFormat.format("kk:mm", cachedLeftTime).toString(); //$NON-NLS-1$
Calendar c = Calendar.getInstance();
cachedLeftTimeString = DateFormat.format("kk:mm", cachedLeftTime - c.getTimeZone().getOffset(0) ).toString(); //$NON-NLS-1$
}
}
if(cachedLeftTimeString != null) {

View file

@ -86,7 +86,7 @@ public class PointLocationLayer implements OsmandMapLayer {
if(appMode == ApplicationMode.CAR){
if(!lastKnownLocation.hasBearing()){
canvas.drawCircle(locationX, locationY, RADIUS * 2.5f, location);
canvas.drawCircle(locationX, locationY, RADIUS, bearingOver);
canvas.drawCircle(locationX, locationY, RADIUS * 2.5f, bearingOver);
}
} else {
canvas.drawCircle(locationX, locationY, RADIUS, location);