index.js (4022B)
1 // Conversion methods from EPSG Geomatics Guidance Note number 7, part 2 – September 2019 2 3 /* eslint-disable camelcase */ 4 // EPSG 4284 5 const ellipsoidKrassowsky1940 = { 6 a: 6378245, 7 inv_f: 298.3, 8 }; 9 10 // EPSG 4326 11 const ellipsoidWGS1984 = { 12 a: 6378137, 13 inv_f: 298.257223563, 14 }; 15 16 // EPSG 5044 17 const pulkovo1942ToWgs84TransformationParams = { 18 // translation in meters 19 dx: 23.57, 20 dy: -140.95, 21 dz: -79.8, 22 // rotation in arc-seconds 23 rx: 0, 24 ry: -0.35, 25 rz: -0.79, 26 // scale difference in parts per million 27 ds: -0.22, 28 }; 29 30 // Approximation according to note in EPSG 9607 31 // const wgs84ToPulkovo1942TransformationParams = { 32 // dx: -pulkovo1942ToWgs84TransformationParams.dx, 33 // dy: -pulkovo1942ToWgs84TransformationParams.dy, 34 // dz: -pulkovo1942ToWgs84TransformationParams.dz, 35 // rx: -pulkovo1942ToWgs84TransformationParams.rx, 36 // ry: -pulkovo1942ToWgs84TransformationParams.ry, 37 // rz: -pulkovo1942ToWgs84TransformationParams.rz, 38 // ds: -pulkovo1942ToWgs84TransformationParams.ds, 39 // }; 40 41 // EPSG 9602 42 function geographic3DToGeocentric({lat, lon, h}, {a, inv_f}) { 43 const degToRad = Math.PI / 180; 44 const ϕ = lat * degToRad; 45 const λ = lon * degToRad; 46 const sin_ϕ = Math.sin(ϕ); 47 const cos_ϕ = Math.cos(ϕ); 48 const cos_λ = Math.cos(λ); 49 const sin_λ = Math.sin(λ); 50 const f = 1 / inv_f; 51 const e_2 = 2 * f - f * f; 52 const ν = a / Math.sqrt(1 - e_2 * sin_ϕ * sin_ϕ); 53 return { 54 x: (ν + h) * cos_ϕ * cos_λ, 55 y: (ν + h) * cos_ϕ * sin_λ, 56 z: ((1 - e_2) * ν + h) * sin_ϕ, 57 }; 58 } 59 60 // EPSG 9602 61 function geocentricToGeographic3D({x, y, z}, {a, inv_f}) { 62 const radToDeg = 180 / Math.PI; 63 const f = 1 / inv_f; 64 const b = a * (1 - f); 65 const p = Math.sqrt(x * x + y * y); 66 const q = Math.atan2(z * a, p * b); 67 const sin_q_3 = Math.sin(q) ** 3; 68 const cos_q_3 = Math.cos(q) ** 3; 69 const e_2 = 2 * f - f * f; 70 const ε = e_2 / (1 - e_2); 71 const ϕ = Math.atan2(z + ε * b * sin_q_3, p - e_2 * a * cos_q_3); 72 const λ = Math.atan2(y, x); 73 const ν = a / Math.sqrt(1 - e_2 * Math.sin(ϕ) ** 2); 74 const h = p / Math.cos(ϕ) - ν; 75 return { 76 lat: ϕ * radToDeg, 77 lon: λ * radToDeg, 78 h, 79 }; 80 } 81 82 /* eslint-enable camelcase */ 83 84 // EPSG 1032 85 function rotateCoordinateFrameGeocentric({x, y, z}, params) { 86 const arcSecToRad = Math.PI / 180 / 3600; 87 const m = 1 + params.ds * 1e-6; 88 const rx = params.rx * arcSecToRad; 89 const ry = params.ry * arcSecToRad; 90 const rz = params.rz * arcSecToRad; 91 return { 92 x: m * (x + y * rz - z * ry) + params.dx, 93 y: m * (-x * rz + y + z * rx) + params.dy, 94 z: m * (x * ry - y * rx + z) + params.dz, 95 }; 96 } 97 98 // EPSG 9659 99 function geographic2DTo3D({lat, lon}) { 100 return {lat, lon, h: 0}; 101 } 102 103 // EPSG 9659 104 // eslint-disable-next-line no-unused-vars 105 function geographic3DTo2D({lat, lon, h}) { 106 return {lat, lon}; 107 } 108 109 // EPSG 9607 110 function rotateCoordinateFrameGeog2D({lat, lon}, transformationParams, srcEllipsoid, targetEllipsoid) { 111 const srcGeod3D = geographic2DTo3D({lat, lon}); 112 const srcGeocentric = geographic3DToGeocentric(srcGeod3D, srcEllipsoid); 113 const destGeocentric = rotateCoordinateFrameGeocentric(srcGeocentric, transformationParams); 114 const destGeog3D = geocentricToGeographic3D(destGeocentric, targetEllipsoid); 115 return geographic3DTo2D(destGeog3D); 116 } 117 118 function pulkovo1942ToWgs84({lat, lon}) { 119 return rotateCoordinateFrameGeog2D( 120 { 121 lat, 122 lon, 123 }, 124 pulkovo1942ToWgs84TransformationParams, 125 ellipsoidKrassowsky1940, 126 ellipsoidWGS1984 127 ); 128 } 129 130 // function wgs84ToPulkovo1942({lat, lon}) { 131 // return rotateCoordinateFrameGeog2D( 132 // { 133 // lat, 134 // lon, 135 // }, 136 // wgs84ToPulkovo1942TransformationParams, 137 // ellipsoidWGS1984, 138 // ellipsoidKrassowsky1940 139 // ); 140 // } 141 142 export {pulkovo1942ToWgs84};