I am using the Directions API from Google. Now I would like to determine the current step to the current location of a user.
Here is an example from the google website:
{
"status": "OK",
"geocoded_waypoints" : [
{
"geocoder_status" : "OK",
"place_id" : "ChIJ7cv00DwsDogRAMDACa2m4K8",
"types" : [ "locality", "political" ]
},
{
"geocoder_status" : "OK",
"place_id" : "ChIJ69Pk6jdlyIcRDqM1KDY3Fpg",
"types" : [ "locality", "political" ]
},
{
"geocoder_status" : "OK",
"place_id" : "ChIJgdL4flSKrYcRnTpP0XQSojM",
"types" : [ "locality", "political" ]
},
{
"geocoder_status" : "OK",
"place_id" : "ChIJE9on3F3HwoAR9AhGJW_fL-I",
"types" : [ "locality", "political" ]
}
],
"routes": [ {
"summary": "I-40 W",
"legs": [ {
"steps": [ {
"travel_mode": "DRIVING",
"start_location": {
"lat": 41.8507300,
"lng": -87.6512600
},
"end_location": {
"lat": 41.8525800,
"lng": -87.6514100
},
"polyline": {
"points": "a~l~Fjk~uOwHJy@P"
},
"duration": {
"value": 19,
"text": "1 min"
},
"html_instructions": "Head \u003cb\u003enorth\u003c/b\u003e on \u003cb\u003eS
Morgan St\u003c/b\u003e toward \u003cb\u003eW Cermak Rd\u003c/b\u003e",
"distance": {
"value": 207,
"text": "0.1 mi"
}
},
...
... additional steps of this leg
...
... additional legs of this route
"duration": {
"value": 74384,
"text": "20 hours 40 mins"
},
"distance": {
"value": 2137146,
"text": "1,328 mi"
},
"start_location": {
"lat": 35.4675602,
"lng": -97.5164276
},
"end_location": {
"lat": 34.0522342,
"lng": -118.2436849
},
"start_address": "Oklahoma City, OK, USA",
"end_address": "Los Angeles, CA, USA"
} ],
"copyrights": "Map data ©2010 Google, Sanborn",
"overview_polyline": {
"points": "a~l~Fjk~uOnzh@vlbBtc~@tsE`vnApw{A`dw@~w\\|tNtqf@l{Yd_Fblh@rxo@b}@xxSfytA
blk@xxaBeJxlcBb~t@zbh@jc|Bx}C`rv@rw|@rlhA~dVzeo@vrSnc}Axf]fjz@xfFbw~@dz{A~d{A|zOxbrBbdUvpo@`
cFp~xBc`Hk@nurDznmFfwMbwz@bbl@lq~@loPpxq@bw_@v|{CbtY~jGqeMb{iF|n\\~mbDzeVh_Wr|Efc\\x`Ij{kE}mAb
~uF{cNd}xBjp]fulBiwJpgg@|kHntyArpb@bijCk_Kv~eGyqTj_|@`uV`k|DcsNdwxAott@r}q@_gc@nu`CnvHx`k@dse
@j|p@zpiAp|gEicy@`omFvaErfo@igQxnlApqGze~AsyRzrjAb__@ftyB}pIlo_BflmA~yQftNboWzoAlzp@mz`@|}_
@fda@jakEitAn{fB_a]lexClshBtmqAdmY_hLxiZd~XtaBndgC"
},
"warnings": [ ],
"waypoint_order": [ 0, 1 ],
"bounds": {
"southwest": {
"lat": 34.0523600,
"lng": -118.2435600
},
"northeast": {
"lat": 41.8781100,
"lng": -87.6297900
}
}
} ]
}
I thought I could use the start_location field and determine the distance between the current location and the start_location fields but I guess that is wrong. Has anybody a working solution for this? Any help will be appreciated.
You need to decode "points"
tag from "polyline"
section (from documentation:
polyline contains a single points object that holds an encoded polyline representation of the step. This polyline is an approximate (smoothed) path of the step.
more information about polyline encoding in Google Maps you can find e.g. here) of each step and leg from "legs"
array:
"legs": [ {
"steps": [ {
...
"polyline": {
"points": "a~l~Fjk~uOwHJy@P" <--- need to decode this string
},
...
} ]
}]
for example via PolyUtil.decode()
of Maps SDK for Android Utility Library and you got a sequence of LatLngs for steps.
Than you need to create loop via all steps and find step that contains point with current location coordinates via PolyUtil.isLocationOnPath()
call. Something like that:
JSONObject jsonObject = new JSONObject(jsonStringBuilder.toString());
JSONArray legsArr = jsonObject.getJSONArray("legs");
// for each leg
for (int i = 0; i < legsArr.length(); i++) {
// get array of steps
JSONArray stepsArr = legsArr.getJSONObject(i).getJSONArray("steps");
// for each step
for (int j = 0; j < stepsArr.length(); j++) {
// get step
JSONObject step = stepsArr.getJSONObject(j);
JSONObject polyline = step.getJSONObject("polyline");
String encodedPoints = polyline.getString("points");
// decode encoded path to list of points LatLng
List<LatLng> decodedPoints = PolyUtil.decode(encodedPoints);
if (PolyUtil.isLocationOnPath(currentLocation, decodedPoints, true, 100)) {
// your currentLocation is on the step of route
// constant 100 - is tolerance in meters
}
}
}
If you need to determine exactly segment for currentLocation
, not entire step
you need to add loop via all segments in step:
...
// decode encoded path to list of points LatLng
List<LatLng> decodedPoints = PolyUtil.decode(encodedPoints);
List<LatLng> segment = new ArrayList(2);
for (int k = 0; k < decodedPoints.size() - 1; k++) {
segment.clear();
segment.add(decodedPoints.get(k));
segment.add(decodedPoints.get(k+1));
if (PolyUtil.isLocationOnPath(currentLocation, segment, true, 100)) {
// your currentLocation is on the segment of step
}
}
NB! It's just approach description, not fully functional code.