tile_overview.py 9.4 KB
# coding=utf-8
#author:        4N
#createtime:    2021/12/20
#email:         nheweijun@sina.com

import math
import requests
import numpy
import cv2
from osgeo import gdal,osr
from osgeo.gdal import *


# Math functions taken from https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames #spellok
# TMS 经纬度转
def deg2num( lon_deg,lat_deg, zoom):
    lat_rad = math.radians(lat_deg)
    n = 2.0 ** zoom
    xtile = int((lon_deg + 180.0) / 360.0 * n)
    ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
    return (xtile, ytile)

def num2deg(xtile, ytile, zoom):
    n = 2.0 ** zoom
    lon_deg = xtile / n * 360.0 - 180.0
    lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
    lat_deg = math.degrees(lat_rad)
    return (lat_deg, lon_deg)

def tms_overview(extent,url_format):


    lev = 0
    r1 = 0
    r2 = 0
    c1 = 0
    c2 = 0

    while r1 - r2 < 2:
        lev += 1
        # 左下角所在行列号
        c1, r1 = deg2num( extent[0],extent[2], lev)
        # 右上角所在行列号
        c2, r2 = deg2num( extent[1],extent[3], lev)
        if lev > 20 :
            break

    print(lev)

    # 左下角瓦片的左上角坐标
    lat1, lon1 = num2deg(c1, r1, lev)
    # 左下角瓦片的右下角坐标
    lat2, lon2 = num2deg(c1 + 1, r1 + 1, lev)

    # 右上角瓦片的左上角坐标
    lat3, lon3 = num2deg(c2, r2, lev)
    # 右上角瓦片的右下角坐标
    lat4, lon4 = num2deg(c2 + 1, r2 + 1, lev)

    # 瓦片拼接底图
    dat = numpy.zeros(((r1 - r2 + 1) * 256, (c2 - c1 + 1) * 256, 3), dtype=int) + 255

    # x偏移量
    offx = (extent[0] - lon1) / ((lon4 - lon1) / ((c2 - c1 + 1) * 256))
    # x方向像素量
    xnum = (extent[1] - extent[0]) / ((lon4 - lon1) / ((c2 - c1 + 1) * 256))

    # y偏移量
    offy = (lat3 - extent[3]) / ((lat3 - lat2) / ((r1 - r2 + 1) * 256))
    # y方向像素量
    ynum = (extent[3] - extent[2]) / ((lat3 - lat2) / ((r1 - r2 + 1) * 256))

    # 拼接瓦片
    for r in range(r2, r1 + 1):
        for c in range(c1, c2 + 1):
            url = "{}/{}/{}/{}.png".format(url_format,lev, c, r)
            dataset: Dataset = gdal.Open(url, 0)
            for b in range(1, 4):
                band: Band = dataset.GetRasterBand(b)
                dat[(r - r2) * 256:(r - r2 + 1) * 256, (c - c1) * 256: (c - c1 + 1) * 256,
                2 - (b - 1)] = band.ReadAsArray(0, 0, 256, 256)

    #裁剪
    dat2 = dat[int(offy):int(offy + ynum), int(offx):int(offx + xnum), :]

    cv2.imwrite("over.jpg", dat2, [cv2.IMWRITE_JPEG_QUALITY, 30])

def get_polygon(parameter,level,row,col):
    level=int(level)
    row = int(row)
    col = int(col)
    detaxy = parameter.get(str(level)).get("resolution")* parameter.get("cols")

    lon1 = detaxy * col + int(parameter.get("x"))
    lat2 = -detaxy * row + int(parameter.get("y"))
    lon2 = detaxy + lon1
    lat1 = -detaxy + lat2

    return [lon1,lat1,lon2,lat2]

def get_rc(parameter,l,lon,lat):

    detaxy = parameter.get(str(l)).get("resolution")* parameter.get("cols")

    dd = lon - int(parameter.get("x"))
    c = math.floor((lon - int(parameter.get("x")))/detaxy)
    r = math.floor((int(parameter.get("y"))-lat)/detaxy)
    return int(r),int(c)

def wmts_overview(extent,url_format):

    # scheme = {"0": {"resolution": 1.4062500000059488, "scale": 590995186.12}, "1": {"resolution": 0.7031250000029744, "scale": 295497593.06}, "2": {"resolution": 0.3515625000014872, "scale": 147748796.53}, "3": {"resolution": 0.1757812500007436, "scale": 73874398.265}, "4": {"resolution": 0.0878906250003718, "scale": 36937199.1325}, "5": {"resolution": 0.0439453125001859, "scale": 18468599.56625}, "6": {"resolution": 0.02197265625009295, "scale": 9234299.783125}, "7": {"resolution": 0.010986328125046475, "scale": 4617149.8915625}, "8": {"resolution": 0.0054931640625232375, "scale": 2308574.94578125}, "9": {"resolution": 0.0027465820312616187, "scale": 1154287.472890625}, "10": {"resolution": 0.0013732910156308094, "scale": 577143.7364453125}, "11": {"resolution": 0.0006866455078154047, "scale": 288571.86822265625}, "12": {"resolution": 0.00034332275390770234, "scale": 144285.93411132813}, "13": {"resolution": 0.00017166137695385117, "scale": 72142.96705566406}, "14": {"resolution": 8.583068847692559e-05, "scale": 36071.48352783203}, "15": {"resolution": 4.291534423846279e-05, "scale": 18035.741763916016}, "16": {"resolution": 2.1457672119231396e-05, "scale": 9017.870881958008}, "17": {"resolution": 1.0728836059615698e-05, "scale": 4508.935440979004}, "18": {"resolution": 5.364418029807849e-06, "scale": 2254.467720489502}, "19": {"resolution": 2.6822090149039246e-06, "scale": 1127.233860244751}, "20": {"resolution": 1.3411045074519623e-06, "scale": 563.6169301223755}, "cols": 256, "rows": 256, "dpi": 96, "wkt": "", "x": -400, "y": 400}

    scheme = {"0": {"resolution": 156543.34701231902, "scale": 591658710.9},
              "1": {"resolution": 78271.67350615951, "scale":  295829355.45},
              "2": {"resolution": 39135.83675440268 , "scale": 147914677.73} ,
              "3": {"resolution": 19567.91837587842, "scale":   73957338.86},
              "4": {"resolution": 9783.95918793921, "scale":  36978669.43},
              "5": {"resolution": 4891.979593969605, "scale":  18489334.715},
              "6": {"resolution": 2445.9897969848025, "scale":   9244667.3575},
              "7": {"resolution": 1222.9948984924013 , "scale":  4622333.67875},
              "8": {"resolution": 611.4974492462006, "scale":  2311166.839375},
              "9": {"resolution": 305.7487246231003, "scale":  1155583.4196875},
              "10": {"resolution": 152.87436231155016, "scale":  577791.70984375},
              "11": {"resolution": 76.43718115577508, "scale":  288895.854921875},
              "12": {"resolution": 38.21859057788754, "scale":   144447.9274609375},
              "13": {"resolution": 0.00017166137695385117, "scale": 72142.96705566406},
              "14": {"resolution": 8.583068847692559e-05, "scale": 36071.48352783203},
              "15": {"resolution": 4.291534423846279e-05, "scale": 18035.741763916016},
              "16": {"resolution": 2.1457672119231396e-05, "scale": 9017.870881958008},
              "17": {"resolution": 1.0728836059615698e-05, "scale": 4508.935440979004},
              "18": {"resolution": 5.364418029807849e-06, "scale": 2254.467720489502},
              "19": {"resolution": 2.6822090149039246e-06, "scale": 1127.233860244751},
              "20": {"resolution": 1.3411045074519623e-06, "scale": 563.6169301223755},
              "cols": 256, "rows": 256, "dpi": 96, "wkt": "", "x":-4923200, "y":10002100}

    lev = 0
    r1 = 0
    r2 = 0
    c1 = 0
    c2 = 0
    while r1 - r2 <1:
        lev += 1

        # 左下角所在瓦片
        r1,c1 = get_rc(scheme,lev, extent[0],extent[2])
        # 右上角所在瓦片
        r2,c2 = get_rc(scheme,lev, extent[1],extent[3])
        if lev > 20 :
            break



    print(lev)
    # 左下角瓦片的范围
    [lon1, lat1, lon2, lat2] = get_polygon(scheme, lev, r1, c1)
    # 右上角角瓦片的范围
    [lon12, lat12, lon22, lat22] = get_polygon(scheme, lev, r2, c2)

    # 瓦片拼接底图
    dat = numpy.zeros(((r1 - r2 + 1) * 256, (c2 - c1 + 1) * 256, 3), dtype=int)


    # x偏移量
    offx = (extent[0] - lon1) / ((lon22 - lon1) / ((c2 - c1 + 1) * 256))
    # x方向像素量
    xnum = (extent[1] - extent[0]) / ((lon22 - lon1)  / ((c2 - c1 + 1) * 256))

    # y偏移量
    offy = (lat22 - extent[3]) / ((lat22 - lat1) / ((r1 - r2 + 1) * 256))
    # y方向像素量
    ynum = (extent[3] - extent[2]) / ((lat22 - lat1) / ((r1 - r2 + 1) * 256))
    # 拼接瓦片
    for r in range(r2, r1 + 1):
        for c in range(c1, c2 + 1):

            url = url_format.format(lev, c, r)
            print(url)
            dataset: Dataset = gdal.Open(url, 0)



            if dataset.RasterCount==1:
                continue

            for b in range(1, 4):
                band: Band = dataset.GetRasterBand(b)

                dat[(r - r2) * 256:(r - r2 + 1) * 256, (c - c1) * 256: (c - c1 + 1) * 256,
                2 - (b - 1)] = band.ReadAsArray(0, 0, 256, 256)
    cv2.imwrite("overwmtsori2.jpg", dat, [cv2.IMWRITE_JPEG_QUALITY, 30])

    dat2 = dat[int(offy):int(offy + ynum), int(offx):int(offx + xnum), :]

    #裁剪
    cv2.imwrite("overwmts2.jpg", dat2, [cv2.IMWRITE_JPEG_QUALITY, 30])

if __name__ == '__main__':

    # tms_overview([107.78981494180618, 120.43553603935675, 18.870480519260582, 25.999868757737033],"http://172.26.60.101:8820/DMap/Services/GDMap/TileServer/TMSService"
    #               )
    # wmts_url = "http://172.26.60.101:8820/DMap/Services/GDMap/TileServer/WMTSService?layer=&style=default&tilematrixset=nativeTileMatrixSet&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fpng&TileMatrix={}&TileCol={}&TileRow={}"
    # wmts_overview([107.78981494180618, 120.43553603935675, 18.870480519260582, 25.999868757737033],wmts_url)


    wmts_url = "http://172.26.60.101:8820/DMap/Services/SDMap/TileServer/WMTSService?layer=&style=default&tilematrixset=nativeTileMatrixSet&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fpng&TileMatrix={}&TileCol={}&TileRow={}"
    wmts_overview([699385.63699999999,740828.85219999996,2507679.2525999998,2546752.4369999999],wmts_url)