lbs.core.tile 源代码

# encoding: utf-8
from __future__ import absolute_import, unicode_literals, division

import math


[文档]class Tile(object): EARTH_RADIUS = 6378137 MIN_LATITUDE = -85.05112878 MAX_LATITUDE = 85.05112878 MIN_LONGITUDE = -180 MAX_LONGITUDE = 180
[文档] @classmethod def clip(cls, n, min_value, max_value): """ 将数字剪辑到指定的最小值和最大值 :param n: 要裁剪的数字 :param min_value: 最小值 :param max_value: 最大值 :return: 裁剪后结果 """ return min(max(n, min_value), max_value)
[文档] @classmethod def map_size(cls, level_of_detail): """ 确定指定级别上的地图宽度和高度(以像素为单位) :param level_of_detail: 地图级别 :return: 地图边长(像素) """ return 256 << level_of_detail
[文档] @classmethod def ground_resolution(cls, latitude, level_of_detail): """ 获取指定位置的地面分辨率(米/像素) :param latitude: 纬度 :param level_of_detail: 地图级别 :return: 地面分辨率,单位为米/像素 """ latitude = cls.clip(latitude, cls.MIN_LATITUDE, cls.MAX_LATITUDE) return math.cos(latitude * math.pi / 180) * 2 * math.pi * cls.EARTH_RADIUS / cls.map_size(level_of_detail)
[文档] @classmethod def map_scale(cls, latitude, level_of_detail, screen_dpi): """ 获取指定位置的地图比例 :param latitude: 纬度 :param level_of_detail: 地图级别 :param screen_dpi: 屏幕分辨率,单位为像素每英寸 :return: 地图比例,表示为比率1:N的分母N """ return cls.ground_resolution(latitude, level_of_detail) * screen_dpi / 0.0254
[文档] @classmethod def lat_long_to_pixel_xy(cls, latitude, longitude, level_of_detail): """ 经纬度转换为像素坐标 :param latitude: 纬度 :param longitude: 经度 :param level_of_detail: 地图级别 :return: 像素坐标x, 像素坐标y """ latitude = cls.clip(latitude, cls.MIN_LATITUDE, cls.MAX_LATITUDE) longitude = cls.clip(longitude, cls.MIN_LONGITUDE, cls.MAX_LONGITUDE) x = (longitude + 180) / 360 sin_latitude = math.sin(latitude * math.pi / 180) y = 0.5 - math.log((1 + sin_latitude) / (1 - sin_latitude)) / (4 * math.pi) map_size = cls.map_size(level_of_detail) pixel_x = int(cls.clip(x * map_size + 0.5, 0, map_size - 1)) pixel_y = int(cls.clip(y * map_size + 0.5, 0, map_size - 1)) return pixel_x, pixel_y
[文档] @classmethod def pixel_xy_to_lat_long(cls, pixel_x, pixel_y, level_of_detail): """ 像素坐标转换为经纬度 :param pixel_x: 像素坐标x :param pixel_y: 像素坐标y :param level_of_detail: 地图级别 :return: 纬度, 经度 """ map_size = cls.map_size(level_of_detail) x = (cls.clip(pixel_x, 0, map_size - 1) / map_size) - 0.5 y = 0.5 - (cls.clip(pixel_y, 0, map_size - 1) / map_size) latitude = 90 - 360 * math.atan(math.exp(-y * 2 * math.pi)) / math.pi longitude = 360 * x return latitude, longitude
[文档] @classmethod def pixel_xy_to_tile_xy(cls, pixel_x, pixel_y): """ 像素坐标转换为图块序号 :param pixel_x: 像素坐标x :param pixel_y: 像素坐标y :return: 图块序号x, 图块序号y """ tile_x = pixel_x // 256 tile_y = pixel_y // 256 return tile_x, tile_y
[文档] @classmethod def tile_xy_to_pixel_xy(cls, tile_x, tile_y): """ 图块序号转换为像素坐标 :param tile_x: 图块序号x :param tile_y: 图块序号y :return: 像素坐标x, 像素坐标y """ pixel_x = tile_x * 256 pixel_y = tile_y * 256 return pixel_x, pixel_y
[文档] @classmethod def tile_xy_to_quad_key(cls, tile_x, tile_y, level_of_detail): """ 图块序号转换为四叉树键值 :param tile_x: 图块序号x :param tile_y: 图块序号y :param level_of_detail: 地图级别 :return: 四叉树键值 """ quad_key = [] i = level_of_detail while i > 0: digit = 0 mask = 1 << (i - 1) if tile_x & mask: digit += 1 if tile_y & mask: digit += 2 quad_key.append(str(digit)) i -= 1 return "".join(quad_key)
[文档] @classmethod def quad_key_to_tile_xy(cls, quad_key): """ 四叉树键值转换为图块序号 :param quad_key: 四叉树键值 :return: 图块序号x, 图块序号y, 地图级别 """ tile_x = 0 tile_y = 0 i, level_of_detail = len(quad_key) while i > 0: mask = 1 << (i - 1) if quad_key[level_of_detail - i] == '0': pass elif quad_key[level_of_detail - i] == '1': tile_x |= mask elif quad_key[level_of_detail - i] == '2': tile_y |= mask elif quad_key[level_of_detail - i] == '3': tile_x |= mask tile_y |= mask else: raise ValueError('Invalid QuadKey digit sequence') return tile_x, tile_y, level_of_detail