Announce gpx waypoint
This commit is contained in:
parent
ea4d6fe364
commit
2e864b3098
10 changed files with 154 additions and 20 deletions
|
@ -5,7 +5,10 @@
|
|||
android:layout_height="fill_parent" android:orientation="vertical">
|
||||
<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"/>
|
||||
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
|
||||
|
|
|
@ -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…</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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -687,6 +687,10 @@ public class OsmandSettings {
|
|||
public final OsmandPreference<Boolean> SPEAK_STREET_NAMES = new BooleanPreference("speak_street_names", true).makeProfile().cache();
|
||||
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();
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
@ -470,6 +508,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
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
@ -200,6 +201,13 @@ public class VoiceRouter {
|
|||
lastAnnouncedOffRoute = ms;
|
||||
}
|
||||
}
|
||||
|
||||
public void announceWaypoint(String w) {
|
||||
CommandBuilder p = getNewCommandPlayerToPlay();
|
||||
if(p != null) {
|
||||
p.arrivedAtWayPoint(w).play();
|
||||
}
|
||||
}
|
||||
|
||||
public void announceAlarm(AlarmInfo alarm) {
|
||||
if(alarm == null) {
|
||||
|
|
Loading…
Reference in a new issue