墨卡托投影计算工具 - 在线经纬度与墨卡托坐标转换,支持Web墨卡托EPSG3857正算反算

墨卡托投影计算工具

经纬度与Web墨卡托坐标互转,支持EPSG:3857/EPSG:900913投影

使用说明
该工具支持经纬度到墨卡托坐标的正算和墨卡托坐标到经纬度的反算,计算结果已验证准确。

正算:经纬度 → 墨卡托坐标

投影说明

Web墨卡托投影(Web Mercator)是一种圆柱投影方式,广泛应用于网络地图服务(如Google Maps、OpenStreetMap、高德地图等)。

投影特点

  • 投影代码:EPSG:3857(也称为 EPSG:900913,Google Maps使用)
  • 基准椭球:WGS84椭球,但按球体处理(半径 6378137 米)
  • 适用范围:纬度 -85.05° 至 85.05°(超出范围无法投影)
  • 特性:保持角度关系,但面积和距离会产生变形,越靠近两极变形越大

计算公式

正算(经纬度 → 墨卡托):

  • X = R × λ(λ为经度弧度值)
  • Y = R × ln[tan(π/4 + φ/2)](φ为纬度弧度值)

反算(墨卡托 → 经纬度):

  • λ = X / R
  • φ = 2 × arctan[e^(Y/R)] - π/2

其中 R = 6378137(地球半径,单位:米)

代码实现

JavaScript

/**
 * Web墨卡托投影计算(EPSG:3857)
 */
const EARTH_RADIUS = 6378137; // 地球半径(米)

/**
 * 正算:经纬度转墨卡托坐标
 * @param {number} lng - 经度(-180 ~ 180)
 * @param {number} lat - 纬度(-85.05 ~ 85.05)
 * @returns {{x: number, y: number}} 墨卡托坐标(米)
 */
function lngLatToMercator(lng, lat) {
  const x = lng * Math.PI * EARTH_RADIUS / 180;
  const y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) * EARTH_RADIUS;
  return { x, y };
}

/**
 * 反算:墨卡托坐标转经纬度
 * @param {number} x - X坐标(米)
 * @param {number} y - Y坐标(米)
 * @returns {{lng: number, lat: number}} 经纬度
 */
function mercatorToLngLat(x, y) {
  const lng = x / EARTH_RADIUS / Math.PI * 180;
  const lat = Math.atan(Math.exp(y / EARTH_RADIUS)) * 360 / Math.PI - 90;
  return { lng, lat };
}

// 使用示例
const mercator = lngLatToMercator(116.397428, 39.90923);
console.log(`墨卡托坐标: X=${mercator.x.toFixed(2)}, Y=${mercator.y.toFixed(2)}`);

const lngLat = mercatorToLngLat(12958009.87, 4825364.68);
console.log(`经纬度: 经度=${lngLat.lng.toFixed(6)}°, 纬度=${lngLat.lat.toFixed(6)}°`);

Java

public class MercatorProjection {

    private static final double EARTH_RADIUS = 6378137.0; // 地球半径(米)

    /**
     * 正算:经纬度转墨卡托坐标
     * @param lng 经度(-180 ~ 180)
     * @param lat 纬度(-85.05 ~ 85.05)
     * @return 墨卡托坐标 [x, y](米)
     */
    public static double[] lngLatToMercator(double lng, double lat) {
        double x = lng * Math.PI * EARTH_RADIUS / 180;
        double y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) * EARTH_RADIUS;
        return new double[]{x, y};
    }

    /**
     * 反算:墨卡托坐标转经纬度
     * @param x X坐标(米)
     * @param y Y坐标(米)
     * @return 经纬度 [lng, lat]
     */
    public static double[] mercatorToLngLat(double x, double y) {
        double lng = x / EARTH_RADIUS / Math.PI * 180;
        double lat = Math.atan(Math.exp(y / EARTH_RADIUS)) * 360 / Math.PI - 90;
        return new double[]{lng, lat};
    }

    public static void main(String[] args) {
        // 正算示例
        double[] mercator = lngLatToMercator(116.397428, 39.90923);
        System.out.printf("墨卡托坐标: X=%.2f, Y=%.2f%n", mercator[0], mercator[1]);

        // 反算示例
        double[] lngLat = mercatorToLngLat(12958009.87, 4825364.68);
        System.out.printf("经纬度: 经度=%.6f°, 纬度=%.6f°%n", lngLat[0], lngLat[1]);
    }
}

Python

import math

# 地球半径(米)
EARTH_RADIUS = 6378137

def lng_lat_to_mercator(lng: float, lat: float) -> tuple[float, float]:
    """
    正算:经纬度转墨卡托坐标

    Args:
        lng: 经度(-180 ~ 180)
        lat: 纬度(-85.05 ~ 85.05)

    Returns:
        (x, y) 墨卡托坐标(米)
    """
    x = lng * math.pi * EARTH_RADIUS / 180
    y = math.log(math.tan((90 + lat) * math.pi / 360)) * EARTH_RADIUS
    return x, y

def mercator_to_lng_lat(x: float, y: float) -> tuple[float, float]:
    """
    反算:墨卡托坐标转经纬度

    Args:
        x: X坐标(米)
        y: Y坐标(米)

    Returns:
        (lng, lat) 经纬度
    """
    lng = x / EARTH_RADIUS / math.pi * 180
    lat = math.atan(math.exp(y / EARTH_RADIUS)) * 360 / math.pi - 90
    return lng, lat


if __name__ == "__main__":
    # 正算示例
    x, y = lng_lat_to_mercator(116.397428, 39.90923)
    print(f"墨卡托坐标: X={x:.2f}, Y={y:.2f}")

    # 反算示例
    lng, lat = mercator_to_lng_lat(12958009.87, 4825364.68)
    print(f"经纬度: 经度={lng:.6f}°, 纬度={lat:.6f}°")

评论 (0)

登录 后发表评论

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