Plotting locations on Google Maps

Re: Plotting locations on Google Maps

Postby anserkk » Fri Mar 10, 2017 4:22 am

TimStone wrote:The translation time for the geocode is quite long when creating a map. So I decided to get the codes and store them in the database for each address.

Obviously this will take time because google has to search its database based on the address provided by you and then return the most accurate result from a bunch of data. If your list is too long then it increases the time further. For this reason, I keep the Lat and Lng in the database. May be you can run this routine once in a while to update the Lat and Lng in your Customer address DBF/Table. For large list of address there are services from Google named Google App Scripts.

My initial example in this thread was to display a Google Map based on the available Lat and Lng. I created the sample to get the Lat and Lng based on the address when you said that your requirement was to display a Googe Map based on the Address details that you have in your database. It is just a sample to demonstrate that this is possible using FiveWin. Its my mistake that, I have not gone deep into catching the run time errors if there are no results from Google.

TimStone wrote:Thoughts on trapping hjson values that do not have an array would be appreciated.

You should add the lat long to the array only if hJson["status"] == "OK"
OR you can put a try catch

Anyway here is one of the methods to consider to gracefully control the run time error which may occur if the searched address is not found by Google.
Code: Select all  Expand view
#Include "FiveWin.ch"

//-----------------------------
Function Main()
    Local aLatLng:={}
    Local aAddress:={ {"Anser","K K"            , "just dummy so that it  ", "will not give"       ,"any results" },;
                      {"Eiffel Tower","Champ de Mars"            , "5 Avenue Anatole France", "75007 Paris"         ,"France" },;
                      {"Taj Mahal"   ,"Dharmapuri, Forest Colony", "Tajganj, Agra"          , "Uttar Pradesh 282001","India"   } }

    // This function will grab the Lat and Lng information from Google and returns an array
    aLatLng:=GetLatLng(aAddress)

    // Displays Markers on a Google Map
    ViewGoogleMap(aLatLng)
Return NIL

//------------------------------------------//
Function GetLatLng(aData)
  Local i,cName,cAddress,cCity,cState,cCountry,aLatLng:={},nLatitude,nLongitude
  Local oHttp, cURL, lNetError, cResponse,hJson
 
  For i:=1 to Len(aData)
 
    cName:=STRTRAN(ALLTRIM(aData[i][1])," ","+")
    cName:=STRTRAN(ALLTRIM(aData[i][1]),"&"," E ")
    cAddress:=STRTRAN(ALLTRIM(aData[i][2]),",","")
    cAddress:=STRTRAN(ALLTRIM(aData[i][2])," ","+")
    cCity:=STRTRAN(ALLTRIM(aData[i][3])," ","+")
    cCountry:=STRTRAN(ALLTRIM(aData[i][5])," ","+")  
    cState:=aData[i][4]
   
    oHttp:=CreateObject("Microsoft.XMLHTTP")
    cURL:="http://maps.google.com/maps/api/geocode/json?address="+cAddress+"+"+cCity+"+-+"+cState+"+"+cCountry+"&sensor=false"
    oHttp:Open("GET",cURL,.F.)
    lNetError:=.F.
    TRY
        oHttp:Send()
    CATCH oError
        lNetError:=.T.
    END TRY
   
    IF !lNetError
      cResponse := oHttp:ResponseBody
    ELSE
      // Search Error. Could not find the details on Google Maps.
      Loop
    ENDIF    

    hb_jsonDecode(cResponse,@hJson)
    IF hJson["status"] == "OK"
        nLatitude:= hJson["results"][1]["geometry"]["location"]["lat"]
        nLongitude:=hJson["results"][1]["geometry"]["location"]["lng"]    
        Aadd(aLatLng,{aData[i][1],nLatitude, nLongitude} )
    ENDIF
   
  Next
 
Return aLatLng

//-----------------------------------------------------------------------/
Function ViewGoogleMap(aData)
   Local cMapFile:="D:\GMaps.htm", cHtmlContent1,cHtmlContent2, oOle, i
   Local cAppendStr:="var locations = ["+CRLF
   
   If Len(aData) == 0
      MsgInfo("Location data not available in the list")
      Return
   Endif
   
   For i:=1 to Len(aData)
       cAppendStr+=Space(4)+"['" +aData[i][1] +"',"+Ltrim(Str(aData[i][2]))+","+ Ltrim(Str(aData[i][3]))+ If( i < Len(aData), "],", "]") +CRLF
   Next
   cAppendStr+="];"+CRLF

TEXT INTO cHtmlContent1
   
    <html>
    <head>
     
      <title>Google Maps Multiple Markers</title>
      <script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
    </head>
    <body>
      <div id="map" style="height: 100%; width: 100%;">
    </div>
    <script type="text/javascript">
   
ENDTEXT
   
   
TEXT INTO cHtmlContent2    
       
        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 0,          
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });
        var bounds = new google.maps.LatLngBounds();
        var infowindow = new google.maps.InfoWindow();
   
        var marker, i;
   
        for (i = 0; i < locations.length; i++) {
         var position = new google.maps.LatLng(locations[i][1], locations[i][2]);
            bounds.extend(position);
          marker = new google.maps.Marker({
            position: new google.maps.LatLng(locations[i][1], locations[i][2]),        
            map: map
          });
   
          google.maps.event.addListener(marker, 'click', (function(marker, i) {
            return function() {
              infowindow.setContent(locations[i][0]);
              infowindow.open(map, marker);
            }
          })(marker, i));

          // Automatically center the map fitting all markers on the screen
          map.fitBounds(bounds);
         
        }
      </script>
    </body>
    </html>
   
ENDTEXT

     MEMOWRIT( cMapFile, cHtmlContent1+cAppendStr+cHtmlContent2 )

     Shellexecute( NIL, "open", cMapFile )    
   
Return
User avatar
anserkk
 
Posts: 1332
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Re: Plotting locations on Google Maps

Postby nageswaragunupudi » Fri Mar 10, 2017 5:14 am

May be you can run this routine once in a while to update the Lat and Lng in your Customer address DBF/Table.

It is a good idea to find latlong and save it in database when adding a contact or modifying the address of a contact.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10624
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: Plotting locations on Google Maps

Postby anserkk » Fri Mar 10, 2017 5:44 am

nageswaragunupudi wrote:
May be you can run this routine once in a while to update the Lat and Lng in your Customer address DBF/Table.

It is a good idea to find latlong and save it in database when adding a contact or modifying the address of a contact.
.
Yes. you are right. That's the right way to do.
User avatar
anserkk
 
Posts: 1332
Joined: Fri Jun 13, 2008 11:04 am
Location: Kochi, India

Re: Plotting locations on Google Maps

Postby TimStone » Fri Mar 10, 2017 5:41 pm

As I noted previously, I have been doing exactly what was suggested ... and that is to get the coordinates and save them to the database. I did find a way yesterday to trap no data found responses, but apparently there are other types of responses also so I will be working more on this today.

What I am trying to do is build a map that shows where clients come from over a period of time. Hidden deeply inside the Google documents, however, I found that you the API apparently only allows for 15 markers. That is strange because I see applications frequently that show far more than 15 points. I suppose I will have to work on that issue.

The reason for the maps is that they are often used in marketing programs to show areas that yield the best results from communications by businesses.

Thanks for the ideas ... they are being incorporated ... and my goal will to ultimately build a class that allows us greater use of Google Maps from within FWH.

Tim
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Re: Plotting locations on Google Maps

Postby cnavarro » Fri Mar 10, 2017 6:28 pm

The most important thing is that: I consider that the Anserkk example is the best way to do this work
But, I have another way of getting this data (latitude and longitude)
Then you can apply the function to draw the map

Code: Select all  Expand view


#include "FiveWin.ch"

Static cUrl     := ""

Function Main()

   SET 3DLOOK OFF
   VerMapa2( "", "Calle Gran Via", "17", "Madrid", "Madrid", "Spain" )
   VerMapa2( "75007", "Avenue Anatole France", "5", "", "Paris", "France" )

   
Return nil

//----------------------------------------------------------------------------//

Function VerMapa2( cPostal_Code, cStreet, cNumber, cLocality, cState, cNation )
   
   Local cWeb  := "http://maps.google.es/maps/place/"
   local cMap
   local cRet  := ""
   local oOle
   local nPos1
   local nPos2
   local aCoor := { 0, 0, 0 }
   cPostal_Code := StrTran( AllTrim( cPostal_Code ), ' ', '+' )
   cStreet      := StrTran( AllTrim( cStreet ), ' ', '+' )
   cNumber      := StrTran( AllTrim( cNumber ), ' ', '+' )
   cLocality    := StrTran( AllTrim( cLocality ), ' ', '+' )
   cState       := StrTran( AllTrim( cState ), ' ', '+' )
   cNation      := StrTran( AllTrim( cNation ), ' ', '+' )
   cMap     :=  AllTrim( cPostal_Code ) + "+" + AllTrim( cStreet ) + "+" + ;
                AllTrim( cNumber ) + "+" + AllTrim( cLocality ) + "+" + ;
                AllTrim( cState ) + "+" + AllTrim( cNation )
   oOle  := CreateObject("Winhttp.WinHttpRequest.5.1")
   oOle:Open( "GET", cWeb + AllTrim( cMap ), .F. )
   oOle:Send()
   cURL := oOle:ResponseText

   nPos1  := At( "cacheResponse([[[", Left( cURL, 2048 ) )
   if !Empty( nPos1 )
      cRet   := Substr( Left( cURL, 1024 ), nPos1 + 17, 2048 - nPos1 )
      nPos2  := At( "]", cRet )
      if !Empty( nPos2 )
         cRet   := Left( cRet, nPos2 - 1 )
         aCoor  := hb_ATokens( cRet, "," )
      endif
   endif
   XBrowse( aCoor )

Return aCoor

//----------------------------------------------------------------------------//
 
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6541
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Plotting locations on Google Maps

Postby TimStone » Wed Mar 15, 2017 5:08 pm

A few observations:

1) I built a utility to do just the geocode, and save the result to the database. GOOGLE LIMITS ACTIVITY - a) You need a key ( free ), and b) you still have a limit of the number of searches you can do in a 24 hour period. Google says the key lets you do 25,000, but I find it only allows 2500. I have to run the routine over several days before I can get results for the whole database.

2) It is very common to add to an address. For example, 241 South St. Apt 6 Anytown, NY is submitted as 241+South+St.+Apt+6+Anytown,+NY and because of the apartment and number, this will not decode. Make sure you use only the street number and name.

3) I wanted to plot many locations on the map to show where customers live. I see this done a lot, but Google Maps has a limit of 15 points we can plot at one time. They do have an alternative for clustering locations which shows one pin in an area.

Mapping is very popular now, and Google seems to be the main resource people use.
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Re: Plotting locations on Google Maps

Postby cnavarro » Wed Mar 15, 2017 9:16 pm

My son, has recommended this lib

http://leafletjs.com/index.html

This is a sample
If you have the length and latitude, you do not need to run the function VerMapa2()

Code: Select all  Expand view


#include "FiveWin.ch"

Static cUrl     := ""

Function Main()

   Local aDatas := {}
   SET 3DLOOK OFF

   AAdd( aDatas, VerMapa2( "28850", "Calle Manuel Sandoval", "1", "Torrejon de Ardoz", "Madrid", "Spain" ) )
   AAdd( aDatas, VerMapa2( "28850", "Calle Buenos Aires", "1", "Torrejon de Ardoz", "Madrid", "Spain" ) )
   AAdd( aDatas, VerMapa2( "28850", "Calle Ferrocarril", "10", "Torrejon de Ardoz", "Madrid", "Spain" ) )
   ViewLeafLet( aDatas )

Return nil

//----------------------------------------------------------------------------//

Function VerMapa2( cPostal_Code, cStreet, cNumber, cLocality, cState, cNation )
   
   Local cWeb  := "http://maps.google.es/maps/place/"
   local cMap
   local cRet  := ""
   local oOle
   local nPos1
   local nPos2
   local aCoor := { 0, 0, 0 }
   cPostal_Code := StrTran( AllTrim( cPostal_Code ), ' ', '+' )
   cStreet      := StrTran( AllTrim( cStreet ), ' ', '+' )
   cNumber      := StrTran( AllTrim( cNumber ), ' ', '+' )
   cLocality    := StrTran( AllTrim( cLocality ), ' ', '+' )
   cState       := StrTran( AllTrim( cState ), ' ', '+' )
   cNation      := StrTran( AllTrim( cNation ), ' ', '+' )
   cMap     :=  AllTrim( cPostal_Code ) + "+" + AllTrim( cStreet ) + "+" + ;
                AllTrim( cNumber ) + "+" + AllTrim( cLocality ) + "+" + ;
                AllTrim( cState ) + "+" + AllTrim( cNation )
   oOle  := CreateObject("Winhttp.WinHttpRequest.5.1")
   oOle:Open( "GET", cWeb + AllTrim( cMap ), .F. )
   oOle:Send()
   cURL := oOle:ResponseText

   nPos1  := At( "cacheResponse([[[", Left( cURL, 2048 ) )
   if !Empty( nPos1 )
      cRet   := Substr( Left( cURL, 1024 ), nPos1 + 17, 2048 - nPos1 )
      nPos2  := At( "]", cRet )
      if !Empty( nPos2 )
         cRet   := Left( cRet, nPos2 - 1 )
         aCoor  := hb_ATokens( cRet, "," )
      endif
   endif
   //XBrowse( aCoor )

Return aCoor

//----------------------------------------------------------------------------//

Function ViewLeafLet(aData)
   
   local cMapFile   := "D:\fwh\fwhteam\samples\GMaps.htm"
   local cHtmlContent1
   local cHtmlContent2
   local cHtmlContent3
   local cInitMap   := "   var mymap = L.map('mapid').setView( [ "
   local cAppendStr := "   L.polygon([" + CRLF
   local oOle
   local i

   TEXT INTO cHtmlContent1
   
   <!DOCTYPE html>
   <html>
   <head>
       <title>Quick Start - Leaflet</title>

       <meta charset="utf-8" />
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
   
       <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />

       <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" />
       <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
   </head>
   <body>
      <div id="mapid" style="width: 700px; height: 560px;"></div>
      <script>
   ENDTEXT

   cInitMap  += aData[ 1 ][ 3 ] + ", " + aData[ 1 ][ 2 ] + " ], 13);" + CRLF

   TEXT INTO cHtmlContent2
    L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
        maxZoom: 18,
        attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
            '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="http://mapbox.com">Mapbox</a>',
        id: 'mapbox.streets'
    }).addTo(mymap);

   ENDTEXT

   For i := 1 to Len( aData )
      cAppendStr += Space( 4 ) + "[ " + aData[ i ][ 3 ] + ", " + ;
                    Ltrim( aData[ i ][ 2 ] )
      if i < Len( aData )
         cAppendStr += "]," + CRLF
      else
         cAppendStr += "]" + CRLF      
      endif
   Next
   cAppendStr += "]).addTo(mymap).bindPopup('I am a polygon.');" + CRLF + CRLF

   For i := 1 to Len( aData )
      cAppendStr += "L.marker( "
      cAppendStr += "[ " + aData[ i ][ 3 ] + ", " + ;
                    Ltrim( aData[ i ][ 2 ] ) + " ] )."
      cAppendStr += "addTo(mymap).bindPopup('<b>Marker" + Str( i ) + " !</b><br />I am a popup.').openPopup();" + CRLF + CRLF
   Next
   
   TEXT INTO cHtmlContent3
    var popup = L.popup();

    function onMapClick(e) {
        popup
            .setLatLng(e.latlng)
            .setContent("Position is: " + e.latlng.toString())
            .openOn(mymap);
    }

   mymap.on('click', onMapClick);

   </script>

   </body>
   </html>

   ENDTEXT

   MEMOWRIT( cMapFile, cHtmlContent1 + cInitMap + cHtmlContent2 + cAppendStr + cHtmlContent3 )

   oOle := CreateObject( "InternetExplorer.Application" )
   oOle:Width     := 750
   oOle:Height    := 650
   oOle:Visible   := .T.     // Displays the Browser
   oOle:ToolBar   := .F.     // Disables the toolbar
   oOle:StatusBar := .F.     // Disables status bar
   oOle:MenuBar   := .F.     // Disables the menu bar
   oOle:Navigate( cMapFile ) // Open the Webpage
   SysRefresh()
   
Return nil

//----------------------------------------------------------------------------//

 
Last edited by cnavarro on Wed Mar 15, 2017 10:20 pm, edited 1 time in total.
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6541
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Plotting locations on Google Maps

Postby TimStone » Wed Mar 15, 2017 9:28 pm

Thank you. I will explore that resource.
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Re: Plotting locations on Google Maps

Postby vilian » Thu Mar 16, 2017 12:22 pm

Guys,

Do you know if is possible show a text beside the mark for all locations plotted? Something Like tooltips.

I know if I click in the mark, the text is shown, but i would like to show the text without be necessary to click in the mark. Is it possible?
Sds,
Vilian F. Arraes
vilian@vfatec.com.br
Belém-Pa-Brazil
User avatar
vilian
 
Posts: 975
Joined: Wed Nov 09, 2005 2:17 am
Location: Brazil

Re: Plotting locations on Google Maps

Postby cnavarro » Thu Mar 16, 2017 1:35 pm

Look, Is that something you need?

http://leafletjs.com/examples/choropleth/
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6541
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Plotting locations on Google Maps

Postby vilian » Thu Mar 16, 2017 2:39 pm

Cnavarro,

No, is something like this:
Image

But for to be shown for all points, without be necessary to do a click over them.
Sds,
Vilian F. Arraes
vilian@vfatec.com.br
Belém-Pa-Brazil
User avatar
vilian
 
Posts: 975
Joined: Wed Nov 09, 2005 2:17 am
Location: Brazil

Re: Plotting locations on Google Maps

Postby cnavarro » Thu Mar 16, 2017 3:14 pm

Yes, but I think you can not define popup and tooltip to the same marker

Image

In my previous sample, replace

Code: Select all  Expand view

   For i := 1 to Len( aData )
      cAppendStr += "L.marker( "
      cAppendStr += "[ " + aData[ i ][ 3 ] + ", " + ;
                    Ltrim( aData[ i ][ 2 ] ) + " ] )."
      cAppendStr += "addTo(mymap).bindPopup('<b>Marker" + Str( i ) + " !</b><br />I am a popup.').openPopup();" + CRLF + CRLF
   Next
 


with

Code: Select all  Expand view


   For i := 1 to Len( aData )
      cAppendStr += "L.marker( "
      cAppendStr += "[ " + aData[ i ][ 3 ] + ", " + ;
                    Ltrim( aData[ i ][ 2 ] ) + " ] ).addTo(mymap).bindTooltip('my tooltip text').openTooltip();" + CRLF + CRLF
   Next

 
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6541
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Plotting locations on Google Maps

Postby cnavarro » Thu Mar 16, 2017 3:55 pm

Change images for markers

Image

Code: Select all  Expand view


   For i := 1 to Len( aData )
      cAppendStr += "L.marker( "
      cAppendStr += "[ " + aData[ i ][ 3 ] + ", " + ;
                    Ltrim( aData[ i ][ 2 ] ) + " ], {icon: greenIcon} )."
      cAppendStr += "addTo(mymap).bindPopup('<b>Marker" + Str( i ) + " !</b><br />I am a popup.').openPopup();" + CRLF + CRLF
   Next

 
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6541
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Plotting locations on Google Maps

Postby vilian » Fri Mar 17, 2017 11:27 am

Cnavarro,

You are creating the markers trough its address, isn't it ?
What i need to change for to do this trough lat/lng?
Sds,
Vilian F. Arraes
vilian@vfatec.com.br
Belém-Pa-Brazil
User avatar
vilian
 
Posts: 975
Joined: Wed Nov 09, 2005 2:17 am
Location: Brazil

Re: Plotting locations on Google Maps

Postby cnavarro » Fri Mar 17, 2017 1:41 pm

Sorry, I do not understand your question and your needs
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6541
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

PreviousNext

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 61 guests