Python 写的 Google Map 地图下载工具

GoogleMap的切片地址改变了,以下内容已成历史:)


 

我们最近的遥感实习要做野外调绘,没想到老师给的图竟然比 Google Map 上的图还要旧,想想干脆就把 Google Map 上的图下载下来参考一下。

主要代码是这里面的:http://intepid.com/stuff/gmkh/,它是JS写的,我改成 Python,并增加大图拼接的功能。

Python 里面有两个数学库,一个是叫 cmath 另一个是 math。cmath 里面的东西好像比 math 的少,比如 log() 就只有 math 库里面才有。JS 代码转为 Python 基本上没有难度,就是有些比如 ? : 的运算符不同,还有一些格式上有问题而已。

一开始本来想用 urllib 来下载图片就行了,但是它没有像 httplib 那样的可以知道返回的状态(比如是 200 还是 404)。在某些放大级别下因为找不到图片是会返回 404 的,所以 httplib 在这里还是比较有用的。httplib.HTTPConnection()的参数里面的字符串是不需要有"http://"的,一开始我写成了httplib.HTTPConnection("http://kh2.google.com")那样,调试了半天才知道是这个错误。

因为下载下来的是图片数据,不是普通的文本,所以写入文件时的 open() 函数要用 "wb" 标志。要不然写入的时候程序会把 0x0A 都变为 0x0D 0x0A(回车换行符),这样图片就显示不对了。

# -*- coding:UTF-8 -*-
import  Image
import  httplib
from  math  import   *


class  MapImage():
    
""" 将经纬度坐标转换为 Google Map 的 URL,并且可以把图片下载下来,合成一幅大图。
    下载后的图片依次命名为 1.jpg 2.jpg ...,最后合并的大图命名为 map.jpg
    合并成大图的话需要 PIL 库。
    
"""

    
def   __init__ (self, Zoom  =   10 , nX  =   3 , nY  =   3 ):
        
""" nX 和 nY 的设置就会由3x3个图生成大图。
        Zoom 是放大级别(1 - 20),某些地区的最大级别不到 20 或更小。
        
"""
        self.w 
=  0
        self.h 
=  0
        self.nx 
=  nX
        self.ny 
=  nY
        self.zoom 
=  Zoom
        self.outputImg 
=   " map.jpg "
        self.imgFiles 
=  []

    
def  SetTiles(self, nX, nY):
        self.nx 
=  nX
        self.ny 
=  nY

    
def  SetZoom(self, Zoom):
        self.zoom 
=  Zoom
    
    
def  GetAddress(self, lon, lat):
        
" 转换为 Mercator 投影 "
        
        PI 
=   3.1415926535897
        digits 
=   20
        x 
=  ( 180.0   +  lon)  /   360.0

        y 
=   - lat  *  PI  /   180.0
        y 
=   0.5   *  log( ( 1   +  sin(y))  /  ( 1   -  sin(y)) )
        y 
*=   1.0   /  ( 2   *  PI)
        y 
+=   0.5

        quad 
=   " t "
        lookup 
=   " qrts "

        
while  digits  >  0:
            x 
-=  floor(x)
            y 
-=  floor(y)
            quad 
=  quad  +  lookup[(x  >=   0.5   and   1   or  0)  +  (y  >=   0.5   and   2   or  0)]
            x 
*=   2
            y 
*=   2
            digits 
-=   1
        
        
return  quad


    
def  GetNextTileX(self, addr, forward):
        
" 获得下一个横图块 "
        
        
if  addr  ==   '' :
            
return  addr
            
        parent 
=  addr[:len(addr)  -   1 ]
        last 
=  addr[len(addr)  -   1 ]
        
        
if  last  ==   ' q ' :
            last 
=   ' r '
            
if  ( not  forward):
                    parent 
=  self.GetNextTileX(parent, forward)
        
elif  last  ==   ' r ' :
            last 
=   ' q '
            
if  (forward):
                    parent 
=  self.GetNextTileX(parent, forward)
        
elif  last  ==   ' s ' :
            last 
=   ' t '
            
if  (forward):
                    parent 
=  self.GetNextTileX(parent, forward)
        
elif  last  ==   ' t ' :
            last 
=   ' s '
            
if  ( not  forward):
                    parent 
=  self.GetNextTileX(parent, forward)
                
        
return  parent  +  last


    
def  GetNextTileY(self, addr, forward):
        
" 获得下一个纵图块 "
        
        
if  addr  ==   '' :
            
return  addr
            
        parent 
=  addr[:len(addr)  -   1 ]
        last 
=  addr[len(addr)  -   1 ]
        
        
if  last  ==   ' q ' :
            last 
=   ' t '
            
if  ( not  forward):
                    parent 
=  self.GetNextTileY(parent, forward)
        
elif  last  ==   ' r ' :
            last 
=   ' s '
            
if  ( not  forward):
                    parent 
=  self.GetNextTileY(parent, forward)
        
elif  last  ==   ' s ' :
            last 
=   ' r '
            
if  (forward):
                    parent 
=  self.GetNextTileY(parent, forward)
        
elif  last  ==   ' t ' :
            last 
=   ' q '
            
if  (forward):
                    parent 
=  self.GetNextTileY(parent, forward)
                
        
return  parent  +  last


    
def  GetURL(self, lat, lon):
        
""" 转换经纬度为 URL。
        输入经度、纬度
"""
        
        address 
=  []
        addr 
=  self.GetAddress(lon, lat)
        cursor 
=  addr[:self.zoom]
        cursor 
=  self.GetNextTileX(cursor,0)
        cursor 
=  self.GetNextTileY(cursor,0)
        
        
for  x  in  range(0, self.nx):
            c2 
=  cursor
            cursor 
=  self.GetNextTileX(cursor, 1 )
            
for  y  in  range(0, self.ny):
                address.append(
" /kh?v=3&t= "   +  c2)
                c2 
=  self.GetNextTileY(c2, 1 )
        
        self.imgList 
=  address
        
return  tuple(address)


    
def  DownloadImg(self):
        
" 下载列表中的图片 "
        
        files 
=  []
        
for  imgurl  in  self.imgList:
            con1  =  httplib.HTTPConnection( " kh2.google.com " )
            con1.request(
" GET " , imgurl)
            r1 
=  con1.getresponse()
            
try :
                
if  r1.status  ==   200 :
                    data 
=  r1.read()

                    files.append(
" %s.jpg "   %  (self.imgList.index(imgurl)))
                    f 
=  open( " %s.jpg "   %  (self.imgList.index(imgurl)), " wb " )
                    f.write(data)
                    f.close()
                    
print   " %s.jpg OK... "   %  (self.imgList.index(imgurl))
                
elif  r1.status  ==   404 :
                    
print   " %s.jpg no found "   %  (self.imgList.index(imgurl))
                
else :
                    
print   " %s.jpg unkown error "   %  (self.imgList.index(imgurl))
                
            
except :
                
print   " img: %s download error "   %  (self.imgList.index(imgurl))

        self.imgFiles 
=  tuple(files)
        
return  self.imgFiles
                

    
def  Merge(self):
        
" 合并图片 "

        self.w 
=  self.nx  *   256
        self.h 
=  self.ny  *   256

        img 
=  Image.new( " RGB " , (self.w, self.h))
        stepX 
=  0
        stepY 
=  0

        
for  i  in  self.imgFiles:
            im 
=  Image.open(i)
            img.paste(im, (0 
+  stepX, 0  +  stepY,  256   +  stepX,  256   +  stepY))
            stepY 
+=   256
            
if  stepY  >=  self.h:
                stepX 
+=   256
                stepY 
=  0
        img.save(self.outputImg)
        img.show()
        
return  self.outputImg



gmap 
=  MapImage( 20 4 4 )
print   " " .join(gmap.GetURL( 40.703610 - 73.931630 )) # 这是New York的某个地方
print   " " .join(gmap.DownloadImg())
print  gmap.Merge()



下面是下载拼接后的图,由4x4个小图拼接成。

Python 写的 Google Map 地图下载工具_第1张图片

你可能感兴趣的:(C/C++,和,Python)