Add basic intermediate support

This commit is contained in:
Victor Shcherb 2012-09-17 01:37:20 +02:00
parent aa2fe68d90
commit 4e99dd0ebf
42 changed files with 512 additions and 123 deletions

View file

@ -165,6 +165,10 @@ public class BinaryRoutePlanner {
return road; return road;
} }
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, List<RouteSegment> intermediate, boolean leftSideNavigation) throws IOException {
// TODO
return searchRoute(ctx, start, end, leftSideNavigation);
}
/** /**

View file

@ -36,6 +36,8 @@ and_arrive_destination == ['and arrive at your destination '].
then == ['then ']. then == ['then '].
reached_destination == ['you have reached your destination ']. reached_destination == ['you have reached your destination '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
bear_right == ['keep right ']. bear_right == ['keep right '].
bear_left == ['keep left ']. bear_left == ['keep left '].

View file

@ -38,8 +38,12 @@ roundabout(Dist, _Angle, Exit) == ['after-m.ogg', delay_300, D, delay_300, 'ente
roundabout(_Angle, Exit) == ['taking.ogg', delay_250, E, 'exit-e.ogg'] :- nth(Exit, E). roundabout(_Angle, Exit) == ['taking.ogg', delay_250, E, 'exit-e.ogg'] :- nth(Exit, E).
and_arrive_destination == ['arrive_at_your_destination-e.ogg']. % Miss and? and_arrive_destination == ['arrive_at_your_destination-e.ogg']. % Miss and?
then == ['then.ogg', delay_350].
reached_destination == ['you_have_reached_your_destination.ogg']. reached_destination == ['you_have_reached_your_destination.ogg'].
and_arrive_intermediate == ['arrive_at_viapoint-e.ogg'].
reached_intermediate == ['you_have_reached_a_viapoint.ogg'].
then == ['then.ogg', delay_350].
bear_right == ['keep_right-e.ogg']. bear_right == ['keep_right-e.ogg'].
bear_left == ['keep_left-e.ogg']. bear_left == ['keep_left-e.ogg'].
route_recalc(_Dist) == ['recalc.ogg']. %nothing to said possibly beep? route_recalc(_Dist) == ['recalc.ogg']. %nothing to said possibly beep?

View file

@ -38,6 +38,8 @@ roundabout(Dist, _Angle, Exit) == ['despues_de.ogg', delay_300, D, delay_300, 'e
roundabout(_Angle, Exit) == ['tomando la.ogg', delay_250, E, 'salida.ogg'] :- nth(Exit, E). roundabout(_Angle, Exit) == ['tomando la.ogg', delay_250, E, 'salida.ogg'] :- nth(Exit, E).
and_arrive_destination == ['destino.ogg']. % Miss and? and_arrive_destination == ['destino.ogg']. % Miss and?
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['entonces.ogg', delay_350]. then == ['entonces.ogg', delay_350].
reached_destination == ['llegado.ogg']. reached_destination == ['llegado.ogg'].
bear_right == ['mantener_derecha.ogg']. bear_right == ['mantener_derecha.ogg'].

View file

@ -42,6 +42,8 @@ go_ahead == ['Jatka suoraan '].
go_ahead(Dist) == ['Jatka suoraan ', D]:- distance(Dist, metria) == D. go_ahead(Dist) == ['Jatka suoraan ', D]:- distance(Dist, metria) == D.
and_arrive_destination == ['ja olet perillä ']. and_arrive_destination == ['ja olet perillä '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['sitten ']. then == ['sitten '].
reached_destination == ['olet perillä ']. reached_destination == ['olet perillä '].

View file

@ -36,6 +36,8 @@ and_arrive_destination == ['et arrivez à destination '].
then == ['puis ']. then == ['puis '].
reached_destination == ['vous êtes arrivé à destination ']. reached_destination == ['vous êtes arrivé à destination '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
bear_right == ['serrez à droite ']. bear_right == ['serrez à droite '].
bear_left == ['serrez à gauche ']. bear_left == ['serrez à gauche '].

View file

@ -33,6 +33,8 @@ go_ahead == [' सीधे आगे जाये '].
go_ahead(Dist) == [D, ' तक रास्ते का पालन करे ']:- distance(Dist) == D. go_ahead(Dist) == [D, ' तक रास्ते का पालन करे ']:- distance(Dist) == D.
and_arrive_destination == [' और अपनी मंजिल पर पहोचे ']. and_arrive_destination == [' और अपनी मंजिल पर पहोचे '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['और फिर ']. then == ['और फिर '].
reached_destination == ['आप अपनी मंजिल पर पहोच चुके है ']. reached_destination == ['आप अपनी मंजिल पर पहोच चुके है '].

View file

@ -33,6 +33,8 @@ go_ahead == ['Haladj tovább egyenesen '].
go_ahead(Dist) == ['Menj tovább ', D] :- distance(Dist, t) == D. go_ahead(Dist) == ['Menj tovább ', D] :- distance(Dist, t) == D.
and_arrive_destination == ['és megérkezel az úti célhoz ']. and_arrive_destination == ['és megérkezel az úti célhoz '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['majd ']. then == ['majd '].
reached_destination == ['megérkeztél az úti célhoz ']. reached_destination == ['megérkeztél az úti célhoz '].

View file

@ -33,6 +33,8 @@ go_ahead == ['Sempre dritto '].
go_ahead(Dist) == ['Sempre dritto per ', D]:- distance(Dist) == D. go_ahead(Dist) == ['Sempre dritto per ', D]:- distance(Dist) == D.
and_arrive_destination == ['e arrivate a destinazione']. and_arrive_destination == ['e arrivate a destinazione'].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == [', poi ']. then == [', poi '].
reached_destination == ['arrivato a destinazione']. reached_destination == ['arrivato a destinazione'].

View file

@ -33,6 +33,8 @@ go_ahead == ['직진을 계속하세요 '].
go_ahead(Dist) == [D, ' 직진하세요 ']:- distance(Dist) == D. go_ahead(Dist) == [D, ' 직진하세요 ']:- distance(Dist) == D.
and_arrive_destination == [' 다음은 목적지에 도착합니다 ']. % Miss and? and_arrive_destination == [' 다음은 목적지에 도착합니다 ']. % Miss and?
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == [', 다음은 ']. then == [', 다음은 '].
reached_destination == ['목적지에 도착하였습니다 ']. reached_destination == ['목적지에 도착하였습니다 '].

View file

@ -33,6 +33,8 @@ go_ahead == ['Dodaties taisni uz priekšu '].
go_ahead(Dist) == ['Brauciet pa ceļu ', D]:- distance2(Dist) == D. go_ahead(Dist) == ['Brauciet pa ceļu ', D]:- distance2(Dist) == D.
and_arrive_destination == ['un ierodaties galapunktā ']. and_arrive_destination == ['un ierodaties galapunktā '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['tad ']. then == ['tad '].
reached_destination == ['jūs esiet nokļuvis galapunktā ']. reached_destination == ['jūs esiet nokļuvis galapunktā '].

View file

@ -33,6 +33,8 @@ go_ahead == ['Verder dóorrijden '].
go_ahead(Dist) == ['De weg', D,'volgen']:- distance(Dist) == D. go_ahead(Dist) == ['De weg', D,'volgen']:- distance(Dist) == D.
and_arrive_destination == ['dan heeft u uw bestemming bereikt ']. and_arrive_destination == ['dan heeft u uw bestemming bereikt '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['dan ']. then == ['dan '].
reached_destination == ['Bestemming bereikt ']. reached_destination == ['Bestemming bereikt '].

View file

@ -33,6 +33,8 @@ go_ahead == ['Jedź prosto '].
go_ahead(Dist) == ['Jedź prosto ', D]:- distance(Dist) == D. go_ahead(Dist) == ['Jedź prosto ', D]:- distance(Dist) == D.
and_arrive_destination == ['następnie dojedź do celu ']. and_arrive_destination == ['następnie dojedź do celu '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['następnie ']. then == ['następnie '].
reached_destination == ['Cel został osiągnięty! ']. reached_destination == ['Cel został osiągnięty! '].

View file

@ -33,6 +33,8 @@ go_ahead == ['Продолжайте движение прямо '].
go_ahead(Dist) == ['Продолжайте движение ', D]:- distance(Dist) == D. go_ahead(Dist) == ['Продолжайте движение ', D]:- distance(Dist) == D.
and_arrive_destination == ['и вы прибудете в пункт назначения ']. and_arrive_destination == ['и вы прибудете в пункт назначения '].
and_arrive_intermediate == ['и вы прибудете в промежуточный пункт '].
reached_intermediate == ['вы прибыли в промежуточный пункт'].
then == ['затем ']. then == ['затем '].
reached_destination == ['вы прибыли в пункт назначения ']. reached_destination == ['вы прибыли в пункт назначения '].

View file

@ -40,6 +40,9 @@ roundabout(_Angle, Exit) == ['taking_the.ogg', delay_250, E, 'exit-e.ogg'] :- n
and_arrive_destination == ['arrive_at_your_destination-e.ogg']. % Miss and? and_arrive_destination == ['arrive_at_your_destination-e.ogg']. % Miss and?
then == ['then.ogg', delay_350]. then == ['then.ogg', delay_350].
reached_destination == ['you_have_reached_your_destination.ogg']. reached_destination == ['you_have_reached_your_destination.ogg'].
and_arrive_intermediate == ['arrive_at_viapoint-e.ogg'].
reached_intermediate == ['you_have_reached_a_viapoint.ogg'].
bear_right == ['keep_right-e.ogg']. bear_right == ['keep_right-e.ogg'].
bear_left == ['keep_left-e.ogg']. bear_left == ['keep_left-e.ogg'].
route_recalc(_Dist) == []. % ['recalc.ogg']. %nothing to said possibly beep? route_recalc(_Dist) == []. % ['recalc.ogg']. %nothing to said possibly beep?

View file

@ -37,8 +37,12 @@ roundabout(Dist, _Angle, Exit) == ['after-n.ogg',D, 'enter_the_roundabout-e.ogg'
roundabout(_Angle, Exit) == ['take_the.ogg', E, 'exit-e.ogg'] :- nth(Exit, E). roundabout(_Angle, Exit) == ['take_the.ogg', E, 'exit-e.ogg'] :- nth(Exit, E).
and_arrive_destination == ['then.ogg', delay_150, 'arrive_at_your_destination-e.ogg']. and_arrive_destination == ['then.ogg', delay_150, 'arrive_at_your_destination-e.ogg'].
then == ['then.ogg', delay_150].
reached_destination == ['you_have_reached_your_destination.ogg']. reached_destination == ['you_have_reached_your_destination.ogg'].
and_arrive_intermediate == ['arrive_at_viapoint-e.ogg'].
reached_intermediate == ['you_have_reached_a_viapoint.ogg'].
then == ['then.ogg', delay_150].
bear_right == ['keep_right-e.ogg']. bear_right == ['keep_right-e.ogg'].
location_lost == ['gps_signal_lost.ogg']. location_lost == ['gps_signal_lost.ogg'].
bear_left == ['keep_left-e.ogg']. bear_left == ['keep_left-e.ogg'].

View file

@ -40,6 +40,8 @@ go_ahead == ['pokračujte rovno'].
go_ahead(Dist) == ['pokračujte ', D]:- distance(Dist) == D. go_ahead(Dist) == ['pokračujte ', D]:- distance(Dist) == D.
and_arrive_destination == ['a dorazíte do cieľa']. and_arrive_destination == ['a dorazíte do cieľa'].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['potom ']. then == ['potom '].
reached_destination == ['dorazili ste do cieľa']. reached_destination == ['dorazili ste do cieľa'].

View file

@ -33,6 +33,8 @@ go_ahead == ['Kör rakt fram '].
go_ahead(Dist) == ['Följ den här vägen ', D]:- distance(Dist) == D. go_ahead(Dist) == ['Följ den här vägen ', D]:- distance(Dist) == D.
and_arrive_destination == ['och du är framme ']. and_arrive_destination == ['och du är framme '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['sedan ']. then == ['sedan '].
reached_destination == ['du är framme ']. reached_destination == ['du är framme '].

View file

@ -33,6 +33,8 @@ go_ahead == ['直直往前開 '].
go_ahead(Dist) == ['沿著馬路往前 ', D]:- distance(Dist) == D. go_ahead(Dist) == ['沿著馬路往前 ', D]:- distance(Dist) == D.
and_arrive_destination == ['然後可達終點 ']. and_arrive_destination == ['然後可達終點 '].
and_arrive_intermediate == ['and arrive at your via point '].
reached_intermediate == ['you have reached your via point'].
then == ['然後 ']. then == ['然後 '].
reached_destination == ['抵達終點 ']. reached_destination == ['抵達終點 '].

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -9,6 +9,10 @@
1. All your modified/created strings are in the top of the file (to make easier find what\'s translated). 1. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
--> -->
<string name="intermediate_point_too_far">Intermediate point %1$s too far from nearest road.</string>
<string name="arrived_at_intermediate_point">You have arrived at your intermediate point</string>
<string name="context_menu_item_intermediate_point">Add intermediate point</string>
<string name="map_widget_intermediate_distance">Intermediate point</string>
<string name="ending_point_too_far">Starting point too far from nearest road.</string> <string name="ending_point_too_far">Starting point too far from nearest road.</string>
<string name="btn_add_tag">Add Tag</string> <string name="btn_add_tag">Add Tag</string>
<string name="btn_advanced_mode">Advanced Mode...</string> <string name="btn_advanced_mode">Advanced Mode...</string>

View file

@ -2,6 +2,7 @@ package net.osmand.plus;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
@ -973,6 +974,7 @@ public class OsmandSettings {
public final static String POINT_NAVIGATE_LAT = "point_navigate_lat"; //$NON-NLS-1$ public final static String POINT_NAVIGATE_LAT = "point_navigate_lat"; //$NON-NLS-1$
public final static String POINT_NAVIGATE_LON = "point_navigate_lon"; //$NON-NLS-1$ public final static String POINT_NAVIGATE_LON = "point_navigate_lon"; //$NON-NLS-1$
public final static String POINT_NAVIGATE_ROUTE = "point_navigate_route"; //$NON-NLS-1$ public final static String POINT_NAVIGATE_ROUTE = "point_navigate_route"; //$NON-NLS-1$
public final static String INTERMEDIATE_POINTS = "intermediate_points"; //$NON-NLS-1$
public LatLon getPointToNavigate() { public LatLon getPointToNavigate() {
float lat = globalPreferences.getFloat(POINT_NAVIGATE_LAT, 0); float lat = globalPreferences.getFloat(POINT_NAVIGATE_LAT, 0);
@ -989,6 +991,52 @@ public class OsmandSettings {
return t; return t;
} }
public boolean clearIntermediatePoints() {
return globalPreferences.edit().remove(INTERMEDIATE_POINTS).commit();
}
public List<LatLon> getIntermediatePoints() {
List<LatLon> list = new ArrayList<LatLon>();
String ip = globalPreferences.getString(INTERMEDIATE_POINTS, "");
if (ip.trim().length() > 0) {
StringTokenizer tok = new StringTokenizer(ip, ",");
while (tok.hasMoreTokens()) {
String lat = tok.nextToken();
if (!tok.hasMoreTokens()) {
break;
}
String lon = tok.nextToken();
list.add(new LatLon(Float.parseFloat(lat), Float.parseFloat(lon)));
}
}
return list;
}
public boolean setIntermediatePoint(double latitude, double longitude, String historyDescription, int index) {
List<LatLon> ps = getIntermediatePoints();
ps.add(index, new LatLon(latitude, longitude));
if (historyDescription != null) {
SearchHistoryHelper.getInstance().addNewItemToHistory(latitude, longitude, historyDescription, ctx);
}
return saveIntermediatePoints(ps);
}
public boolean deleteIntermediatePoint( int index) {
List<LatLon> ps = getIntermediatePoints();
ps.remove(index);
return saveIntermediatePoints(ps);
}
private boolean saveIntermediatePoints(List<LatLon> ps) {
StringBuilder sb = new StringBuilder();
for(int i=0; i<ps.size(); i++) {
if(i > 0){
sb.append(",");
}
sb.append(((float)ps.get(i).getLatitude()+"")).append(",").append(((float)ps.get(i).getLongitude()+""));
}
return globalPreferences.edit().putString(INTERMEDIATE_POINTS, sb.toString()).commit();
}
public boolean clearPointToNavigate() { public boolean clearPointToNavigate() {
return globalPreferences.edit().remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON). return globalPreferences.edit().remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON).
remove(POINT_NAVIGATE_ROUTE).commit(); remove(POINT_NAVIGATE_ROUTE).commit();

View file

@ -10,9 +10,6 @@ import android.view.Gravity;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
/* Based on
* from http://stackoverflow.com/questions/2617266/how-to-adjust-text-font-size-to-fit-textview
*/
public class FontFitTextView extends LinearLayout { public class FontFitTextView extends LinearLayout {
private static float MAX_TEXT_SIZE = 28; private static float MAX_TEXT_SIZE = 28;

View file

@ -194,13 +194,11 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
savingTrackHelper = getMyApplication().getSavingTrackHelper(); savingTrackHelper = getMyApplication().getSavingTrackHelper();
liveMonitoringHelper = getMyApplication().getLiveMonitoringHelper(); liveMonitoringHelper = getMyApplication().getLiveMonitoringHelper();
LatLon pointToNavigate = settings.getPointToNavigate();
routingHelper = getMyApplication().getRoutingHelper(); routingHelper = getMyApplication().getRoutingHelper();
// This situtation could be when navigation suddenly crashed and after restarting // This situtation could be when navigation suddenly crashed and after restarting
// it tries to continue the last route // it tries to continue the last route
if(settings.FOLLOW_THE_ROUTE.get() && !routingHelper.isRouteCalculated()){ if(settings.FOLLOW_THE_ROUTE.get() && !routingHelper.isRouteCalculated()){
restoreRoutingMode(pointToNavigate); restoreRoutingMode(settings.getPointToNavigate(), settings.getIntermediatePoints());
} }
mapView.setMapLocationListener(this); mapView.setMapLocationListener(this);
@ -241,7 +239,8 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
setRequestedOrientation(settings.MAP_SCREEN_ORIENTATION.get()); setRequestedOrientation(settings.MAP_SCREEN_ORIENTATION.get());
// can't return from this method we are not sure if activity will be recreated or not // can't return from this method we are not sure if activity will be recreated or not
} }
mapLayers.getNavigationLayer().setPointToNavigate(settings.getPointToNavigate()); mapLayers.getNavigationLayer().setPointToNavigate(settings.getPointToNavigate(), settings.getIntermediatePoints());
Location loc = getLastKnownLocation(); Location loc = getLastKnownLocation();
if (loc != null && (System.currentTimeMillis() - loc.getTime()) > 30 * 1000) { if (loc != null && (System.currentTimeMillis() - loc.getTime()) > 30 * 1000) {
setLocation(null); setLocation(null);
@ -266,8 +265,13 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
setMapLinkedToLocation(false); setMapLinkedToLocation(false);
// if destination point was changed try to recalculate route // if destination point was changed try to recalculate route
if (routingHelper.isFollowingMode() && !Algoritms.objectEquals(settings.getPointToNavigate(), routingHelper.getFinalLocation())) { if (routingHelper.isFollowingMode() && (
routingHelper.setFinalAndCurrentLocation(settings.getPointToNavigate(), getLastKnownLocation(), routingHelper.getCurrentGPXRoute()); !Algoritms.objectEquals(settings.getPointToNavigate(), routingHelper.getFinalLocation() )||
!Algoritms.objectEquals(settings.getIntermediatePoints(), routingHelper.getIntermediatePoints())
)) {
routingHelper.setFinalAndCurrentLocation(settings.getPointToNavigate(),
settings.getIntermediatePoints(),
getLastKnownLocation(), routingHelper.getCurrentGPXRoute());
} }
startLocationRequests(); startLocationRequests();
@ -328,11 +332,11 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
private void notRestoreRoutingMode(){ private void notRestoreRoutingMode(){
boolean changed = settings.APPLICATION_MODE.set(settings.PREV_APPLICATION_MODE.get()); boolean changed = settings.APPLICATION_MODE.set(settings.PREV_APPLICATION_MODE.get());
updateApplicationModeSettings(); updateApplicationModeSettings();
routingHelper.clearCurrentRoute(null); routingHelper.clearCurrentRoute(null, new ArrayList<LatLon>());
mapView.refreshMap(changed); mapView.refreshMap(changed);
} }
private void restoreRoutingMode(final LatLon pointToNavigate) { private void restoreRoutingMode(final LatLon pointToNavigate, final List<LatLon> intermediates) {
final String gpxPath = settings.FOLLOW_THE_GPX_ROUTE.get(); final String gpxPath = settings.FOLLOW_THE_GPX_ROUTE.get();
if (pointToNavigate == null && gpxPath == null) { if (pointToNavigate == null && gpxPath == null) {
notRestoreRoutingMode(); notRestoreRoutingMode();
@ -423,7 +427,7 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
notRestoreRoutingMode(); notRestoreRoutingMode();
} else { } else {
routingHelper.setFollowingMode(true); routingHelper.setFollowingMode(true);
routingHelper.setFinalAndCurrentLocation(endPoint, startPoint, gpxRoute); routingHelper.setFinalAndCurrentLocation(endPoint, intermediates, startPoint, gpxRoute);
getMyApplication().showDialogInitializingCommandPlayer(MapActivity.this); getMyApplication().showDialogInitializingCommandPlayer(MapActivity.this);
} }
} }
@ -931,17 +935,24 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
return zoomDelta; return zoomDelta;
} }
public void navigateToPoint(LatLon point, boolean updateRoute){ public void navigateToPoint(LatLon point, boolean updateRoute, boolean intermediate){
if(point != null){ if(point != null){
settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null); if(!intermediate) {
settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null);
} else {
int sz = mapLayers.getNavigationLayer().getIntermediatePoints().size();
settings.setIntermediatePoint(point.getLatitude(), point.getLongitude(), null, sz);
}
} else { } else {
settings.clearPointToNavigate(); settings.clearPointToNavigate();
settings.clearIntermediatePoints();
} }
if(updateRoute && ( routingHelper.isRouteBeingCalculated() || routingHelper.isRouteCalculated() || if(updateRoute && ( routingHelper.isRouteBeingCalculated() || routingHelper.isRouteCalculated() ||
routingHelper.isFollowingMode())) { routingHelper.isFollowingMode())) {
routingHelper.setFinalAndCurrentLocation(point, getLastKnownLocation(), routingHelper.getCurrentGPXRoute()); routingHelper.setFinalAndCurrentLocation(settings.getPointToNavigate(),
settings.getIntermediatePoints(), getLastKnownLocation(), routingHelper.getCurrentGPXRoute());
} }
mapLayers.getNavigationLayer().setPointToNavigate(point); mapLayers.getNavigationLayer().setPointToNavigate(settings.getPointToNavigate(), settings.getIntermediatePoints());
} }
public Location getLastKnownLocation(){ public Location getLastKnownLocation(){
@ -956,6 +967,18 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
return mapLayers.getNavigationLayer().getPointToNavigate(); return mapLayers.getNavigationLayer().getPointToNavigate();
} }
public List<LatLon> getIntermediatePoitns(){
return mapLayers.getNavigationLayer().getIntermediatePoints();
}
public LatLon getFirstIntermediatePoint(){
List<LatLon> ip = mapLayers.getNavigationLayer().getIntermediatePoints();
if(ip.size() > 0) {
return ip.get(0);
}
return null;
}
public RoutingHelper getRoutingHelper() { public RoutingHelper getRoutingHelper() {
return routingHelper; return routingHelper;
} }

View file

@ -473,7 +473,8 @@ public class MapActivityActions implements DialogProvider {
settings.FOLLOW_THE_ROUTE.set(false); settings.FOLLOW_THE_ROUTE.set(false);
settings.FOLLOW_THE_GPX_ROUTE.set(null); settings.FOLLOW_THE_GPX_ROUTE.set(null);
routingHelper.setFollowingMode(false); routingHelper.setFollowingMode(false);
routingHelper.setFinalAndCurrentLocation(mapActivity.getPointToNavigate(), from, null); routingHelper.setFinalAndCurrentLocation(mapActivity.getPointToNavigate(),
mapActivity.getIntermediatePoitns(),from, null);
} }
}; };
@ -511,7 +512,8 @@ public class MapActivityActions implements DialogProvider {
settings.FOLLOW_THE_ROUTE.set(true); settings.FOLLOW_THE_ROUTE.set(true);
settings.FOLLOW_THE_GPX_ROUTE.set(null); settings.FOLLOW_THE_GPX_ROUTE.set(null);
routingHelper.setFollowingMode(true); routingHelper.setFollowingMode(true);
routingHelper.setFinalAndCurrentLocation(mapActivity.getPointToNavigate(), current, null); routingHelper.setFinalAndCurrentLocation(mapActivity.getPointToNavigate(), mapActivity.getIntermediatePoitns(),
current, null);
dialog.dismiss(); dialog.dismiss();
getMyApplication().showDialogInitializingCommandPlayer(mapActivity); getMyApplication().showDialogInitializingCommandPlayer(mapActivity);
} }
@ -587,7 +589,7 @@ public class MapActivityActions implements DialogProvider {
} }
if(endPoint != null) { if(endPoint != null) {
settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null); settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null);
mapLayers.getNavigationLayer().setPointToNavigate(point); mapLayers.getNavigationLayer().setPointToNavigate(point, new ArrayList<LatLon>());
} }
} }
// change global settings // change global settings
@ -604,7 +606,8 @@ public class MapActivityActions implements DialogProvider {
settings.FOLLOW_THE_ROUTE.set(true); settings.FOLLOW_THE_ROUTE.set(true);
settings.FOLLOW_THE_GPX_ROUTE.set(result.path); settings.FOLLOW_THE_GPX_ROUTE.set(result.path);
routingHelper.setFollowingMode(true); routingHelper.setFollowingMode(true);
routingHelper.setFinalAndCurrentLocation(endPoint, startForRouting, gpxRoute); routingHelper.setFinalAndCurrentLocation(endPoint,
new ArrayList<LatLon>(), startForRouting, gpxRoute);
getMyApplication().showDialogInitializingCommandPlayer(mapActivity); getMyApplication().showDialogInitializingCommandPlayer(mapActivity);
} }
} }
@ -710,6 +713,7 @@ public class MapActivityActions implements DialogProvider {
adapter.registerItem(R.string.context_menu_item_search, R.drawable.list_view_search_near_here); adapter.registerItem(R.string.context_menu_item_search, R.drawable.list_view_search_near_here);
adapter.registerItem(R.string.context_menu_item_share_location, R.drawable.list_view_share_location); adapter.registerItem(R.string.context_menu_item_share_location, R.drawable.list_view_share_location);
adapter.registerItem(R.string.context_menu_item_add_favorite, R.drawable.list_activities_favorites); adapter.registerItem(R.string.context_menu_item_add_favorite, R.drawable.list_activities_favorites);
adapter.registerItem(R.string.context_menu_item_intermediate_point, R.drawable.list_view_set_intermediate);
OsmandPlugin.registerMapContextMenu(mapActivity, latitude, longitude, adapter, selectedObj); OsmandPlugin.registerMapContextMenu(mapActivity, latitude, longitude, adapter, selectedObj);
@ -750,10 +754,10 @@ public class MapActivityActions implements DialogProvider {
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mapActivity.startActivity(intent); mapActivity.startActivity(intent);
} else if (standardId == R.string.context_menu_item_navigate_point) { } else if (standardId == R.string.context_menu_item_navigate_point) {
mapActivity.navigateToPoint(new LatLon(latitude, longitude), true); mapActivity.navigateToPoint(new LatLon(latitude, longitude), true, false);
} else if (standardId == R.string.context_menu_item_directions) { } else if (standardId == R.string.context_menu_item_directions) {
Location loc = mapActivity.getLastKnownLocation(); Location loc = mapActivity.getLastKnownLocation();
mapActivity.navigateToPoint(new LatLon(latitude, longitude), false); mapActivity.navigateToPoint(new LatLon(latitude, longitude), false, false);
// always enable and follow and let calculate it (GPS is not accessible in garage) // always enable and follow and let calculate it (GPS is not accessible in garage)
getDirections(loc, true); getDirections(loc, true);
} else if (standardId == R.string.context_menu_item_show_route) { } else if (standardId == R.string.context_menu_item_show_route) {
@ -763,6 +767,8 @@ public class MapActivityActions implements DialogProvider {
loc.setLongitude(longitude); loc.setLongitude(longitude);
getDirections(loc, true); getDirections(loc, true);
} }
} else if (standardId == R.string.context_menu_item_intermediate_point) {
mapActivity.navigateToPoint(new LatLon(latitude, longitude), true, true);
} else if (standardId == R.string.context_menu_item_share_location) { } else if (standardId == R.string.context_menu_item_share_location) {
shareLocation(latitude, longitude, mapActivity.getMapView().getZoom()); shareLocation(latitude, longitude, mapActivity.getMapView().getZoom());
} else if (standardId == R.string.context_menu_item_add_favorite) { } else if (standardId == R.string.context_menu_item_add_favorite) {
@ -921,14 +927,14 @@ public class MapActivityActions implements DialogProvider {
@Override @Override
public boolean onClick(MenuItem item) { public boolean onClick(MenuItem item) {
if (routingHelper.isRouteCalculated() || routingHelper.isFollowingMode() || routingHelper.isRouteBeingCalculated()) { if (routingHelper.isRouteCalculated() || routingHelper.isFollowingMode() || routingHelper.isRouteBeingCalculated()) {
routingHelper.setFinalAndCurrentLocation(null, mapActivity.getLastKnownLocation(), routingHelper.setFinalAndCurrentLocation(null, new ArrayList<LatLon>(), mapActivity.getLastKnownLocation(),
routingHelper.getCurrentGPXRoute()); routingHelper.getCurrentGPXRoute());
// restore default mode // restore default mode
boolean changed = settings.APPLICATION_MODE.set(settings.PREV_APPLICATION_MODE.get()); boolean changed = settings.APPLICATION_MODE.set(settings.PREV_APPLICATION_MODE.get());
mapActivity.updateApplicationModeSettings(); mapActivity.updateApplicationModeSettings();
mapView.refreshMap(changed); mapView.refreshMap(changed);
} else { } else {
mapActivity.navigateToPoint(null, true); mapActivity.navigateToPoint(null, true, false);
} }
mapView.refreshMap(); mapView.refreshMap();
return true; return true;

View file

@ -11,7 +11,7 @@ import android.database.sqlite.SQLiteOpenHelper;
public class SearchHistoryHelper { public class SearchHistoryHelper {
private static SearchHistoryHelper helper = new SearchHistoryHelper(); private static SearchHistoryHelper helper = new SearchHistoryHelper();
private static final int HISTORY_LIMIT = 10; private static final int HISTORY_LIMIT = 50;
public static SearchHistoryHelper getInstance(){ public static SearchHistoryHelper getInstance(){
return helper; return helper;

View file

@ -91,8 +91,10 @@ public class TestVoiceActivity extends Activity {
addButton(ll, "GPS signal lost", builder(p).gpsLocationLost()); addButton(ll, "GPS signal lost", builder(p).gpsLocationLost());
addButton(ll, "Route recalculated (23150m)", builder(p).routeRecalculated(23150)); addButton(ll, "Route recalculated (23150m)", builder(p).routeRecalculated(23150));
addButton(ll, "Continue straight ahead", builder(p).goAhead()); addButton(ll, "Continue straight ahead", builder(p).goAhead());
addButton(ll, "Arrive at intermediate point", builder(p).andArriveAtIntermediatePoint());
addButton(ll, "Follow the road for 2350m", builder(p).goAhead(2350)); addButton(ll, "Follow the road for 2350m", builder(p).goAhead(2350));
addButton(ll, "Follow the road for 800m and arrive at destination", builder(p).goAhead(800).andArriveAtDestination()); addButton(ll, "Follow the road for 800m and arrive at destination", builder(p).goAhead(800).andArriveAtDestination());
addButton(ll, "Follow the road for 360m and arrive at intermediate point", builder(p).goAhead(360).andArriveAtIntermediatePoint());
addButton(ll, "Arrive at destination", builder(p).arrivedAtDestination()); addButton(ll, "Arrive at destination", builder(p).arrivedAtDestination());
ll.forceLayout(); ll.forceLayout();
} }

View file

@ -26,21 +26,24 @@ public class RouteCalculationResult {
private final List<AlarmInfo> alarmInfo; private final List<AlarmInfo> alarmInfo;
private final String errorMessage; private final String errorMessage;
private final int[] listDistance; private final int[] listDistance;
private final int[] intermediatePoints;
// Note always currentRoute > get(currentDirectionInfo).routeOffset, // Note always currentRoute > get(currentDirectionInfo).routeOffset,
// but currentRoute <= get(currentDirectionInfo+1).routeOffset // but currentRoute <= get(currentDirectionInfo+1).routeOffset
protected int currentDirectionInfo = 0; protected int currentDirectionInfo = 0;
protected int currentRoute = 0; protected int currentRoute = 0;
protected int nextIntermediate = 0;
protected int nextAlarmInfo = 0; protected int nextAlarmInfo = 0;
public RouteCalculationResult(String errorMessage) { public RouteCalculationResult(String errorMessage) {
this(null, null, null, null, errorMessage, null, false, false); this(null, null, null, null, null, errorMessage, null, false, false);
} }
public RouteCalculationResult(List<Location> list, List<RouteDirectionInfo> directions, Location start, LatLon end, String errorMessage, public RouteCalculationResult(List<Location> list, List<RouteDirectionInfo> directions, Location start, LatLon end,
Context ctx, boolean leftSide, boolean addMissingTurns) { List<LatLon> intermediates, String errorMessage, Context ctx, boolean leftSide, boolean addMissingTurns) {
this.errorMessage = errorMessage; this.errorMessage = errorMessage;
this.intermediatePoints = new int[intermediates == null ? 0 : intermediates.size()];
List<Location> locations = list == null ? new ArrayList<Location>() : new ArrayList<Location>(list); List<Location> locations = list == null ? new ArrayList<Location>() : new ArrayList<Location>(list);
List<RouteDirectionInfo> localDirections = directions == null? new ArrayList<RouteDirectionInfo>() : new ArrayList<RouteDirectionInfo>(directions); List<RouteDirectionInfo> localDirections = directions == null? new ArrayList<RouteDirectionInfo>() : new ArrayList<RouteDirectionInfo>(directions);
if (!locations.isEmpty()) { if (!locations.isEmpty()) {
@ -59,15 +62,16 @@ public class RouteCalculationResult {
this.listDistance = new int[locations.size()]; this.listDistance = new int[locations.size()];
updateListDistanceTime(); updateListDistanceTime();
this.alarmInfo = new ArrayList<AlarmInfo>(); this.alarmInfo = new ArrayList<AlarmInfo>();
calculateIntermediateIndexes(ctx, intermediates, localDirections);
this.directions = Collections.unmodifiableList(localDirections); this.directions = Collections.unmodifiableList(localDirections);
updateDirectionsTime(); updateDirectionsTime();
} }
public RouteCalculationResult(List<RouteSegmentResult> list, Location start, LatLon end, public RouteCalculationResult(List<RouteSegmentResult> list, Location start, LatLon end, List<LatLon> intermediates,
Context ctx, boolean leftSide) { Context ctx, boolean leftSide) {
List<RouteDirectionInfo> computeDirections = new ArrayList<RouteDirectionInfo>(); List<RouteDirectionInfo> computeDirections = new ArrayList<RouteDirectionInfo>();
this.errorMessage = null; this.errorMessage = null;
this.intermediatePoints = new int[intermediates == null ? 0 : intermediates.size()];
List<Location> locations = new ArrayList<Location>(); List<Location> locations = new ArrayList<Location>();
ArrayList<AlarmInfo> alarms = new ArrayList<AlarmInfo>(); ArrayList<AlarmInfo> alarms = new ArrayList<AlarmInfo>();
List<RouteSegmentResult> segments = convertVectorResult(computeDirections, locations, list, alarms, ctx); List<RouteSegmentResult> segments = convertVectorResult(computeDirections, locations, list, alarms, ctx);
@ -76,13 +80,55 @@ public class RouteCalculationResult {
this.locations = Collections.unmodifiableList(locations); this.locations = Collections.unmodifiableList(locations);
this.segments = Collections.unmodifiableList(segments); this.segments = Collections.unmodifiableList(segments);
this.listDistance = new int[locations.size()]; this.listDistance = new int[locations.size()];
calculateIntermediateIndexes(ctx, intermediates, computeDirections);
updateListDistanceTime(); updateListDistanceTime();
this.directions = Collections.unmodifiableList(computeDirections); this.directions = Collections.unmodifiableList(computeDirections);
updateDirectionsTime(); updateDirectionsTime();
this.alarmInfo = Collections.unmodifiableList(alarms); this.alarmInfo = Collections.unmodifiableList(alarms);
} }
private void calculateIntermediateIndexes(Context ctx, List<LatLon> intermediates, List<RouteDirectionInfo> localDirections) {
if(intermediates != null && localDirections != null) {
int[] interLocations = new int[intermediates.size()];
int currentIntermediate = 0;
int currentLocation = 0;
while(currentIntermediate < intermediates.size() && currentLocation < this.locations.size()){
if(MapUtils.getDistance(intermediates.get(currentIntermediate),
this.locations.get(currentLocation).getLatitude(), this.locations.get(currentLocation).getLongitude()) <
15) {
interLocations[currentIntermediate] = currentLocation;
currentIntermediate++;
}
currentLocation ++;
}
int currentDirection = 0;
currentIntermediate = 0;
while(currentIntermediate < intermediates.size() && currentDirection < localDirections.size()){
int locationIndex = localDirections.get(currentDirection).routePointOffset ;
if (locationIndex >= interLocations[currentIntermediate]) {
// split directions
if (locationIndex > interLocations[currentIntermediate]
&& MapUtils.getDistance(intermediates.get(currentIntermediate),
this.locations.get(locationIndex).getLatitude(), this.locations.get(locationIndex).getLongitude()) > 50) {
RouteDirectionInfo toSplit = localDirections.get(currentDirection);
RouteDirectionInfo info = new RouteDirectionInfo(localDirections.get(currentDirection).getAverageSpeed(), TurnType.valueOf(TurnType.C,
false));
info.setRef(toSplit.getRef());
info.setStreetName(toSplit.getStreetName());
info.routePointOffset = interLocations[currentIntermediate];
info.setDescriptionRoute(ctx.getString(R.string.route_head));//; //$NON-NLS-1$
localDirections.add(currentDirection, info);
}
intermediatePoints[currentIntermediate] = currentDirection;
currentIntermediate++;
}
currentDirection ++;
}
}
}
private void attachAlarmInfo(List<AlarmInfo> alarms, RouteSegmentResult res, int intId, int locInd) { private void attachAlarmInfo(List<AlarmInfo> alarms, RouteSegmentResult res, int intId, int locInd) {
int[] pointTypes = res.getObject().getPointTypes(intId); int[] pointTypes = res.getObject().getPointTypes(intId);
RouteRegion reg = res.getObject().region; RouteRegion reg = res.getObject().region;
@ -565,6 +611,14 @@ public class RouteCalculationResult {
while (nextAlarmInfo < alarmInfo.size() && alarmInfo.get(nextAlarmInfo).locationIndex < currentRoute) { while (nextAlarmInfo < alarmInfo.size() && alarmInfo.get(nextAlarmInfo).locationIndex < currentRoute) {
nextAlarmInfo++; nextAlarmInfo++;
} }
while(nextIntermediate < intermediatePoints.length) {
RouteDirectionInfo dir = directions.get(intermediatePoints[nextIntermediate]);
if(dir.routePointOffset < currentRoute) {
nextIntermediate ++;
} else {
break;
}
}
} }
public Location getLocationFromRouteDirection(RouteDirectionInfo i){ public Location getLocationFromRouteDirection(RouteDirectionInfo i){
@ -596,6 +650,9 @@ public class RouteCalculationResult {
info.directionInfo = directions.get(nextInd); info.directionInfo = directions.get(nextInd);
dist -= listDistance[directions.get(nextInd).routePointOffset]; dist -= listDistance[directions.get(nextInd).routePointOffset];
} }
if(intermediatePoints != null && nextIntermediate < intermediatePoints.length) {
info.intermediatePoint = intermediatePoints[nextIntermediate] == nextInd;
}
info.directionInfoInd = nextInd; info.directionInfoInd = nextInd;
info.distanceTo = dist; info.distanceTo = dist;
return info; return info;
@ -624,6 +681,9 @@ public class RouteCalculationResult {
next.directionInfo = directions.get(nextInd); next.directionInfo = directions.get(nextInd);
dist -= listDistance[directions.get(nextInd).routePointOffset]; dist -= listDistance[directions.get(nextInd).routePointOffset];
} }
if(intermediatePoints != null && nextIntermediate < intermediatePoints.length) {
next.intermediatePoint = intermediatePoints[nextIntermediate] == nextInd;
}
next.distanceTo = dist; next.distanceTo = dist;
next.directionInfoInd = nextInd; next.directionInfoInd = nextInd;
return next; return next;
@ -709,6 +769,30 @@ public class RouteCalculationResult {
return 0; return 0;
} }
public int getDistanceToNextIntermediate(Location fromLoc) {
if(listDistance != null && currentRoute < listDistance.length){
int dist = listDistance[currentRoute];
Location l = locations.get(currentRoute);
if(fromLoc != null){
dist += fromLoc.distanceTo(l);
}
if(nextIntermediate >= intermediatePoints.length ){
return 0;
} else {
int directionInd = intermediatePoints[nextIntermediate];
return dist - listDistance[directions.get(directionInd).routePointOffset];
}
}
return 0;
}
public int getIntermediatePointsToPass(){
if(nextIntermediate >= intermediatePoints.length) {
return 0;
}
return intermediatePoints.length - nextIntermediate;
}
public int getLeftTime(Location fromLoc){ public int getLeftTime(Location fromLoc){
int time = 0; int time = 0;
if(currentDirectionInfo < directions.size()) { if(currentDirectionInfo < directions.size()) {
@ -732,7 +816,7 @@ public class RouteCalculationResult {
public static class NextDirectionInfo { public static class NextDirectionInfo {
public RouteDirectionInfo directionInfo; public RouteDirectionInfo directionInfo;
public int distanceTo; public int distanceTo;
// public boolean intermediatePoint;
public int imminent; public int imminent;
private int directionInfoInd; private int directionInfoInd;
} }

View file

@ -148,7 +148,7 @@ public class RouteProvider {
public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, ApplicationMode mode, RouteService type, Context ctx, public RouteCalculationResult calculateRouteImpl(Location start, LatLon end, List<LatLon> intermediates, ApplicationMode mode, RouteService type, Context ctx,
GPXRouteParams gpxRoute, RouteCalculationResult previousToRecalculate, boolean fast, boolean leftSide, Interruptable interruptable){ GPXRouteParams gpxRoute, RouteCalculationResult previousToRecalculate, boolean fast, boolean leftSide, Interruptable interruptable){
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if (start != null && end != null) { if (start != null && end != null) {
@ -168,9 +168,9 @@ public class RouteProvider {
if(previousToRecalculate != null) { if(previousToRecalculate != null) {
originalRoute = previousToRecalculate.getOriginalRoute(); originalRoute = previousToRecalculate.getOriginalRoute();
} }
res = findVectorMapsRoute(start, end, mode, (OsmandApplication)ctx.getApplicationContext(), originalRoute, leftSide, interruptable); res = findVectorMapsRoute(start, end, intermediates, mode, (OsmandApplication)ctx.getApplicationContext(), originalRoute, leftSide, interruptable);
} else { } else {
res = findCloudMadeRoute(start, end, mode, ctx, fast, leftSide); res = findCloudMadeRoute(start, end, intermediates, mode, ctx, fast, leftSide);
} }
if(log.isInfoEnabled() ){ if(log.isInfoEnabled() ){
log.info("Finding route contained " + res.getImmutableLocations().size() + " points for " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ log.info("Finding route contained " + res.getImmutableLocations().size() + " points for " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@ -220,7 +220,7 @@ public class RouteProvider {
} }
ArrayList<Location> sublist = new ArrayList<Location>(gpxRoute.subList(startI, endI)); ArrayList<Location> sublist = new ArrayList<Location>(gpxRoute.subList(startI, endI));
if(params.directions == null){ if(params.directions == null){
res = new RouteCalculationResult(sublist, params.directions, start, end, null, ctx, leftSide, true); res = new RouteCalculationResult(sublist, params.directions, start, end, null, null, ctx, leftSide, true);
} else { } else {
List<RouteDirectionInfo> subdirections = new ArrayList<RouteDirectionInfo>(); List<RouteDirectionInfo> subdirections = new ArrayList<RouteDirectionInfo>();
for (RouteDirectionInfo info : params.directions) { for (RouteDirectionInfo info : params.directions) {
@ -235,7 +235,7 @@ public class RouteProvider {
subdirections.add(ch); subdirections.add(ch);
} }
} }
res = new RouteCalculationResult(sublist, subdirections, start, end, null, ctx, leftSide, true); res = new RouteCalculationResult(sublist, subdirections, start, end, null, null, ctx, leftSide, true);
} }
return res; return res;
} }
@ -305,10 +305,10 @@ public class RouteProvider {
} }
} }
return new RouteCalculationResult(res, null, start, end, null, ctx, leftSide, true); return new RouteCalculationResult(res, null, start, end, null, null, ctx, leftSide, true);
} }
protected RouteCalculationResult findVectorMapsRoute(Location start, LatLon end, ApplicationMode mode, OsmandApplication app, protected RouteCalculationResult findVectorMapsRoute(Location start, LatLon end, List<LatLon> intermediates, ApplicationMode mode, OsmandApplication app,
List<RouteSegmentResult> previousRoute, List<RouteSegmentResult> previousRoute,
boolean leftSide, Interruptable interruptable) throws IOException { boolean leftSide, Interruptable interruptable) throws IOException {
BinaryMapIndexReader[] files = app.getResourceManager().getRoutingMapFiles(); BinaryMapIndexReader[] files = app.getResourceManager().getRoutingMapFiles();
@ -361,9 +361,25 @@ public class RouteProvider {
if (en == null) { if (en == null) {
return new RouteCalculationResult(app.getString(R.string.ending_point_too_far)); return new RouteCalculationResult(app.getString(R.string.ending_point_too_far));
} }
List<RouteSegment> inters = new ArrayList<BinaryRoutePlanner.RouteSegment>();
if (intermediates != null) {
int ind = 1;
for (LatLon il : intermediates) {
RouteSegment is = router.findRouteSegment(il.getLatitude(), il.getLongitude(), ctx);
if (is == null) {
return new RouteCalculationResult(app.getString(R.string.intermediate_point_too_far, "'" + ind + "'"));
}
ind++;
}
}
try { try {
List<RouteSegmentResult> result = router.searchRoute(ctx, st, en, leftSide); List<RouteSegmentResult> result;
return new RouteCalculationResult(result, start, end, app, leftSide); if(inters.size() > 0){
result = router.searchRoute(ctx, st, en, inters, leftSide);
} else {
result = router.searchRoute(ctx, st, en, leftSide);
}
return new RouteCalculationResult(result, start, end, intermediates, app, leftSide);
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
ActivityManager activityManager = (ActivityManager)app.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager activityManager = (ActivityManager)app.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
@ -373,7 +389,7 @@ public class RouteProvider {
} }
protected RouteCalculationResult findCloudMadeRoute(Location start, LatLon end, ApplicationMode mode, Context ctx, boolean fast, boolean leftSide) protected RouteCalculationResult findCloudMadeRoute(Location start, LatLon end, List<LatLon> intermediates, ApplicationMode mode, Context ctx, boolean fast, boolean leftSide)
throws MalformedURLException, IOException, ParserConfigurationException, FactoryConfigurationError, SAXException { throws MalformedURLException, IOException, ParserConfigurationException, FactoryConfigurationError, SAXException {
List<Location> res = new ArrayList<Location>(); List<Location> res = new ArrayList<Location>();
List<RouteDirectionInfo> directions = null; List<RouteDirectionInfo> directions = null;
@ -382,6 +398,20 @@ public class RouteProvider {
uri.append("http://routes.cloudmade.com/A6421860EBB04234AB5EF2D049F2CD8F/api/0.3/"); //$NON-NLS-1$ 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.getLatitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$
uri.append(start.getLongitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$ uri.append(start.getLongitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$
if(intermediates != null && intermediates.size() > 0) {
uri.append("[");
boolean first = true;
for(LatLon il : intermediates) {
if(!first){
uri.append(",");
} else {
first = false;
}
uri.append(il.getLatitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$
uri.append(il.getLongitude() + ""); //$NON-NLS-1$ //$NON-NLS-2$
}
uri.append("],");
}
uri.append(end.getLatitude() + "").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$ uri.append(end.getLongitude() + "").append("/"); //$NON-NLS-1$ //$NON-NLS-2$
@ -406,7 +436,7 @@ public class RouteProvider {
GPXFile gpxFile = GPXUtilities.loadGPXFile(ctx, connection.getInputStream(), false); GPXFile gpxFile = GPXUtilities.loadGPXFile(ctx, connection.getInputStream(), false);
directions = parseCloudmadeRoute(res, gpxFile, false, leftSide, speed); directions = parseCloudmadeRoute(res, gpxFile, false, leftSide, speed);
return new RouteCalculationResult(res, directions, start, end, null, ctx, leftSide, true); return new RouteCalculationResult(res, directions, start, end, intermediates, null, ctx, leftSide, true);
} }
private static List<RouteDirectionInfo> parseCloudmadeRoute(List<Location> res, GPXFile gpxFile, boolean osmandRouter, private static List<RouteDirectionInfo> parseCloudmadeRoute(List<Location> res, GPXFile gpxFile, boolean osmandRouter,
@ -585,7 +615,7 @@ public class RouteProvider {
} }
} }
return new RouteCalculationResult(res, null, start, end, null, ctx, leftSide, true); return new RouteCalculationResult(res, null, start, end, null, null, ctx, leftSide, true);
} }
public GPXFile createOsmandRouterGPX(RouteCalculationResult srcRoute){ public GPXFile createOsmandRouterGPX(RouteCalculationResult srcRoute){

View file

@ -49,6 +49,7 @@ public class RoutingHelper {
private RouteCalculationResult route = new RouteCalculationResult(""); private RouteCalculationResult route = new RouteCalculationResult("");
private LatLon finalLocation; private LatLon finalLocation;
private List<LatLon> intermediatePoints;
private Location lastProjection; private Location lastProjection;
private Location lastFixedLocation; private Location lastFixedLocation;
@ -67,6 +68,7 @@ public class RoutingHelper {
private long makeUTwpDetected = 0; private long makeUTwpDetected = 0;
public boolean makeUturnWhenPossible() { public boolean makeUturnWhenPossible() {
return makeUturnWhenPossible; return makeUturnWhenPossible;
} }
@ -89,15 +91,15 @@ public class RoutingHelper {
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, Location currentLocation, GPXRouteParams gpxRoute){ public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation, GPXRouteParams gpxRoute){
clearCurrentRoute(finalLocation); clearCurrentRoute(finalLocation, intermediatePoints);
currentGPXRoute = gpxRoute; currentGPXRoute = gpxRoute;
// to update route // to update route
setCurrentLocation(currentLocation, false); setCurrentLocation(currentLocation, false);
} }
public synchronized void clearCurrentRoute(LatLon newFinalLocation) { public synchronized void clearCurrentRoute(LatLon newFinalLocation, List<LatLon> newIntermediatePoints) {
route = new RouteCalculationResult(""); route = new RouteCalculationResult("");
makeUturnWhenPossible = false; makeUturnWhenPossible = false;
evalWaitInterval = 3000; evalWaitInterval = 3000;
@ -110,6 +112,7 @@ public class RoutingHelper {
} }
}); });
this.finalLocation = newFinalLocation; this.finalLocation = newFinalLocation;
this.intermediatePoints = newIntermediatePoints;
if(currentRunningJob != null) { if(currentRunningJob != null) {
currentRunningJob.stopCalculation(); currentRunningJob.stopCalculation();
} }
@ -144,6 +147,10 @@ public class RoutingHelper {
return finalLocation; return finalLocation;
} }
public List<LatLon> getIntermediatePoints() {
return intermediatePoints;
}
public boolean isRouteCalculated(){ public boolean isRouteCalculated(){
return route.isCalculated(); return route.isCalculated();
} }
@ -233,7 +240,7 @@ public class RoutingHelper {
} }
if (calculateRoute) { if (calculateRoute) {
recalculateRouteInBackground(currentLocation, finalLocation, currentGPXRoute, recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute,
route.isCalculated()? route : null); route.isCalculated()? route : null);
} }
double projectDist = mode == ApplicationMode.CAR ? posTolerance : posTolerance / 2; double projectDist = mode == ApplicationMode.CAR ? posTolerance : posTolerance / 2;
@ -330,13 +337,27 @@ public class RoutingHelper {
break; break;
} }
} }
// 2. check if intermediate found
if(getLeftDistanceNextIntermediate() < posTolerance * 1.5f){
showMessage(context.getString(R.string.arrived_at_intermediate_point));
voiceRouter.arrivedIntermediatePoint();
}
if(intermediatePoints != null && intermediatePoints.size() > 0) {
while(route.getIntermediatePointsToPass() > settings.getIntermediatePoints().size()) {
settings.deleteIntermediatePoint(0);
}
while(route.getIntermediatePointsToPass() > intermediatePoints.size()) {
intermediatePoints.remove(0);
}
}
// 2. check if destination found // 3. check if destination found
Location lastPoint = routeNodes.get(routeNodes.size() - 1); Location lastPoint = routeNodes.get(routeNodes.size() - 1);
if (currentRoute > routeNodes.size() - 3 && currentLocation.distanceTo(lastPoint) < posTolerance * 1.5) { if (currentRoute > routeNodes.size() - 3 && currentLocation.distanceTo(lastPoint) < posTolerance * 1.5) {
showMessage(context.getString(R.string.arrived_at_destination)); showMessage(context.getString(R.string.arrived_at_destination));
voiceRouter.arrivedDestinationPoint(); voiceRouter.arrivedDestinationPoint();
clearCurrentRoute(null); clearCurrentRoute(null, null);
return true; return true;
} }
return false; return false;
@ -444,6 +465,10 @@ public class RoutingHelper {
return route.getDistanceToFinish(lastFixedLocation); return route.getDistanceToFinish(lastFixedLocation);
} }
public synchronized int getLeftDistanceNextIntermediate() {
return route.getDistanceToNextIntermediate(lastFixedLocation);
}
public synchronized int getLeftTime() { public synchronized int getLeftTime() {
return route.getLeftTime(lastFixedLocation); return route.getLeftTime(lastFixedLocation);
} }
@ -535,15 +560,17 @@ public class RoutingHelper {
private final RouteCalculationResult previousRoute; private final RouteCalculationResult previousRoute;
private RouteService service; private RouteService service;
private boolean interrupted = false; private boolean interrupted = false;
private final List<LatLon> intermediates;
public RouteRecalculationThread(String name, public RouteRecalculationThread(String name,
Location start, LatLon end, GPXRouteParams gpxRoute, RouteCalculationResult previousRoute){ Location start, LatLon end, List<LatLon> intermediates, GPXRouteParams gpxRoute, RouteCalculationResult previousRoute){
super(name); super(name);
this.start = start; this.start = start;
this.end = end; this.end = end;
this.intermediates = intermediates;
this.gpxRoute = gpxRoute; this.gpxRoute = gpxRoute;
this.previousRoute = previousRoute; this.previousRoute = previousRoute;
service = settings.ROUTER_SERVICE.get(); service = settings.ROUTER_SERVICE.getModeValue(mode);
} }
@ -560,7 +587,7 @@ public class RoutingHelper {
public void run() { public void run() {
boolean leftSide = settings.LEFT_SIDE_NAVIGATION.get(); boolean leftSide = settings.LEFT_SIDE_NAVIGATION.get();
boolean fastRoute = settings.FAST_ROUTE_MODE.get(); boolean fastRoute = settings.FAST_ROUTE_MODE.get();
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, context, gpxRoute, previousRoute, fastRoute, RouteCalculationResult res = provider.calculateRouteImpl(start, end, intermediates, mode, service, context, gpxRoute, previousRoute, fastRoute,
leftSide, this); leftSide, this);
if (interrupted) { if (interrupted) {
currentRunningJob = null; currentRunningJob = null;
@ -595,7 +622,7 @@ public class RoutingHelper {
} }
private void recalculateRouteInBackground(final Location start, final LatLon end, final GPXRouteParams gpxRoute, final RouteCalculationResult previousRoute){ private void recalculateRouteInBackground(final Location start, final LatLon end, final List<LatLon> intermediates, final GPXRouteParams gpxRoute, final RouteCalculationResult previousRoute){
if (start == null || end == null) { if (start == null || end == null) {
return; return;
} }
@ -603,7 +630,7 @@ public class RoutingHelper {
// do not evaluate very often // do not evaluate very often
if (System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) { if (System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) {
synchronized (this) { synchronized (this) {
currentRunningJob = new RouteRecalculationThread("Calculating route", start, end, gpxRoute, previousRoute); //$NON-NLS-1$ currentRunningJob = new RouteRecalculationThread("Calculating route", start, end, intermediates, gpxRoute, previousRoute); //$NON-NLS-1$
currentRunningJob.start(); currentRunningJob.start();
} }
} }
@ -641,5 +668,5 @@ public class RoutingHelper {
public GPXFile generateGPXFileWithRoute(){ public GPXFile generateGPXFileWithRoute(){
return provider.createOsmandRouterGPX(route); return provider.createOsmandRouterGPX(route);
} }
} }

View file

@ -191,7 +191,6 @@ public class VoiceRouter {
// after last turn say: // after last turn say:
if (nextInfo == null || nextInfo.directionInfo == null || nextInfo.directionInfo.distance == 0) { if (nextInfo == null || nextInfo.directionInfo == null || nextInfo.directionInfo.distance == 0) {
// if(currentStatus <= STATUS_UNKNOWN && currentDirection > 0){ This caused this prompt to be suppressed when coming back from a // if(currentStatus <= STATUS_UNKNOWN && currentDirection > 0){ This caused this prompt to be suppressed when coming back from a
// UTwp situation
if (currentStatus <= STATUS_UNKNOWN) { if (currentStatus <= STATUS_UNKNOWN) {
if (playGoAheadToDestination()) { if (playGoAheadToDestination()) {
currentStatus = STATUS_TOLD; currentStatus = STATUS_TOLD;
@ -200,6 +199,15 @@ public class VoiceRouter {
} }
return; return;
} }
if(nextInfo.intermediatePoint){
if (currentStatus <= STATUS_UNKNOWN) {
if (playGoAheadToIntermediate()) {
currentStatus = STATUS_TOLD;
playGoAheadDist = 0;
}
}
return;
}
int dist = nextInfo.distanceTo; int dist = nextInfo.distanceTo;
RouteDirectionInfo next = nextInfo.directionInfo; RouteDirectionInfo next = nextInfo.directionInfo;
@ -343,6 +351,15 @@ public class VoiceRouter {
return false; return false;
} }
private boolean playGoAheadToIntermediate() {
CommandBuilder play = getNewCommandPlayerToPlay();
if(play != null){
play.goAhead(router.getLeftDistanceNextIntermediate()).andArriveAtDestination().play();
return true;
}
return false;
}
private boolean playMakeUTwp() { private boolean playMakeUTwp() {
CommandBuilder play = getNewCommandPlayerToPlay(); CommandBuilder play = getNewCommandPlayerToPlay();
if(play != null){ if(play != null){
@ -505,6 +522,13 @@ public class VoiceRouter {
play.arrivedAtDestination().play(); play.arrivedAtDestination().play();
} }
} }
public void arrivedIntermediatePoint() {
CommandBuilder play = getNewCommandPlayerToPlay();
if(play != null){
play.arrivedAtIntermediatePoint().play();
}
}
public void onApplicationTerminate(Context ctx) { public void onApplicationTerminate(Context ctx) {
if (player != null) { if (player != null) {

View file

@ -239,23 +239,25 @@ public class MapInfoLayer extends OsmandMapLayer {
//mapInfoControls.registerSideWidget(miniMap, R.drawable.widget_next_turn, R.string.map_widget_mini_route, "mini_route", true, none, none, 20); //mapInfoControls.registerSideWidget(miniMap, R.drawable.widget_next_turn, R.string.map_widget_mini_route, "mini_route", true, none, none, 20);
// right stack // right stack
TextInfoControl dist = ric.createDistanceControl(map, paintText, paintSubText); TextInfoControl dist = ric.createDistanceControl(map, paintText, paintSubText);
mapInfoControls.registerSideWidget(dist, R.drawable.widget_target, R.string.map_widget_distance, "distance", false, carDefault, none, 5); mapInfoControls.registerSideWidget(dist, R.drawable.widget_target, R.string.map_widget_distance, "distance", false, all, none, 5);
TextInfoControl time = ric.createTimeControl(map, paintText, paintSubText); TextInfoControl time = ric.createTimeControl(map, paintText, paintSubText);
mapInfoControls.registerSideWidget(time, R.drawable.widget_time, R.string.map_widget_time, "time",false, carDefault, none, 10); mapInfoControls.registerSideWidget(time, R.drawable.widget_time, R.string.map_widget_time, "time",false, all, none, 10);
TextInfoControl speed = ric.createSpeedControl(map, paintText, paintSubText); TextInfoControl speed = ric.createSpeedControl(map, paintText, paintSubText);
mapInfoControls.registerSideWidget(speed, R.drawable.widget_speed, R.string.map_widget_speed, "speed", false, carDefault, none, 15); mapInfoControls.registerSideWidget(speed, R.drawable.widget_speed, R.string.map_widget_speed, "speed", false, all, none, 15);
TextInfoControl intermediateDist = ric.createIntermediateDistanceControl(map, paintText, paintSubText);
mapInfoControls.registerSideWidget(intermediateDist, R.drawable.widget_intermediate, R.string.map_widget_intermediate_distance, "intermediate_distance", false, all, none, 17);
TextInfoControl alt = ric.createAltitudeControl(map, paintText, paintSubText); TextInfoControl alt = ric.createAltitudeControl(map, paintText, paintSubText);
mapInfoControls.registerSideWidget(alt, R.drawable.widget_altitude, R.string.map_widget_altitude, "altitude", false, EnumSet.of(ApplicationMode.PEDESTRIAN), none, 20); mapInfoControls.registerSideWidget(alt, R.drawable.widget_altitude, R.string.map_widget_altitude, "altitude", false, EnumSet.of(ApplicationMode.PEDESTRIAN), none, 20);
// Top widgets // Top widgets
ImageViewControl compassView = createCompassView(map); ImageViewControl compassView = createCompassView(map);
mapInfoControls.registerTopWidget(compassView, R.drawable.compass, R.string.map_widget_compass, "compass", MapInfoControls.LEFT_CONTROL, carDefault, 5); mapInfoControls.registerTopWidget(compassView, R.drawable.compass, R.string.map_widget_compass, "compass", MapInfoControls.LEFT_CONTROL, all, 5);
View config = createConfiguration(); View config = createConfiguration();
mapInfoControls.registerTopWidget(config, R.drawable.widget_config, R.string.map_widget_config, "config", MapInfoControls.RIGHT_CONTROL, carDefault, 10).required(ApplicationMode.DEFAULT); mapInfoControls.registerTopWidget(config, R.drawable.widget_config, R.string.map_widget_config, "config", MapInfoControls.RIGHT_CONTROL, all, 10).required(ApplicationMode.DEFAULT);
ImageView lockView = lockInfoControl.createLockScreenWidget(view, map); ImageView lockView = lockInfoControl.createLockScreenWidget(view, map);
mapInfoControls.registerTopWidget(lockView, R.drawable.lock_enabled, R.string.bg_service_screen_lock, "bgService", MapInfoControls.LEFT_CONTROL, exceptCar, 15); mapInfoControls.registerTopWidget(lockView, R.drawable.lock_enabled, R.string.bg_service_screen_lock, "bgService", MapInfoControls.LEFT_CONTROL, exceptCar, 15);
backToLocation = createBackToLocation(map); backToLocation = createBackToLocation(map);
mapInfoControls.registerTopWidget(backToLocation, R.drawable.default_location, R.string.map_widget_back_to_loc, "back_to_location", MapInfoControls.RIGHT_CONTROL, carDefault, 5); mapInfoControls.registerTopWidget(backToLocation, R.drawable.default_location, R.string.map_widget_back_to_loc, "back_to_location", MapInfoControls.RIGHT_CONTROL, all, 5);
View globus = createGlobus(); View globus = createGlobus();
mapInfoControls.registerTopWidget(globus, R.drawable.globus, R.string.map_widget_map_select, "progress", MapInfoControls.RIGHT_CONTROL, none, 15); mapInfoControls.registerTopWidget(globus, R.drawable.globus, R.string.map_widget_map_select, "progress", MapInfoControls.RIGHT_CONTROL, none, 15);

View file

@ -1,12 +1,18 @@
package net.osmand.plus.views; package net.osmand.plus.views;
import java.util.ArrayList;
import java.util.List;
import net.osmand.osm.LatLon; import net.osmand.osm.LatLon;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.routing.RoutingHelper;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.RectF; import android.graphics.RectF;
@ -21,12 +27,18 @@ public class PointNavigationLayer extends OsmandMapLayer {
private Paint bitmapPaint; private Paint bitmapPaint;
protected LatLon pointToNavigate = null; protected LatLon pointToNavigate = null;
protected List<LatLon> intermediatePoints = new ArrayList<LatLon>();
private OsmandMapTileView view; private OsmandMapTileView view;
private float[] calculations = new float[2]; private float[] calculations = new float[2];
private DisplayMetrics dm; private DisplayMetrics dm;
private Bitmap targetPoint; private Bitmap targetPoint;
private Bitmap intermediatePoint;
private Bitmap arrowToDestination; private Bitmap arrowToDestination;
private Paint textPaint;
private RoutingHelper routingHelper;
@ -41,7 +53,13 @@ public class PointNavigationLayer extends OsmandMapLayer {
bitmapPaint.setDither(true); bitmapPaint.setDither(true);
bitmapPaint.setAntiAlias(true); bitmapPaint.setAntiAlias(true);
bitmapPaint.setFilterBitmap(true); bitmapPaint.setFilterBitmap(true);
textPaint = new Paint();
float sp = Resources.getSystem().getDisplayMetrics().scaledDensity;
textPaint.setTextSize(sp * 18);
textPaint.setTextAlign(Align.CENTER);
textPaint.setAntiAlias(true);
targetPoint = BitmapFactory.decodeResource(view.getResources(), R.drawable.target_point); targetPoint = BitmapFactory.decodeResource(view.getResources(), R.drawable.target_point);
intermediatePoint = BitmapFactory.decodeResource(view.getResources(), R.drawable.intermediate_point);
arrowToDestination = BitmapFactory.decodeResource(view.getResources(), R.drawable.arrow_to_destination); arrowToDestination = BitmapFactory.decodeResource(view.getResources(), R.drawable.arrow_to_destination);
@ -53,6 +71,7 @@ public class PointNavigationLayer extends OsmandMapLayer {
dm = new DisplayMetrics(); dm = new DisplayMetrics();
WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE); WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
wmgr.getDefaultDisplay().getMetrics(dm); wmgr.getDefaultDisplay().getMetrics(dm);
routingHelper = view.getApplication().getRoutingHelper();
initUI(); initUI();
} }
@ -60,17 +79,35 @@ public class PointNavigationLayer extends OsmandMapLayer {
@Override @Override
public void onDraw(Canvas canvas, RectF latLonBounds, RectF tilesRect, DrawSettings nightMode) { public void onDraw(Canvas canvas, RectF latLonBounds, RectF tilesRect, DrawSettings nightMode) {
if(pointToNavigate == null){ int index = 0;
return;
if(routingHelper != null && routingHelper.isFollowingMode() && routingHelper.isRouteCalculated()) {
List<LatLon> ip = routingHelper.getIntermediatePoints();
int sz = ip == null ? 0 : ip.size();
while(sz > intermediatePoints.size()) {
intermediatePoints.remove(0);
}
} }
if (isLocationVisible()) { for (LatLon ip : intermediatePoints) {
index ++;
if (isLocationVisible(ip)) {
int marginX = intermediatePoint.getWidth() / 3;
int marginY = 2 * intermediatePoint.getHeight() / 3;
int locationX = view.getMapXForPoint(ip.getLongitude());
int locationY = view.getMapYForPoint(ip.getLatitude());
canvas.rotate(-view.getRotate(), locationX, locationY);
canvas.drawBitmap(intermediatePoint, locationX - marginX, locationY - marginY, bitmapPaint);
canvas.drawText(index + "", locationX + marginX, locationY, textPaint);
}
}
if (isLocationVisible(pointToNavigate)) {
int marginX = targetPoint.getWidth() / 3; int marginX = targetPoint.getWidth() / 3;
int marginY = 2 * targetPoint.getHeight() / 3; int marginY = 2 * targetPoint.getHeight() / 3;
int locationX = view.getMapXForPoint(pointToNavigate.getLongitude()); int locationX = view.getMapXForPoint(pointToNavigate.getLongitude());
int locationY = view.getMapYForPoint(pointToNavigate.getLatitude()); int locationY = view.getMapYForPoint(pointToNavigate.getLatitude());
canvas.rotate(-view.getRotate(), locationX, locationY); canvas.rotate(-view.getRotate(), locationX, locationY);
canvas.drawBitmap(targetPoint, locationX - marginX, locationY - marginY, bitmapPaint); canvas.drawBitmap(targetPoint, locationX - marginX, locationY - marginY, bitmapPaint);
} else { } else if (pointToNavigate != null) {
Location.distanceBetween(view.getLatitude(), view.getLongitude(), pointToNavigate.getLatitude(), Location.distanceBetween(view.getLatitude(), view.getLongitude(), pointToNavigate.getLatitude(),
pointToNavigate.getLongitude(), calculations); pointToNavigate.getLongitude(), calculations);
float bearing = calculations[1] - 90; float bearing = calculations[1] - 90;
@ -78,15 +115,15 @@ public class PointNavigationLayer extends OsmandMapLayer {
canvas.rotate(bearing, view.getCenterPointX(), view.getCenterPointY()); canvas.rotate(bearing, view.getCenterPointX(), view.getCenterPointY());
canvas.translate(-24 * dm.density + radiusBearing, -22 * dm.density); canvas.translate(-24 * dm.density + radiusBearing, -22 * dm.density);
canvas.drawBitmap(arrowToDestination, view.getCenterPointX(), view.getCenterPointY(), bitmapPaint); canvas.drawBitmap(arrowToDestination, view.getCenterPointX(), view.getCenterPointY(), bitmapPaint);
} }
} }
public boolean isLocationVisible(){ public boolean isLocationVisible(LatLon p){
if(pointToNavigate == null || view == null){ if(p == null || view == null){
return false; return false;
} }
return view.isPointOnTheRotatedMap(pointToNavigate.getLatitude(), pointToNavigate.getLongitude()); return view.isPointOnTheRotatedMap(p.getLatitude(), p.getLongitude());
} }
@ -94,10 +131,17 @@ public class PointNavigationLayer extends OsmandMapLayer {
return pointToNavigate; return pointToNavigate;
} }
public void setPointToNavigate(LatLon pointToNavigate) { public void setPointToNavigate(LatLon pointToNavigate, List<LatLon> intermediatePoints) {
this.pointToNavigate = pointToNavigate; this.pointToNavigate = pointToNavigate;
this.intermediatePoints.clear();
this.intermediatePoints.addAll(intermediatePoints);
view.refreshMap(); view.refreshMap();
} }
public List<LatLon> getIntermediatePoints() {
return intermediatePoints;
}
@Override @Override
public void destroyLayer() { public void destroyLayer() {

View file

@ -339,62 +339,103 @@ public class RouteInfoControls {
return speedControl; return speedControl;
} }
protected TextInfoControl createDistanceControl(final MapActivity map, Paint paintText, Paint paintSubText) { public abstract static class DistanceToPointInfoControl extends TextInfoControl {
final OsmandMapTileView view = map.getMapView();
TextInfoControl distanceControl = new TextInfoControl(map, 0, paintText, paintSubText) { private final OsmandMapTileView view;
private float[] calculations = new float[1]; private float[] calculations = new float[1];
private int cachedMeters = 0; private int cachedMeters;
public DistanceToPointInfoControl(Context ctx, int leftMargin, Paint textPaint, Paint subtextPaint, Drawable d,
@Override final OsmandMapTileView view) {
public boolean updateInfo() { super(ctx, leftMargin, textPaint, subtextPaint);
if (map.getPointToNavigate() != null) { this.view = view;
int d = 0; setImageDrawable(d);
if (map.getRoutingHelper().isRouteCalculated()) { setText(null, null);
d = map.getRoutingHelper().getLeftDistance(); setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread();
LatLon pointToNavigate = getPointToNavigate();
if (pointToNavigate != null) {
float fZoom = view.getFloatZoom() < 15 ? 15 : view.getFloatZoom();
thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true);
} }
if (d == 0) { }
Location.distanceBetween(view.getLatitude(), view.getLongitude(), map.getPointToNavigate().getLatitude(), map });
.getPointToNavigate().getLongitude(), calculations); }
d = (int) calculations[0]; @Override
} public boolean updateInfo() {
if (distChanged(cachedMeters, d)) { int d = getDistance();
cachedMeters = d; if (distChanged(cachedMeters, d)) {
if (cachedMeters <= 20) { cachedMeters = d;
cachedMeters = 0; if (cachedMeters <= 20) {
setText(null, null);
} else {
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, map);
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setText(ds, null);
} else {
setText(ds.substring(0, ls), ds.substring(ls + 1));
}
}
return true;
}
} else if (cachedMeters != 0) {
cachedMeters = 0; cachedMeters = 0;
setText(null, null); setText(null, null);
return true; } else {
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, view.getContext());
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setText(ds, null);
} else {
setText(ds.substring(0, ls), ds.substring(ls + 1));
}
} }
return false; return true;
}
return false;
}
public abstract LatLon getPointToNavigate();
public int getDistance() {
int d = 0;
LatLon l = getPointToNavigate();
if (l != null) {
Location.distanceBetween(view.getLatitude(), view.getLongitude(), l.getLatitude(), l.getLongitude(), calculations);
d = (int) calculations[0];
}
return d;
}
}
protected TextInfoControl createDistanceControl(final MapActivity map, Paint paintText, Paint paintSubText) {
final OsmandMapTileView view = map.getMapView();
DistanceToPointInfoControl distanceControl = new DistanceToPointInfoControl(map, 0, paintText, paintSubText, map.getResources()
.getDrawable(R.drawable.info_target), view) {
@Override
public LatLon getPointToNavigate() {
return map.getPointToNavigate();
}
@Override
public int getDistance() {
if (map.getRoutingHelper().isRouteCalculated()) {
return map.getRoutingHelper().getLeftDistance();
}
return super.getDistance();
} }
}; };
distanceControl.setOnClickListener(new View.OnClickListener() { return distanceControl;
}
protected TextInfoControl createIntermediateDistanceControl(final MapActivity map, Paint paintText, Paint paintSubText) {
final OsmandMapTileView view = map.getMapView();
DistanceToPointInfoControl distanceControl = new DistanceToPointInfoControl(map, 0, paintText, paintSubText, map.getResources()
.getDrawable(R.drawable.info_intermediate), view) {
@Override @Override
public void onClick(View v) { public LatLon getPointToNavigate() {
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread(); return map.getFirstIntermediatePoint();
LatLon pointToNavigate = view.getSettings().getPointToNavigate();
if (pointToNavigate != null) {
float fZoom = view.getFloatZoom() < 15 ? 15 : view.getFloatZoom();
thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true);
}
} }
});
distanceControl.setText(null, null); @Override
distanceControl.setImageDrawable(view.getResources().getDrawable(R.drawable.info_target)); public int getDistance() {
if (getPointToNavigate() != null && map.getRoutingHelper().isRouteCalculated()) {
return map.getRoutingHelper().getLeftDistanceNextIntermediate();
}
return super.getDistance();
}
};
return distanceControl; return distanceControl;
} }
@ -602,7 +643,7 @@ public class RouteInfoControls {
} }
public boolean distChanged(int oldDist, int dist){ public static boolean distChanged(int oldDist, int dist){
if(oldDist != 0 && Math.abs(oldDist - dist) < 10){ if(oldDist != 0 && Math.abs(oldDist - dist) < 10){
return false; return false;
} }

View file

@ -25,8 +25,11 @@ public class CommandBuilder {
protected static final String C_MAKE_UTWP = "make_ut_wp"; //$NON-NLS-1$ protected static final String C_MAKE_UTWP = "make_ut_wp"; //$NON-NLS-1$
protected static final String C_PREAMBLE = "preamble"; //$NON-NLS-1$ protected static final String C_PREAMBLE = "preamble"; //$NON-NLS-1$
protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$ protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$
protected static final String C_THEN = "then"; //$NON-NLS-1$
protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$ protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$
protected static final String C_AND_ARRIVE_INTERMEDIATE = "and_arrive_intermediate"; //$NON-NLS-1$
protected static final String C_REACHED_INTERMEDIATE = "reached_intermediate"; //$NON-NLS-1$
protected static final String C_THEN = "then"; //$NON-NLS-1$
protected static final String C_BEAR_LEFT = "bear_left"; //$NON-NLS-1$ protected static final String C_BEAR_LEFT = "bear_left"; //$NON-NLS-1$
protected static final String C_BEAR_RIGHT = "bear_right"; //$NON-NLS-1$ protected static final String C_BEAR_RIGHT = "bear_right"; //$NON-NLS-1$
protected static final String C_ROUTE_RECALC = "route_recalc"; //$NON-NLS-1$ protected static final String C_ROUTE_RECALC = "route_recalc"; //$NON-NLS-1$
@ -151,6 +154,14 @@ public class CommandBuilder {
return addCommand(C_REACHED_DESTINATION); return addCommand(C_REACHED_DESTINATION);
} }
public CommandBuilder arrivedAtIntermediatePoint() {
return addCommand(C_REACHED_INTERMEDIATE);
}
public CommandBuilder andArriveAtIntermediatePoint(){
return addCommand(C_AND_ARRIVE_INTERMEDIATE);
}
public CommandBuilder bearLeft(){ public CommandBuilder bearLeft(){
return addCommand(C_BEAR_LEFT); return addCommand(C_BEAR_LEFT);
} }
@ -186,5 +197,6 @@ public class CommandBuilder {
return this.commandPlayer.execute(listStruct); return this.commandPlayer.execute(listStruct);
} }
} }