Virtual Earth Maps on the Go
For a map client, it is necessary to get the maps for a given location. Most GPS navigation systems store the maps of the entire nation at all zoom levels in their memory. On handsets, this might not be the best strategy. We know that Virtual Earth server has all the maps required for a map client, just an HTTP request away. All we need to know is how to get them.
Background
In the last log, we checked out some of the geocoding services provided by virtual earth and used them in our Python on S60 programs. In this one, we will see how to download the maps of the location of your choice. Our primary goal here is to find a mapping function from latitude, longitude, zoom to a URL to download the map. Once we have a mapping function, Python will take care of all the basic functionality to give us a fully functional map client without having to store large amount of data.
How Virtual Earth Stores Maps
The Virtual Earth map system, like many map systems (e.g. Google Maps) uses Mercator projection to fit Earth's curved suface onto a flat sheet (screen in present case). The Mercator projection as described in the Wikipedia article is a mathematical scheme that converts latitude into an y value and longitude into x. These x and y values are then used very easily to store and retrieve maps from the server. When I started putting together a map client for Virtual Earth, I thought that once this mapping function is implemented, half my job will be done. But that wasn't to be as Virtual Earth server stores quad-tree encoded x, y values (a la Google Maps satellite images server).
Mapping Function
The mapping function to map the latitude, longitude, zoom to map URL is as follows:
url = f(latitude, longitude, zoom)
import math
earthRadius = 6378137
earthCircum = earthRadius * 2.0 * math.pi
earthHalfCirc = earthCircum / 2.0
def LongitudeToXAtZoom(lon, zl):
arc = earthCircum / ((1 << zl) * 256)
metersX = earthRadius * DegToRad(lon)
return int(round((metersX + earthHalfCirc) / arc))
def LatitudeToYAtZoom(lat, zl):
arc = earthCircum / ((1 << zl) * 256)
sinLat = math.sin(DegToRad(lat))
metersY = earthRadius / 2 * math.log((1.0 + sinLat) / (1.0 - sinLat))
return int(round((earthHalfCirc - metersY) / arc))
def DegToRad(d):
return d * math.pi / 180.0
def RadToDeg(r):
return r * 180.0 / math.pi
def TileToQuadKey(tx, ty, zl):
quad = ''
for i in range(zl, 0, -1):
mask = 1 << (i - 1)
cell = 0
if (tx & mask) != 0:
cell = cell + 1
if (ty & mask) != 0:
cell = cell + 2
quad = quad + str(cell)
return quad
def GetTileSpecs(lat, lon, zoom):
tx = LongitudeToXAtZoom(lon, zoom) / 256
cx = LongitudeToXAtZoom(lon, zoom) % 256
ty = LatitudeToYAtZoom(lat, zoom) / 256
cy = LatitudeToYAtZoom(lat, zoom) % 256
server = ((tx & 1) + ((ty & 1) << 1)) % 4
q = TileToQuadKey(tx, ty, zoom)
filename = 'r%s.png' % q
url = 'http://r%d.ortho.tiles.virtualearth.net/tiles/%s?g=22' % (server, filename)
return (filename, url, cx, cy)
lon = -117.068092
lat = 32.9913528
zoom = 17
print GetTileSpecs(lat, lon, zoom)
This Python code snippet is another exmaple of how easily we can implement mapping client in Python. Adding Python for S60 wrapper around this to have a map client on the phone. I have done some ground work to get you started. Avaiable at:
Summary
Hopefully, this log will get you excited, not just about Python, but about mapping techniques as well. It is very interesting to learn how map service providers implement their services. I hope you can build upon the available code to add address search and direction finding using the routines in velocation.py. Happy mapping...
Background
In the last log, we checked out some of the geocoding services provided by virtual earth and used them in our Python on S60 programs. In this one, we will see how to download the maps of the location of your choice. Our primary goal here is to find a mapping function from latitude, longitude, zoom to a URL to download the map. Once we have a mapping function, Python will take care of all the basic functionality to give us a fully functional map client without having to store large amount of data.
How Virtual Earth Stores Maps
The Virtual Earth map system, like many map systems (e.g. Google Maps) uses Mercator projection to fit Earth's curved suface onto a flat sheet (screen in present case). The Mercator projection as described in the Wikipedia article is a mathematical scheme that converts latitude into an y value and longitude into x. These x and y values are then used very easily to store and retrieve maps from the server. When I started putting together a map client for Virtual Earth, I thought that once this mapping function is implemented, half my job will be done. But that wasn't to be as Virtual Earth server stores quad-tree encoded x, y values (a la Google Maps satellite images server).
Mapping Function
The mapping function to map the latitude, longitude, zoom to map URL is as follows:
url = f(latitude, longitude, zoom)
import math
earthRadius = 6378137
earthCircum = earthRadius * 2.0 * math.pi
earthHalfCirc = earthCircum / 2.0
def LongitudeToXAtZoom(lon, zl):
arc = earthCircum / ((1 << zl) * 256)
metersX = earthRadius * DegToRad(lon)
return int(round((metersX + earthHalfCirc) / arc))
def LatitudeToYAtZoom(lat, zl):
arc = earthCircum / ((1 << zl) * 256)
sinLat = math.sin(DegToRad(lat))
metersY = earthRadius / 2 * math.log((1.0 + sinLat) / (1.0 - sinLat))
return int(round((earthHalfCirc - metersY) / arc))
def DegToRad(d):
return d * math.pi / 180.0
def RadToDeg(r):
return r * 180.0 / math.pi
def TileToQuadKey(tx, ty, zl):
quad = ''
for i in range(zl, 0, -1):
mask = 1 << (i - 1)
cell = 0
if (tx & mask) != 0:
cell = cell + 1
if (ty & mask) != 0:
cell = cell + 2
quad = quad + str(cell)
return quad
def GetTileSpecs(lat, lon, zoom):
tx = LongitudeToXAtZoom(lon, zoom) / 256
cx = LongitudeToXAtZoom(lon, zoom) % 256
ty = LatitudeToYAtZoom(lat, zoom) / 256
cy = LatitudeToYAtZoom(lat, zoom) % 256
server = ((tx & 1) + ((ty & 1) << 1)) % 4
q = TileToQuadKey(tx, ty, zoom)
filename = 'r%s.png' % q
url = 'http://r%d.ortho.tiles.virtualearth.net/tiles/%s?g=22' % (server, filename)
return (filename, url, cx, cy)
lon = -117.068092
lat = 32.9913528
zoom = 17
print GetTileSpecs(lat, lon, zoom)
This Python code snippet is another exmaple of how easily we can implement mapping client in Python. Adding Python for S60 wrapper around this to have a map client on the phone. I have done some ground work to get you started. Avaiable at:
Summary
Hopefully, this log will get you excited, not just about Python, but about mapping techniques as well. It is very interesting to learn how map service providers implement their services. I hope you can build upon the available code to add address search and direction finding using the routines in velocation.py. Happy mapping...


1 Comments:
What are you returning?
--> return (filename, url, cx, cy)
What are values cx, and cy? The x and y points on the tile?
Post a Comment
Links to this post:
Create a Link
<< Home