Python 写的 Google Map

发布时间:2019-09-07 08:03:53编辑:auto阅读(1594)

    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(2044)
    print " ".join(gmap.GetURL(40.703610-73.931630))#这是New York的某个地方
    print " ".join(gmap.DownloadImg())
    print gmap.Merge()



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

关键字