GIS比例尺计算工具 - Web墨卡托投影地图层级比例尺与距离计算

GIS比例尺计算工具

计算Web墨卡托投影(EPSG:3857)每个层级的比例尺、地面分辨率、图上距离与实地距离

距离换算计算器

纬度越高,地面分辨率越小

图上距离 → 实地距离

实地距离 → 图上距离

当前层级参数 (Zoom 10)

比例尺

1:577,791

赤道地面分辨率

152.87 米/像素

当前纬度地面分辨率

199.30 米/像素

瓦片数量

1024 × 1024

各层级参数一览

层级比例尺赤道分辨率 (米/像素)256px对应实地距离瓦片数
01:591,657,528156543.0340075.02 km1
11:295,828,76478271.5220037.51 km2
21:147,914,38239135.7610018.75 km4
31:73,957,19119567.885009.38 km8
41:36,978,5959783.942504.69 km16
51:18,489,2984891.971252.34 km32
61:9,244,6492445.98626.17 km64
71:4,622,3241222.99313.09 km128
81:2,311,162611.50156.54 km256
91:1,155,581305.7578.27 km512
101:577,791152.8739.14 km1024
111:288,89576.4419.57 km2048
121:144,44838.229.78 km4096
131:72,22419.114.89 km8192
141:36,1129.552.45 km16384
151:18,0564.781.22 km32768
161:9,0282.39611.50 m65536
171:4,5141.19305.75 m131072
181:2,2570.597164152.87 m262144
191:1,1280.29858276.44 m524288

计算原理

Web墨卡托投影 (EPSG:3857)

Web墨卡托投影(又称球面墨卡托、伪墨卡托)是Google Maps、百度地图等Web地图服务采用的投影方式。 它将WGS84椭球体视为半径为 R = 6378137m 的正球体,使用正轴等角圆柱投影将球面坐标映射到平面。

核心参数

  • 地球半径 R = 6,378,137 m(WGS84椭球长半轴)
  • 瓦片尺寸 = 256 × 256 像素
  • 第0级:整个世界用 1 张 256×256 瓦片表示
  • 每升一级:瓦片数量在行和列上各翻倍
  • 屏幕DPI = 96(ArcGIS标准)
  • 数据来源:比例尺和分辨率直接取自 ArcGIS MapServer 的 tileInfo.lods

计算公式

各层级的比例尺赤道地面分辨率直接使用 ArcGIS MapServer 提供的精确值, 其他参数据此推导。设缩放层级为 z,ArcGIS 提供的赤道地面分辨率为 Resolution,则:

  • 赤道地面分辨率(每像素对应的实地距离):
    Resolution = 2πR / (256 × 2z) 米/像素
    (本工具直接使用ArcGIS MapServer提供的精确值)
  • 比例尺(ArcGIS标准,DPI=96):
    Scale = 1 : (Resolution × 96 / 0.0254)
    其中 0.0254 = 1英寸对应的米数(本工具直接使用ArcGIS MapServer提供的精确值)
  • 任意纬度的地面分辨率
    Resolutionlat = Resolution / cos(lat) 米/像素
    (纬度越高,cos(lat)越小,分辨率越小,表示更精细)
  • 瓦片数
    Tiles = 2z(行和列各 2z 张)
  • 单张瓦片覆盖的实地距离(赤道):
    TileSpan = 256 × Resolution

距离换算

  • 图上距离 → 实地距离
    Ground Distance = Pixel Distance × Resolutionlat
  • 实地距离 → 图上距离
    Pixel Distance = Ground Distance / Resolutionlat

比例尺与层级的关系

在Web墨卡托投影中,比例尺是相对于赤道的。由于墨卡托投影的等角特性,在地图上任意位置的比例尺 (图上距离与实地距离的比值)在同一缩放层级下是一致的,这与传统纸质地图不同。 但需要注意,地面分辨率会随纬度变化——纬度越高,每像素代表的实地距离越短, 这是因为高纬度地区在墨卡托投影中被放大了。

代码实现

JavaScript

/**
 * Web墨卡托投影比例尺与距离计算
 * EPSG:3857 (球面墨卡托)
 * 数据来源: ArcGIS MapServer tileInfo.lods
 */
const TILE_SIZE = 256;

// ArcGIS MapServer 提供的各层级参数 (EPSG:3857, DPI=96)
const LODS = [
  { level: 0, resolution: 156543.03392800014, scale: 591657527.591555 },
  { level: 1, resolution: 78271.51696399994, scale: 295828763.795777 },
  { level: 2, resolution: 39135.75848200009, scale: 147914381.897889 },
  { level: 3, resolution: 19567.87924099992, scale: 73957190.948944 },
  { level: 4, resolution: 9783.93962049996, scale: 36978595.474472 },
  { level: 5, resolution: 4891.96981024998, scale: 18489297.737236 },
  { level: 6, resolution: 2445.98490512499, scale: 9244648.868618 },
  { level: 7, resolution: 1222.992452562495, scale: 4622324.434309 },
  { level: 8, resolution: 611.4962262813797, scale: 2311162.217155 },
  { level: 9, resolution: 305.74811314055756, scale: 1155581.108577 },
  { level: 10, resolution: 152.87405657041106, scale: 577790.554289 },
  { level: 11, resolution: 76.43702828507324, scale: 288895.277144 },
  { level: 12, resolution: 38.21851414253662, scale: 144447.638572 },
  { level: 13, resolution: 19.10925707126831, scale: 72223.819286 },
  { level: 14, resolution: 9.554628535634155, scale: 36111.909643 },
  { level: 15, resolution: 4.77731426794937, scale: 18055.954822 },
  { level: 16, resolution: 2.388657133974685, scale: 9027.977411 },
  { level: 17, resolution: 1.1943285668550503, scale: 4513.988705 },
  { level: 18, resolution: 0.5971642835598172, scale: 2256.994353 },
  { level: 19, resolution: 0.29858214164761665, scale: 1128.497176 },
];

/**
 * 获取指定层级的赤道地面分辨率
 * @param {number} zoom - 缩放层级 (0-19)
 * @returns {number} 地面分辨率(米/像素)
 */
function getResolution(zoom) {
  const lod = LODS.find(l => l.level === zoom);
  return lod ? lod.resolution : 0;
}

/**
 * 计算指定层级和纬度的地面分辨率
 * @param {number} zoom - 缩放层级
 * @param {number} lat - 纬度(度)
 * @returns {number} 地面分辨率(米/像素)
 */
function getResolutionAtLat(zoom, lat) {
  return getResolution(zoom) / Math.cos(lat * Math.PI / 180);
}

/**
 * 图上距离转实地距离
 * @param {number} pixels - 图上距离(像素)
 * @param {number} zoom - 缩放层级
 * @param {number} lat - 纬度(度)
 * @returns {number} 实地距离(米)
 */
function pixelToGroundDistance(pixels, zoom, lat) {
  return pixels * getResolutionAtLat(zoom, lat);
}

/**
 * 实地距离转图上距离
 * @param {number} meters - 实地距离(米)
 * @param {number} zoom - 缩放层级
 * @param {number} lat - 纬度(度)
 * @returns {number} 图上距离(像素)
 */
function groundToPixelDistance(meters, zoom, lat) {
  return meters / getResolutionAtLat(zoom, lat);
}

// 使用示例
const zoom = 10;
const lat = 39.90923; // 北京纬度
const resolution = getResolutionAtLat(zoom, lat);
const lod = LODS.find(l => l.level === zoom);
console.log(`层级 ${zoom} 在纬度 ${lat}° 的分辨率: ${resolution.toFixed(2)} 米/像素`);
console.log(`层级 ${zoom} 的比例尺: 1:${Math.round(lod.scale)}`);
console.log(`256像素对应实地距离: ${pixelToGroundDistance(256, zoom, lat).toFixed(2)} 米`);

Python

import math

# ArcGIS MapServer 提供的各层级参数 (EPSG:3857, DPI=96)
LODS = [
    {"level": 0, "resolution": 156543.03392800014, "scale": 591657527.591555},
    {"level": 1, "resolution": 78271.51696399994, "scale": 295828763.795777},
    {"level": 2, "resolution": 39135.75848200009, "scale": 147914381.897889},
    {"level": 3, "resolution": 19567.87924099992, "scale": 73957190.948944},
    {"level": 4, "resolution": 9783.93962049996, "scale": 36978595.474472},
    {"level": 5, "resolution": 4891.96981024998, "scale": 18489297.737236},
    {"level": 6, "resolution": 2445.98490512499, "scale": 9244648.868618},
    {"level": 7, "resolution": 1222.992452562495, "scale": 4622324.434309},
    {"level": 8, "resolution": 611.4962262813797, "scale": 2311162.217155},
    {"level": 9, "resolution": 305.74811314055756, "scale": 1155581.108577},
    {"level": 10, "resolution": 152.87405657041106, "scale": 577790.554289},
    {"level": 11, "resolution": 76.43702828507324, "scale": 288895.277144},
    {"level": 12, "resolution": 38.21851414253662, "scale": 144447.638572},
    {"level": 13, "resolution": 19.10925707126831, "scale": 72223.819286},
    {"level": 14, "resolution": 9.554628535634155, "scale": 36111.909643},
    {"level": 15, "resolution": 4.77731426794937, "scale": 18055.954822},
    {"level": 16, "resolution": 2.388657133974685, "scale": 9027.977411},
    {"level": 17, "resolution": 1.1943285668550503, "scale": 4513.988705},
    {"level": 18, "resolution": 0.5971642835598172, "scale": 2256.994353},
    {"level": 19, "resolution": 0.29858214164761665, "scale": 1128.497176},
]

TILE_SIZE = 256


def get_resolution(zoom: int) -> float:
    """
    获取指定层级的赤道地面分辨率(来自ArcGIS MapServer)

    Args:
        zoom: 缩放层级 (0-19)

    Returns:
        地面分辨率(米/像素)
    """
    lod = next((l for l in LODS if l["level"] == zoom), None)
    return lod["resolution"] if lod else 0


def get_resolution_at_lat(zoom: int, lat: float) -> float:
    """
    计算指定层级和纬度的地面分辨率

    Args:
        zoom: 缩放层级
        lat: 纬度(度)

    Returns:
        地面分辨率(米/像素)
    """
    return get_resolution(zoom) / math.cos(math.radians(lat))


def pixel_to_ground_distance(pixels: float, zoom: int, lat: float) -> float:
    """
    图上距离转实地距离

    Args:
        pixels: 图上距离(像素)
        zoom: 缩放层级
        lat: 纬度(度)

    Returns:
        实地距离(米)
    """
    return pixels * get_resolution_at_lat(zoom, lat)


def ground_to_pixel_distance(meters: float, zoom: int, lat: float) -> float:
    """
    实地距离转图上距离

    Args:
        meters: 实地距离(米)
        zoom: 缩放层级
        lat: 纬度(度)

    Returns:
        图上距离(像素)
    """
    return meters / get_resolution_at_lat(zoom, lat)


if __name__ == "__main__":
    zoom = 10
    lat = 39.90923  # 北京纬度
    resolution = get_resolution_at_lat(zoom, lat)
    lod = next(l for l in LODS if l["level"] == zoom)
    print(f"层级 {zoom} 在纬度 {lat}° 的分辨率: {resolution:.2f} 米/像素")
    print(f"层级 {zoom} 的比例尺: 1:{round(lod['scale'])}")
    print(f"256像素对应实地距离: {pixel_to_ground_distance(256, zoom, lat):.2f} 米")

评论 (0)

登录 后发表评论

暂无评论,快来发表第一条评论吧!