package com.arman.osmdroidmapsforge.routing; /** * Created by Arman on 7/10/2015. */ import android.content.Context; import android.util.Log; import com.graphhopper.GHResponse; import com.graphhopper.util.Instruction; import com.graphhopper.util.PointList; import com.graphhopper.util.shapes.BBox; import com.graphhopper.util.shapes.GHPoint; import org.osmdroid.bonuspack.routing.Road; import org.osmdroid.bonuspack.routing.RoadManager; import org.osmdroid.bonuspack.routing.RoadNode; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.util.BoundingBoxE6; import org.osmdroid.util.GeoPoint; import java.util.ArrayList; import java.util.HashMap; /** get a route between a start and a destination point, going through a list of waypoints. * It uses GraphHopper, an open source routing service based on OpenSteetMap data. <br> * * It requests by default the GraphHopper demo site. * Use setService() to request another (for instance your own) GraphHopper-compliant service. <br> * * @see <a href="https://github.com/graphhopper/web-api/blob/master/docs-routing.md">GraphHopper</a> * @author M.Kergall */ public class GraphHopperRoadManager extends RoadManager { public static final int STATUS_NO_ROUTE = Road.STATUS_TECHNICAL_ISSUE+1; public RouteCalculator mRouteCalculator; private Context mContext; protected boolean mWithElevation; /** mapping from GraphHopper directions to MapQuest maneuver IDs: */ static final HashMap<Integer, Integer> MANEUVERS; static { MANEUVERS = new HashMap<Integer, Integer>(); MANEUVERS.put(0, 1); //Continue MANEUVERS.put(1, 6); //Slight right MANEUVERS.put(2, 7); //Right MANEUVERS.put(3, 8); //Sharp right MANEUVERS.put(-3, 5); //Sharp left MANEUVERS.put(-2, 4); //Left MANEUVERS.put(-1, 3); //Slight left MANEUVERS.put(4, 24); //Arrived MANEUVERS.put(5, 24); //Arrived at waypoint } public GraphHopperRoadManager(Context context){ super(); mWithElevation = false; this.mContext = context; } /** set if altitude of every route point should be requested or not. Default is false. */ public void setElevation(boolean withElevation){ mWithElevation = withElevation; } @Override public Road getRoad(ArrayList<GeoPoint> waypoints) { if (mRouteCalculator == null) { mRouteCalculator = new RouteCalculator(mContext); mRouteCalculator.loadGraphStorage(); } ArrayList<GHPoint> points = new ArrayList<GHPoint>(); for (int i =0; i < waypoints.size(); i++) { points.add(new GHPoint(waypoints.get(i).getLatitude(), waypoints.get(i).getLongitude())); } GHResponse response = mRouteCalculator.calculatePath(points); Road road = new Road(); try { if (response.hasErrors()){ road = new Road(waypoints); road.mStatus = STATUS_NO_ROUTE; return road; } ArrayList<GeoPoint> allPoints = new ArrayList<GeoPoint>(); PointList tmpPointList = response.getPoints(); for (int i = 0; i < tmpPointList.getSize(); i++) { allPoints.add(new GeoPoint(tmpPointList.getLatitude(i), tmpPointList.getLongitude(i))); } road.mRouteHigh = allPoints; int n = response.getInstructions().getSize(); for (int i = 0; i < n; i++){ Instruction instruction = response.getInstructions().get(i); RoadNode node = new RoadNode(); //JSONArray jInterval = instruction // int positionIndex = jInterval.getInt(0); node.mLocation = new GeoPoint(instruction.getPoints().getLatitude(0), instruction.getPoints().getLongitude(0)); node.mLength = instruction.getDistance()/1000.0; node.mDuration = instruction.getTime()/1000.0; //Segment duration in seconds. int direction = instruction.getSign(); node.mManeuverType = getManeuverCode(direction); String instructionStr = ""; switch (direction) { case 0: instructionStr += "مستقیم بروید"; break; case 1: instructionStr += "کمی به راست بچیپید"; break; case 2: instructionStr += "به راست بپیچید"; break; case 3: instructionStr += "کامل به راست بپیچید"; break; case -1: instructionStr += "کمی به چپ بپیچید"; break; case -2: instructionStr += "به چپ بپیچید"; break; case -3: instructionStr += "کامل به چپ بچیپید"; break; case 4: instructionStr += "به مقصد رسیدید"; break; case 5: instructionStr += "به نقطه ی میانی رسیدید"; break; } if (instruction.getName().equals("")) { node.mInstructions = instructionStr + " " + instruction.getName(); } else node.mInstructions = instructionStr + " به " + instruction.getName(); road.mNodes.add(node); } road.mLength = response.getDistance()/1000.0; road.mDuration = response.getMillis()/1000.0; BBox bBox = response.calcRouteBBox(new BBox(32.00, 33.99, 51.00, 53.00)); road.mBoundingBox = new BoundingBoxE6(bBox.maxLat, bBox.maxLon, bBox.minLat, bBox.minLon); road.mStatus = Road.STATUS_OK; } catch (Exception e) { road.mStatus = Road.STATUS_TECHNICAL_ISSUE; e.printStackTrace(); } if (road.mStatus != Road.STATUS_OK){ //Create default road: int status = road.mStatus; road = new Road(waypoints); road.mStatus = status; } else { road.buildLegs(waypoints); } Log.d(BonusPackHelper.LOG_TAG, "GraphHopper.getRoad - finished"); return road; } protected int getManeuverCode(int direction){ Integer code = MANEUVERS.get(direction); if (code != null) return code; else return 0; } }