iOS Question Navigation : Find a Route and navigate

tufanv

Expert
Licensed User
Longtime User
Hello,

As I learned from previous topics, in mobile sdk , there is no find route or navigate option. IS there a library that can be wrapped for this purpose to use with google maps or any other tricky way to find a route between two points or navigate to a point ?

What should we focus on to learn to do this ?

TY
 

marcick

Well-Known Member
Licensed User
Longtime User
Similar to Android, You can use this to obtain a JSON result that contain the route between two points.
Scanning the JSON you extract a list of points that can be used to draw a polylin eon the map.

B4X:
Dim RequestUrl As StringBuilder
RequestUrl.Initialize
RequestUrl.Append("http://maps.googleapis.com/maps/api/directions/json?origin=" & NavigaFrom.Latitude & "," & NavigaFrom.Longitude & "&destination=" & NavigaTo.Latitude & "," & NavigaTo.Longitude & "&sensor=false&region=it")
Dim HttpRequest1 As HttpRequest
HttpRequest1.InitializeGet(RequestUrl.ToString)
HttpClient1.Execute(HttpRequest1, 1)

and this is my code to exctract the list of points:

B4X:
Sub HttpClient1_ResponseSuccess (Response As HttpResponse, TaskId As Int)
    Dim status As String
    Main.hd.ProgressDialogHide   
    Try
        JSONParser1.Initialize(Response.GetString)
        Dim Map1 As Map
        Map1=JSONParser1.NextObject
        If Map1.ContainsKey("status") And Map1.ContainsKey("routes") Then
            status=Map1.Get("status")
            Log("Status : " & status)
            If status="OK" Then
                Dim routes, steps As List
                Dim legs As List
                Dim m1, m2 As Map
                Dim EndLocation As LatLng
                Dim DistanceValue, DurationValue As Int
                Dim lMapsPoints As List
                lMapsPoints.Initialize
                NavigationPoints.Initialize
                routes=Map1.Get("routes")
                m1=routes.Get(0)        ' prendo solo il primo itinerario perchè non è specificato di proporne multipli
                legs=m1.Get("legs")
                m1=legs.Get(0)        ' prendo solo il primo legs perchè non ci sono waypoints
                steps=m1.Get("steps")
                NavigationDistance=0
                NavigationTime=0
                Dim points As List
                points.Initialize
                If steps.Size>0 Then
                    For s=0 To steps.Size-1
                        m1=steps.Get(s)
                        m2=m1.Get("end_location")
                        EndLocation.Initialize(m2.Get("lat"),m2.Get("lng"))
                        m2=m1.Get("polyline")
                        MapsDecodePolyline(m2.Get("points"))
                        m2=m1.Get("distance")
                        DistanceValue=m2.Get("value")
                        m2=m1.Get("duration")
                        DurationValue=m2.Get("value")
                        NavigationDistance=NavigationDistance+DistanceValue
                        NavigationTime=NavigationTime+DurationValue
                    Next
                    NavigationPolyline.points = NavigationPoints
                    NavigationPolyline.Color = Colors.Green
                    NavigationPolyline.Width=5
                    UpdateNavigationData
                End If
            Else If status="OVER_QUERY_LIMIT" Then
                Main.Toast.ShowToastMessage("Richiesta itinerario respinta",1000)
                ' aspetto quando arriva una nuova posizione
            Else
                Main.Toast.ShowToastMessage("Itinerario non trovato",1000)
            End If           
        Else
            Main.Toast.ShowToastMessage("Errore2 avvio navigatore",1000)
            EndNavigation
        End If   
    Catch
        Log("Navigator JSONParser1 error")
        Main.Toast.ShowToastMessage("Errore aggiornamento navigatore", 2000)
    End Try   
    NavCalculating=False
End Sub

A real navigation with voice assistant is instead a very hard task .....
 
Last edited:
Upvote 0

tufanv

Expert
Licensed User
Longtime User
Thank You . This will be
Similar to Android, You can use this to obtain a JSON result that contain the route between two points.
Scanning the JSON you extract a list of points that can be used to draw a polylin eon the map.

B4X:
Dim RequestUrl As StringBuilder
RequestUrl.Initialize
RequestUrl.Append("http://maps.googleapis.com/maps/api/directions/json?origin=" & NavigaFrom.Latitude & "," & NavigaFrom.Longitude & "&destination=" & NavigaTo.Latitude & "," & NavigaTo.Longitude & "&sensor=false&region=it")
Dim HttpRequest1 As HttpRequest
HttpRequest1.InitializeGet(RequestUrl.ToString)
HttpClient1.Execute(HttpRequest1, 1)

and this is my code to exctract the list of points:

B4X:
Sub HttpClient1_ResponseSuccess (Response As HttpResponse, TaskId As Int)
    Dim status As String
    Main.hd.ProgressDialogHide  
    Try
        JSONParser1.Initialize(Response.GetString)
        Dim Map1 As Map
        Map1=JSONParser1.NextObject
        If Map1.ContainsKey("status") And Map1.ContainsKey("routes") Then
            status=Map1.Get("status")
            Log("Status : " & status)
            If status="OK" Then
                Dim routes, steps As List
                Dim legs As List
                Dim m1, m2 As Map
                Dim EndLocation As LatLng
                Dim DistanceValue, DurationValue As Int
                Dim lMapsPoints As List
                lMapsPoints.Initialize
                NavigationPoints.Initialize
                routes=Map1.Get("routes")
                m1=routes.Get(0)        ' prendo solo il primo itinerario perchè non è specificato di proporne multipli
                legs=m1.Get("legs")
                m1=legs.Get(0)        ' prendo solo il primo legs perchè non ci sono waypoints
                steps=m1.Get("steps")
                NavigationDistance=0
                NavigationTime=0
                Dim points As List
                points.Initialize
                If steps.Size>0 Then
                    For s=0 To steps.Size-1
                        m1=steps.Get(s)
                        m2=m1.Get("end_location")
                        EndLocation.Initialize(m2.Get("lat"),m2.Get("lng"))
                        m2=m1.Get("polyline")
                        MapsDecodePolyline(m2.Get("points"))
                        m2=m1.Get("distance")
                        DistanceValue=m2.Get("value")
                        m2=m1.Get("duration")
                        DurationValue=m2.Get("value")
                        NavigationDistance=NavigationDistance+DistanceValue
                        NavigationTime=NavigationTime+DurationValue
                    Next
                    NavigationPolyline.points = NavigationPoints
                    NavigationPolyline.Color = Colors.Green
                    NavigationPolyline.Width=5
                    UpdateNavigationData
                End If
            Else If status="OVER_QUERY_LIMIT" Then
                Main.Toast.ShowToastMessage("Richiesta itinerario respinta",1000)
                ' aspetto quando arriva una nuova posizione
            Else
                Main.Toast.ShowToastMessage("Itinerario non trovato",1000)
            End If          
        Else
            Main.Toast.ShowToastMessage("Errore2 avvio navigatore",1000)
            EndNavigation
        End If  
    Catch
        Log("Navigator JSONParser1 error")
        Main.Toast.ShowToastMessage("Errore aggiornamento navigatore", 2000)
    End Try  
    NavCalculating=False
End Sub

A real navigation with voice assistant is instead a very hard task .....

very usefull
 
Upvote 0

tufanv

Expert
Licensed User
Longtime User
Similar to Android, You can use this to obtain a JSON result that contain the route between two points.
Scanning the JSON you extract a list of points that can be used to draw a polylin eon the map.

B4X:
Dim RequestUrl As StringBuilder
RequestUrl.Initialize
RequestUrl.Append("http://maps.googleapis.com/maps/api/directions/json?origin=" & NavigaFrom.Latitude & "," & NavigaFrom.Longitude & "&destination=" & NavigaTo.Latitude & "," & NavigaTo.Longitude & "&sensor=false&region=it")
Dim HttpRequest1 As HttpRequest
HttpRequest1.InitializeGet(RequestUrl.ToString)
HttpClient1.Execute(HttpRequest1, 1)

and this is my code to exctract the list of points:

B4X:
Sub HttpClient1_ResponseSuccess (Response As HttpResponse, TaskId As Int)
    Dim status As String
    Main.hd.ProgressDialogHide 
    Try
        JSONParser1.Initialize(Response.GetString)
        Dim Map1 As Map
        Map1=JSONParser1.NextObject
        If Map1.ContainsKey("status") And Map1.ContainsKey("routes") Then
            status=Map1.Get("status")
            Log("Status : " & status)
            If status="OK" Then
                Dim routes, steps As List
                Dim legs As List
                Dim m1, m2 As Map
                Dim EndLocation As LatLng
                Dim DistanceValue, DurationValue As Int
                Dim lMapsPoints As List
                lMapsPoints.Initialize
                NavigationPoints.Initialize
                routes=Map1.Get("routes")
                m1=routes.Get(0)        ' prendo solo il primo itinerario perchè non è specificato di proporne multipli
                legs=m1.Get("legs")
                m1=legs.Get(0)        ' prendo solo il primo legs perchè non ci sono waypoints
                steps=m1.Get("steps")
                NavigationDistance=0
                NavigationTime=0
                Dim points As List
                points.Initialize
                If steps.Size>0 Then
                    For s=0 To steps.Size-1
                        m1=steps.Get(s)
                        m2=m1.Get("end_location")
                        EndLocation.Initialize(m2.Get("lat"),m2.Get("lng"))
                        m2=m1.Get("polyline")
                        MapsDecodePolyline(m2.Get("points"))
                        m2=m1.Get("distance")
                        DistanceValue=m2.Get("value")
                        m2=m1.Get("duration")
                        DurationValue=m2.Get("value")
                        NavigationDistance=NavigationDistance+DistanceValue
                        NavigationTime=NavigationTime+DurationValue
                    Next
                    NavigationPolyline.points = NavigationPoints
                    NavigationPolyline.Color = Colors.Green
                    NavigationPolyline.Width=5
                    UpdateNavigationData
                End If
            Else If status="OVER_QUERY_LIMIT" Then
                Main.Toast.ShowToastMessage("Richiesta itinerario respinta",1000)
                ' aspetto quando arriva una nuova posizione
            Else
                Main.Toast.ShowToastMessage("Itinerario non trovato",1000)
            End If         
        Else
            Main.Toast.ShowToastMessage("Errore2 avvio navigatore",1000)
            EndNavigation
        End If 
    Catch
        Log("Navigator JSONParser1 error")
        Main.Toast.ShowToastMessage("Errore aggiornamento navigatore", 2000)
    End Try 
    NavCalculating=False
End Sub

A real navigation with voice assistant is instead a very hard task .....



I am trying to adapt this to my code but what does these do, they are not in the code:

updatenavigationdata,mapsdecodepolyline,endnavigation

also : what is navigationpolyline ? when i declare it as polyline it gives me error : Not initialized and it does not have a event for initialize.

Thanks!
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
Hi, you're right..... sorry for the missing parts

updatenavigationdata just update two label with distance and time:

B4X:
Label_NavDistance.text="D:  " & NumberFormat(NavigationDistance/1000,3,1) & " Km"
Dim hh As Float = NavigationTime/3600
Dim mm As Int = (hh-Floor(hh)) * 60
Label_NavTime.text="T:  " & NumberFormat(Floor(hh),2,0) & "h " & NumberFormat(mm,2,0) & "m"

mapsdecodepolyline is:

B4X:
Sub MapsDecodePolyline(encoded As String, poly As List)
     
    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
    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

Endnavigation ... do what you want
And navigationpolyline,yes, it is a polyline, you don't have to inizialite it but just declare and add to your map

B4X:
Dim NavigationPolyline As Polyline
NavigationPolyline = GoogleMap1.AddPolyline
 
Upvote 0

tufanv

Expert
Licensed User
Longtime User
Hi, you're right..... sorry for the missing parts

updatenavigationdata just update two label with distance and time:

B4X:
Label_NavDistance.text="D:  " & NumberFormat(NavigationDistance/1000,3,1) & " Km"
Dim hh As Float = NavigationTime/3600
Dim mm As Int = (hh-Floor(hh)) * 60
Label_NavTime.text="T:  " & NumberFormat(Floor(hh),2,0) & "h " & NumberFormat(mm,2,0) & "m"

mapsdecodepolyline is:

B4X:
Sub MapsDecodePolyline(encoded As String, poly As List)
   
    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
    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

Endnavigation ... do what you want
And navigationpolyline,yes, it is a polyline, you don't have to inizialite it but just declare and add to your map

B4X:
Dim NavigationPolyline As Polyline
NavigationPolyline = GoogleMap1.AddPolyline

also just a one more little question

1) Dim mpiCurrent As MapsPointItem gives me a missing library refernce error ? Is this a lib or what ?

2) MapsDecodePolyline(m2.Get("points")) needs also a ,poly it gives "," expected error as this is : Sub MapsDecodePolyline(encoded As String, poly As List)



Thanks !
 
Upvote 0

marcick

Well-Known Member
Licensed User
Longtime User
Yes .... better to put together a full working sample before give some hints .....
1) declare this in process_globals
B4X:
     Type MapsPointItem (dLatitude As Double, dLongitude As Double, iPassed As Int)
2) My fault, I have copied a piece of code from B4A and another from B4I ... this is the correct code for IOS

B4X:
Sub MapsDecodePolyline(encoded As String)
    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 poly As List
    poly.Initialize
    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 ll As LatLng
        ll.Initialize(fLat/100000, fLng/100000)
        Dim mpiCurrent As MapsPointItem
        mpiCurrent.Initialize
        mpiCurrent.iPassed = 0
        mpiCurrent.dLatitude = fLat / 100000
        mpiCurrent.dLongitude = fLng / 100000
        poly.add(mpiCurrent)
        NavigationPoints.Add(ll)
    Loop   
End Sub
 
Last edited:
Upvote 0

tufanv

Expert
Licensed User
Longtime User
Yes .... better to put together a full working sample before give some hints .....
1) declare this in process_globals
B4X:
     Type MapsPointItem (dLatitude As Double, dLongitude As Double, iPassed As Int)
2) My fault, I have copied a piece of code from B4A and another from B4I ... this is the correct code for IOS

B4X:
Sub MapsDecodePolyline(encoded As String)
    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 poly As List
    poly.Initialize
    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 ll As LatLng
        ll.Initialize(fLat/100000, fLng/100000)
        Dim mpiCurrent As MapsPointItem
        mpiCurrent.Initialize
        mpiCurrent.iPassed = 0
        mpiCurrent.dLatitude = fLat / 100000
        mpiCurrent.dLongitude = fLng / 100000
        poly.add(mpiCurrent)
        NavigationPoints.Add(ll)
    Loop  
End Sub

Works perfect now ! Thanks for all your help !

Just a little question, is it possible to find a destination with a search textfield , for example the user will write "heathrow airport" and it will find the results. IS it possible with google maps ap like the actual google maps ?
 
Upvote 0
Top