Skip to content

Instantly share code, notes, and snippets.

@rdelrosario
Created May 16, 2019 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rdelrosario/4a5a0f78bae140c6b485e72adeb1506c to your computer and use it in GitHub Desktop.
Save rdelrosario/4a5a0f78bae140c6b485e72adeb1506c to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms.GoogleMaps;
namespace TrackingSample.Helpers
{
public static class PolylineHelper
{
/// <summary>
/// Decode google style polyline coordinates.
/// </summary>
/// <param name="encodedPoints"></param>
/// <returns></returns>
public static IEnumerable<Position> Decode(string encodedPoints)
{
if (string.IsNullOrEmpty(encodedPoints))
throw new ArgumentNullException("encodedPoints");
char[] polylineChars = encodedPoints.ToCharArray();
int index = 0;
int currentLat = 0;
int currentLng = 0;
int next5bits;
int sum;
int shifter;
while (index < polylineChars.Length)
{
// calculate next latitude
sum = 0;
shifter = 0;
do
{
next5bits = (int)polylineChars[index++] - 63;
sum |= (next5bits & 31) << shifter;
shifter += 5;
} while (next5bits >= 32 && index < polylineChars.Length);
if (index >= polylineChars.Length)
break;
currentLat += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
//calculate next longitude
sum = 0;
shifter = 0;
do
{
next5bits = (int)polylineChars[index++] - 63;
sum |= (next5bits & 31) << shifter;
shifter += 5;
} while (next5bits >= 32 && index < polylineChars.Length);
if (index >= polylineChars.Length && next5bits >= 32)
break;
currentLng += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
yield return new Position(Convert.ToDouble(currentLat) / 1E5, Convert.ToDouble(currentLng) / 1E5);
}
}
/// <summary>
/// Encode it
/// </summary>
/// <param name="points"></param>
/// <returns></returns>
public static string Encode(IEnumerable<Position> points)
{
var str = new StringBuilder();
var encodeDiff = (Action<int>)(diff =>
{
int shifted = diff << 1;
if (diff < 0)
shifted = ~shifted;
int rem = shifted;
while (rem >= 0x20)
{
str.Append((char)((0x20 | (rem & 0x1f)) + 63));
rem >>= 5;
}
str.Append((char)(rem + 63));
});
int lastLat = 0;
int lastLng = 0;
foreach (var point in points)
{
int lat = (int)Math.Round(point.Latitude * 1E5);
int lng = (int)Math.Round(point.Longitude * 1E5);
encodeDiff(lat - lastLat);
encodeDiff(lng - lastLng);
lastLat = lat;
lastLng = lng;
}
return str.ToString();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment