[LUA] Please Help Me! --Polyline Decode--

Hello Everyone,

 

I have been working on adding a map view to my application, however the issue I am having is that the platform/service I am connected to sends me a route in the form of a polyline. (Google’s Polyline Algorithm) I tried to find any Lua Libraries for decoding polylines but all I found were ones in different languages. I attempted at replicating some of the code, but I cannot get it to work. Please Help. Corona Simulator hangs when I run my code. 

 

This is the encoded string:

u~kgEpxvmQ?bA?`D?|@?Z}@?c@?m@?e@?S??[?{C?wA?aA?m@D?`B?b@?~@?

and this should be the output: (In an array or table)

(32.83451,-96.78745) Level: 3 (32.83451,-96.78779) Level: 3 etc.

JS and VB examples:

 

JS:

function decodePolyline(encoded) { if (!encoded) { return []; } var poly = []; var index = 0, len = encoded.length; var lat = 0, lng = 0; while (index \< len) { var b, shift = 0, result = 0; do { b = encoded.charCodeAt(index++) - 63; result = result | ((b & 0x1f) \<\< shift); shift += 5; } while (b \>= 0x20); var dlat = (result & 1) != 0 ? ~(result \>\> 1) : (result \>\> 1); lat += dlat; shift = 0; result = 0; do { b = encoded.charCodeAt(index++) - 63; result = result | ((b & 0x1f) \<\< shift); shift += 5; } while (b \>= 0x20); var dlng = (result & 1) != 0 ? ~(result \>\> 1) : (result \>\> 1); lng += dlng; var p = { latitude: lat / 1e5, longitude: lng / 1e5, }; poly.push(p); } return poly; }

Visual Basic:

Structure LatLng Dim Lat As Decimal Dim Lon As Decimal End Structure Function decodePoly(ByRef encoded As String) As List(Of LatLng) Dim poly As List(Of LatLng) = New List(Of LatLng) Dim index As Integer = 0 Dim len As Integer = encoded.Length() Dim lat As Integer = 0 Dim lng As Integer = 0 While (index \< len) Dim b As Integer Dim shift As Integer = 0 Dim result As Integer = 0 Do b = AscW(encoded.Chars(index)) - 63 index += 1 result = result Or (b And &H1F) \<\< shift shift += 5 Loop While (b \>= &H20) Dim dlat As Integer If (result And 1) \<\> 0 Then dlat = Not (result \>\> 1) Else dlat = result \>\> 1 End If lat += dlat shift = 0 result = 0 Do b = AscW(encoded.Chars(index)) - 63 index += 1 result = result Or (b And &H1F) \<\< shift shift += 5 Loop While (b \>= &H20) Dim dlng As Integer If (result And 1) \<\> 0 Then dlng = Not (result \>\> 1) Else dlng = result \>\> 1 End If lng += dlng Dim p As LatLng = New LatLng With {.Lat = (lat / 100000.0), .Lon = (lng / 100000.0)} poly.Add(p) End While decodePoly = poly End Function

My Lua Code: (P.S. I tried my best to convert/transcribe this code)

local bitLib = require( "plugin.bit" ) local lshift = bit.lshift local rshift = bit.rshift local bnot = bit.bnot function decodePolyline(encoded) poly = {}; index = 0 len = string.len(encoded) lat = 0 lng = 0 while (index \< len) do shift = 0 result = 0 end do --index2 = index + 1 b = encoded.byte((index + 1)) - 63 result = result or ( lshift((b and 0x1f), shift) ) shift = shift + 5 end while (b \>= 0x20) do dlat = (result and 1) ~= 0 and bnot(( rshift(result, 1))) or (rshift(result, 1)) lat = lat + dlat shift = 0 result = 0 end do --index2 = index + 1 b = encoded.byte((index + 1)) - 63 result = result or ( lshift((b and 0x1f), shift) ) shift = shift + 5 end while (b \>= 0x20) do dlng = (result and 1) ~= 0 and bnot(( rshift(result, 1))) or (rshift(result, 1)) lng = lng + dlng; p = { latitude = lat / 1e5, longitude = lng / 1e5, } table.insert(poly, p) end return poly; end

This is how I am calling the function and passing parameter(the string/encoded polyline)

local decodedCords = decodePolyline(polyLine) timer.performWithDelay(500) print(decodedCords)

Please help me with this. Anyone! 

 

(P.S. my head hurts)

 

Thanks,

Feliz Games

 

Hi.

I had a go transcribing the Javascript version and get the values you describe.

(I began without the bit library, but you should be able to switch those back.)

My guesses on what you were missing: not using the colon operator for encoded:byte() and not incrementing index (almost certainly why it’s hanging): index++ means “get the value, use it, then increment it” basically.

Anyhow, here’s my quick code:

local bit = require("plugin.bit") function decodePolyline (encoded) if not encoded then return {} end local poly = {} local index, len = 1, #encoded local lat, lng = 0, 0 while index \< len do local shift, result, b = 0, 0 repeat b = encoded:byte(index) - 63 index = index + 1 result = result + (b % 0x20) \* 2^shift shift = shift + 5 until b \< 0x20 local hlat = bit.rshift(result, 1) local dlat = result % 2 ~= 0 and bit.bnot(hlat) or hlat lat = lat + dlat shift, result = 0, 0 repeat b = encoded:byte(index) - 63 index = index + 1 result = result + (b % 0x20) \* 2^shift shift = shift + 5 until b \< 0x20 local hlng = bit.rshift(result, 1) local dlng = result % 2 ~= 0 and bit.bnot(hlng) or hlng lng = lng + dlng local p = { latitude = lat / 1e5, longitude = lng / 1e5 } poly[#poly + 1] = p end return poly end local p = decodePolyline("u~kgEpxvmQ?bA?`D?|@?Z}@?c@?m@?e@?S??[?{C?wA?aA?m@D?`B?b@?~@?") for k, v in pairs(p) do print("?", k) for kk, vv in pairs(v) do print("", kk, vv) end print("") end

Hi.

I had a go transcribing the Javascript version and get the values you describe.

(I began without the bit library, but you should be able to switch those back.)

My guesses on what you were missing: not using the colon operator for encoded:byte() and not incrementing index (almost certainly why it’s hanging): index++ means “get the value, use it, then increment it” basically.

Anyhow, here’s my quick code:

local bit = require("plugin.bit") function decodePolyline (encoded) if not encoded then return {} end local poly = {} local index, len = 1, #encoded local lat, lng = 0, 0 while index \< len do local shift, result, b = 0, 0 repeat b = encoded:byte(index) - 63 index = index + 1 result = result + (b % 0x20) \* 2^shift shift = shift + 5 until b \< 0x20 local hlat = bit.rshift(result, 1) local dlat = result % 2 ~= 0 and bit.bnot(hlat) or hlat lat = lat + dlat shift, result = 0, 0 repeat b = encoded:byte(index) - 63 index = index + 1 result = result + (b % 0x20) \* 2^shift shift = shift + 5 until b \< 0x20 local hlng = bit.rshift(result, 1) local dlng = result % 2 ~= 0 and bit.bnot(hlng) or hlng lng = lng + dlng local p = { latitude = lat / 1e5, longitude = lng / 1e5 } poly[#poly + 1] = p end return poly end local p = decodePolyline("u~kgEpxvmQ?bA?`D?|@?Z}@?c@?m@?e@?S??[?{C?wA?aA?m@D?`B?b@?~@?") for k, v in pairs(p) do print("?", k) for kk, vv in pairs(v) do print("", kk, vv) end print("") end