Android Open Source - SmartNavi Map Quest Road Manager






From Project

Back to project page SmartNavi.

License

The source code is released under:

Apache License

If you think the Android project SmartNavi listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.osmdroid.bonuspack.routing;
/*from  ww  w .  j  a  va  2 s . c om*/
import java.io.InputStream;
import java.util.ArrayList;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.osmdroid.bonuspack.utils.BonusPackHelper;
import org.osmdroid.bonuspack.utils.HttpConnection;
import org.osmdroid.bonuspack.utils.PolylineEncoder;
import org.osmdroid.util.BoundingBoxE6;
import org.osmdroid.util.GeoPoint;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;

/** class to get a route between a start and a destination point, 
 * going through a list of waypoints. 
 * 
 * It uses MapQuest open, public and free API, based on OpenStreetMap data. <br>
 * See http://open.mapquestapi.com/guidance
 * @return a "Road" object. 
 * 
 * @author M.Kergall
 */
public class MapQuestRoadManager extends RoadManager {
  
  static final String MAPQUEST_GUIDANCE_SERVICE = "http://open.mapquestapi.com/guidance/v1/route?";
  protected String mApiKey;
  
  /**
   * @param apiKey MapQuest API key, mandatory to use the MapQuest Open service. 
   * @see http://developer.mapquest.com
   */
  public MapQuestRoadManager(String apiKey){
    super();
    mApiKey = apiKey;
  }
  
  /**
   * Build the URL to MapQuest service returning a route in XML format
   * @param waypoints: array of waypoints, as [lat, lng], from start point to end point. 
   */
  protected String getUrl(ArrayList<GeoPoint> waypoints) {
    StringBuffer urlString = new StringBuffer(MAPQUEST_GUIDANCE_SERVICE);
    urlString.append("key="+mApiKey);
    urlString.append("&from=");
    GeoPoint p = waypoints.get(0);
    urlString.append(geoPointAsString(p));
    
    for (int i=1; i<waypoints.size(); i++){
      p = waypoints.get(i);
      urlString.append("&to="+geoPointAsString(p));
    }
    
    urlString.append("&outFormat=xml");
    urlString.append("&shapeFormat=cmp"); //encoded polyline, much faster
    
    urlString.append("&narrativeType=text"); //or "none"
    //Locale locale = Locale.getDefault();
    //urlString.append("&locale="+locale.getLanguage()+"_"+locale.getCountry());
    
    urlString.append("&unit=k&fishbone=false");
    
    //urlString.append("&generalizeAfter=500" /*+&generalize=2"*/); 
      //500 points max, 2 meters tolerance
    
    //Warning: MapQuest Open API doc is sometimes WRONG:
    //- use unit, not units
    //- use fishbone, not enableFishbone
    //- locale (fr_FR, en_US) is supported but not documented. 
    //- generalize and generalizeAfter are not properly implemented
    urlString.append(mOptions);
    return urlString.toString();
  }
  
  /**
   * @param waypoints list of GeoPoints. Must have at least 2 entries, start and end points. 
   * @return the road
   */
  @Override public Road getRoad(ArrayList<GeoPoint> waypoints) {
    String url = getUrl(waypoints);
    Log.d(BonusPackHelper.LOG_TAG, "MapQuestRoadManager.getRoute:"+url);
    Road road = null;
    HttpConnection connection = new HttpConnection();
    connection.doGet(url);
    InputStream stream = connection.getStream();
    if (stream != null)
      road = getRoadXML(stream, waypoints);
    connection.close();
    Log.d(BonusPackHelper.LOG_TAG, "MapQuestRoadManager.getRoute - finished");
    return road;
  }

  /** 
   * XML implementation
   * @param is: input stream to parse
   * @return the road
   */
  protected Road getRoadXML(InputStream is, ArrayList<GeoPoint> waypoints) {
    MapQuestGuidanceHandler handler = new MapQuestGuidanceHandler();
    try {
      SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
      parser.parse(is, handler);
    } catch (Exception e) {
      e.printStackTrace();
    }
    Road road = handler.mRoad;
    if (road != null && road.mStatus == Road.STATUS_OK){
      road.mNodes = finalizeNodes(road.mNodes, handler.mLinks, road.mRouteHigh);
      road.mRouteHigh = finalizeRoadShape(road, handler.mLinks);
      road.buildLegs(waypoints);
      road.mStatus = Road.STATUS_OK;
    } else {
      int status = (road != null ? road.mStatus : Road.STATUS_TECHNICAL_ISSUE);
      //Create default road:
      road = new Road(waypoints);
      road.mStatus = status;
    }
    return road;
  }
  
  protected ArrayList<RoadNode> finalizeNodes(ArrayList<RoadNode> mNodes, 
      ArrayList<RoadLink> mLinks, ArrayList<GeoPoint> polyline){
    int n = mNodes.size();
    if (n == 0)
      return mNodes;
    ArrayList<RoadNode> newNodes = new ArrayList<RoadNode>(n);
    RoadNode lastNode = null;
    for (int i=1; i<n-1; i++){ //1, n-1 => first and last MapQuest nodes are irrelevant.
      RoadNode node = mNodes.get(i);
      RoadLink link = mLinks.get(node.mNextRoadLink);
      if (lastNode!=null && (node.mInstructions == null || node.mManeuverType == 0)){
        //this node is irrelevant, don't keep it, 
        //but update values of last node:
        lastNode.mLength += link.mLength;
        lastNode.mDuration += (node.mDuration + link.mDuration);
      } else {
        //TODO: check not the end node (n-2)
        node.mLength = link.mLength;
        node.mDuration += link.mDuration;
        int locationIndex = link.mShapeIndex;
        node.mLocation = polyline.get(locationIndex);
        newNodes.add(node);
        lastNode = node;
      }
    }
    //switch to the new array of nodes:
    return newNodes;
  }
  
  /**
   * Clean-up 2 useless portions of MapQuest road shape: before start node, and after end node. 
   * @return new road shape
   */
  public ArrayList<GeoPoint> finalizeRoadShape(Road road, ArrayList<RoadLink> links){
    ArrayList<GeoPoint> newShape = new ArrayList<GeoPoint>(road.mRouteHigh.size());
    RoadNode nodeStart = road.mNodes.get(0);
    RoadNode nodeEnd = road.mNodes.get(road.mNodes.size()-1);
    int shapeIndexStart = links.get(nodeStart.mNextRoadLink).mShapeIndex;
    int shapeIndexEnd = links.get(nodeEnd.mNextRoadLink).mShapeIndex;
    for (int i=shapeIndexStart; i<=shapeIndexEnd; i++){
        newShape.add(road.mRouteHigh.get(i));
    }
    return newShape;
  }
}

/** Road Link is a portion of road between 2 "nodes" or intersections */
class RoadLink {
  /** in km/h */
  public double mSpeed; 
  /** in km */
  public double mLength; 
  /** in sec */
  public double mDuration;
  /** starting point of the link, as index in initial polyline */
  public int mShapeIndex; 
}

/** class to handle XML generated by MapQuest "guidance" open API. */
class MapQuestGuidanceHandler extends DefaultHandler {
  public Road mRoad;
  public ArrayList<RoadLink> mLinks;
  
  boolean isBB;
  boolean isGuidanceNodeCollection;
  private StringBuilder mStringBuilder = new StringBuilder(1024);
  double mLat, mLng;
  double mNorth, mWest, mSouth, mEast;
  RoadLink mLink;
  RoadNode mNode;
  
  public MapQuestGuidanceHandler() {
    isBB = isGuidanceNodeCollection = false;
    mRoad = new Road();
    mLinks = new ArrayList<RoadLink>();
  }

  @Override public void startElement(String uri, String localName, String name,
      Attributes attributes) throws SAXException {    
    if (localName.equals("boundingBox"))
      isBB = true;
    else if (localName.equals("link"))
      mLink = new RoadLink();
    else if (localName.equals("node"))
      mNode = new RoadNode();
    else if (localName.equals("GuidanceNodeCollection"))
      isGuidanceNodeCollection = true;
    mStringBuilder.setLength(0);
  }

  /**
   * Overrides org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
   */
  @Override public void characters(char[] ch, int start, int length)
      throws SAXException {
      mStringBuilder.append(ch, start, length);
  }
  
  @Override public void endElement(String uri, String localName, String name)
  throws SAXException {
    if (localName.equals("lat")) {
      mLat = Double.parseDouble(mStringBuilder.toString());
    } else if (localName.equals("lng")) {
      mLng = Double.parseDouble(mStringBuilder.toString());
    } else if (localName.equals("shapePoints")) {
      mRoad.mRouteHigh = PolylineEncoder.decode(mStringBuilder.toString(), 10);
      //Log.d("DD", "High="+mRoad.mRouteHigh.size());
    } else if (localName.equals("generalizedShape")) {
      mRoad.setRouteLow(PolylineEncoder.decode(mStringBuilder.toString(), 10));
      //Log.d("DD", "Low="+mRoad.mRouteLow.size());
      } else if (localName.equals("length")) {
      mLink.mLength = Double.parseDouble(mStringBuilder.toString());
      } else if (localName.equals("speed")) {
      mLink.mSpeed = Double.parseDouble(mStringBuilder.toString());
      } else if (localName.equals("shapeIndex")){
      mLink.mShapeIndex = Integer.parseInt(mStringBuilder.toString());
      } else if (localName.equals("link")) {
            //End of a link: update road attributes:
            //GuidanceLinkCollection could in theory contain additional unused links, 
            //but normally not with fishbone set to false. 
            mLink.mDuration = mLink.mLength / mLink.mSpeed * 3600.0;
            mLinks.add(mLink);
            mRoad.mLength += mLink.mLength;
            mRoad.mDuration += mLink.mDuration;
            mLink = null;
    } else if (localName.equals("turnCost")){
      int turnCost = Integer.parseInt(mStringBuilder.toString());
      mNode.mDuration += turnCost;
      mRoad.mDuration += turnCost;
    } else if (localName.equals("maneuverType")){
      mNode.mManeuverType = Integer.parseInt(mStringBuilder.toString());
    } else if (localName.equals("info")){
      if (isGuidanceNodeCollection){
        if (mNode.mInstructions == null) 
          //this is first "info" value for this node, keep it:
          mNode.mInstructions = mStringBuilder.toString();
      }
    } else if (localName.equals("linkId")){
      if (isGuidanceNodeCollection)
        mNode.mNextRoadLink = Integer.parseInt(mStringBuilder.toString());
    } else if (localName.equals("node")){
      mRoad.mNodes.add(mNode);
      mNode = null;
    } else if (localName.equals("GuidanceNodeCollection")){
      isGuidanceNodeCollection = false;
    } else if (localName.equals("ul")){
      if (isBB){
        mNorth = mLat;
        mWest = mLng;
      }
    } else if (localName.equals("lr")){
      if (isBB){
        mSouth = mLat;
        mEast = mLng;
      }
    } else if (localName.equals("boundingBox")){
      mRoad.mBoundingBox = new BoundingBoxE6(mNorth, mEast, mSouth, mWest);
      isBB = false;
    } else if (localName.equals("statusCode")){
      mRoad.mStatus = Integer.parseInt(mStringBuilder.toString());
    }
  }
}




Java Source Code List

com.ilm.sandwich.BuildConfig.java
com.ilm.sandwich.Config.java
com.ilm.sandwich.GoogleMapActivity.java
com.ilm.sandwich.Info.java
com.ilm.sandwich.MySupportMapFragment.java
com.ilm.sandwich.OsmMapActivity.java
com.ilm.sandwich.Settings.java
com.ilm.sandwich.Smartgeo.java
com.ilm.sandwich.StartChooser.java
com.ilm.sandwich.TouchableWrapper.java
com.ilm.sandwich.helferklassen.HttpRequests.java
com.ilm.sandwich.helferklassen.Locationer.java
com.ilm.sandwich.helferklassen.MapDownload.java
com.ilm.sandwich.helferklassen.MyItemizedOverlay.java
com.ilm.sandwich.helferklassen.PlacesAutoComplete.java
com.ilm.sandwich.helferklassen.PlacesTextSearch.java
com.ilm.sandwich.helferklassen.Rechnung.java
com.ilm.sandwich.helferklassen.SuggestionsAdapter.java
org.osmdroid.bonuspack.BuildConfig.java
org.osmdroid.bonuspack.BuildConfig.java
org.osmdroid.bonuspack.cachemanager.CacheManager.java
org.osmdroid.bonuspack.clustering.GridMarkerClusterer.java
org.osmdroid.bonuspack.clustering.MarkerClusterer.java
org.osmdroid.bonuspack.clustering.StaticCluster.java
org.osmdroid.bonuspack.kml.ColorStyle.java
org.osmdroid.bonuspack.kml.IconStyle.java
org.osmdroid.bonuspack.kml.KmlDocument.java
org.osmdroid.bonuspack.kml.KmlFeature.java
org.osmdroid.bonuspack.kml.KmlFolder.java
org.osmdroid.bonuspack.kml.KmlGeometry.java
org.osmdroid.bonuspack.kml.KmlGroundOverlay.java
org.osmdroid.bonuspack.kml.KmlLineString.java
org.osmdroid.bonuspack.kml.KmlMultiGeometry.java
org.osmdroid.bonuspack.kml.KmlPlacemark.java
org.osmdroid.bonuspack.kml.KmlPoint.java
org.osmdroid.bonuspack.kml.KmlPolygon.java
org.osmdroid.bonuspack.kml.LineStyle.java
org.osmdroid.bonuspack.kml.Style.java
org.osmdroid.bonuspack.location.FlickrPOIProvider.java
org.osmdroid.bonuspack.location.GeoNamesPOIProvider.java
org.osmdroid.bonuspack.location.GeocoderGisgraphy.java
org.osmdroid.bonuspack.location.GeocoderNominatimOld.java
org.osmdroid.bonuspack.location.GeocoderNominatim.java
org.osmdroid.bonuspack.location.NominatimPOIProvider.java
org.osmdroid.bonuspack.location.POI.java
org.osmdroid.bonuspack.location.PicasaPOIProvider.java
org.osmdroid.bonuspack.mapsforge.GenericMapView.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileModuleProvider.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileProvider.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileSource.java
org.osmdroid.bonuspack.overlays.DefaultInfoWindow.java
org.osmdroid.bonuspack.overlays.ExtendedOverlayItem.java
org.osmdroid.bonuspack.overlays.FolderOverlay.java
org.osmdroid.bonuspack.overlays.GroundOverlay.java
org.osmdroid.bonuspack.overlays.InfoWindow.java
org.osmdroid.bonuspack.overlays.ItemizedOverlayWithBubble.java
org.osmdroid.bonuspack.overlays.MapEventsOverlay.java
org.osmdroid.bonuspack.overlays.MapEventsReceiver.java
org.osmdroid.bonuspack.overlays.MarkerInfoWindow.java
org.osmdroid.bonuspack.overlays.Marker.java
org.osmdroid.bonuspack.overlays.Polygon.java
org.osmdroid.bonuspack.overlays.Polyline.java
org.osmdroid.bonuspack.routing.GoogleRoadManager.java
org.osmdroid.bonuspack.routing.MapQuestRoadManager.java
org.osmdroid.bonuspack.routing.OSRMRoadManager.java
org.osmdroid.bonuspack.routing.RoadLeg.java
org.osmdroid.bonuspack.routing.RoadManager.java
org.osmdroid.bonuspack.routing.RoadNode.java
org.osmdroid.bonuspack.routing.Road.java
org.osmdroid.bonuspack.utils.BonusPackHelper.java
org.osmdroid.bonuspack.utils.DouglasPeuckerReducer.java
org.osmdroid.bonuspack.utils.HttpConnection.java
org.osmdroid.bonuspack.utils.PolylineEncoder.java
org.osmdroid.bonuspack.utils.WebImageCache.java