大地坐标系转换工具 - 北京54西安80转WGS84四参数七参数计算器

大地坐标系转换工具

北京54/西安80 → WGS84/CGCS2000,支持四参数和七参数转换

使用说明
支持四参数和七参数进行坐标系转换,需要输入实测参数。

完整转换(投影坐标→WGS84)

计算原理

完整转换流程

从投影坐标(如北京54)转换为WGS84经纬度需要以下步骤:

  1. 高斯投影反算:投影坐标(X,Y) → 大地坐标(B,L)
  2. 大地转空间:大地坐标 → 空间直角坐标(X,Y,Z)
  3. 七参数转换:源椭球空间坐标 → 目标椭球空间坐标
  4. 空间转大地:空间直角坐标 → WGS84大地坐标

四参数(平面)

X₂ = ΔX + (1+K×10⁻⁶)(X₁cosθ - Y₁sinθ)
Y₂ = ΔY + (1+K×10⁻⁶)(X₁sinθ + Y₁cosθ)

七参数(布尔莎模型)

X₂ = ΔX + (1+K×10⁻⁶)(X₁ - Rz×Y₁ + Ry×Z₁)
Y₂ = ΔY + (1+K×10⁻⁶)(Rz×X₁ + Y₁ - Rx×Z₁)
Z₂ = ΔZ + (1+K×10⁻⁶)(-Ry×X₁ + Rx×Y₁ + Z₁)

参数说明

  • ΔX,ΔY,ΔZ:三个平移参数(米)
  • Rx,Ry,Rz:三个旋转参数(秒)
  • K:尺度因子(ppm)

代码实现

JavaScript

// 完整坐标转换:投影坐标 → WGS84经纬度
const ellipsoids = {
  BJ54: { a: 6378245, f: 1 / 298.3 },
  XA80: { a: 6378140, f: 1 / 298.257 },
  WGS84: { a: 6378137, f: 1 / 298.257223563 }
};

// 高斯投影反算
function gaussInverse(x, y, L0, ellipsoid) {
  const { a, f } = ellipsoid;
  const e2 = 2 * f - f * f;
  const Bf = x / (a * (1 - e2 / 4));
  const Wf = Math.sqrt(1 - e2 * Math.sin(Bf) ** 2);
  const Nf = a / Wf;
  const Mf = a * (1 - e2) / Wf ** 3;
  const tf = Math.tan(Bf);
  const B = Bf - (Nf * tf / Mf) * (y ** 2 / (2 * Nf ** 2));
  const L = L0 + y / (Nf * Math.cos(Bf));
  return { B: B * 180 / Math.PI, L: L * 180 / Math.PI };
}

// 大地坐标→空间直角坐标
function blhToXyz(B, L, H, ellipsoid) {
  const { a, f } = ellipsoid;
  const e2 = 2 * f - f * f;
  const N = a / Math.sqrt(1 - e2 * Math.sin(B * Math.PI / 180) ** 2);
  const x = (N + H) * Math.cos(B * Math.PI / 180) * Math.cos(L * Math.PI / 180);
  const y = (N + H) * Math.cos(B * Math.PI / 180) * Math.sin(L * Math.PI / 180);
  const z = (N * (1 - e2) + H) * Math.sin(B * Math.PI / 180);
  return { x, y, z };
}

// 七参数转换
function sevenParam(x, y, z, dx, dy, dz, rx, ry, rz, k) {
  const rxr = rx * Math.PI / 648000;
  const ryr = ry * Math.PI / 648000;
  const rzr = rz * Math.PI / 648000;
  const m = 1 + k * 1e-6;
  return {
    x: dx + m * (x - rzr * y + ryr * z),
    y: dy + m * (rzr * x + y - rxr * z),
    z: dz + m * (-ryr * x + rxr * y + z)
  };
}

// 空间直角坐标→大地坐标
function xyzToBlh(x, y, z, ellipsoid) {
  const { a, f } = ellipsoid;
  const e2 = 2 * f - f * f;
  const L = Math.atan2(y, x);
  let B = Math.atan2(z, Math.sqrt(x ** 2 + y ** 2));
  for (let i = 0; i < 5; i++) {
    const N = a / Math.sqrt(1 - e2 * Math.sin(B) ** 2);
    const H = Math.sqrt(x ** 2 + y ** 2) / Math.cos(B) - N;
    B = Math.atan2(z, Math.sqrt(x ** 2 + y ** 2) * (1 - e2 * N / (N + H)));
  }
  return { B: B * 180 / Math.PI, L: L * 180 / Math.PI };
}

// 使用示例:北京54投影坐标转WGS84
const projX = 4426641.2, projY = -2148744.5, L0 = 117 * Math.PI / 180;
const bl = gaussInverse(projX, projY, L0, ellipsoids.BJ54);
const xyz1 = blhToXyz(bl.B, bl.L, 0, ellipsoids.BJ54);
const xyz2 = sevenParam(xyz1.x, xyz1.y, xyz1.z, -29.7, -130.6, -95.8, 0.0025, 0.0033, 0, 2.4);
const wgs84 = xyzToBlh(xyz2.x, xyz2.y, xyz2.z, ellipsoids.WGS84);
console.log('WGS84:', wgs84);

Java

public class DatumTransform {
    static class Ellipsoid {
        double a, f;
        Ellipsoid(double a, double f) { this.a = a; this.f = f; }
    }

    static Ellipsoid BJ54 = new Ellipsoid(6378245, 1.0/298.3);
    static Ellipsoid WGS84 = new Ellipsoid(6378137, 1.0/298.257223563);

    // 高斯投影反算
    static double[] gaussInverse(double x, double y, double L0, Ellipsoid e) {
        double e2 = 2 * e.f - e.f * e.f;
        double Bf = x / (e.a * (1 - e2 / 4));
        double Wf = Math.sqrt(1 - e2 * Math.sin(Bf) * Math.sin(Bf));
        double Nf = e.a / Wf;
        double B = Bf - (Nf * Math.tan(Bf) / (e.a * (1 - e2) / Math.pow(Wf, 3))) *
                   (y * y / (2 * Nf * Nf));
        double L = L0 + y / (Nf * Math.cos(Bf));
        return new double[] {Math.toDegrees(B), Math.toDegrees(L)};
    }

    // 大地坐标→空间直角坐标
    static double[] blhToXyz(double B, double L, double H, Ellipsoid e) {
        double e2 = 2 * e.f - e.f * e.f;
        double Br = Math.toRadians(B), Lr = Math.toRadians(L);
        double N = e.a / Math.sqrt(1 - e2 * Math.sin(Br) * Math.sin(Br));
        return new double[] {
            (N + H) * Math.cos(Br) * Math.cos(Lr),
            (N + H) * Math.cos(Br) * Math.sin(Lr),
            (N * (1 - e2) + H) * Math.sin(Br)
        };
    }

    // 七参数转换
    static double[] sevenParam(double x, double y, double z,
        double dx, double dy, double dz, double rx, double ry, double rz, double k) {
        double rxr = rx * Math.PI / 648000;
        double ryr = ry * Math.PI / 648000;
        double rzr = rz * Math.PI / 648000;
        double m = 1 + k * 1e-6;
        return new double[] {
            dx + m * (x - rzr * y + ryr * z),
            dy + m * (rzr * x + y - rxr * z),
            dz + m * (-ryr * x + rxr * y + z)
        };
    }
}

Python

import math

class Ellipsoid:
    def __init__(self, a, f):
        self.a = a
        self.f = f

BJ54 = Ellipsoid(6378245, 1/298.3)
WGS84 = Ellipsoid(6378137, 1/298.257223563)

def gauss_inverse(x, y, L0, ellipsoid):
    """高斯投影反算"""
    e2 = 2 * ellipsoid.f - ellipsoid.f ** 2
    Bf = x / (ellipsoid.a * (1 - e2 / 4))
    Wf = math.sqrt(1 - e2 * math.sin(Bf) ** 2)
    Nf = ellipsoid.a / Wf
    Mf = ellipsoid.a * (1 - e2) / Wf ** 3
    tf = math.tan(Bf)
    B = Bf - (Nf * tf / Mf) * (y ** 2 / (2 * Nf ** 2))
    L = L0 + y / (Nf * math.cos(Bf))
    return math.degrees(B), math.degrees(L)

def blh_to_xyz(B, L, H, ellipsoid):
    """大地坐标→空间直角坐标"""
    e2 = 2 * ellipsoid.f - ellipsoid.f ** 2
    N = ellipsoid.a / math.sqrt(1 - e2 * math.sin(math.radians(B)) ** 2)
    x = (N + H) * math.cos(math.radians(B)) * math.cos(math.radians(L))
    y = (N + H) * math.cos(math.radians(B)) * math.sin(math.radians(L))
    z = (N * (1 - e2) + H) * math.sin(math.radians(B))
    return x, y, z

def seven_param(x, y, z, dx, dy, dz, rx, ry, rz, k):
    """七参数转换"""
    rxr = rx * math.pi / 648000
    ryr = ry * math.pi / 648000
    rzr = rz * math.pi / 648000
    m = 1 + k * 1e-6
    return (
        dx + m * (x - rzr * y + ryr * z),
        dy + m * (rzr * x + y - rxr * z),
        dz + m * (-ryr * x + rxr * y + z)
    )

def xyz_to_blh(x, y, z, ellipsoid):
    """空间直角坐标→大地坐标"""
    e2 = 2 * ellipsoid.f - ellipsoid.f ** 2
    L = math.atan2(y, x)
    B = math.atan2(z, math.sqrt(x ** 2 + y ** 2))
    for _ in range(5):
        N = ellipsoid.a / math.sqrt(1 - e2 * math.sin(B) ** 2)
        H = math.sqrt(x ** 2 + y ** 2) / math.cos(B) - N
        B = math.atan2(z, math.sqrt(x ** 2 + y ** 2) * (1 - e2 * N / (N + H)))
    return math.degrees(B), math.degrees(L)

# 使用示例
B, L = gauss_inverse(4426641.2, -2148744.5, math.radians(117), BJ54)
xyz1 = blh_to_xyz(B, L, 0, BJ54)
xyz2 = seven_param(*xyz1, -29.7, -130.6, -95.8, 0.0025, 0.0033, 0, 2.4)
wgs84 = xyz_to_blh(*xyz2, WGS84)
print(f"WGS84: B={wgs84[0]:.8f}°, L={wgs84[1]:.8f}°")

评论 (0)

登录 后发表评论

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

评论 (0)

登录 后发表评论

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