You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.5 KiB
119 lines
3.5 KiB
//-----------------------------------------------------------------------
|
|
// <copyright file="PolylineUtils.cs" company="Mapbox">
|
|
// Copyright (c) 2016 Mapbox. All rights reserved.
|
|
// </copyright>
|
|
//-----------------------------------------------------------------------
|
|
|
|
namespace Mapbox.Utils
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
/// <summary>
|
|
/// A set of Polyline utils.
|
|
/// </summary>
|
|
public static class PolylineUtils
|
|
{
|
|
/// <summary>Decodes an encoded path string into a sequence of Positions.</summary>
|
|
/// <remarks>
|
|
/// Adapted from <see href="https://github.com/mapbox/mapbox-java/blob/9bda93a2f84e26ad67434de1a5c73c335ecac12c/libjava/lib/src/main/java/com/mapbox/services/commons/utils/PolylineUtils.java"/>
|
|
/// </remarks>
|
|
/// <param name="encodedPath">A string representing a path.</param>
|
|
/// <param name="precision">Level of precision. OSRMv4 uses 6, OSRMv5 and Google use 5.</param>
|
|
/// <returns>List of <see cref="Vector2d"/> making up the line.</returns>
|
|
public static List<Vector2d> Decode(string encodedPath, int precision = 5)
|
|
{
|
|
int len = encodedPath.Length;
|
|
|
|
double factor = Math.Pow(10, precision);
|
|
|
|
// For speed we preallocate to an upper bound on the final length, then
|
|
// truncate the array before returning.
|
|
var path = new List<Vector2d>();
|
|
int index = 0;
|
|
int lat = 0;
|
|
int lng = 0;
|
|
|
|
while (index < len)
|
|
{
|
|
int result = 1;
|
|
int shift = 0;
|
|
int b;
|
|
do
|
|
{
|
|
b = encodedPath[index++] - 63 - 1;
|
|
result += b << shift;
|
|
shift += 5;
|
|
}
|
|
while (b >= 0x1f);
|
|
lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
|
|
|
|
result = 1;
|
|
shift = 0;
|
|
do
|
|
{
|
|
b = encodedPath[index++] - 63 - 1;
|
|
result += b << shift;
|
|
shift += 5;
|
|
}
|
|
while (b >= 0x1f);
|
|
lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
|
|
|
|
path.Add(new Vector2d(y: lng / factor, x: lat / factor));
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Encodes a sequence of Positions into an encoded path string.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Adapted from <see href="https://github.com/mapbox/mapbox-java/blob/9bda93a2f84e26ad67434de1a5c73c335ecac12c/libjava/lib/src/main/java/com/mapbox/services/commons/utils/PolylineUtils.java"/>
|
|
/// </remarks>
|
|
/// <param name="path">List of <see cref="Vector2d"/> making up the line.</param>
|
|
/// <param name="precision">Level of precision. OSRMv4 uses 6, OSRMv5 and Google use 5..</param>
|
|
/// <returns>A string representing a polyLine.</returns>
|
|
public static string Encode(List<Vector2d> path, int precision = 5)
|
|
{
|
|
long lastLat = 0;
|
|
long lastLng = 0;
|
|
|
|
var result = new StringBuilder();
|
|
|
|
double factor = Math.Pow(10, precision);
|
|
|
|
foreach (Vector2d point in path)
|
|
{
|
|
var lat = (long)Math.Round(point.x * factor);
|
|
var lng = (long)Math.Round(point.y * factor);
|
|
|
|
Encode(lat - lastLat, result);
|
|
Encode(lng - lastLng, result);
|
|
|
|
lastLat = lat;
|
|
lastLng = lng;
|
|
}
|
|
|
|
return result.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Encode the latitude or longitude.
|
|
/// </summary>
|
|
/// <param name="variable">The value to encode.</param>
|
|
/// <param name="result">String representation of latitude or longitude.</param>
|
|
private static void Encode(long variable, StringBuilder result)
|
|
{
|
|
variable = variable < 0 ? ~(variable << 1) : variable << 1;
|
|
while (variable >= 0x20)
|
|
{
|
|
result.Append((char)((int)((0x20 | (variable & 0x1f)) + 63)));
|
|
variable >>= 5;
|
|
}
|
|
|
|
result.Append((char)((int)(variable + 63)));
|
|
}
|
|
}
|
|
}
|
|
|