From dbfde54237b811e628f1163d55825c4cb49ce8d7 Mon Sep 17 00:00:00 2001 From: Starcom Date: Sun, 7 Oct 2018 22:31:25 +0200 Subject: [PATCH] Allow to navigate from outside the map. - Simple compass-direction-navigation while outside. - Full navigation starts when entering map. Enter correct lat lon for fromCurrentLocation. --- .../pocketmaps/activities/MapActions.java | 36 ++++----- .../junjunguo/pocketmaps/map/MapHandler.java | 44 +++++++--- .../junjunguo/pocketmaps/map/Navigator.java | 76 +++++++++++------- .../pocketmaps/navigator/NaviEngine.java | 26 +++++- .../junjunguo/pocketmaps/util/GeoMath.java | 2 +- .../pocketmaps/util/TargetDirComputer.java | 80 +++++++++++++++++++ .../junjunguo/pocketmaps/util/Variable.java | 19 ++--- .../app/src/main/res/values-de/strings.xml | 2 +- 8 files changed, 213 insertions(+), 72 deletions(-) create mode 100644 PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/TargetDirComputer.java diff --git a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/activities/MapActions.java b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/activities/MapActions.java index 22c2476..9eeb03f 100644 --- a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/activities/MapActions.java +++ b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/activities/MapActions.java @@ -380,8 +380,7 @@ private void initUseCurrentLocationHandler(final boolean isStartP, int viewID, f if (MapActivity.getmCurrentLocation() != null) { GeoPoint newPos = new GeoPoint(MapActivity.getmCurrentLocation().getLatitude(), MapActivity.getmCurrentLocation().getLongitude()); - String text = Destination.getDestination().getStartPointToString(); - if (!isStartP) { text = Destination.getDestination().getEndPointToString(); } + String text = "" + newPos.getLatitude() + ", " + newPos.getLongitude(); doSelectCurrentPos(newPos, text, isStartP); } else { Toast.makeText(activity, "Current Location not available, Check your GPS signal!", @@ -644,16 +643,17 @@ private void initTravelModeSetting() { bikeBtn = (ImageButton) activity.findViewById(R.id.nav_settings_bike_btn); carBtn = (ImageButton) activity.findViewById(R.id.nav_settings_car_btn); // init travel mode - switch (Variable.getVariable().getTravelMode()) { - case "foot": - footBtn.setImageResource(R.drawable.ic_directions_walk_orange_24dp); - break; - case "bike": - bikeBtn.setImageResource(R.drawable.ic_directions_bike_orange_24dp); - break; - case "car": - carBtn.setImageResource(R.drawable.ic_directions_car_orange_24dp); - break; + if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Foot) + { + footBtn.setImageResource(R.drawable.ic_directions_walk_orange_24dp); + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Bike) + { + bikeBtn.setImageResource(R.drawable.ic_directions_bike_orange_24dp); + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Car) + { + carBtn.setImageResource(R.drawable.ic_directions_car_orange_24dp); } //foot @@ -662,8 +662,8 @@ private void initTravelModeSetting() { footBtn.setImageResource(R.drawable.ic_directions_walk_orange_24dp); bikeBtn.setImageResource(R.drawable.ic_directions_bike_white_24dp); carBtn.setImageResource(R.drawable.ic_directions_car_white_24dp); - if (!Variable.getVariable().getTravelMode().equalsIgnoreCase("foot")) { - Variable.getVariable().setTravelMode("foot"); + if (Variable.getVariable().getTravelMode() != Variable.TravelMode.Foot) { + Variable.getVariable().setTravelMode(Variable.TravelMode.Foot); if (activateNavigator()) { MapHandler.getMapHandler().recalcPath(); @@ -677,8 +677,8 @@ private void initTravelModeSetting() { footBtn.setImageResource(R.drawable.ic_directions_walk_white_24dp); bikeBtn.setImageResource(R.drawable.ic_directions_bike_orange_24dp); carBtn.setImageResource(R.drawable.ic_directions_car_white_24dp); - if (!Variable.getVariable().getTravelMode().equalsIgnoreCase("bike")) { - Variable.getVariable().setTravelMode("bike"); + if (Variable.getVariable().getTravelMode() != Variable.TravelMode.Bike) { + Variable.getVariable().setTravelMode(Variable.TravelMode.Bike); if (activateNavigator()) { MapHandler.getMapHandler().recalcPath(); @@ -692,8 +692,8 @@ private void initTravelModeSetting() { footBtn.setImageResource(R.drawable.ic_directions_walk_white_24dp); bikeBtn.setImageResource(R.drawable.ic_directions_bike_white_24dp); carBtn.setImageResource(R.drawable.ic_directions_car_orange_24dp); - if (!Variable.getVariable().getTravelMode().equalsIgnoreCase("car")) { - Variable.getVariable().setTravelMode("car"); + if (Variable.getVariable().getTravelMode() != Variable.TravelMode.Car) { + Variable.getVariable().setTravelMode(Variable.TravelMode.Car); if (activateNavigator()) { MapHandler.getMapHandler().recalcPath(); diff --git a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/MapHandler.java b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/MapHandler.java index 120385e..c2d1cc3 100644 --- a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/MapHandler.java +++ b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/MapHandler.java @@ -12,7 +12,6 @@ import java.io.File; import java.util.ArrayList; import java.util.List; - import org.oscim.android.MapView; import org.oscim.android.canvas.AndroidGraphics; import org.oscim.backend.canvas.Bitmap; @@ -48,6 +47,7 @@ import com.junjunguo.pocketmaps.R; import com.junjunguo.pocketmaps.model.listeners.MapHandlerListener; import com.junjunguo.pocketmaps.navigator.NaviEngine; +import com.junjunguo.pocketmaps.util.TargetDirComputer; import com.junjunguo.pocketmaps.util.Variable; @@ -406,17 +406,29 @@ public void calcPath(final double fromLat, final double fromLon, @Override protected GHResponse doInBackground(Void... v) { - StopWatch sw = new StopWatch().start(); - GHRequest req = new GHRequest(fromLat, fromLon, toLat, toLon). - setAlgorithm(Algorithms.DIJKSTRA_BI); - req.getHints().put(Routing.INSTRUCTIONS, Variable.getVariable().getDirectionsON()); - req.setVehicle(Variable.getVariable().getTravelMode()); - req.setWeighting(Variable.getVariable().getWeighting()); - GHResponse resp = hopper.route(req); - time = sw.stop().getSeconds(); - return resp; + StopWatch sw = new StopWatch().start(); + GHRequest req = new GHRequest(fromLat, fromLon, toLat, toLon). + setAlgorithm(Algorithms.DIJKSTRA_BI); + req.getHints().put(Routing.INSTRUCTIONS, Variable.getVariable().getDirectionsON()); + req.setVehicle(Variable.getVariable().getTravelMode().toString().toLowerCase()); + req.setWeighting(Variable.getVariable().getWeighting()); + GHResponse resp = hopper.route(req); + if (resp.hasErrors()) + { + NaviEngine.getNaviEngine().setDirectTargetDir(true); + List errors = resp.getErrors(); + log("Multible errors, first: " + errors.get(0)); + resp = TargetDirComputer.getInstance().createTargetdirResponse(fromLat, fromLon, toLat, toLon); + } + else + { + NaviEngine.getNaviEngine().setDirectTargetDir(false); + } + time = sw.stop().getSeconds(); + return resp; } + @Override protected void onPostExecute(GHResponse ghResp) { if (!ghResp.hasErrors()) { @@ -468,6 +480,18 @@ private PathLayer updatePathLayer(PathLayer ref, PointList pointList, int color, ref.setPoints(geoPoints); return ref; } + + public void joinPathLayerToPos(double lat, double lon) + { + try + { + List geoPoints = new ArrayList<>(); + geoPoints.add(new GeoPoint(lat,lon)); + geoPoints.add(pathLayer.getPoints().get(1)); + pathLayer.setPoints(geoPoints); + } + catch (Exception e) { log("Error: " + e); } + } private PathLayer createPathLayer(int color, int strokeWidth) { diff --git a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/Navigator.java b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/Navigator.java index aff830a..c3ab6b6 100644 --- a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/Navigator.java +++ b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/map/Navigator.java @@ -183,51 +183,67 @@ public String toString() { * @return int resId */ public int getTravelModeResId(boolean dark) { - if (dark) { - switch (Variable.getVariable().getTravelMode()) { - case "foot": - return R.drawable.ic_directions_walk_orange_24dp; - case "bike": - return R.drawable.ic_directions_bike_orange_24dp; - case "car": - return R.drawable.ic_directions_car_orange_24dp; - } - } else { - switch (Variable.getVariable().getTravelMode()) { - case "foot": - return R.drawable.ic_directions_walk_white_24dp; - case "bike": - return R.drawable.ic_directions_bike_white_24dp; - case "car": - return R.drawable.ic_directions_car_white_24dp; - } + if (dark) + { + if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Foot) + { + return R.drawable.ic_directions_walk_orange_24dp; + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Bike) + { + return R.drawable.ic_directions_bike_orange_24dp; + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Car) + { + return R.drawable.ic_directions_car_orange_24dp; + } + } + else + { + if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Foot) + { + return R.drawable.ic_directions_walk_white_24dp; + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Bike) + { + return R.drawable.ic_directions_bike_white_24dp; + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Car) + { + return R.drawable.ic_directions_car_white_24dp; + } } throw new NullPointerException("this method can only used when Variable class is ready!"); } - public int getTravelModeArrayIndex() { - switch (Variable.getVariable().getTravelMode()) { - case "foot": - return 0; - case "bike": - return 1; - case "car": - return 2; + public int getTravelModeArrayIndex() + { + if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Foot) + { + return 0; + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Bike) + { + return 1; + } + else if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Car) + { + return 2; } throw new NullPointerException("this method can only used when Variable class is ready!"); } public boolean setTravelModeArrayIndex(int index) { - String selected; + Variable.TravelMode selected; switch (index) { case 0: - selected = "foot"; + selected = Variable.TravelMode.Foot; break; case 1: - selected = "bike"; + selected = Variable.TravelMode.Bike; break; default: - selected = "car"; + selected = Variable.TravelMode.Car; } Variable.getVariable().setTravelMode(selected); return Variable.getVariable().saveVariables(); diff --git a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/navigator/NaviEngine.java b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/navigator/NaviEngine.java index 3798cfd..9d81bed 100644 --- a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/navigator/NaviEngine.java +++ b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/navigator/NaviEngine.java @@ -32,6 +32,7 @@ public class NaviEngine private static final int BEST_NAVI_ZOOM = 18; enum UiJob { Nothing, RecalcPath, UpdateInstruction, Finished }; private UiJob uiJob = UiJob.Nothing; + private boolean directTargetDir = false; NaviVoice naviVoice; LightSensor lightSensor; boolean naviVoiceSpoken = false; @@ -101,10 +102,20 @@ else if ((!active) && lightSensor!=null) } } + /** This allows to update pathLayer, when instructions is just a line from target to curLoc. + * @param directTargetDir True to update pathLayer, join to curPos. **/ + public void setDirectTargetDir(boolean directTargetDir) + { + this.directTargetDir = directTargetDir; + } + public void onUpdateInstructions(InstructionList instructions) { if (uiJob != UiJob.RecalcPath) { throw new IllegalStateException("Getting instructions but state is not RecalcPath!"); } - nearestP.checkDirectionOk(pos, instructions.get(0), naviVoice); + if (!directTargetDir) + { + nearestP.checkDirectionOk(pos, instructions.get(0), naviVoice); + } this.instructions = instructions; getNewInstruction(); uiJob = UiJob.UpdateInstruction; @@ -152,6 +163,7 @@ public void updatePosition(Activity activity, Location pos) private void calculatePositionAsync(GeoPoint curPos) { if (naviEngineTask == null) { createNaviEngineTask(); } + updateDirectTargetDir(curPos); if (naviEngineTask.getStatus() == Status.RUNNING) { log("Error, NaviEngineTask is still running! Drop job ..."); @@ -167,6 +179,12 @@ else if (naviEngineTask.hasError()) } } + private void updateDirectTargetDir(GeoPoint curPos) + { + if (!directTargetDir) { return; } + MapHandler.getMapHandler().joinPathLayerToPos(curPos.getLatitude(), curPos.getLongitude()); + } + @UiThread private void createNaviEngineTask() { @@ -334,11 +352,13 @@ else if (nearestP.arrPos == instructions.get(0).getPoints().size()-1 && } if (!nearestP.isDistanceOk()) { - Instruction nearestNext = instructions.find(curPos.getLatitude(), curPos.getLongitude(), MAX_WAY_TOLERANCE_METER); + double maxWayTolMeters = MAX_WAY_TOLERANCE_METER; + if (directTargetDir) { maxWayTolMeters = maxWayTolMeters * 10.0; } + Instruction nearestNext = instructions.find(curPos.getLatitude(), curPos.getLongitude(), maxWayTolMeters); if (nearestNext == null) { GeoPoint closestP = findClosestStreet(curPos); - nearestNext = instructions.find(closestP.getLatitude(), closestP.getLongitude(), MAX_WAY_TOLERANCE_METER); + nearestNext = instructions.find(closestP.getLatitude(), closestP.getLongitude(), maxWayTolMeters); } if (nearestNext == null) { diff --git a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/GeoMath.java b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/GeoMath.java index f22430b..d6a9a43 100644 --- a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/GeoMath.java +++ b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/GeoMath.java @@ -17,7 +17,7 @@ public static double dist2(double v_x, double v_y, double w_x, double w_y) return sqr(v_x - w_x) + sqr(v_y - w_y); } - /** Function from GeoPoint.java! **/ + /** Calculates the estimated distance in degree. Function from GeoPoint.java! **/ public static double fastDistance(double lat1, double lon1, double lat2, double lon2) { return Math.hypot(lon1 - lon2, lat1 - lat2); diff --git a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/TargetDirComputer.java b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/TargetDirComputer.java new file mode 100644 index 0000000..7b3e3f9 --- /dev/null +++ b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/TargetDirComputer.java @@ -0,0 +1,80 @@ +package com.junjunguo.pocketmaps.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import com.graphhopper.GHResponse; +import com.graphhopper.PathWrapper; +import com.graphhopper.util.Instruction; +import com.graphhopper.util.InstructionAnnotation; +import com.graphhopper.util.InstructionList; +import com.graphhopper.util.PointList; +import com.graphhopper.util.Translation; +import com.junjunguo.pocketmaps.map.Tracking; + +import android.util.Log; + +public class TargetDirComputer +{ + private static TargetDirComputer instance = new TargetDirComputer(); + + public static TargetDirComputer getInstance() + { + return instance; + } + + public GHResponse createTargetdirResponse(double fromLat, double fromLon, double toLat, double toLon) + { + GHResponse resp = new GHResponse(); + PathWrapper pr = new PathWrapper(); + PointList pl = new PointList(); + pl.add(fromLat, fromLon); + pl.add(toLat, toLon); + pr.setPoints(pl); + double distance = GeoMath.fastDistance(fromLat, fromLon, toLat, toLon); + distance = distance * GeoMath.METER_PER_DEGREE; + pr.setDistance(distance); + double distKm = distance / 1000.0; + double hours = distKm / 50; // 50km == 1h + if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Bike) { hours = hours * 3.0; } + if (Variable.getVariable().getTravelMode() == Variable.TravelMode.Foot) { hours = hours * 9.0; } + long timeMs = (long)(hours * 60.0 * 60.0 * 1000.0); + pr.setTime(timeMs); + InstructionList insL = new InstructionList(createEmptyTranslator()); + int sign = Instruction.CONTINUE_ON_STREET; + String name = "direction to target"; + InstructionAnnotation ia = InstructionAnnotation.EMPTY; + Instruction ins = new Instruction(sign, name, ia, pl); + ins.setDistance(distance); + ins.setTime(timeMs); + insL.add(ins); + pr.setInstructions(insL); + resp.add(pr); + return resp; + } + + private Translation createEmptyTranslator() + { + Translation t = new Translation() + { + @Override public String tr(String key, Object... params) + { + StringBuilder sb = new StringBuilder(key); + for (Object o : params) { sb.append(" ").append(o.toString()); } + return sb.toString(); + } + + @Override public Map asMap() + { + return new HashMap(); + } + + @Override public Locale getLocale() { return Locale.ENGLISH; } + + @Override public String getLanguage() { return Locale.ENGLISH.getLanguage(); } + }; + return t; + } +} diff --git a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/Variable.java b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/Variable.java index fc86a63..ea2ddb6 100644 --- a/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/Variable.java +++ b/PocketMaps/app/src/main/java/com/junjunguo/pocketmaps/util/Variable.java @@ -28,10 +28,9 @@ * Created by GuoJunjun on June 27, 2015. */ public class Variable { - /** - * foot, bike, car - */ - private String travelMode; + public enum TravelMode{Foot, Bike, Car}; + + private TravelMode travelMode; /** * fastest, shortest (route) */ @@ -142,7 +141,7 @@ public class Variable { private static Variable variable; private Variable() { - this.travelMode = "foot"; + this.travelMode = TravelMode.Foot; this.weighting = "fastest"; this.routingAlgorithms = "astarbi"; this.zoomLevelMax = 22; @@ -177,11 +176,11 @@ public String getMapUrlJSON() { return mapUrlJSON; } - public String getTravelMode() { + public TravelMode getTravelMode() { return travelMode; } - public void setTravelMode(String travelMode) { + public void setTravelMode(TravelMode travelMode) { this.travelMode = travelMode; } @@ -403,10 +402,12 @@ public void updateCloudMaps(List cloudMaps) { this.cloudMaps = newList; } + /** Similar as getTravelMode() but used for spinner. **/ public int getSportCategoryIndex() { return sportCategoryIndex; } + /** Similar as setTravelMode() but used for spinner. **/ public void setSportCategoryIndex(int sportCategoryIndex) { this.sportCategoryIndex = sportCategoryIndex; } @@ -426,7 +427,7 @@ public boolean loadVariables() { JSONObject jo; try { jo = new JSONObject(file); - setTravelMode(jo.getString("travelMode")); + setTravelMode(TravelMode.valueOf(jo.getString("travelMode"))); setWeighting(jo.getString("weighting")); setRoutingAlgorithms(jo.getString("routingAlgorithms")); setDirectionsON(jo.getBoolean("directionsON")); @@ -464,7 +465,7 @@ public boolean loadVariables() { public boolean saveVariables() { JSONObject jo = new JSONObject(); try { - jo.put("travelMode", getTravelMode()); + jo.put("travelMode", getTravelMode().toString()); jo.put("weighting", getWeighting()); jo.put("routingAlgorithms", getRoutingAlgorithms()); jo.put("advancedSetting", isAdvancedSetting()); diff --git a/PocketMaps/app/src/main/res/values-de/strings.xml b/PocketMaps/app/src/main/res/values-de/strings.xml index ef3e187..64581b1 100644 --- a/PocketMaps/app/src/main/res/values-de/strings.xml +++ b/PocketMaps/app/src/main/res/values-de/strings.xml @@ -14,7 +14,7 @@ Von Nach Wähle von Favoriten - Eingabe Längengrad Breigengrad + Eingabe Längengrad Breitengrad Punkt auf Karte Reise Modus Fuß