【问题标题】:C# to VB.NET Conversion (Google Polyline Algorithm Decoder)C# 到 VB.NET 的转换(谷歌折线算法解码器)
【发布时间】:2011-02-27 18:14:59
【问题描述】:

我有一些 C# 代码可以解码使用 Google 的折线算法编码的地图路径,并尝试将其转换为 VB.NET。

下面是完全运行的 C# 代码:

Collection<Double> decodePolyline(string polyline)
    {
        if (polyline == null || polyline == "") return null;

        char[] polylinechars = polyline.ToCharArray();
        int index = 0;
        Collection<Double> points = new Collection<Double>();
        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);

            points.Add(Convert.ToDouble(currentLat) / 100000.0);
            points.Add(Convert.ToDouble(currentLng) / 100000.0);
        }

        return points;
    }

这是 VB.NET 代码 - 适用于经度,但不适用于纬度。

Public Function decodePolyline(ByVal polyline As String) As Collection(Of Double)
    If polyline Is Nothing OrElse polyline = "" Then Return Nothing

    Dim polylinechars As Char() = polyline.ToCharArray()
    Dim points As New Collection(Of Double)
    Dim currentLat As Integer = 0
    Dim currentLng As Integer = 0
    Dim next5bits As Integer
    Dim sum As Integer
    Dim shifter As Integer

    For index As Integer = 0 To polylinechars.Length - 1
        'calculate next latitude
        sum = 0
        shifter = 0
        Do
            index += 1
            next5bits = AscW(polylinechars(index)) - 63
            sum = sum Or (next5bits And 31) << shifter
            shifter += 5
        Loop While next5bits >= 32 AndAlso index < polylinechars.Length

        If index >= polylinechars.Length Then
            Exit For
        End If

        currentLat += If((sum And 1) = 1, Not (sum >> 1), (sum >> 1))

        'calculate next longitude
        sum = 0
        shifter = 0
        Do
            index += 1
            next5bits = AscW(polylinechars(index)) - 63
            sum = sum Or (next5bits And 31) << shifter
            shifter += 5
        Loop While next5bits >= 32 AndAlso index < polylinechars.Length

        If index >= polylinechars.Length AndAlso next5bits >= 32 Then
            Exit For
        End If

        currentLng += If((sum And 1) = 1, Not (sum >> 1), (sum >> 1))

        points.Add(Convert.ToDouble(currentLat) / 100000.0)
        points.Add(Convert.ToDouble(currentLng) / 100000.0)
    Next

    Return points
End Function

缺少什么?

编辑:解决了这个问题(我在下面的答案中更正了代码,我无法再选择 2 天作为答案)。

【问题讨论】:

  • (删除了我的答案,因为我认为它没有帮助,而且我的 VB 已退化为只读,所以我无法仅凭一眼修复)
  • 在什么情况下不起作用?它编译吗?显示错误的结果,与 C# 版本不同?
  • 给出不正确的纬度输出。
  • 也许只有我一个人,但我认为在 for 循环中更改循环索引的值是一件坏事。
  • 是的-将其改回while(尽管for确实有效)-问题在于增加循环索引-C#中的index++返回原始值,而转换后的代码给出了递增的值(下面我的答案中的更正代码)。

标签: c# vb.net polyline


【解决方案1】:

如果您不了解目标语言,最好的方法是在调试模式下编译源代码,然后使用 Reflector 进行反编译。这样您就可以保留 var 名称,并确保生成的代码有效。

请注意,VB.Net 具有“微妙”的逻辑运算符,可能会破坏您的代码逻辑:OR vs OrElse...

【讨论】:

  • 逻辑运算符不是“微妙的”。 OrElse 增加短路功能。 Or 是一个位运算符,并且进行逻辑比较没有短路。仅仅因为它需要程序员了解它是如何工作的,就称它为“精致”是不公平的。
  • 嗯,他们是。如果您不懂目标语言并且想要一些实用的东西,那么您不必阅读一本大书来完成这项工作。
  • 我真的很好奇你可以用哪种编程语言编写函数式代码而不知道它的操作符是如何工作的。你能给我举个名字吗? 保证一本好的 VB 综合书籍不像 C++ 书籍那么“庞大”。
  • @Cody Gray:如果我必须用新语言为现有代码添加 5 分钟修复,我不必为此阅读一本书,只需快速 google 搜索即可.好的 VB.net 语法并不难,但我的观点是,如果您不知道 Or 和 OrElse 之间的区别,您可能会引入错误和/或性能问题。顺便说一句,我来自VB6背景,只是因为我认为语法相同,所以我遇到了这样的问题。
  • 说真的,您的回答应该是“VB.NET 的语法与 VB6 不同,尽管表面上相似。请注意不要无意中将错误引入代码中。”但那将是无关紧要的,因为问题是关于从 C# 转换到 VB.NET。除此之外,Or 在 VB.NET 中的工作方式与在 VB6 中的工作方式相同。您实际上不必更改代码即可使用OrElse;这就是为什么它被添加为 separate 运算符。性能问题很小,如果您因为短路评估而引入错误,我会责怪您的编码风格。
【解决方案2】:

啊,所以问题是 C# ++ 运算符增加变量但返回原始值,而我上面的 VB.NET 转换是增加 index 然后使用增加的值。不知何故,这仍然适用于经度,但搞砸了纬度解码。

这是更正后的 VB.NET 代码:

Public Function decodePolyline(ByVal polyline As String) As Collection(Of Double)
    If polyline Is Nothing OrElse polyline = "" Then Return Nothing

    Dim polylinechars As Char() = polyline.ToCharArray()
    Dim points As New Collection(Of Double)
    Dim currentLat As Integer = 0
    Dim currentLng As Integer = 0
    Dim next5bits As Integer
    Dim sum As Integer
    Dim shifter As Integer
    Dim index As Integer = 0

    While index < polylinechars.Length
        ' calculate next latitude
        sum = 0
        shifter = 0
        Do
            index += 1
            next5bits = AscW(polylinechars(index - 1)) - 63
            sum = sum Or (next5bits And 31) << shifter
            shifter += 5
        Loop While next5bits >= 32 AndAlso index < polylinechars.Length

        If index >= polylinechars.Length Then
            Exit While
        End If

        currentLat += If((sum And 1) = 1, Not (sum >> 1), (sum >> 1))

        'calculate next longitude
        sum = 0
        shifter = 0
        Do
            index += 1
            next5bits = AscW(polylinechars(index - 1)) - 63
            sum = sum Or (next5bits And 31) << shifter
            shifter += 5
        Loop While next5bits >= 32 AndAlso index < polylinechars.Length

        If index >= polylinechars.Length AndAlso next5bits >= 32 Then
            Exit While
        End If

        currentLng += If((sum And 1) = 1, Not (sum >> 1), (sum >> 1))

        points.Add(Convert.ToDouble(currentLat) / 100000.0)
        points.Add(Convert.ToDouble(currentLng) / 100000.0)
    End While

    Return points
End Function

【讨论】:

    【解决方案3】:

    Telerik 有一个在线转换器:Convert VB to C# or C# to VB

    【讨论】:

    • 是的,这就是我开始的地方 - 清理 VB.NET 输出以获得我在上面发布的内容。
    • @amb9800 您的 VB.NET 代码和 Telerik 生成的代码不一样。您将while loop 更改为for loop 等。为什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    • 2015-03-13
    相关资源
    最近更新 更多