Python实现空间直角坐标转高斯克吕格平面坐标

空间直角坐标转高斯克吕格平面坐标

有时需要将点展开到地图上,需要的是平面坐标,而手中只有三维的空间直角坐标XYZ或者BLH时该怎么办呢?这时候就需要将坐标进行投影转换,本文给出的程序代码是用高斯克吕格投影进行坐标转换

原理示意

在这里插入图片描述
在这里插入图片描述

源码

源码中还有其他坐标转换的小函数,也可参考

# -*- coding:utf-8 -*-
"""

created on Wed Apr 29 20:30:25 2021
@author: xymeng

"""
import numpy as np
import math as mt
import matplotlib.pyplot as plt
import sklearn.metrics as ms
import csv
import pandas as pd


'''以下为三角函数调用'''
sqrt = mt.sqrt
sin = mt.sin
cos = mt.cos
atan = mt.atan
tan = mt.tan

'''以下为WGS84椭球参数'''
a = 6378137.0         # 参考椭球的长半轴, 单位 m
b = 6356752.31414     # 参考椭球的短半轴, 单位 m
e = sqrt((a**2-b**2)/(a**2)) #椭球第一偏心率
e1 = sqrt((a**2-b**2)/(b**2)) #椭球第二偏心率

'''以下为高斯投影中的参数'''
A1 = 1 + 3/4 * e**2 + 45/64 * e**4 +175/256 * e**6 +11025/16384 * e**8 +43659/65536 * e**10
B1 =     3/4 * e**2 + 15/16 * e**4 +525/512 * e**6 + 2205/2048 * e**8 + 72765/65536 * e**10
C1 =                  15/64 * e**4 +105/256 * e**6 + 2205/4096 * e**8 + 10395/16384 * e**10
D1 =                                35/512 * e**6  + 315/2048 * e**8 + 31185/131072 * e**10
E1 =                                                 315/16384 * e**8  + 3645/65536 * e**10

''''以下为弧度转换角度函数'''
def rad2angle(r):
    """
    该函数可以实现弧度到角度的转换.
    :param r:  弧度
    :return:  a, 对应的角度
    """
    a = r*180.0/mt.pi
    return a

'''以下为角度转换弧度函数'''
def angle2rad(a):
    """
    该函数可以实现角度到弧度的转换.
    :param a:  角度
    :return:  r, 对应的弧度
    """
    r = a*mt.pi/180.0
    return r

'''以下为XYZ转BLH函数'''
def XYZ2BLH(X, Y, Z, a, b):
    """
    该函数实现把某点在参心空间直角坐标系下的坐标(X, Y, Z)转为大地坐标(B, L, H).
    :param X:  X方向坐标,单位 m
    :param Y:  Y方向坐标, 单位 m
    :param Z:  Z方向坐标, 单位 m
    :param a: 地球长半轴,即赤道半径,单位 m
    :param b: 地球短半轴,即大地坐标系原点到两级的距离, 单位 m
    :return:  B, L, H, 大地纬度、经度、海拔高度 (m)
    """

    e = sqrt((a**2-b**2)/(a**2)) #椭球第一偏心率

    if X == 0 and Y > 0:
        L = 90
    elif X == 0 and Y < 0:
        L = -90
    elif X < 0 and Y >= 0:
        L = atan(Y/X)
        L = rad2angle(L)
        L = L+180
    elif X < 0 and Y <= 0:
        L = atan(Y/X)
        L = rad2angle(L)
        L = L-180
    else:
        L = atan(Y / X)
        L = rad2angle(L)

    b0 = atan(Z/sqrt(X**2+Y**2))
    N_temp = a/sqrt((1-e*e*sin(b0)*sin(b0)))
    b1 = atan((Z+N_temp*e*e*sin(b0))/sqrt(X**2+Y**2))

    while abs(b0-b1) > 1e-7:
        b0 = b1
        N_temp = a / sqrt((1 - e * e * sin(b0) * sin(b0)))
        b1 = atan((Z + N_temp * e * e * sin(b0)) / sqrt(X ** 2 + Y ** 2))

    B = b1
    N = a/sqrt((1-e*e*sin(B)*sin(B)))
    H = sqrt(X**2+Y**2)/cos(B)-N
    B = rad2angle(B)
    return B, L, H   # 返回大地纬度B、经度L、海拔高度H (m)

'''以下为高斯克吕格投影6度分带法,经度Lon与投影带号Zone以及带号Zone与投影带中央子午线经度L0的计算'''
def GK(L):
    '''
    高斯克吕格投影6度分带法,经度Lon与投影带号Zone
    以及带号Zone与投影带中央子午线经度L0的计算
    :param L:弧度制
    :return L0:
    '''
    if L>=0:
        '''东半球时'''
        z = int(L/6) + 1
        L0 = (6 * (z) - 3) * mt.pi
    else:
        '''西半球时'''
        z = int(L/6) + 60
        L0 = ((6 * z - 3) - 360)* mt.pi
    return L0

'''以下为将大地坐标转换为高斯平面坐标函数'''
def GKxy(B,L,a,b,A1,B1,C1,D1,E1):
    '''
    将大地坐标转换为高斯平面坐标
    :param B:
    :param L:
    :param a:
    :param b:
    :param A1:
    :param B1:
    :param C1:
    :param D1:
    :param E1:
    :return x,y:
    '''
    X0 = a * (1 - e**2)*(A1 * B - (B1/2)*sin(2*B) + (C1/4)*sin(4*B) - (D1/6)*sin(6*B) + (E1/8)*sin(8*B))
    N = a / sqrt(1 - e*e *sin(B)*sin(B))
    t = tan(B)
    L0 = GK(L)
    l = L - L0
    y2 = e1*e1*cos(B)*cos(B)
    x = X0 + (N/2)*sin(B)*cos(B)*l*l +(N/24)*sin(B)*(cos(B)**3)*(5-t**2 +9*y2 + 4*y2*y2)*(l**4) + (N/720)*sin(B)*(cos(B)**5)*(61 - 58*t*t + (t)**4)*(l**6)
    y = N*cos(B)*l + (N/6)*(cos(B)**3)*(1-t**2 + y2)*(l**3) + (N/120)*(cos(B)**5)*(5-18*(t**2)+(t**4)+14*y2-58*y2*(t**2))*(l**5)
    return x,y

'''以下定义空间直角坐标的存储列表'''
X = []
Y = []
Z = []
'''以下定义大地坐标存储列表'''
B = []
L = []
H = []
'''以下定义高斯平面坐标存储列表'''
x = []
y = []

if __name__ == '__main__':
    path = input('请输入空间直角坐标源文件:') #C://Users//23646//Downloads//数据//IGSNetwork.csv
    with open(path,'r') as f:
        lines = csv.reader(f)
        lines = list(lines)
        for line in lines[1:]:
            X.append(float(line[1]))
            Y.append(float(line[2]))
            Z.append(float(line[3]))

    for i in range(len(X)):
        B0,L0,H0 = XYZ2BLH(X[i],Y[i],Z[i],a,b)
        B.append(B0 * mt.pi/180)
        L.append(L0 * mt.pi/180)
        H.append(H0 * mt.pi/180)

    '''以下是将BLH的弧度数写入到csv文件中'''
    savepath = 'C://Users//23646//Downloads//数据//IGSBLH-rad.csv'
    data = pd.DataFrame({'B':B,'L':L,'H':H})
    data.to_csv(savepath,index=False)

    '''以下为执行大地坐标转高斯平面坐标代码块'''
    for k in range(len(B)):
        x0 ,y0 = GKxy(B[k],L[k],a,b,A1,B1,C1,D1,E1)
        x.append(x0)
        y.append(y0)

    '''以下是将xy的高斯平面坐标写入到csv文件中'''
    savepath1 = 'C://Users//23646//Downloads//数据//IGSxy.csv'
    data = pd.DataFrame({'x': x, 'y': y})
    data.to_csv(savepath1, index=False)








  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十八与她

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值