Polylines in Google Maps [Part 2]
In part 1 I showed how to use and optimize performance on polylines in Google Maps using Javascript. In this article I will show you how to get even better performance by encoding the polylines on the server.
Encoding polylines on the fly
When dealing with dynamic data you may have to encode the polylines on the fly. In this example I will use PHP to perform the encoding. I have rewritten a php script made by Jim Hribar and built his functions into a class for more convenient use. I’ve also made some small changes to the code. The code itself is essentially a rip-off from Mark MacClure’s Javascript class.
The PolylineEncoder Class
To use the class is simple. First you need to call the constructor of the class: $polylineEncoder = new PolylineEncoder($point);
The constructor
PolylineEncoder optionally takes four other arguments. When they are left out these default settings are used:
- numLevels = 18
- zoomFactor = 2
- verySmall = 0.00001
- forceEndpoints = true
numLevels and zoomFactor controls how many zoomlevels the encoding should take account for and in which intervals the map should change the number of displayed coordinates.
verySmall controls what distance between coordinate the algorithm should regard a short enough distance for a coordinate to be removed. So if you want to decrease the number of coordinates used, you should set the verySmall argument to a higher number.
forceEndpoints is a boolean and if set to true ensures that the two ending points of the polyline are displayed at all zoom-levels. I really don’t see a reason to set this to anything but true.
I myself tend to use the default settings since they provide a good result.
Encoding the points
The $encoded_polyline = polylineEncoder->dpEncode() method returns an associative array with the following keys.
- Points
A string containing the encoded points - Levels
A string containing the encoded levels - ZoomFactor
The applied Zoom Factor (Same as passed to the constructor) - NumLevels
The applied NumLevels (Same as passed to the constructor)
A complete call to the EncodePolyline could look something like this.
// Include the file containing the class
include("PolylineEncoder.php");
// Create a nested array containing the coordinates
$points = array(
array(
59.6919,
17.8582
),
array(
59.3030,
18.0395
),
array(
58.9789,
17.5341
)
);
// Create a new instance of PolylineEncoder and supply the array
// as an argument to the constructor
$polylineEncoder = new PolylineEncoder($points);
// Encode the coordinates by calling dpEncode(), it returns an array containing the
// encoded coordinates and levels.
$encoded_points = $polylineEncoder->dpEncode();
// The resulting output
$encoded_points["Points"]; // "kqikJw|~kBr}jAclb@rh~@xuaB"
$encoded_points["Levels"]; // "PMP
$encoded_points["ZoomFactor"]; // 2
$encoded_points["NumLevels"]; // 18
Note: To learn more about how to use the optional settings for tweaking the encoded polyline, read A description of Google’s encoded polylines and The encoding algorithm for the levels string.
Download the class
The PolylineEncoder class is released under GPL MIT license and may be used and changed freely.
Download PolylineEncoder.php.txt
Making use of the encoded polyline
Now that we have an encoded polyline its time to make good use of it in Google Maps. To create a GPolyline from the encoded coordinates you use the method GPolyline.fromEncoded().
// Creating an encoded GPolyline
GPolyline.fromEncoded({
color: string,
weight: number,
opacity: number,
points: string,
levels: string,
numLevels: number,
zoomFactor: number
});
As you can see it takes an object literal as an argument. The first three keys are purely for how the polyline will be styled. The keys points and levels are the ones that will be fed with the encoded polyline. The last two keys, numLevels and zoomFactor should match the settings you used when encoding the coordinates. If they don’t match, the polyline will not be rendered correctly.
Documentation alert
The documentation doesn’t seem to be quite up to date on this, since it specifies the method to be used like this:
GPolyline.fromEncoded(color?, weight?, opacity?, latlngs, zoomFactor, levels, numLevels)
Stay clear from this use since it’s deprecated and probably won’t work or eventually will stop working.
Adding it to the map
So adding an encoded polyline to your map is very much like adding a normal polyline to it. The only difference is that instead of creating the polyline with the constructor of GPolyline(), you call the GPolyline.fromEncoded() method and pass the encoded points and levels to it.
// Instanciate a new map
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(59.3219, 17.6165), 8);
// Create the polyline from the encoded points
var polyline = GPolyline.fromEncoded({
color: '#FF0000',
weight: 6,
opacity: 0.6,
points: 'kqikJw|~kBr}jAclb@rh~@xuaB',
levels: 'PMP',
numLevels: 18,
zoomFactor: 2
});
// Add the polyline to the map
map.addOverlay(polyline);
Even better performance
To get even better performance you have to use a pre-encode polyline to serve directly to the Javascript. This way you save the time the PHP-script takes to execute the encoding. In many cases this might not be possible, but if it is, it delivers the best performance.
Watch the pre-encoded example.
The improved load-time is pretty big. When I compare this example with the one encoding the polyline in the browser using Javascript, I get load times that’s range from 2 seconds (Safari) to over 20 seconds faster (IE).
All test scenarios
Here’s all the tested cases, from both this and the previous article.
- Simple unencoded polyline
- Complex unencoded polylines
- Complex encoded polylines, encoding done in browser with Javascript
- Complex encoded polylines, encoding done dynamically on server
- Complex pre-encoded polylines
Other resources
There are several server-side classes in different languages for encoding polylines, including Perl, Java and Ruby, available at Encoding polylines for Google Maps, a website by Mark McClure.
I have yet to find a class written in C#. If you find one or has written one yourself, I would be more than happy if you could tell me about it.
Update [2008-11-26]
I have now written a C# class to encode polylines by porting Mark Rambows Java class. I’ve also made some other modification to it to make it easier and more natural for C# coders to use.
Encouraged by this article, markw has also made a C# class, which can be download from Google Code.
My Google Maps book
If you found this article useful you might be interested in my book Beginning Google Maps API 3. It covers everything you need to know to create awesome maps on your web sites. Buy it on Amazon.com
Pingback: ? Relations › links for 2009-04-27