Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# to VB.NET Conversion (Google Polyline Algorithm Decoder)

I have some C# code that decodes map paths encoded using Google's polyline algorithm and am trying to convert it to VB.NET.

Here's the C# code, which works fully:

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;
    }

Here's the VB.NET code- works for the longitudes but not latitudes.

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

What's missing?

EDIT: Resolved the issue (corrected code in my answer below, which I can't select as an answer for 2 more days).

like image 900
amb9800 Avatar asked Oct 12 '22 15:10

amb9800


2 Answers

The best way to do it if you don't know the target language, compile your source code in debug mode, and then decompile it using Reflector. That way you keep the var names, and your sure the generated code is valid.

Be aware that VB.Net has "delicate" logical operators that could break your code logic : OR vs OrElse...

like image 176
Lotfi Avatar answered Nov 12 '22 21:11

Lotfi


Ah so the issue was that the C# ++ operator increments the variable but returns the original value, whereas my VB.NET conversion above was incrementing index and then using the incremented value. That somehow still worked for longitudes but messed up the latitude decoding.

Here's the corrected VB.NET code:

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
like image 29
amb9800 Avatar answered Nov 12 '22 21:11

amb9800