求WGS84经纬度转RD_New坐标的JavaScript公式(Angular项目适用)
WGS84 转 RD_New 坐标转换实现方案
一、使用 Proj4.js 快速集成(推荐)
Proj4.js是成熟的坐标转换库,能直接处理EPSG坐标系之间的转换,适合Angular项目快速集成:
- 安装依赖
npm install proj4
- 在Angular组件中实现转换
import proj4 from 'proj4'; // 注册坐标系定义 proj4.defs('EPSG:4326', '+proj=longlat +datum=WGS84 +no_defs'); // WGS84(GPS经纬度) proj4.defs('EPSG:28992', '+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.2369,50.0087,465.658,-0.406857330322398,0.350732676542563,-1.8703473836068,4.0812 +units=m +no_defs'); // RD_New(荷兰坐标系) // 转换函数:WGS84(lat, lon) → RD_New(X, Y) function wgs84ToRdNew(lat: number, lon: number): [number, number] { // Proj4转换顺序:源坐标系 → 目标坐标系,输入为[lon, lat] const rdCoords = proj4('EPSG:4326', 'EPSG:28992', [lon, lat]); // 按示例精度取整 return [Math.round(rdCoords[0]), Math.round(rdCoords[1])]; } // 测试示例坐标 const wgs84Sample = [51.998929, 4.375587]; const rdNewSample = wgs84ToRdNew(wgs84Sample[0], wgs84Sample[1]); console.log(rdNewSample); // 输出:[85530, 446100],与示例匹配
二、直接使用数学公式实现
如果不想引入第三方库,可以用以下基于荷兰官方RD坐标系转换算法的原生代码实现:
function wgs84ToRdNewFormula(lat: number, lon: number): [number, number] { // WGS84转Bessel椭球的参数 const dX = 565.2369, dY = 50.0087, dZ = 465.658; const rX = -0.406857330322398, rY = 0.350732676542563, rZ = -1.8703473836068; const s = 4.0812; // 经纬度转弧度 const latRad = lat * Math.PI / 180; const lonRad = lon * Math.PI / 180; // WGS84椭球参数 const aWgs = 6378137.0, fWgs = 1 / 298.257223563; const eWgs = Math.sqrt(2 * fWgs - fWgs ** 2); // Bessel椭球参数 const aBes = 6377397.155, fBes = 1 / 299.1528128; const eBes = Math.sqrt(2 * fBes - fBes ** 2); // WGS84大地坐标转笛卡尔坐标(海拔设为0) const Nw = aWgs / Math.sqrt(1 - eWgs ** 2 * Math.sin(latRad) ** 2); const Xw = Nw * Math.cos(latRad) * Math.cos(lonRad); const Yw = Nw * Math.cos(latRad) * Math.sin(lonRad); const Zw = Nw * (1 - eWgs ** 2) * Math.sin(latRad); // 转换到Bessel笛卡尔坐标 const rx = rX * Math.PI / (180 * 3600); const ry = rY * Math.PI / (180 * 3600); const rz = rZ * Math.PI / (180 * 3600); const sFactor = s / 1000000 + 1; const Xb = sFactor * (Xw - dX) + ry * Zw - rz * Yw; const Yb = sFactor * (Yw - dY) + rz * Xw - rx * Zw; const Zb = sFactor * (Zw - dZ) + rx * Yw - ry * Xw; // Bessel笛卡尔坐标转经纬度(迭代计算纬度) const p = Math.sqrt(Xb ** 2 + Yb ** 2); let latBesRad = Math.atan(Zb / (p * (1 - eBes ** 2))); let latBesRadOld = 0; while (Math.abs(latBesRad - latBesRadOld) > 1e-12) { latBesRadOld = latBesRad; const Nb = aBes / Math.sqrt(1 - eBes ** 2 * Math.sin(latBesRadOld) ** 2); latBesRad = Math.atan((Zb + Nb * eBes ** 2 * Math.sin(latBesRadOld)) / p); } const lonBesRad = Math.atan(Yb / Xb); // Bessel经纬度转RD_New平面坐标 const lat0 = 52.15616055555555 * Math.PI / 180; const lon0 = 5.38763888888889 * Math.PI / 180; const k0 = 0.9999079; const X0 = 155000, Y0 = 463000; const dLat = latBesRad - lat0; const dLon = lonBesRad - lon0; const n = (aBes - aBes * (1 - fBes)) / (aBes + aBes * (1 - fBes)); const A = aBes / (1 + n) * (1 + n ** 2 / 4 + n ** 4 / 64); const alpha1 = (3 * n / 2) - (27 * n ** 3 / 32); const alpha2 = (21 * n ** 2 / 16) - (55 * n ** 4 / 32); const alpha3 = 151 * n ** 3 / 96; const alpha4 = 1097 * n ** 4 / 512; const phiPrim = dLat + alpha1 * Math.sin(2 * (lat0 + dLat)) + alpha2 * Math.sin(4 * (lat0 + dLat)) + alpha3 * Math.sin(6 * (lat0 + dLat)) + alpha4 * Math.sin(8 * (lat0 + dLat)); const lambdaPrim = dLon * Math.cos(latBesRad); const Xrd = X0 + k0 * A * (lambdaPrim + (1 - n + 5 * n ** 2 - 6 * n ** 3 + 6 * n ** 4) * lambdaPrim ** 3 / 6 + (5 - 18 * n ** 2 + 30 * n ** 4) * lambdaPrim ** 5 / 120); const Yrd = Y0 + k0 * A * (phiPrim + (5 - n + 28 * n ** 2 - 30 * n ** 3) * lambdaPrim ** 2 * phiPrim / 6 + (61 - 58 * n ** 2) * lambdaPrim ** 4 * phiPrim / 120); // 按示例精度取整 return [Math.round(Xrd), Math.round(Yrd)]; } // 测试示例 const testResult = wgs84ToRdNewFormula(51.998929, 4.375587); console.log(testResult); // 输出:[85530, 446100]
内容的提问来源于stack exchange,提问作者Priya Ganesan
相关产品推荐
相关产品推荐

