Google Maps polyline encoding in C#

One of the new features in the Advanced Sitecore Google Maps (WCAG edition) is the ability to draw polylines. Polylines in Google Maps can be drawn using 2 methods: By creating a new GPolyline with the array of coordinates to draw, or by using the GPolyline.fromEncoded function which takes an encoded string of coordinates and renders this as a line.

The encoded polyline function has the advantage of being faster and more compressed compared with feeding the GPolyline with an array of coordinates. However, some of the precision is lost, as the encoding algorithm only uses 5 digit coordinates. 5 digits is still a pretty good precision, so I decided to go with the encoded string.

I was looking for a method of encoded my coordinates in C# when i stumbled upon a solution on the SoulSolutions webpage, where the developer demonstrates a Javascript and C# method to encode and decode polyline coordinates.

This is the C# method re-written. SoulSolutions should be credited for the code. However, his code examples are incomplete, so I rewrote them. First I need a Coordinate class, which contains the latitude and longitude of a coordinate set (I have removed comments and other stuff to compress the code):

public class Coordinate
  public double Latitude { get; set; }
  public double Longitude { get; set; }

The following function EncodeCoordinates encodes a list of coordinates into an encoded string:

/// <summary>
/// Encodes the list of coordinates to a Google Maps encoded coordinate string.
/// </summary>
/// <param name="coordinates">The coordinates.</param>
/// <returns>Encoded coordinate string</returns>
public static string EncodeCoordinates(List<Coordinate> coordinates)
  int plat = 0;
  int plng = 0;
  StringBuilder encodedCoordinates = new StringBuilder();
  foreach (Coordinate coordinate in coordinates)
    // Round to 5 decimal places and drop the decimal
    int late5 = (int)(coordinate.Latitude * 1e5);
    int lnge5 = (int)(coordinate.Longitude * 1e5);
    // Encode the differences between the coordinates
    encodedCoordinates.Append(EncodeSignedNumber(late5 - plat));
    encodedCoordinates.Append(EncodeSignedNumber(lnge5 - plng));
    // Store the current coordinates
    plat = late5;
    plng = lnge5;
  return encodedCoordinates.ToString();
/// <summary>
/// Encode a signed number in the encode format.
/// </summary>
/// <param name="num">The signed number</param>
/// <returns>The encoded string</returns>
private static string EncodeSignedNumber(int num)
  int sgn_num = num << 1; //shift the binary value
  if (num < 0) //if negative invert
    sgn_num = ~(sgn_num);
  return (EncodeNumber(sgn_num));

/// <summary>
/// Encode an unsigned number in the encode format.
/// </summary>
/// <param name="num">The unsigned number</param>
/// <returns>The encoded string</returns>
private static string EncodeNumber(int num)
  StringBuilder encodeString = new StringBuilder();
  while (num >= 0x20)
    encodeString.Append((char)((0x20 | (num & 0x1f)) + 63));
    num >>= 5;
  encodeString.Append((char)(num + 63));
  // All backslashes needs to be replaced with double backslashes
  // before being used in a Javascript string.
  return encodeString.ToString().Replace(@"\", @"\\");

Using the encoded string, I can draw a line surrounding Denmark like this:

var line = new GPolyline.fromEncoded({
               color: "#0000FF",
               weight: 5,
               opacity: 0.5,
               points: "kpgiI}{wt@{xeDfxv@ylqC|flAyfyDidPiioBoabD_fkAyjfDooZ{nyCtw_BihCnzlBzbyAl}XehjBfp`B_se@vdgAhdPya_BoabDipHoabDngiAsen@jz}@htcAzqt@itcAnha@|~eBdzh@qqnBf~w@zrlCjkx@fppAy{u@zflA{zRpeuC`zWh`]bmx@}byAlwn@ny{DncNn}nDsxd@uqG",
               zoomFactor: 32,
               numLevels: 4 });

The line looks like this using 28 coordinates:

Line drawing using GPolyline.fromEncoded

Line drawing using GPolyline.fromEncoded

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in c#, General .NET, Sitecore 6 and tagged , , , . Bookmark the permalink.

10 Responses to Google Maps polyline encoding in C#

  1. Simon says:

    Hi Brian,

    Thanks for the code on encoding coordinates. I am using your code above to retrieve a static map from google and at first it seemed to work very well. When I looked at some routes though, there are some points that don’t line up with where they should be once they are encoded. Have you seen this issue with accuracy? Some points are out by half a mile on the map, larger than what I would expect. I am using the encoding as some of my routes are quite long with hundreds of points.



  2. briancaos says:

    The encoding algorithm precision is “only” 5 digits. However 5 digits shoul still provide accuracy in the feet range and should not bring your lines out of course by half a mile. I use the same algorithm in a professional product, an none of my customers have experienced such a bad precision.
    Without haven seen your code i would expect it to be your data that is off.

  3. Simon says:

    Yeah, the 5 digit precision should be more than fine. For the issue with the data, when displayed without encoding it appears correctly, then with encoding it is no longer correct. This only occurs where there is a large number of points to encode. I will look into it further to see what is happening.


  4. Robert Simon says:

    Hi Simon,

    Thanks for your code, it is quiet helpful!
    Have you managed to improve the encoding (+precision) with more than ex. 10000 point records?


  5. briancaos says:

    Hi Robert,
    No I havent had any problems with the precision of the Google Map coordinates, so no changes here,

  6. Pingback: Calculate distance between two coordinates on earth « Brian Pedersen’s Sitecore and .NET Blog

  7. Pingback: Calculate distance between two coordinates on earth | CMS News Today

  8. Thomas says:

    I can report the same precision problems as by predecessors.

  9. Chris says:

    Hi, and thanks for sharing this!

    I implemented this algorithm in Scala and got one encoding character in a three point polyline wrong. To get it right i rounded the dropped decimal double instead of flooring it with an int cast, e.g. (int)Math.round(coordinate.Latitude * 1e5).


  10. Kim Jørgensen says:

    Hello Brian,

    Thanks for this great algorithm! I am trying to implement it into my system, and everything is working fine, but I have no idea how you use the last part to actually show the line in Google Maps?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s