{"id":324,"date":"2008-05-11T20:35:59","date_gmt":"2008-05-12T01:35:59","guid":{"rendered":"http:\/\/unitstep.net\/?p=324"},"modified":"2008-05-11T20:37:17","modified_gmt":"2008-05-12T01:37:17","slug":"playing-with-google-maps-and-encoded-polylines","status":"publish","type":"post","link":"https:\/\/unitstep.net\/blog\/2008\/05\/11\/playing-with-google-maps-and-encoded-polylines\/","title":{"rendered":"Playing with Google Maps and encoded polylines"},"content":{"rendered":"

\"\"<\/p>\n

I’ve been playing around with the Google Maps API<\/a> for a bit and it’s turned out to be a great way to get started with “mashups” and the like. One of the best uses of the API is the ability to create paths or routes on the map.<\/p>\n

This is done by creating GPolyline<\/code><\/a> object and then adding it as an overlay to the map. Basically, a polyline is just an ordered list of geographical points\/coordinates on the map, each of which is a GLatLng<\/code><\/a> object. For serialization\/storage of polylines, there is an algorithm you can use<\/a> to Base64-encode a series of points; the resultant string can later be passed directly into a factory method to regenerate the GPolyline<\/code>. By using encoded polylines, you also get access to a few more interesting and useful options related to rendering and performance issues.<\/p>\n

<\/p>\n

Encoded Polylines<\/h3>\n

Despite the algorithm for encoding polylines<\/a> being readily available on the Google Maps API documentation site, there is no built-in functionality within the API for generating the encoded polyline string from an existing GPolyline<\/code> object. This might be a bit strange, but it’s probably because the encoding process requires some extra values that aren’t available in the typical polyline.<\/p>\n

As specified on the algorithm page, you also need to specify a list of encoded “levels” in addition to the points themselves. These levels tell the the Google Maps renderer when certain points can be omitted from the polyline depending on the zoom level. For example, with a polyline with n<\/em> points, you’ll always<\/strong> want to show the first and last point, no matter what the zoom level. However, intermediate points can potentially be omitted at low zoom levels and only shown when the map has been sufficiently zoomed in to warrant the detail. This sort of optimization cannot be done with the typical GPolyline<\/code> constructor that just takes an array of points. (GLatLng<\/code> objects)<\/p>\n

Making things easy<\/h3>\n

If you’ve looked at the polyline encoding algorithm<\/a>, you’ll probably notice that it’s a bit tricky unless you’ve taken course in CS or done a lot of this stuff before. (At least it was tricky for me) Google has an interactive utility<\/a> for generating the encoded polyline format for you. The results can then be stored and later fed into a call to the factory method GPolyline.fromEncoded()<\/code><\/a> to regenerate the polyline.<\/p>\n

However if you want to generate the encoded polyline format on-the-fly as part of your application, the interactive utility is not really an option. Instead of coding the algorithm from the ground-up, there’s a much better way of doing things, thanks to the PolylineEncoder class<\/a> and other utilities provided by Mark McClure<\/a>.<\/p>\n

The PolylineEncoder class<\/a> is written in JavaScript and is very straightforward in its usage. (It has been ported to several other languages as listed on his site<\/a>, in case you need to use it in different contexts)<\/p>\n

Using this class allows you to quickly and easily convert a GPolyline<\/code> into a compact encoded format useful for serialization or storage. You can also use the class to convert arrays of points into encoded polylines, thus gaining the benefit of optimized rendering at different zoom levels. McClure goes into an in-depth, but easy to understand explanation of the encoding algorithm used<\/a> complete with animations that show exactly how the polyline approximations work.<\/p>\n

I highly recommend the usage of his polyline encoder as it saves you the headache of implementing it yourself. It’s well-written, thoroughly documented and is free for usage. (It isn’t licensed under open-source terms but has instead been placed in the public domain – which is perhaps even more “free”) McClure also has a few other interesing Google Maps projects<\/a> that you may want to check out.<\/p>\n

Some documentation warnings<\/h3>\n

The Google Maps API documentation is fairly thorough, but it’s out of date in some places, as some people have found<\/a>. Indeed, in this case, it appears that the GPolyline.fromEncoded()<\/code> is documented somewhat wrongly in the API reference, though curiously, is used properly in their examples page<\/a>. <\/p>\n

Specifically, you should not<\/strong> use:<\/p>\n

GPolyline.fromEncoded(color?,  weight?,  opacity?,  latlngs,  zoomFactor,  levels,  numLevels)<\/code><\/pre>\n

if you want to generate a polyline from the encoded format. Instead, you should use something like:<\/p>\n

GPolyline.fromEncoded({\r\n    color: \"#FF0000\",\r\n    weight: 10,\r\n    points: \"yzocFzynhVq}@n}@o}@nzD\",\r\n    levels: \"BBB\",\r\n    zoomFactor: 32,\r\n    numLevels: 4\r\n});<\/code><\/pre>\n

This is because the API has been updated to accept an object of options instead of separate parameters. This, in my opinion, is better for readability and takes advantage of JavaScript’s ability to define inline anonymous object literals. <\/p>\n

As a side note, the example actually calls something like new GPolyline.fromEncoded<\/code>, but I’ve found that you don’t need the new<\/code> keyword, and in fact, it’s a bit confusing that the example has it and that it would work – after all, you are calling a factory method that returns a type of GPolyline<\/code>, and not directly instantiating an object. (At least as far as JavaScript uses the new<\/code> keyword<\/a>)<\/p>","protected":false},"excerpt":{"rendered":"

I’ve been playing around with the Google Maps API for a bit and it’s turned out to be a great way to get started with “mashups” and the like. One of the best uses of the API is the ability to create paths or routes on the map. This is done by creating GPolyline object […]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[208,23,4,139,137],"tags":[226,225,405,439,227],"_links":{"self":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/posts\/324"}],"collection":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/comments?post=324"}],"version-history":[{"count":0,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/posts\/324\/revisions"}],"wp:attachment":[{"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/media?parent=324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/categories?post=324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unitstep.net\/wp-json\/wp\/v2\/tags?post=324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}