Page 1 of 4
Plotting locations on Google Maps
Posted: Fri Mar 03, 2017 10:50 pm
by TimStone
I've had no problem calling a Google map for a single location.
Now I want to do something different. I want to plot multiple locations ( pins ) on a Google Map from my database. The plan is to show where customers exist near a business.
Has anyone done this ? It's a very common activity on the web, so I assume people have done it with FWH.
Help is appreciated.
Re: Plotting locations on Google Maps
Posted: Mon Mar 06, 2017 12:56 pm
by anserkk
Code: Select all
#Include "FiveWin.ch"
//-----------------------------
Function Main()
Local aData:={ {'Antonio (Spain)' , 36.510328, -4.882490},;
{'Sylvio (Italy)' , 42.979704, 13.664149},;
{'Otto (Austria)' , 46.752694,12.419472} }
TestGoogleMap(aData)
Return NIL
//-----------------------------------------------------------------------/
Function TestGoogleMap(aData)
Local cMapFile:="D:\GMaps.htm", cHtmlContent1,cHtmlContent2, oOle, i
Local cAppendStr:="var locations = ["+CRLF
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 )
oOle:=CreateObject("InternetExplorer.Application")
oOle:width:=675
oOle:height:=520
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
Re: Plotting locations on Google Maps
Posted: Mon Mar 06, 2017 1:34 pm
by Marc Venken
Very Nice !!
The FWH community on Google Maps :
Here we go
Marc Venken, Belgium , 51.053734 - 5.606073
Re: Plotting locations on Google Maps
Posted: Mon Mar 06, 2017 4:43 pm
by Silvio.Falconi
Dear anserkk,
your test here not run ( I have win 7 64 bit ie, chrome,firefox )
many days ago I asked a question for the Google Map because On win7/8-7/10 the oldest my function not run ok
None answer to me, I hope you can help me
when I show the map I have script error
this is the test.prg
Code: Select all
Function Mappa_google(cStreet,cCity,cCountry)
local oFrmMappa, oActiveX
DEFAULT cCountry := PadR( "ITALY", 80 )
DEFAULT cStreet := PadR( "SAN MARINO", 80 )
DEFAULT cCity := PadR( "TERAMO", 80 )
IF !IsGoogleup()
MsgAlert("Non trovo la connessione a internet!"+CRLF+"Non posso visualizzare la mappa geografica")
RETURN nil
ENDIF
Define DIALOG oFrmMappa TITLE "Mappa Geografica - con MapGoogle " ;
FROM 452, 774 to 880, 1303 PIXEL COLOR 0, 14215660
oActiveX:=TActiveX():New(oFrmMappa, "Shell.Explorer", 5,5, 255, 140 )
@ 154, 5 SAY "Indirizzo.:" SIZE 80, 7 PIXEL OF oFrmMappa COLOR 0, 14215660
@ 168, 5 SAY "Località.:" SIZE 80, 7 PIXEL OF oFrmMappa COLOR 0, 14215660
@ 184, 5 SAY "Stato.:" SIZE 80, 7 PIXEL OF oFrmMappa COLOR 0, 14215660
@ 152, 30 GET cStreet SIZE 160, 10 PIXEL OF oFrmMappa
@ 168, 30 GET cCity SIZE 120, 10 PIXEL OF oFrmMappa
@ 182, 30 GET cCountry SIZE 100, 10 PIXEL OF oFrmMappa
@ 202, 2 BUTTON oButStampa Prompt "&Stampa" SIZE 45, 10 PIXEL OF oFrmMappa ACTION NIL
@ 202, 157 BUTTON oButConferma Prompt "&Ricerca" SIZE 50, 10 PIXEL OF oFrmMappa ;
ACTION Show( cStreet, cCity, cCountry, oActiveX )
@ 202, 212 BUTTON oButAnnulla Prompt "&Uscita" SIZE 50, 10 PIXEL OF oFrmMappa ACTION oFrmMappa:End()
ACTIVATE DIALOG oFrmMappa CENTERED ;
ON INIT Show( cStreet, cCity, cCountry, oActiveX )
RETURN NIL
Function IsGoogleup()
MsgWait( "Sto provando se trovo una connessione a internet","Aspetta un momento",3 )
WSAStartup()
return GetHostByName( "www.google.com" ) != "0.0.0.0"
this test use
local cHtml := MemoRead( ".\MAPPE\gmap.html" )
Have you a test where I can insert this html into prg code ?
Re: Plotting locations on Google Maps
Posted: Mon Mar 06, 2017 5:37 pm
by TimStone
You are using coordinates. I have addresses. I know we can feed either to Google Maps, but what is the format for using street addresses instead ?
Thank you.
Re: Plotting locations on Google Maps
Posted: Tue Mar 07, 2017 1:20 am
by anserkk
TimStone wrote:You are using coordinates. I have addresses. I know we can feed either to Google Maps, but what is the format for using street addresses instead ?
Thank you.
If you don't have LAT and LNG then you need to call Google API's with the address. If found, Google will return the LAT and LNG, you may then pass the received LAT and LNG from Google to display the Markers on Google Maps using the code I posted in this thread. Few months back, I had already shared the code to find out the LAT and LNG from the address of a place in the forum.
I shall try to create a sample with the latest Google API's.
Regards
Anser
Re: Plotting locations on Google Maps
Posted: Tue Mar 07, 2017 1:34 am
by anserkk
Silvio.Falconi wrote:your test here not run ( I have win 7 64 bit ie, chrome,firefox )
The sample that I posted uses OLE using Internet explorer. If you inspect the code then you would notice the following line at the bottom of the sample.
oOle:=CreateObject("InternetExplorer.Application")
My sample basically creates a .html file. So if you know the trick to call a .html file using Chrome or Firefox (Try shell command). Then it should work. You may modify the bottom portion of the sample code ie instead of calling Internet Explorer call your favorite Internet browser.
Silvio.Falconi wrote:many days ago I asked a question for the Google Map because On win7/8-7/10 the oldest my function not run ok
None answer to me, I hope you can help me
Google keeps changing their API's and you need to keep a watch on this and modify the code accordingly.
Silvio.Falconi wrote:Have you a test where I can insert this html into prg code ?
The sample that I have posted in this thread creates html inside the prg.
Re: Plotting locations on Google Maps
Posted: Tue Mar 07, 2017 4:18 am
by anserkk
TimStone wrote:You are using coordinates. I have addresses. I know we can feed either to Google Maps, but what is the format for using street addresses instead ?
Thank you.
Here is a complete sample that serves your purpose. You can provide Addresses, Google will find out the details (if available) and then displays on the map. The Map's zoom position adjusts itself in such a way that all the markers are displayed on a single screen.
Code: Select all
#Include "FiveWin.ch"
//-----------------------------
Function Main()
Local aLatLng:={}
Local aAddress:={ {"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)
nLatitude:= hJson["results"][1]["geometry"]["location"]["lat"]
nLongitude:=hJson["results"][1]["geometry"]["location"]["lng"]
Aadd(aLatLng,{aData[i][1],nLatitude, nLongitude} )
Next
Return aLatLng
//-----------------------------------------------------------------------/
Function ViewGoogleMap(aData)
Local cMapFile:="D:\GMaps.htm", cHtmlContent1,cHtmlContent2, oOle, i
Local cAppendStr:="var locations = ["+CRLF
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 )
/*
oOle:=CreateObject("InternetExplorer.Application")
oOle:width:=675
oOle:height:=520
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()
*/
// Opens the Map using your default internet browser. A more generic solution
Shellexecute( NIL, "open", cMapFile )
Return
Regards
Anser
Re: Plotting locations on Google Maps
Posted: Wed Mar 08, 2017 2:50 am
by brewster
Mr Anserkk,
Thank you for your sharing of the sample.
I wonder if you have done any work with best route capability.
Meaning, have many stops/destinations and let Google figure out best route.
Thanks in advance.
Bruce S.
Re: Plotting locations on Google Maps
Posted: Thu Mar 09, 2017 4:55 pm
by TimStone
Thank you for the code.
I found that the GetLatLng( ) can fail. I have a list of addresses, and when submitted, the function returned a long stream of data with the message that the location was not found. Then the map fails. You trap for an error code, but this is what Google issues instead. I have seen this happen in a browser also, and the error pops up on the screen.
Also, in this case, you are using the geocode to get the locations and then plug them into the routine. Google Maps should be able to accept the addresses themselves and do the translation. It does this on the Static Maps. The problem with the static maps is there is no control to enlarge or shrink the view, nor can you move the map around.
Tim
Re: Plotting locations on Google Maps
Posted: Thu Mar 09, 2017 5:12 pm
by Silvio.Falconi
here your first and last code not run
Re: Plotting locations on Google Maps
Posted: Thu Mar 09, 2017 6:51 pm
by TimStone
After a lot of testing, I can create the MapFile ( but geolocation translation is very slow ), but it will not display.
Here is the mapfile that is created. Perhaps you can see an error.
Code: Select all
<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">
var locations = [
['25181 Derby Circle',33.5962614,-117.6977416],
['26691 Cortina Dr',33.592491,-117.663996],
['22482 Alma Aldea 308',33.6352467,-117.5928169],
['23242 La Mar Apt A',33.6243645,-117.6726187],
['25675 Taladro Circle B',33.6200999,-117.682796],
['5505-A Paseo del Lago W',33.6131753,-117.7422594],
['29092 Bouquet Canyon Rd',33.6916688,-117.6233598],
['24341 Fordview St',33.609178,-117.696739],
['5544-A Rayo Del Sol',33.6042954,-117.7470005],
['24272 Augustin St',33.609494,-117.681049],
['24631 Spadra Ln',33.605176,-117.662258]
];
var map = new google.maps.Map(document.getElementBZyId('map'), {
zoom 0,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var bounds = new google.maps.LatLngBound();
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.pen(map, marker);
}
))(marker, i));
// Automatically center the map fitting all markers on the screen
map.fitBounds(bounds);
}
</script>
</body>
</html>
Re: Plotting locations on Google Maps
Posted: Thu Mar 09, 2017 7:02 pm
by cnavarro
Silvio.Falconi wrote:here your first and last code not run
For me, first and last code of Anserkk run OK
Re: Plotting locations on Google Maps
Posted: Thu Mar 09, 2017 8:27 pm
by Ruth
Very nice that you also plot "Otto Atzwanger"´s location. Please don´t forget that in July (03-05 July 2017) this place will be the host of the 1st
[xHarbour] INTERNATIONAL CONFERENCE ... hope you all take part. Here is the link to more details. Kind regards and sorry that I place this info a little bit out of topic
Kind regards from Sillian Ruth
http://www.bergland.info/xharbour-2017- ... -20170705/
Re: Plotting locations on Google Maps
Posted: Thu Mar 09, 2017 11:11 pm
by TimStone
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.
I have created a utility as a subset of what was provided above. All works fine except when Google cannot match the location, and at that point it doesn't create an error, but there is no value in the array ( or actually, there is not an array, so then FW errors.
Here is an extract of the code. nLEN is a variable to hold the value returned from the decode. If it is 0, then it should block the next steps ... but apparently it returns a value other than 0 in this process.
Code: Select all
IF !lNetError
cResponse := oHttp:ResponseBody
ELSE
// Search Error. Could not find the details on Google Maps.
LOOP
ENDIF
nLen := hb_jsonDecode(cResponse,@hJson)
IF nLen == 0
MsgInfo("No value returned")
ELSE
nLatitude := hJson["results"][1]["geometry"]["location"]["lat"]
nLongitude := hJson["results"][1]["geometry"]["location"]["lng"]
oMapClients2:clcus4 := TRIM(STR(nLatitude)) + " | " + TRIM(STR(nLongitude) )
oMapClients2:save( )
ENDIF
Unfortunately the database will have some bad addresses. For example, a mobile home located in a park, has an address 123 Main Street Sp 41, Toledo OH. The SP41 ( space 41 ) makes Google not find the address. Since this client ( like most ) has over 30 years of address data, there will be mistakes and thousands of records to be corrected.
Thoughts on trapping hjson values that do not have an array would be appreciated.