Google的“编码折线算法”的C#实现

有没有人在C#中使用Google的编码折线算法实现简洁而强大的实现?

我基本上想要这个签名的实现:

public string Encode(IEnumerable points); 

这是我确定的实施:

 public static string Encode(IEnumerable points) { var str = new StringBuilder(); var encodeDiff = (Action)(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(); } 

希望能帮助别人。

也许是迟到但我刚刚解决了同样的问题,但是为了编码位置列表和解码折线,我使用http://json2csharp.com/在C#中生成相应的类,以便用JsonConvert反序列化响应,如:

  var googleDirectionsResponse = JsonConvert.DeserializeObject(responseString); 

这给了我这个定位的定义(我迟早会清理它):

 public class Location { public double lat { get; set; } public double lng { get; set; } } 

我创建了一个转换器类来完成两个方向的技巧(IT不是原创的,它只是这个类的重构: https : //gist.github.com/shinyzhu/4617989 ):

 ///  /// Google Polyline Converter (Encoder and Decoder) ///  public static class GooglePolylineConverter { ///  /// Decodes the specified polyline string. ///  /// The polyline string. /// A list with Locations public static IEnumerable Decode(string polylineString) { if (string.IsNullOrEmpty(polylineString)) throw new ArgumentNullException(nameof(polylineString)); var polylineChars = polylineString.ToCharArray(); var index = 0; var currentLat = 0; var currentLng = 0; while (index < polylineChars.Length) { // Next lat var sum = 0; var shifter = 0; int nextFiveBits; do { nextFiveBits = polylineChars[index++] - 63; sum |= (nextFiveBits & 31) << shifter; shifter += 5; } while (nextFiveBits >= 32 && index < polylineChars.Length); if (index >= polylineChars.Length) break; currentLat += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1); // Next lng sum = 0; shifter = 0; do { nextFiveBits = polylineChars[index++] - 63; sum |= (nextFiveBits & 31) << shifter; shifter += 5; } while (nextFiveBits >= 32 && index < polylineChars.Length); if (index >= polylineChars.Length && nextFiveBits >= 32) break; currentLng += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1); yield return new Location { lat = Convert.ToDouble(currentLat) / 1E5, lng = Convert.ToDouble(currentLng) / 1E5 }; } } ///  /// Encodes the specified locations list. ///  /// The locations. /// The polyline string. public static string Encode(IEnumerable locations) { var str = new StringBuilder(); var encodeDiff = (Action)(diff => { var shifted = diff << 1; if (diff < 0) shifted = ~shifted; var rem = shifted; while (rem >= 0x20) { str.Append((char)((0x20 | (rem & 0x1f)) + 63)); rem >>= 5; } str.Append((char)(rem + 63)); }); var lastLat = 0; var lastLng = 0; foreach (var point in locations) { var lat = (int)Math.Round(point.lat * 1E5); var lng = (int)Math.Round(point.lng * 1E5); encodeDiff(lat - lastLat); encodeDiff(lng - lastLng); lastLat = lat; lastLng = lng; } return str.ToString(); } } 

我希望它有所帮助。

Javascript实现,如果有人感兴趣:

 var polyline_encoder = (function() { var _ = {}; var invert_bits = function(str) { var ret = ""; for(var i=0; i= 32) { ret += get_ascii_value(((0x20 | (rem & 0x1f)) + 63)); rem >>= 5; } ret += get_ascii_value(rem + 63); return ret; }; var get_ascii_value = function(num) { var ascii_table = // 0 thru 9 "??????????" + // 10 thru 19 "??????????" + // 20 thru 29 "??????????" + // 30 thru 39 "?? !\"#$%&'" + // 40 thru 49 "()*+,-./01" + // 50 thru 59 "23456789:;" + // 60 thru 69 "<=>?@ABCDE" + // 70 thru 79 "FGHIJKLMNO" + // 80 thru 89 "PQRSTUVWXY" + // 90 thru 99 "Z[\\]^_`abc" + // 100 thru 109 "defghijklm" + // 110 thru 119 "nopqrstuvw" + // 120 thru 127 "xyz{|}~?"; var value = ascii_table.substr(num, 1); if(value == "?") value = ""; return value; }; return _; })();