Announce gpx waypoint

This commit is contained in:
Victor Shcherb 2013-07-24 23:58:09 +02:00
parent ea4d6fe364
commit 2e864b3098
10 changed files with 154 additions and 20 deletions

View file

@ -6,6 +6,9 @@
<TextView android:text="@string/select_animate_speedup" android:gravity="center"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp"/>
<CheckBox android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/AnnounceGPXWpt"
android:layout_marginLeft="10dp" android:layout_marginRight="10dp"
android:text="@string/announce_gpx_waypoints"/>
<SeekBar android:id="@+id/Speedup" android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp"/>
<LinearLayout

View file

@ -9,6 +9,7 @@
3. 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
-->
<string name="announce_gpx_waypoints">Announce GPX waypoints</string>
<string name="speak_title">Announce&#8230;</string>
<string name="speak_descr">Configure to announce street names, traffic warnings (forced stops, speed bumps), speed camera warnings, speed limits</string>
<string name="speak_street_names">Announce street names (TTS)</string>

View file

@ -14,6 +14,7 @@ import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.view.View;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
@ -40,6 +41,7 @@ public class OsmAndLocationSimulation {
((TextView)view.findViewById(R.id.MinSpeedup)).setText("1"); //$NON-NLS-1$
((TextView)view.findViewById(R.id.MaxSpeedup)).setText("4"); //$NON-NLS-1$
final SeekBar speedup = (SeekBar) view.findViewById(R.id.Speedup);
final CheckBox ch = (CheckBox ) view.findViewById(R.id.AnnounceGPXWpt);
speedup.setMax(3);
builder.setView(view);
builder.setPositiveButton(R.string.default_buttons_yes, new DialogInterface.OnClickListener() {
@ -50,7 +52,7 @@ public class OsmAndLocationSimulation {
@Override
public boolean processResult(GPXUtilities.GPXFile result) {
GPXRouteParams prms = new RouteProvider.GPXRouteParams(result, false,
GPXRouteParams prms = new RouteProvider.GPXRouteParams(result, false, ch.isChecked(),
app.getSettings());
startAnimationThread(app.getRoutingHelper(), ma, prms.getPoints(), true, speedup.getProgress() + 1);
return true;

View file

@ -688,6 +688,10 @@ public class OsmandSettings {
public final OsmandPreference<Boolean> SPEAK_SPEED_CAMERA = new BooleanPreference("speak_cameras", true).makeProfile().cache();
public final OsmandPreference<Boolean> SPEAK_SPEED_LIMIT = new BooleanPreference("speak_speed_limit", true).makeProfile().cache();
public final OsmandPreference<Boolean> SPEAK_GPX_WPT = new BooleanPreference("speak_gpx_wpt", true).makeGlobal().cache();
public final OsmandPreference<Boolean> AVOID_TOLL_ROADS = new BooleanPreference("avoid_toll_roads", false).makeProfile().cache();
public final OsmandPreference<Boolean> AVOID_MOTORWAY = new BooleanPreference("avoid_motorway", false).makeProfile().cache();
public final OsmandPreference<Boolean> AVOID_UNPAVED_ROADS = new BooleanPreference("avoid_unpaved_roads", false).makeProfile().cache();

View file

@ -758,9 +758,10 @@ public class MapActivityActions implements DialogProvider {
@Override
public boolean processResult(final GPXFile result) {
Builder builder = new AlertDialog.Builder(mapActivity);
final boolean[] props = new boolean[]{false, false, false};
final boolean[] props = new boolean[]{false, false, false, settings.SPEAK_GPX_WPT.get()};
builder.setMultiChoiceItems(new String[] { getString(R.string.gpx_option_reverse_route),
getString(R.string.gpx_option_destination_point), getString(R.string.gpx_option_from_start_point) }, props,
getString(R.string.gpx_option_destination_point), getString(R.string.gpx_option_from_start_point),
getString(R.string.announce_gpx_waypoints) }, props,
new OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
@ -773,7 +774,9 @@ public class MapActivityActions implements DialogProvider {
boolean reverse = props[0];
boolean passWholeWay = props[2];
boolean useDestination = props[1];
GPXRouteParams gpxRoute = new GPXRouteParams(result, reverse, settings);
boolean announceGpxWpt = props[3];
settings.SPEAK_GPX_WPT.set(announceGpxWpt);
GPXRouteParams gpxRoute = new GPXRouteParams(result, reverse, announceGpxWpt, settings);
Location loc = getLastKnownLocation();
if(passWholeWay && loc != null){

View file

@ -123,7 +123,8 @@ public class FailSafeFuntions {
@Override
protected void onPostExecute(GPXFile result) {
final GPXRouteParams gpxRoute = result == null ? null : new GPXRouteParams(result, false, settings);
final GPXRouteParams gpxRoute = result == null ? null : new GPXRouteParams(result, false,
settings.SPEAK_GPX_WPT.get(), settings);
LatLon endPoint = pointToNavigate != null ? pointToNavigate : gpxRoute.getLastPoint();
net.osmand.Location startPoint = gpxRoute == null ? null : gpxRoute.getStartPointForRoute();
if (endPoint == null) {

View file

@ -1,14 +1,20 @@
package net.osmand.plus.routing;
import gnu.trove.list.array.TIntArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.osmand.Location;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule;
import net.osmand.data.DataTileManager;
import net.osmand.data.LatLon;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.ClientContext;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandSettings;
@ -23,9 +29,11 @@ public class RouteCalculationResult {
private final List<RouteDirectionInfo> directions;
private final List<RouteSegmentResult> segments;
private final List<AlarmInfo> alarmInfo;
private final List<WptPt> waypoints;
private final String errorMessage;
private final int[] listDistance;
private final int[] intermediatePoints;
private final int[] waypointIndexes;
private final float routingTime;
@ -35,13 +43,15 @@ public class RouteCalculationResult {
protected int currentRoute = 0;
protected int nextIntermediate = 0;
protected int nextAlarmInfo = 0;
protected int currentWaypointGPX = 0;
protected int lastWaypointGPX = 0;
public RouteCalculationResult(String errorMessage) {
this(null, null, null, null, null, errorMessage, null, false, false);
this(null, null, null, null, null, null, errorMessage, null, false, false);
}
public RouteCalculationResult(List<Location> list, List<RouteDirectionInfo> directions, Location start, LatLon end,
List<LatLon> intermediates, String errorMessage, ClientContext ctx, boolean leftSide, boolean addMissingTurns) {
List<LatLon> intermediates, DataTileManager<WptPt> waypointsTm, String errorMessage, ClientContext ctx, boolean leftSide, boolean addMissingTurns) {
this.routingTime = 0;
this.errorMessage = errorMessage;
this.intermediatePoints = new int[intermediates == null ? 0 : intermediates.size()];
@ -66,6 +76,8 @@ public class RouteCalculationResult {
calculateIntermediateIndexes(ctx, intermediates, localDirections);
this.directions = Collections.unmodifiableList(localDirections);
updateDirectionsTime();
this.waypoints = new ArrayList<WptPt>();
this.waypointIndexes = calculateWaypointIndexes(list, waypointsTm, waypoints);
}
public RouteCalculationResult(List<RouteSegmentResult> list, Location start, LatLon end, List<LatLon> intermediates,
@ -88,7 +100,33 @@ public class RouteCalculationResult {
this.directions = Collections.unmodifiableList(computeDirections);
updateDirectionsTime();
this.alarmInfo = Collections.unmodifiableList(alarms);
this.waypointIndexes = new int[0];
this.waypoints = new ArrayList<WptPt>();
}
public List<WptPt> getWaypointsToAnnounce(Location loc) {
if (currentWaypointGPX != lastWaypointGPX && loc != null) {
ArrayList<WptPt> points = new ArrayList<WptPt>();
Location next = locations.get(currentRoute);
float dist = loc.distanceTo(next);
while (currentWaypointGPX < lastWaypointGPX) {
WptPt w = waypoints.get(currentWaypointGPX);
if(MapUtils.getDistance(w.lat, w.lon, next.getLatitude(), next.getLongitude()) > dist + 50) {
currentWaypointGPX++;
} else {
break;
}
}
while (currentWaypointGPX < lastWaypointGPX) {
WptPt w = waypoints.get(currentWaypointGPX);
if(MapUtils.getDistance(w.lat, w.lon, loc.getLatitude(), next.getLongitude()) < 60) {
currentWaypointGPX++;
points.add(w);
}
}
return points;
}
return Collections.emptyList();
}
private void calculateIntermediateIndexes(ClientContext ctx, List<LatLon> intermediates, List<RouteDirectionInfo> localDirections) {
@ -471,6 +509,47 @@ public class RouteCalculationResult {
}
}
/**
* PREPARATION
*
*/
private int[] calculateWaypointIndexes(List<Location> list, DataTileManager<WptPt> waypointsTm, List<WptPt> waypoints) {
if(waypointsTm == null || waypointsTm.isEmpty() || list.size() == 0) {
return new int[0];
}
TIntArrayList ls = new TIntArrayList();
Location loc = list.get(0);
Location ploc = list.get(0);
Set<WptPt> added = new HashSet<WptPt>();
int prev31x = MapUtils.get31TileNumberX(loc.getLatitude());
int prev31y = MapUtils.get31TileNumberY(loc.getLongitude());
for(int j = 1; j < list.size(); j++) {
loc = list.get(j);
int t31x = MapUtils.get31TileNumberX(loc.getLatitude());
int t31y = MapUtils.get31TileNumberY(loc.getLongitude());
List<WptPt> ws = waypointsTm.getObjects(Math.min(prev31x, t31x) - Math.abs(t31x - prev31x) / 4,
Math.min(prev31y, t31y) - Math.abs(t31y - prev31y) / 4,
Math.max(prev31x, t31x) + Math.abs(t31x - prev31x) / 4,
Math.max(prev31y, t31y) + Math.abs(t31y - prev31y) / 4);
for(WptPt w : ws) {
if (added.contains(w)) {
double ds = MapUtils.getOrthogonalDistance(w.lat, w.lon, ploc.getLatitude(), ploc.getLongitude(), loc.getLatitude(),
loc.getLongitude());
if (ds < 80) {
ls.add(j);
waypoints.add(w);
added.add(w);
}
}
}
prev31x = t31x;
prev31y = t31y;
ploc = loc;
}
return ls.toArray();
}
/**
* PREPARATION
* Check points for duplicates (it is very bad for routing) - cloudmade could return it
@ -631,6 +710,9 @@ public class RouteCalculationResult {
while (nextAlarmInfo < alarmInfo.size() && alarmInfo.get(nextAlarmInfo).locationIndex < currentRoute) {
nextAlarmInfo++;
}
while(lastWaypointGPX < waypointIndexes.length && waypointIndexes[lastWaypointGPX] <= currentRoute) {
lastWaypointGPX++;
}
while(nextIntermediate < intermediatePoints.length) {
RouteDirectionInfo dir = directions.get(intermediatePoints[nextIntermediate]);
if(dir.routePointOffset < currentRoute) {

View file

@ -24,19 +24,19 @@ import javax.xml.parsers.ParserConfigurationException;
import net.osmand.IndexConstants;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.NativeLibrary;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.DataTileManager;
import net.osmand.data.LatLon;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.ClientContext;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.Route;
import net.osmand.plus.GPXUtilities.Track;
import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.router.GeneralRouter;
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
import net.osmand.router.RoutePlannerFrontEnd;
@ -44,6 +44,7 @@ import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.RoutingContext;
import net.osmand.router.TurnType;
import net.osmand.util.MapUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -75,9 +76,10 @@ public class RouteProvider {
public static class GPXRouteParams {
List<Location> points = new ArrayList<Location>();
List<RouteDirectionInfo> directions;
DataTileManager<WptPt> wpt;
public GPXRouteParams(GPXFile file, boolean reverse, OsmandSettings settings){
prepareEverything(file, reverse, settings.LEFT_SIDE_NAVIGATION.get());
public GPXRouteParams(GPXFile file, boolean reverse, boolean announceWaypoints, OsmandSettings settings){
prepareEverything(file, reverse, announceWaypoints, settings.LEFT_SIDE_NAVIGATION.get());
}
public void setStartPoint(Location startPoint) {
@ -104,7 +106,7 @@ public class RouteProvider {
return null;
}
private void prepareEverything(GPXFile file, boolean reverse, boolean leftSide){
private void prepareEverything(GPXFile file, boolean reverse, boolean announceWaypoints, boolean leftSide){
if(file.isCloudmadeRouteFile() || OSMAND_ROUTER.equals(file.author)){
directions = parseCloudmadeRoute(points, file, OSMAND_ROUTER.equals(file.author), leftSide, 10);
if(reverse){
@ -132,6 +134,14 @@ public class RouteProvider {
Collections.reverse(points);
}
}
wpt = null;
if(announceWaypoints && !file.points.isEmpty()) {
wpt = new DataTileManager<WptPt>(17);
for(WptPt w : file.points ) {
wpt.registerObjectXY(MapUtils.get31TileNumberX(w.lon),
MapUtils.get31TileNumberY(w.lat),w) ;
}
}
}
}
@ -223,7 +233,7 @@ public class RouteProvider {
}
ArrayList<Location> sublist = new ArrayList<Location>(gpxRoute.subList(startI, endI));
if(params.directions == null){
res = new RouteCalculationResult(sublist, params.directions, pars.start, pars.end, null, null,
res = new RouteCalculationResult(sublist, params.directions, pars.start, pars.end, null, params.wpt, null,
pars.ctx, pars.leftSide, true);
} else {
List<RouteDirectionInfo> subdirections = new ArrayList<RouteDirectionInfo>();
@ -239,7 +249,7 @@ public class RouteProvider {
subdirections.add(ch);
}
}
res = new RouteCalculationResult(sublist, subdirections, pars.start, pars.end, null, null,
res = new RouteCalculationResult(sublist, subdirections, pars.start, pars.end, null, null, null,
pars.ctx, pars.leftSide, true);
}
return res;
@ -310,7 +320,7 @@ public class RouteProvider {
}
}
return new RouteCalculationResult(res, null, params.start, params.end, null, null,
return new RouteCalculationResult(res, null, params.start, params.end, null, null, null,
params.ctx, params.leftSide, true);
}
@ -472,7 +482,7 @@ public class RouteProvider {
GPXFile gpxFile = GPXUtilities.loadGPXFile(params.ctx, connection.getInputStream(), false);
directions = parseCloudmadeRoute(res, gpxFile, false, params.leftSide, speed);
return new RouteCalculationResult(res, directions, params.start, params.end, params.intermediates,
return new RouteCalculationResult(res, directions, params.start, params.end, params.intermediates, null,
null, params.ctx, params.leftSide, true);
}
@ -651,7 +661,7 @@ public class RouteProvider {
}
}
return new RouteCalculationResult(res, null, params.start, params.end, null, null, params.ctx, params.leftSide, true);
return new RouteCalculationResult(res, null, params.start, params.end, null, null, null, params.ctx, params.leftSide, true);
}
public GPXFile createOsmandRouterGPX(RouteCalculationResult srcRoute){

View file

@ -14,6 +14,7 @@ import net.osmand.data.LatLon;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.ClientContext;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.MetricsConstants;
@ -215,6 +216,7 @@ public class RoutingHelper {
if (finished) {
return null;
}
announceGpxWaypoints(currentLocation);
List<Location> routeNodes = route.getImmutableLocations();
int currentRoute = route.currentRoute;
@ -276,6 +278,24 @@ public class RoutingHelper {
}
}
private void announceGpxWaypoints(Location currentLocation) {
if (currentLocation != null) {
List<WptPt> wpt = route.getWaypointsToAnnounce(currentLocation);
if (wpt.size() > 0) {
String s = "";
for (WptPt w : wpt) {
if(!Algorithms.isEmpty(w.name)) {
s = w.name +",";
}
}
if(!Algorithms.isEmpty(s)) {
voiceRouter.announceWaypoint(s);
}
}
}
}
private static double getOrthogonalDistance(Location loc, Location from, Location to) {
return MapUtils.getOrthogonalDistance(loc.getLatitude(),
loc.getLongitude(), from.getLatitude(), from.getLongitude(),

View file

@ -4,6 +4,7 @@ package net.osmand.plus.routing;
import net.osmand.Location;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.ClientContext;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
import net.osmand.plus.voice.AbstractPrologCommandPlayer;
import net.osmand.plus.voice.CommandBuilder;
@ -201,6 +202,13 @@ public class VoiceRouter {
}
}
public void announceWaypoint(String w) {
CommandBuilder p = getNewCommandPlayerToPlay();
if(p != null) {
p.arrivedAtWayPoint(w).play();
}
}
public void announceAlarm(AlarmInfo alarm) {
if(alarm == null) {
return;