繁体   English   中英

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

[英]C# implementation of Google's 'Encoded Polyline Algorithm'

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

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

public string Encode(IEnumerable<Point> points);

这是我确定的实施:

public static string Encode(IEnumerable<GeoLocation> 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();
}

希望能帮助别人。

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

  var googleDirectionsResponse = JsonConvert.DeserializeObject<RootObject>(responseString);

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

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

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

/// <summary>
/// Google Polyline Converter (Encoder and Decoder)
/// </summary>
public static class GooglePolylineConverter
{
    /// <summary>
    /// Decodes the specified polyline string.
    /// </summary>
    /// <param name="polylineString">The polyline string.</param>
    /// <returns>A list with Locations</returns>
    public static IEnumerable<Location> 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
            };
        }
    }

    /// <summary>
    /// Encodes the specified locations list.
    /// </summary>
    /// <param name="locations">The locations.</param>
    /// <returns>The polyline string.</returns>
    public static string Encode(IEnumerable<Location> locations)
    {
        var str = new StringBuilder();

        var encodeDiff = (Action<int>)(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<str.length; i++) {
            if(str.charAt(i) == "1")
                ret += "0";
            else
                ret += "1";
        }
        return ret;
    };

    var get_binary = function(num) {
        var binary = parseInt(num).toString(2);
        var bit_difference = 32 - binary.length;
        for(var i=0; i<bit_difference; i++)
            binary = "0" + binary;
        if(num < 0) {
            binary = invert_bits(binary);
            binary = parseInt(binary, 2);
            binary++;
            return parseInt(binary).toString(2);
        }
        return binary;
    };

    _.encode_polyline = function(points) {
        var ret = "";
        var last_point, val_1, val_2;
        for(var i=0; i<points.length; i++) {
            if(!last_point) {
                val_1 = points[i][0];
                val_2 = points[i][1];
            } else {
                val_1 = points[i][0] - last_point[0];
                val_2 = points[i][1] - last_point[1];
            }
            last_point = points[i];
            ret += _.encode_polyline_value(val_1) + _.encode_polyline_value(val_2);
        }
        return ret;
    };

    _.encode_polyline_value = function(value) {
        var ret = "";
        value = Math.round(value * 100000);
        var shifted = value << 1;
        if(shifted < 0)
            shifted = ~shifted;
        var rem = shifted;
        while(rem >= 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 _;
})();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM