package com.jdroid.android.google.maps;
import com.jdroid.android.domain.GeoLocation;
import com.jdroid.java.json.JSONArray;
import com.jdroid.java.json.JSONObject;
import com.jdroid.java.http.parser.json.JsonParser;
import java.util.ArrayList;
import java.util.List;
/**
* From https://developers.google.com/maps/documentation/directions/?hl=es#Limits
*/
public class GoogleRouteParser extends JsonParser<JSONObject> {
/**
* @see JsonParser#parse(java.lang.Object)
*/
@Override
public Object parse(JSONObject json) {
Route route = null;
// Tranform the string into a json object
JSONArray jsonRoutes = json.getJSONArray("routes");
// Get the route object
if (jsonRoutes.length() > 0) {
route = new Route();
JSONObject jsonRoute = jsonRoutes.getJSONObject(0);
// Get the leg, only one leg as we don't support waypoints
JSONObject leg = jsonRoute.getJSONArray("legs").getJSONObject(0);
// Get the steps for this leg
JSONArray steps = leg.getJSONArray("steps");
// Number of steps for use in for loop
int numSteps = steps.length();
// Get the total length of the route.
route.setLength(leg.getJSONObject("distance").getInt("value"));
// Loop through the steps, creating a segment for each one and decoding any polylines found as we go to
// add to the route object's map array. Using an explicit for loop because it is faster!
for (int i = 0; i < numSteps; i++) {
// Get the individual step
JSONObject step = steps.getJSONObject(i);
// Retrieve & decode this segment's polyline and add it to the route.
route.addPoints(decodePolyLine(step.getJSONObject("polyline").getString("points")));
}
}
return route;
}
/**
* Decode a polyline string into a list of GeoLocations. From
* https://developers.google.com/maps/documentation/directions/?hl=es#Limits
*
* @param poly polyline encoded string to decode.
* @return the list of GeoLocations represented by this polystring.
*/
private List<GeoLocation> decodePolyLine(String poly) {
int len = poly.length();
int index = 0;
List<GeoLocation> decoded = new ArrayList<>();
int lat = 0;
int lng = 0;
while (index < len) {
int b;
int shift = 0;
int result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
lat += dlat;
shift = 0;
result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
lng += dlng;
decoded.add(new GeoLocation(lat / 1E5, lng / 1E5));
}
return decoded;
}
}