The new version of MapKit in iOS 4 supports polylines, finally. MKPolyline to be precise.
I have been working with the Google Maps API for a while and now I’m learning Objective-C and writing an iPhone app ro Route.ly
Since the best way to send around the net the data to draw a polyline on a map is in encoded format I decided to write a small Objective-C function to decode the encoded string. Since I couldn’t find this anywhere on the net I decided to publish the code here.
You’ll notice that at the beginning of the function I replace “\\\\” with “\\”. This is because I use the encoded data both in web pages with javascript and my iPhone app. In javascript “\\” would be considered an escape and would therefore break my array of points. This is not the case in Objective-C so I switch back to the normal “\\”.
NSString escapedEncodedPoints = [encodedPoints stringByReplacingOccurrencesOfString:@"\\\\" withString:@"\\"];
int len = [escapedEncodedPoints length];
NSMutableArray waypoints = [[NSMutableArray alloc] init];
int index = 0;
float lat = 0;
float lng = 0;
while (index < len) {
char b;
int shift = 0;
int result = 0;
do {
b = [escapedEncodedPoints characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0×20);
float dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [escapedEncodedPoints characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0×20);
float dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
float finalLat = lat * 1e-5;
float finalLong = lng * 1e-5;
Waypoint *newPoint = [[Waypoint alloc] init];
newPoint.lat = [[NSString alloc] initWithFormat:@"%f", finalLat];
newPoint.lng = [[NSString alloc] initWithFormat:@"%f", finalLong];
[waypoints addObject:newPoint];
[newPoint release];
}
return waypoints;
}
Waypoints is a simple model class I’ve written with two NSString properties: lat and lng.













[...] This post was mentioned on Twitter by Links About Google and sapessi, iphone god. iphone god said: Decode a GPolyline in Objective-C: http://bit.ly/bq3Dq3 [...]
[...] Decode a GPolyline in Objective-C [...]
Thanks for the code, Stefano! I was just about to code this myself, so you saved me some work.
Haven’t tested it yet, but I will soon. If anything noteworthy comes up when I do I’ll post it here.
Cheers,
Arthur
Hi Stefano,
The code works like a charm.
Two little typos: escapedEncodedPoints and waypoints should both be pointers:
NSString *escapedEncodedPoints = ..
NSMutableArray *waypoints = ..
Thanks again!
Arthur
I see that late night coding has not gone out of style. I found this just moments ago and came back here to say so, but you beat me to it. Well-timed, sir.
Thank you for posting this code. It was very helpful in solving a programming problem I have been puzzling over.
The code crashes for the following encoded points string. I entered two zip codes for directions: 97229 to 95054.
The index reaches the length and for the calculation of longitude, the array goes out of bound in the second do..while loop.
So I added a check to break the loops before the statement as follows:
if (index >= len) return;
b = [escapedEncodedPoints characterAtIndex:index++] – 63;
But that causes the trip from 97229 to 95054 (Portland to Santa Clara) to return location points which go over the Pacific Ocean.
This used to be working a few months ago. Google started returning something different, recently.
Please help. If unable to recreate please let me know and I will provide more info.
Encoded Pts string:
ogwtG~fklVbBhAlA`AxAjA`BzAd@`@\f@l@l@l@r@x@fAt@bAp@hA~@jBbBxDn@fBbCpFbEvJz@lBb@|@Zf@jAhBt@`Ar@v@p@p@n@h@`An@z@d@t@\\HLDx@V|@NhARvKlAHBtCRh@DxEb@rD^fJ|@L@NBJ@PBhP~AtCVv@Hd@BVBr@DD@x@DfABbABr@?jAAj@C^ArAGfE]fBUFABAVEXGbAQfAWr@S\KXKXIZK|@[h@QpAg@vAs@h@W|@e@\SbAk@x@g@~AgA`BmAVSd@_@ZWj@e@l@g@\YTS^[|DaDn@i@\Yh@c@z@q@l@a@l@_@VQXO\Q^Oh@SVIRGXGJCREj@ITC~@Ex@Cn@?j@?x@@p@@z@@b@@@?jNNdDFL@V?t@@t@@r@?l@@j@@d@?b@A^?f@Al@Ct@Ej@Eh@Gt@Id@IZE^ITEt@OtEiArEcAhAUn@MdAO~BYl@Ed@En@Eb@Cj@C`@AjCCxC@jB?|B?zA@rB?~DBfA?|AENARCl@GlBYz@SnA]fDeA`Be@nA[zDwAxAw@f@c@z@{@jAkBh@eAjAmCBENc@vDeKn@gB`AgC@?h@wArAoD~FeP~DmKbEyKdCeGvE{JbAwBx@qAzB_ElB}C~A}BtBeC@?jC}ClFgFhBiBjFmFlDgD|I}I`CmCbBoC~AaDnCgGr@_B?A`@w@rB_Et@iAh@q@lAmAnCyB`Ay@vEgEl@i@
I just removed the statement which was replacing \\ by \ as in C it is not required.
Didn’t realize you were the input in your code had padded slashes.
It’s working now.
Thans for this comment! I hade the same problem, it seems to be solved now.
I was using this, but was getting some weird routes. removed the
NSString escapedEncodedPoints = [encodedPoints stringByReplacingOccurrencesOfString:@"\\\\" withString:@"\\"];
it will work