Does it exist any python code snippet which shows how to download map tiles from googlemaps, virtualearth, yahoo or any other map provider?
I can only find perl scripts, but I don't understand perl!
Does it exist any python code snippet which shows how to download map tiles from googlemaps, virtualearth, yahoo or any other map provider?
I can only find perl scripts, but I don't understand perl!
Hi cassioli,
Try this example mobymaps.py (from book Mobile Python: Rapid Prototyping of Applications on the Mobile Platform)
http://www.mobilenin.com/mobilepytho...87-mopymaps.py
enjoy
eMO
thank you very much, that's just what I was looking for!
Try this. It's not the most sophisticated way, but it works with Google Maps.
Instantiate a GoogleZoom object, get x,y with lon_lat_to_pixel and get the URL with get_tile_url.Code:from math import pi, sin, cos, log, exp, atan, floor # Constants used for degree to radian conversion, and vice-versa. DTOR = pi / 180. RTOD = 180. / pi TILE_SIZE = 256 class GoogleZoom(object): def __init__(self, num_zoom=18, tilesize=TILE_SIZE): # Google's tilesize is 256x256, square tiles are assumed. self.tilesize = tilesize # Initializing arrays to hold the parameters for each # one of the zoom levels. self.degpp = [] # Degrees per pixel self.radpp = [] # Radians per pixel self.npix = [] # 1/2 the number of pixels for a tile at the given zoom level # Incrementing through the zoom levels and populating the # parameter arrays. z = tilesize # The number of pixels per zoom level. for i in xrange(num_zoom): # Getting the degrees and radians per pixel, and the 1/2 the number of # for every zoom level. self.degpp.append(z / 360.) # degrees per pixel self.radpp.append(z / (2 * pi)) # radians per pixl self.npix.append(z / 2) # number of pixels to center of tile # Multiplying `z` by 2 for the next iteration. z *= 2 def lonlat_to_pixel(self, lat, lon, zoom): # Calculating the pixel x coordinate by multiplying the longitude # value with with the number of degrees/pixel at the given # zoom level. px_x = round(self.npix[zoom] + (lon * self.degpp[zoom])) # Creating the factor, and ensuring that 1 or -1 is not passed in as the # base to the logarithm. Here's why: # if fac = -1, we'll get log(0) which is undefined; # if fac = 1, our logarithm base will be divided by 0, also undefined. fac = min(max(sin(DTOR * lat), -0.9999), 0.9999) # Calculating the pixel y coordinate. px_y = round(self.npix[zoom] + (0.5 * log((1 + fac)/(1 - fac)) * (-1.0 * self.radpp[zoom]))) # Returning the pixel x, y to the caller of the function. return (px_x, px_y) def get_tile_url(self, px_x, px_y, zoom): # Determine Google tile URL tile_x = floor(px_x / TILE_SIZE) tile_y = floor(px_y / TILE_SIZE) return "http://mt.google.com/mt?x=%d&y=%d&zoom=%d" % (tile_x, tile_y, 17-zoom)
NOTE: You are violating the Google T&C
Regards
You should follow the discussions in the MGMaps-Forum concerning this. MGMaps has been "asked" kindly by Google to not continue using their API the way they did before. MGMaps has dropped support for Google Maps and continues with Microsoft and Yahoo only.
Indeed, the T&C just talk about and allow the usage from a web based entity.
Have a look and decide by yourself. I doubt that Google will strike against everybody everywhere. I just wanted to note, that there is a potential pitfall.
Regards
Hi,
is it possible to display an exact geo position on the downloaded map to show e.g. my position?
If you are using the code above you'll always get just 1 tile for a geo code. You'll find your point there, but it's generally not centered. From the latSo you have
a) to do some math in order to find out, what tiles around you have to draw aditionally in order to build up a bitmap (of variable size) and cut an area out so that your coordinate is centered. The floor part of x,y is always the x,y coordinate to be queried at google. The ceil part multiplied with 256 is always the position of your geocode within the tile
b) To draw some flag or circle is up to you. You have a bitmap, draw on it.
Regards
Is it possible to give a geo coordinate to the map server instead of an adress?
Thx
It seems to be possible. You should just open up your browser, move to Google Maps, and move to a location. Have Wireshark running in the background and see what happens.
I haven't investigated in this API, but found some other probably usefull hints. Written down at
http://freenet-homepage.de/neilyoung/index.html
HTH
Thx neil.young,
I tried and it works with geo coordinates.
example:
http://maps.google.com/maps?f=q&hl=d...432,+10.533072
No, I doubt that. You will have difficulities if using this URL outside your browser, e.g. in a python script. I bet you can't deal with the stuff returned by google, because you know nothing about the inner structure. This is up to the diverse GM JavaScript files, making the map visible to you in a browser.
The hardcore way is to get the tiles by x,y and build the map by yourself.
Regards
Hi James,
as I said above:
BTW: Zoom level 0 is rather simple: There is just one tile available for that level, hence the tile coords are x=0, y=0. I think, you mean the largest zoom level 17, so the 3 liner is as follows:Code:Instantiate a GoogleZoom object, get x,y with lon_lat_to_pixel and get the URL with get_tile_url.
gz = GoogleZoom()
(x, y) = gz.lonlat_to_pixel(-36.856257, 174.765058, 17)
print gz.get_tile_url(x, y, 17)
After that open your browser with the URL printed. And please let me know, if the result doesn't match your expectations.
EDIT: I'm currently reviewing your post and just seeing your real question (sorry, it's early in the morning here over...) I'm in a rush, but return to you ASAP.
Regards
So James,
your post gave me the opportunity to make some reworks and complete my series of articles at http://maps.alphadex.de (topic "Get a map") with a Python sample. As already stated above, the algorithm wasn't mine and wasn't sophisticated enough , because it does not explain anything. But the results compared with my algorithm are of course the same. Please visit my site in order to get a detailed explanation of all this.
So I rewrote a C# sample in Python, which now answers your initial question. And to be more specific: The sample coordinate you provided is somewhere in a triangle formed by Airedale St. and Symonds St.
Here is a "more sophisticated" approach, because it makes the Mercator roots more transparent:
Here is how to use it:Code:from math import pi, sin, log # Python sample. How to ask Google for map tiles? # This script is published under GPL (included below) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # Constants used for degree to radian conversion, and vice-versa. DTOR = pi / 180. RTOD = 180. / pi TILE_SIZE = 256 class GoogleZoom(object): def locationCoord(self, lat, lon, zoom): # Per se earth coordinates are -90° <= lat <= +90° and -180° <= lon <= 180° # Mercator is NOT applicable for abs(lat) > 85.0511287798066 degrees if (abs(lat) > 85.0511287798066): raise "Invalid latitude" # latitude (deg) -> latitude (rad) sin_phi = sin(float(lat) * DTOR) # Use Mercator to calculate x and normalize this to -1 <= x <= +1 by division by 180. # The center of the map is lambda_0 = 0, hence x = lat. norm_x = lon / 180. # Use Mercator to calculate y and normalize this to -1 <= y <= +1 by division by PI. # According to Mercator y is defined in the range of -PI <= y <= PI only norm_y = (0.5 * log((1 + sin_phi) / (1 - sin_phi))) / pi # Apply the normalized point coordinations to any application (here the coordinates of # a 256*256 image holding that point in a thought grid with origin 0,0 top/left) col = pow(2, zoom) * ((norm_x + 1) / 2); row = pow(2, zoom) * ((1 - norm_y) / 2); return (col, row, zoom);
# Main
gz = GoogleZoom()
col, row, zoom = gz.locationCoord(-36.856257, 174.765058, 17)
print "Google Tile URL: http://mt.google.com/mt?x=%d&y=%d&zoom=%d" % (col, row, 17-zoom)
print "X coordinate within the tile =", (col - long(col)) * TILE_SIZE
print "Y coordinate within the tile =", (row - long(row)) * 256
Enjoy and let me know