I am drawing a route between two points in a map. I receive the points this way:
StringBuilder urlString = new StringBuilder();
urlString.append("htt
I changed the decodePoly that I was using for this one I found after a long search in Google, and now the route is drawn properly.
http://wptrafficanalyzer.in/blog/route-between-two-locations-with-waypoints-in-google-map-android-api-v2/
Changing
LatLng p = new LatLng((int) (((double) lat /1E5)* 1E6), (int) (((double) lng/1E5 * 1E6)));
for
LatLng p = new LatLng((((double) lat / 1E5)),(((double) lng / 1E5)));
And now works.
Same in Pascal (Delphi):
function DecodeLine(inputstring: String): String;
var
lat, lon, lat_f, lon_f: Double;
index: Integer;
len: Integer;
b: Integer;
shift: Integer;
decodeResult: Integer;
encoded: String;
dlat: Integer;
dlng: Integer;
begin
Result := '';
encoded := inputstring;
len := Length(encoded);
index := 1;
lat := 0;
lon := 0;
while (index <= len) do begin
b := $20;
shift := 0;
decodeResult := 0;
while (b >= $20) do begin
b := ord(encoded[index]);
b := b - 63;
inc(index);
decodeResult := decodeResult or (b and $1f) Shl shift;
shift := shift + 5;
end;
if (decodeResult and 1) <> 0 then
dlat := not (decodeResult shr 1)
else
dlat := decodeResult shr 1;
lat := lat+dlat;
shift := 0;
decodeResult := 0;
b := $20;
while (b >= $20) do begin
b := ord(encoded[index]);
b := b-63;
inc(index);
decodeResult := decodeResult or (b and $1f) Shl shift;
shift := shift + 5;
end;
if (decodeResult and 1) <> 0 then
dlng := not (decodeResult shr 1)
else
dlng := decodeResult shr 1;
lon := lon + dlng;
{ The coordinates of the point are used for our purposes }
lon_f := lon/100000.0;
lat_f := lat/100000.0;
if Result <> '' then
Result := Result + ', ';
Result := Result + '(' + FloatToStr(lon_f) + ' - ' + FloatToStr(lat_f) + ')';
end; //while
end;
procedure TForm1.Button1Click(Sender: TObject);
var
str: String;
begin
// Do stuff
str := DecodeLine('ibgqGq}ycIMvM');
ShowMessage(str);
end;
This method is useful for decoding polyline
private List<LatLng> decodePoly(String encoded) {
List<LatLng> poly = new ArrayList<>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.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 = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
This is how i'm getting polyline
JSONObject poly = route.getJSONObject("overview_polyline");
String polyline = poly.getString("points");
polyLineList = decodePoly(polyline);
Here is the implementation in iOS, for anybody who is curious, which is entirely based upon @Fustigador's answer, but converted to iOS. Note that I have not formatted the code accordingly. I only added some variables for the sake of returning the promised object.
- (GMSPath *)decodedPolylinePathFromEncodedPolylineString:(NSString *)encodedPolylineString {
NSString *decodedPolylineString = @"";
GMSMutablePath *decodedPolylinePath = [GMSMutablePath new];
CLLocationCoordinate2D decodedCoordinate;
CLLocationDegrees latitude, longitude;
int index = 0;
NSUInteger len = encodedPolylineString.length;
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = [encodedPolylineString characterAtIndex: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 = [encodedPolylineString characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
latitude = (((double) lat / 1E5));
longitude = (((double) lng / 1E5));
decodedCoordinate = CLLocationCoordinate2DMake(latitude, longitude);
decodedPolylineString = [NSString stringWithFormat:@"%f%f", latitude, longitude];
;
NSLog(@"%@",decodedPolylineString);
[decodedPolylinePath addCoordinate:decodedCoordinate];
}
return decodedPolylinePath;
}
Same in Javascript
function decodePolyline(encoded) {
if (!encoded) {
return [];
}
var poly = [];
var index = 0, len = encoded.length;
var lat = 0, lng = 0;
while (index < len) {
var b, shift = 0, result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result = result | ((b & 0x1f) << shift);
shift += 5;
} while (b >= 0x20);
var dlat = (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result = result | ((b & 0x1f) << shift);
shift += 5;
} while (b >= 0x20);
var dlng = (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
lng += dlng;
var p = {
latitude: lat / 1e5,
longitude: lng / 1e5,
};
poly.push(p);
}
return poly;
}
For those who need this now, there's an open-source library with a lot of useful stuff regarding the Google Maps Android API, including decoding and encoding of polylines.
Check it out at Android Maps Utils and Android Maps Util Github. For decoding and encoding use:
PolyUtil.decode(String encodedPath);
PolyUtil.encode(List<LatLng> path);