Android Example MapsDecodePolyline

Discussion in 'Tutorials & Examples' started by me68, Aug 2, 2013.

  1. me68

    me68 Member Licensed User

    Hello!

    As already told in another thread, i'm working on a navigation app using Google Maps API in combination with Google Directions http-requests for routing.

    The http-Requests looks as following:

    http://maps.googleapis.com/maps/api...1,16.324900053441525&sensor=false&language=de

    As origin parameter i use the current gps data of the android device and as destination parameter i use the gps coordinates of one poi on the map.

    The result is formatted in json.

    After decoding json with the json-library i decode polyline points and store them in lMapsPoints list.

    So i'm able to draw the route to maps:

    [​IMG]

    You'll find some implementations in internet to this topic - but they are all written in C++. So i used this code and transferred it to b4a. There are a lot of bit-operations. Input is the polyline string and output is a list of MapsPointItem-elements:

    Code:
    Sub MapsDecodePolyline(encoded As String, poly As List)
        
    Log("MapsDecodePolyline")
       
        
    Dim index As Int
        
    Dim lat As Int
        
    Dim lng As Int
        
    Dim fLat As Float
        
    Dim fLng As Float
        
    Dim b As Int
        
    Dim shift As Int
        
    Dim result As Int
        
    Dim dlat As Int
        
    Dim dlng As Int
        
    Dim p As LatLng
        
    Dim i As Int
        
    Dim l As LatLng

        index = 
    0 : lat = 0 : lng = 0
        
    Do While index < encoded.Length
            shift = 
    0 : result = 0
            
    Do While True
                b = 
    Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
                result = 
    Bit.OR(result, Bit.ShiftLeft(Bit.AND(b, 0x1f), shift))
                shift = shift + 
    5
                
    If b < 0x20 Then Exit
            
    Loop
           
            
    If Bit.AND(result, 1) = 1 Then
                dlat = 
    Bit.Not(Bit.ShiftRight(result, 1))
            
    Else
                dlat = 
    Bit.ShiftRight(result, 1)
            
    End If
            lat = lat + dlat
            shift = 
    0 : result = 0
            
    Do While True
                b = 
    Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
                result = 
    Bit.OR(result, Bit.ShiftLeft(Bit.AND(b, 0x1f), shift))
                shift = shift + 
    5
                
    If b < 0x20 Then Exit
            
    Loop
           
            
    If Bit.AND(result, 1) = 1 Then
                dlng = 
    Bit.Not(Bit.ShiftRight(result, 1))
            
    Else
                dlng = 
    Bit.ShiftRight(result, 1)
            
    End If
            lng = lng + dlng
            fLat = lat
            fLng = lng
           
            
    Dim mpiCurrent As MapsPointItem
            mpiCurrent.Initialize
            mpiCurrent.iPassed = 
    0
            mpiCurrent.dLatitude = fLat / 
    100000
            mpiCurrent.dLongitude = fLng / 
    100000
            poly.add(mpiCurrent)
        
    Loop
    End Sub

    Code:
    Type MapsPointItem (dLatitude As Double, dLongitude As Double, iPassed As Int)
    Drawing the route is very easy:

    Code:
    MapsDecodePolyline(sPolyline, lMapsPoints)
       
    Dim i As Int
    Dim llPoint As LatLng
    Dim points As List
    Dim mpiCurrent As MapsPointItem

    bMapsRoutingInProgress = 
    True
    bMapsManeuverPassed = 
    False
    Main.bDoNotDisturb = 
    True
    points.Initialize

    For i = 0 To lMapsPoints.Size - 1
      mpiCurrent = lMapsPoints.Get(i)
      llPoint.Initialize(mpiCurrent.dLatitude, mpiCurrent.dLongitude)
      points.Add(llPoint)
    Next

    Dim pl As Polyline = gmap.AddPolyline
    pl.points = points
    pl.Color = utilities.v4_Colors(
    "holo_blue_light")
    Feel free to use it!

    Martin
     
    DonManfred, corwin42, Devan and 9 others like this.
  2. daniloverdugo

    daniloverdugo New Member Licensed User

    hi,
    great great work!!

    do you have array to string coding code??
     
  3. jhT

    jhT New Member Licensed User

    Thanks very much for posting this - I managed to link this up to my code and it worked a treat.

    Do you automatically zoom to the size of the overall route too?
     
  4. me68

    me68 Member Licensed User

    No. But if you figure out something, please let me know.

    Martin
     
    Devan likes this.
  5. me68

    me68 Member Licensed User

    No, wherefore do you need this?

    Martin
     
  6. jhT

    jhT New Member Licensed User

    I have managed to get automatic zoom using the AnimateToBounds method in the GoogleMapsExtras library.

    If you use the list of points generated by the MapsDecodePolyline sub, you can work out the Lat/Lng boundaries and then apply them to the map

    Code:
    Sub SetMapZoom(PointsList As List)

        
    'Zoom to centre and include the lat/lng boundaries given by the route

        
    Dim gmE As GoogleMapsExtras
        
    Dim llBounds As LatLngBounds
        
    Dim llNE As LatLng, llSW As LatLng, llPoint As LatLng
        
    Dim dblNELat As Double, dblNELng As Double, dblSWLat As Double, dblSWLng As Double
        
    Dim i As Int
       
        
    'Initialise points
        llPoint = PointsList.Get(0)
        dblNELat = llPoint.Latitude
        dblNELng = llPoint.Longitude
        dblSWLat = llPoint.Latitude
        dblSWLng = llPoint.Longitude
       
        
    'Go through all points to get greatest and smallest
        For i = 1 To PointsList.Size -1
            llPoint = PointsList.Get(i)
            
    If dblNELat < llPoint.Latitude Then dblNELat = llPoint.Latitude
            
    If dblNELng < llPoint.Longitude Then dblNELng = llPoint.Longitude
            
    If dblSWLat > llPoint.Latitude Then dblSWLat = llPoint.Latitude
            
    If dblSWLng > llPoint.Longitude Then dblSWLng = llPoint.Longitude
        
    Next
     
        
    'Set the Lat/Lng boundaries
        llNE.Initialize(dblNELat, dblNELng)
        llSW.Initialize(dblSWLat, dblSWLng)
        llBounds.Initialize(llSW,llNE)
       
        
    'Perform animation on google map (pnlMap is the panel containing the Google map)
        gmE.AnimateToBounds2(gmap, llBounds, pnlMap.Width, pnlMap.Height, 40)

    End Sub
    Hope this is useful to you.

    Jonathan
     
    Devan likes this.
  7. warwound

    warwound Expert Licensed User

    The new version of GoogleMapsExtras will contain the LatLngBounds.Builder object thar will simplify your posted code.

    Contact me if you want a preview version to test.

    Martin.
     
  8. marcick

    marcick Well-Known Member Licensed User

    Hi, I have used your code to decode polyline from Google direction api, thanks.
    I would like to know if you had success in writing a good navigation system with voice guidance.
    I need to implement it in my app and don't want to use intent to call the external navigator.
     
  9. claude330

    claude330 Member Licensed User

    I have used your code to decode polyline from Google directions. It works fine. Thanks very much.
     
  10. Carlos Bernardino

    Carlos Bernardino New Member Licensed User

    Martin, could you please tell me how to decode the result of the Google Directions http request with the json-library? Thank you.
     
  11. Petrovic

    Petrovic Member Licensed User

    I tried to use your code but can you please explain me something?
    I used httputils2 lib and job.download to get and store google direction json in a string. After that I used that stiring as encoded parameter
    in your MapsDecodePolyline function to decode it and put points in lMapsPoints list but I got an error when calling MapsDecodePolyline function
    when it comes to this part:
    It gives me following error:
    I have tried in couple of days to find a solution but no luck.
    Can you please help me solve this problem and guide me in right direction.
     
  12. Petrovic

    Petrovic Member Licensed User

    I solved it, made a misprint in json parsing, sorry :)
     
    Devan likes this.
  13. Luiz Fernando Orlandini

    Luiz Fernando Orlandini Active Member Licensed User

    Hello All!

    I had implemented this routine with success.

    In my case, I have to redraw the polylines every 10 seconds. In the first execution the route is draw perfectly. But after the second time, one line is draw, making a connection from initial to end point.

    Anybody can help me to solve this?

    Regards.
     
  14. marcick

    marcick Well-Known Member Licensed User

    Do you clear the polyline before redrwaing it ?

    something like this:

    Code:
    If Pline.IsInitialized=True Then
            Points.Clear
            Pline.Points=Points
        
    End If
     
    Devan likes this.
  15. Luiz Fernando Orlandini

    Luiz Fernando Orlandini Active Member Licensed User

    Thx dude!!! Now works fine!
     
  16. Nikita Mae Tuanquin

    Nikita Mae Tuanquin New Member Licensed User

    Hi. I know it's been so long since you posted this but.. I also encountered this error.. Just like you, I obtained my google direction JSON data using httputils2 and fed that string to the MapsDecodePolyline function.. Do you happen to still remember what you did with the JSON parsing? I've been stuck with this problem for a few days..
     
    Devan likes this.
  17. Mikonios

    Mikonios Active Member Licensed User

    For ::::
    MiUrl = "http://maps.googleapis.com/maps/api...on=39.50758,-3.52579&sensor=False&language=de"

    Error in ::::
    b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1

    It gives me following error:
    java.lang.StringIndexOutOfBoundsException: length=15414; regionStart=15414; regionLength=1

    I have tried in couple of days to find a solution but no luck.
    Can you please help me solve this problem and guide me in right direction.

    See Attach Image!!!!
     

    Attached Files:

  18. Mikonios

    Mikonios Active Member Licensed User

    Sorry.
    I solved it, made a XML parsing.

    Code:
    Sub GeneraRuta()
       
        wm = 
    ""
        
    Dim MiUrl As String
        
    Dim request As HttpRequest
        
    Dim MiTaskId As String
       
        
    Dim MiFechaHora, MiFecha As String
        
    DateTime.DateFormat = "yyyy-MM-dd HH:mm:ss"               
        MiFechaHora = 
    DateTime.Now
           
        
    If CheckConnection Then
            url = 
    "http://maps.googleapis.com/maps/api/directions/json?origin=48.267058,16.425503&destination=48.13769992466281,16.324900053441525&sensor=false&language=de"
            MiUrl = 
    "http://maps.googleapis.com/maps/api/directions/xml?origin=40.38404,-3.69250&destination=39.50758,-3.52579&sensor=False&language=es"
    '        MiUrl = MiUrl.Replace("LATI", Latitud)
    '        MiUrl = MiUrl.Replace("LONG", Longitud)
           
            request.InitializeGet(MiUrl)
            request.Timeout = 
    10000 'set timeout to 10 seconds
           
            
    If HttpClient1.Execute(request, MiFechaHora) = False Then
                
    Return 'Will be false if there is already a running task (with the same id).
            Else
                
    'HttpClient1_ResponseSuccess (Response As HttpResponse, TaskId As Int)   
            End If
            
    ProgressDialogShow("Calling address server...")
           
        
    End If
       
    End Sub

    Sub HttpClient1_ResponseSuccess (Response As HttpResponse, TaskId As Int)
       
        
    Dim SQL1 As SQL
        
    Dim Query As String
       
           
    ProgressDialogHide
           
    Dim result As InputStream
        
    Try
               result = Response.GetInputStream 
    'GetString("UTF8") 'Convert the response to a string
        Catch
            
    Log("Error ::: Response.GetInputStream ")
        
    End Try
        
    '--------------------------------------------------------------------------------------------------------------
        Response.GetAsynchronously("Response"File.OpenOutput(Main.DirCcDta, TaskId & "wm.txt"False), True, TaskId)
        
    '--------------------------------------------------------------------------------------------------------------
       
           
    Log("ResponseSuccess")
           
    Log(result)
       
        MiListaPoly.Initialize
           Parser.Parse(result, 
    "Parser")
        MiListaPoly = MiListaPoly
        wm = 
    ""
      
           result.Close
       
    End Sub

    Sub HttpClient1_ResponseError (Reason As String, StatusCode As Int, TaskId As Int)
        
    Log(Reason)   
        
    Log(StatusCode)
        
    ProgressDialogHide
        
    If StatusCode = -1 Then msg = "The phone is offline"
        
    ToastMessageShow (Reason, True)
    End Sub

    Sub Response_StreamFinish (Success As Boolean, TaskId As Int)
        
    Dim another_buffer () As Byte
        another_buffer = my_buffer.ToBytesArray
        
    Log (BytesToString(another_buffer, 0, another_buffer.Length, "UTF8"))
    End Sub

    Sub Parser_StartElement (Uri As String, Name As StringAttributes As Attributes)

    End Sub

    Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)
       
    'http://maps.google.com/maps/api/geocode/xml?latlng=40.47981437,-3.37913171&sensor=false
        If Name = "points" Then
            
    If wm.Length > 0 Then Return
                wm = 
    "" & Text.ToString & CRLF
                MapsDecodePolyline(Text.ToString, MiListaPoly)
                wm = 
    ""
          
    End If
    End Sub

    Sub CheckConnection As Boolean
    ' If MyLan.IsInitialized Then WifiOn = CheckWiFi
    ' CheckConnection
    Dim p AsPhone
    If (p.GetDataState == "CONNECTED"Then
    ReturnTrue
    EndIf
    If (p.GetSettings ("wifi_on") == 1Then
    ReturnTrue
    EndIf
    If (p.GetDataState == "DISCONNECTED"Then
    ReturnFalse
    EndIf
    If (p.GetDataState == "SUSPENDED"Then
    ReturnFalse
    EndIf
    End Sub
     
    Devan likes this.
  19. BarryW

    BarryW Active Member Licensed User

    Can you post a running sample for this... tnx
     
    ihabsharaf likes this.
  20. SCIS

    SCIS Active Member Licensed User

    Do you need libraries for this? I can't seem to find them. If not, I've no idea how I should start on this since I'm new to b4a
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice