墨卡托投影计算工具 - 在线经纬度与墨卡托坐标转换,支持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}°")