Page 1 of 2
Use Google Maps in PureBasic (Easy Procedure)
Posted: Sun May 22, 2011 4:10 am
by JustinJack
Code: Select all
InitNetwork()
UsePNGImageDecoder()
Enumeration
#ROADMAP
#SATELLITE
#TERRAIN
#HYBRID
EndEnumeration
Procedure.l getMapImage( MapAddress.s, Zoom=15, MapType = #ROADMAP, Markers.s = "" )
RetVal = 0
If Markers <> ""
myRequestTwo.s = "/maps/api/staticmap?center="+ URLEncoder(MapAddress) + "&" + URLEncoder(Markers) + "&zoom=" + Str(Zoom) + "&size=500x500"
Else
myRequestTwo.s = "/maps/api/staticmap?center="+ URLEncoder(MapAddress) + "&zoom=" + Str(Zoom) + "&size=500x500"
EndIf
Select MapType
Case #SATELLITE
myRequestTwo.s + "&maptype=satellite"
Case #TERRAIN
myRequestTwo.s + "&maptype=terrain"
Case #HYBRID
myRequestTwo.s + "&maptype=hybrid"
Default
myRequestTwo.s + "&maptype=roadmap"
EndSelect
myRequestTwo.s + "&sensor=false"
myConnection = OpenNetworkConnection("maps.google.com", 80, #PB_Network_TCP)
If myConnection = 0
ProcedureReturn 0
EndIf
myRequest.s = "GET "+ myRequestTwo + " HTTP/1.0" + #CRLF$
myRequest.s + "Content-Type: application/x-www-form-urlencoded; charset=iso-8859-1" + #CRLF$
myRequest.s + "Host: maps.google.com" + #CRLF$ + #CRLF$
*buffer = AllocateMemory(65535)
*bufferTwo = AllocateMemory(65535)
bfTwoPtr = 0
mSize = 65535
SendNetworkString(myConnection, myRequest)
dwBytes = 1
While dwBytes > 0
dwBytes = ReceiveNetworkData(myConnection, *buffer, 65535)
If dwBytes > 0
If (*bufferTwo + dwBytes) >= mSize
mSize + 65535
*bufferTwo = ReAllocateMemory(*bufferTwo, mSize)
EndIf
CopyMemory(*buffer, (*bufferTwo+bfTwoPtr), dwBytes)
bfTwoPtr + dwBytes
EndIf
Wend
CloseNetworkConnection(myConnection)
FreeMemory(*buffer)
dblCrlf.s = #CRLF$+#CRLF$
found = 0
dataLength = 0
For k = 0 To bfTwoPtr
If k > bfTwoPtr
Break
EndIf
If PeekS(*bufferTwo+k, 4) = dblCrlf
found = k
headerInfo.s = PeekS(*bufferTwo, k)
dataBeginSpot = (k + 4)
*dataBegin = (*bufferTwo + dataBeginSpot)
dataLength = (bfTwoPtr - dataBeginSpot)
Break
EndIf
Next
If ((dataLength > 0) And (found > 0))
RetVal = CatchImage(#PB_Any, *dataBegin, dataLength)
EndIf
FreeMemory(*bufferTwo)
ProcedureReturn RetVal
EndProcedure
; MapAddress.s Can be a physical address or a set of Lat / Lon Coordinates like : "32.15648, -97.54235"
; Zoom: Googles Map Zoom Level from: 1 Less Zoom to I dunno...20? More Zoom....
; MapTypes:
;#ROADMAP
;#SATELLITE
;#TERRAIN
;#HYBRID
; Markers. Google draws your map with markers....Check Out Markers at: http://code.google.com/apis/maps/documentation/staticmaps/#MarkerLocations
myImage = getMapImage("Dallas, TX", 15, #HYBRID, "markers=color:blue|label:A|Dallas, TX&markers=color:red|label:B|5706 Lindell Ave, 75206")
If IsImage(myImage)
OpenWindow(0, 0, 0, 500, 500, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ImageGadget(1, 0, 0, 500, 500, ImageID(myImage))
Repeat : Until WaitWindowEvent() = 16
FreeImage(myImage)
Else
MessageBox_(0, "Didn't get a map image!", "Hmm, Strange...", #MB_ICONERROR|#MB_OK)
EndIf
This is really cool. I play with googles API's all the time through PureBasic!
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Sun May 22, 2011 4:15 am
by MachineCode
Awesome! Just awesome!

Thanks for sharing! How can we make it show satellite images, though?
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Sun May 22, 2011 4:33 am
by JustinJack
Good Thinking! There you go, I changed it to be able to switch up map types.
I actually spent a lot of time figuring out how to decipher the lat / lon of the bounding rect of the map returned so I could, on some of my apps, draw my own markers and perform hit test to pop up data on the google maps, (all of which is do-able with java script in a web app) but it's cool to have that in a desktop app. I wish they'd give you the view lat / lon of the map returned in the HTTP Response. I did it by placing markers on maps at lat / lons I knew, then setting the map center to a specific lat / lon, and checking it with different coordinates at different zoom levels. But man that stinks!
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Sun May 22, 2011 7:00 am
by Michael Vogel
Fine stuff
Some of these older snippets for cropping a map to exact coordinates and to get geo coordinates from named spaces
here may help using Google Maps, too.
Because the thread mentioned above haven't been updated for a while, the included links to the compiled programs may not work -- here's the correct place for checking my
GPS tools written in PureBasic, of course
Michael
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Sun May 22, 2011 5:19 pm
by JustinJack
Very cool. Your forerunner program is very nice! I was messing around with yahoo's maps also, but that hasn't solved my issue either. I can get the maps and divide the lat/lon per pixel and spit out in an edit box the lat / lons as I drag my mouse around no prob, I would just love to be able to get my own maps and accurately have the geo-locations of the corners of the map or at least opposite / diagonal corners... In google I played with their zoom levels and figured out the coords DOUBLE or are cut in half, depending on how you look at it, with each zoom level, so all you need is to manipulate the map to be positioned how you want the first time, then calculate each zoom levels change..
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Mon May 23, 2011 2:32 am
by IdeasVacuum
Could be very handy
On compile, I get an error @ line 75
Code: Select all
RetVal = CatchImage(#PB_Any, *dataBegin, dataLength)
[ERROR] The specified pointer is null.
It's because myConnection fails but the code is allowed to continue without a connection. Fail-safe:
Code: Select all
InitNetwork()
UsePNGImageDecoder()
Enumeration
#ROADMAP
#SATELLITE
#TERRAIN
#HYBRID
EndEnumeration
Procedure.l getMapImage( MapAddress.s, Zoom=15, MapType = #ROADMAP, Markers.s = "")
;----------------------------------------------------------------------------------
RetVal = 0
If Markers <> ""
myRequestTwo.s = "/maps/api/staticmap?center="+ URLEncoder(MapAddress) + "&" + URLEncoder(Markers) + "&zoom=" + Str(Zoom) + "&size=500x500"
Else
myRequestTwo.s = "/maps/api/staticmap?center="+ URLEncoder(MapAddress) + "&zoom=" + Str(Zoom) + "&size=500x500"
EndIf
Select MapType
Case #SATELLITE
myRequestTwo.s + "&maptype=satellite"
Case #TERRAIN
myRequestTwo.s + "&maptype=terrain"
Case #HYBRID
myRequestTwo.s + "&maptype=hybrid"
Default
myRequestTwo.s + "&maptype=roadmap"
EndSelect
myRequestTwo.s + "&sensor=false"
myConnection = OpenNetworkConnection("maps.google.com", 80, #PB_Network_TCP)
If myConnection > 0
myRequest.s = "GET "+ myRequestTwo + " HTTP/1.0" + #CRLF$
myRequest.s + "Content-Type: application/x-www-form-urlencoded; charset=iso-8859-1" + #CRLF$
myRequest.s + "Host: maps.google.com" + #CRLF$ + #CRLF$
*buffer = AllocateMemory(65535)
*bufferTwo = AllocateMemory(65535)
bfTwoPtr = 0
mSize = 65535
SendNetworkString(myConnection, myRequest)
dwBytes = 1
While dwBytes > 0
dwBytes = ReceiveNetworkData(myConnection, *buffer, 65535)
If dwBytes > 0
If (*bufferTwo + dwBytes) >= mSize
mSize + 65535
*bufferTwo = ReAllocateMemory(*bufferTwo, mSize)
EndIf
CopyMemory(*buffer, (*bufferTwo+bfTwoPtr), dwBytes)
bfTwoPtr + dwBytes
EndIf
Wend
CloseNetworkConnection(myConnection)
FreeMemory(*buffer)
dblCrlf.s = #CRLF$+#CRLF$
found = 0
For k = 0 To bfTwoPtr
If k > bfTwoPtr
Break
EndIf
If PeekS(*bufferTwo+k, 4) = dblCrlf
found = k
headerInfo.s = PeekS(*bufferTwo, k)
dataBeginSpot = (k + 4)
*dataBegin = (*bufferTwo + dataBeginSpot)
dataLength = (bfTwoPtr - dataBeginSpot)
Break
EndIf
Next
RetVal = CatchImage(#PB_Any, *dataBegin, dataLength)
FreeMemory(*bufferTwo)
Else
RetVal = -1
EndIf
ProcedureReturn RetVal
EndProcedure
; MapAddress.s Can be a physical address or a set of Lat / Lon Coordinates like : "32.15648, -97.54235"
; Zoom: Googles Map Zoom Level from: 1 Less Zoom to I dunno...20? More Zoom....
; MapTypes:
;#ROADMAP
;#SATELLITE
;#TERRAIN
;#HYBRID
; Markers. Google draws your map with markers....Check Out Markers at: http://code.google.com/apis/maps/documentation/staticmaps/#MarkerLocations
myImage = getMapImage("Dallas, TX", 15, #HYBRID, "markers=color:blue|label:A|Dallas, TX&markers=color:red|label:B|5706 Lindell Ave, 75206")
If IsImage(myImage)
OpenWindow(0, 0, 0, 500, 500, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ImageGadget(1, 0, 0, 500, 500, ImageID(myImage))
Repeat : Until WaitWindowEvent() = 16
FreeImage(myImage)
Else
MessageBox_(0, "Didn't get a map image!", "Hmm, Strange...", #MB_ICONERROR|#MB_OK)
EndIf
End
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Mon May 23, 2011 7:29 am
by JustinJack
Hmm...thats strange thats exactly why i have the bit in there about:
Code: Select all
if myConnection =0
ProcedureReturn 0
Endif
I tested it and when i didnt get a connection or it failed...myConnection equals 0
I think more likely what caused your error is that you DID get a connection... but i didnt spend a lot of time error_proofing the processing of the http response. I just assumed google would send a map image because ut DOES for me since i use geo coords...all we need to do it process the Content-Length: http header, then look for after the dblcrlf, allocate mem for that size,or just check that that ptr is a valid address in our block b4 trying to catch the image...any wayz glad u found that little tid-bit.
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Mon May 23, 2011 8:32 am
by JustinJack
There, I fixed the original code [post]. I just made it to where if it didn't find the end of the HTTP header i.e. #CRLF$+CRLF$, found = 0, so we don't try to access the memory, and if the calculated dataLength is zero we dont either. That way even if HTTP/1.1 is returned and we don't have a Content-Length, (like yahoo maps does) we wont try to read from a null pointer.
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Mon May 23, 2011 4:52 pm
by RichAlgeni
I found a site that is indispensable for me, I've used it to write real-time Ambulance tracking on Google maps.
http://econym.org.uk/gmap/
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Sun Jun 12, 2011 6:55 pm
by jesperbrannmark
I did a followup on this code to use with Google Charts Static Image.
But I posted it in Mac OS Forum instead, because.... mac rules...
http://www.purebasic.fr/english/viewtop ... 05#p354586
Jesper
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Mon Jul 04, 2011 5:04 pm
by ultralazor
I was randomly browsing this section and seen this thread, and sometimes use maps.
Things to 'proper' this:
- HTTP 1.1 and chunking(simple header value gives chunk size and last chunk notifier)
- gzip handling on data(drastically faster network exchange(deflate content with algo or lib))
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Tue Jul 12, 2011 9:41 pm
by zefiro_flashparty
wow!
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Fri Jul 22, 2011 2:44 pm
by jamirokwai
Hi,
nice finding!
Doesn't work in UNICODE-mode, though...
I changed your code using the URLEncoderX()-function to this...
It's just a fast hack, and uses the ReceiveHTTPFile, but it works in UNICODE-mode

It also adds optional Width and Heigth of the resulting image, maximum 640x640 px
Code: Select all
; add the URL-functions from here: http://forums.purebasic.com/german/viewtopic.php?f=8&t=22286 - made by helpy
; this code is based on http://www.purebasic.fr/english/viewtopic.php?f=12&t=46428#p353302 - made by JustinJack
InitNetwork()
UsePNGImageDecoder()
Enumeration
#ROADMAP
#SATELLITE
#TERRAIN
#HYBRID
EndEnumeration
Procedure.l getMapImage( MapAddress.s, Zoom=15, Width = 500, Height = 500, MapType = #ROADMAP, Markers.s = "" )
RetVal = 0
myRequestTwo.s = "http://maps.google.com"
If Markers <> ""
myRequestTwo + "/maps/api/staticmap?center="+ URLEncoderX(MapAddress) + "&" + URLEncoderX(Markers) + "&zoom=" + Str(Zoom) + "&size=" + Str(Width) + "x" + Str(Height)
Else
myRequestTwo + "/maps/api/staticmap?center="+ URLEncoderX(MapAddress) + "&zoom=" + Str(Zoom) + "&size=" + Str(Width) + "x" + Str(Height)
EndIf
Select MapType
Case #SATELLITE : myRequestTwo.s + "&maptype=satellite"
Case #TERRAIN : myRequestTwo.s + "&maptype=terrain"
Case #HYBRID : myRequestTwo.s + "&maptype=hybrid"
Default : myRequestTwo.s + "&maptype=roadmap"
EndSelect
myRequestTwo.s + "&sensor=false"
tempFile.s = GetTemporaryDirectory() + "map.png"
ReceiveHTTPFile(myRequestTwo, tempFile)
RetVal = LoadImage(#PB_Any, tempFile)
DeleteFile(tempFile)
ProcedureReturn RetVal
EndProcedure
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Fri Jul 22, 2011 6:33 pm
by Andre
I'm sure this is a great piece of code, even if I couldn't test it now...
But anyone looked at the Google "terms of use"?
Maybe it's only allowed to use such stuff for private use, but not for (business) software you want to release to the public... or you have to register and pay royalty fees to Google, or......?
Re: Use Google Maps in PureBasic (Easy Procedure)
Posted: Fri Jul 22, 2011 9:08 pm
by jamirokwai
Andre wrote:I'm sure this is a great piece of code, even if I couldn't test it now...
But anyone looked at the Google "terms of use"?
Maybe it's only allowed to use such stuff for private use, but not for (business) software you want to release to the public... or you have to register and pay royalty fees to Google, or......?
Hi Andre,
thanks for the comment on this. With Google API, you can do both, as it seems

The terms of use say, that if your service is free of charge, you don't need to pay a fee.
If you like to make money with a software or service using the Maps API, you have to pay $10.000 per year...
See
http://code.google.com/intl/en-US/apis/maps/index.html
The Maps API is a free service, available for any web site that is free to consumers. Please see the terms of service for more information.
Businesses that charge fees for access, track assets or build internal applications must use Google Maps API Premier, which provides enhanced features, technical support and a service-level agreement.
I assume for free software, you may use it for free. You have to buy a license, if you earn 1 Cent of more with your commercial software...