利用C#编写一个高斯正反算程序

一、代码界面展示

在这里插入图片描述
整个界面控件为tabControl,groupBox,label,textbox,comboBox,button,richTextBook。

二、代码运算结果展示

  1. 数据结果采用国家统一坐标(横坐标上加上500000m,在坐标前面冠以带号)。
  2. 内置了4种椭球参数(CGCS200,WGS84,西安80,克拉索夫斯基椭球体)。
  3. 可以计算三度带和六度带。
  4. 计算曲率半径功能是我用来做大地测量学作业用的,顺便写在这里的。

2.1 数据相互转换验证

在这里插入图片描述相互转换的结果肯定是一样的(我自己测试了10几次不同的数据,是没有问题的)。

2.2 数据结果正确性验证

2.2.1 高斯正算

数据结果的正确性需要使用其他的软件进行验证。
这里我选取的是https://blog.csdn.net/starmings/article/details/123034189计算的数据进行验证。
在这里插入图片描述 在这里插入图片描述
软件结果如下:
在这里插入图片描述采用西安80椭球参数,高斯正算的结果与软件的结果是一致的。

2.2.2 高斯反算

在这里插入图片描述软件结果如下:
在这里插入图片描述
采用西安80椭球参数,高斯反算的结果与软件的结果是一致的。(我只保留了0.01,已经可以了。)

三、源代码

3.1 变量设置

        //大地经度 度分秒
        public double L;
        public double Ld;
        public double Lf;
        public double Lm;
        //大地纬度 度分秒
        public double B;
        public double Bd;
        public double Bf;
        public double Bm;
        double L0;//中央子午线度数
        double N1;//带号
        double a;//长半轴
        double b;//短半轴
        double e1;//第一偏心率平方
        double e2; //第二偏心率平方
        double m0,m2,m4,m6,m8;
        double a0, a2, a4, a6, a8;
        int i ;

3.2 高斯正算

   		    //m0-m8的值
            m0 = a * (1 - e1);
            m2 = 1.5 * m0 * e1;
            m4 = 1.25 * m2 * e1;
            m6 = (7.0 / 6) * m4 * e1;
            m8 = (9.0 / 8) * m6 * e1;
            //a0-a8的值
            a0 = m0 + m2 / 2.0 + (3.0 / 8) * m4 + (5.0 / 16) * m6 + (35.0 / 128) * m8;
            a2 = (1.0 / 2) * (m2 + m4) + (15.0 / 32) * m6 + (7.0 / 16) * m8;
            a4 = (1.0 / 8) * m4 + (3.0 / 16) * m6 + (7.0 / 32) * m8;
            a6 = (1.0 / 32) * m6 + (1.0 / 16) * m8;
            a8 = (1.0 / 128) * m8;
            //将大地经度转化为度数
            Ld = double.Parse(textBox1.Text);
            Lf = double.Parse(textBox2.Text);
            Lm = double.Parse(textBox3.Text);
            L = Ld + Lf / 60 + Lm / 3600;
            //将大地纬度转化为度数
            Bd = double.Parse(textBox4.Text);
            Bf = double.Parse(textBox5.Text);
            Bm = double.Parse(textBox6.Text);
            B = Bd + Bf / 60 + Bm / 3600;
            if (comboBox2.Text == "三度带")
            {
                N1 = Math.Truncate((L + 1.5) / 3);//带号
                L0 = 3 * N1;
             
            }
            if (comboBox2.Text == "六度带")
            {
                N1 = Math.Truncate(L / 6) + 1;
                L0 = 6 * N1 - 3;
             
            }
            
            //求椭球面上某点到赤道的子午线弧长,精度至0.001m
            double radB = (Math.PI / 180) * B; //将纬度转换为弧度
            double Δ1, Δ2, Δ3, Δ4, Δ5;
            Δ1 = a0 * radB;
            Δ2 = (a2 / 2) * Math.Sin(2 * radB);
            Δ3 = (a4 / 4) * Math.Sin(4 * radB);
            Δ4 = (a6 / 6) * Math.Sin(6 * radB);
            Δ5 = (a8 / 8) * Math.Sin(8 * radB);
            double X =Math.Round(Δ1 - Δ2 + Δ3 - Δ4 + Δ5, 8);
            //卯酉圈曲率半径N
            double N = a / Math.Sqrt(1 - e1 * Math.Sin(radB) * Math.Sin(radB));
            // tan(B)的值
            double t = Math.Tan(radB);
            // η的值
            double η =Math.Sqrt(e2) * Math.Cos(radB) ;
            //l的值
            double ρm = 180 * 60 * 60 / Math.PI;
            double l = ((L - L0) * 3600) / ρm;
            //高斯坐标中的x值和y值
            double x = Math.Round( X + (N / 2) * t * Math.Cos(radB) * Math.Cos(radB) * l * l + (N / 24) * t * (5 - t * t + 9 * η* η + 4 * Math.Pow(η,4)) * Math.Pow(Math.Cos(radB), 4) * Math.Pow(l, 4) + (N / 720) * t * (61 - 58 * t * t + Math.Pow(t, 4)) * Math.Pow(l, 6) * (Math.Pow(Math.Cos(radB), 6)),4);
            double y = Math.Round( N * Math.Cos(radB) * l + (N / 6.0) * (1 - t * t + η* η) * Math.Pow(Math.Cos(radB), 3) * Math.Pow(l, 3) + (N / 120.0) * (5 - 18 * t * t + Math.Pow(t, 4) + 14 * η * η - 58 * η * η * t * t) * Math.Pow(Math.Cos(radB), 5) * Math.Pow(l, 5),4);
            richTextBox1.AppendText(Environment.NewLine);
            richTextBox1.Text = "大地经度为L:" + Ld + "°" + Lf + "′" + Lm + "″" + "        " + "大地经度为B:" + Bd + "°" + Bf + "′" + Bm+"″" + "\r\n";
            richTextBox1.Text += "大地坐标转高斯平面坐标后:" + "\r\n";
            richTextBox1.Text += "高斯X坐标:" + x + "米" + "        " + "高斯Y坐标:" + +N1 + "" + (y+500000)+  "米" + "\r\n";

3.3 高斯反算

 //输入坐标x,y
            double x = double.Parse(textBox7.Text);
            double y1 = double.Parse(textBox8.Text);
            double y = y1-Math.Truncate(y1 / Math.Pow(10, 6)) * Math.Pow(10, 6)-500000;
            double[] Bf1 = new double[20];
            double[] F = new double[20];
            Bf1[0] = x / a0;//底点纬度
            F[0] = (-a2 / 2.0) * Math.Sin(2 * Bf1[0]) + a4 / 4.0 * Math.Sin(4 * Bf1[0]) - a6 / 6.0 * Math.Sin(6 * Bf1[0]);
            Bf1[1] = (x - F[0]) / a0;
            double Δd =Bf1[1] - Bf1[0];
            for ( i = 0;i<10 ; i++)
            {
                F[i] = (-a2 / 2.0) * Math.Sin(2 * Bf1[i]) + a4 / 4.0 * Math.Sin(4 * Bf1[i]) - a6 / 6.0 * Math.Sin(6 * Bf1[i]);
                Bf1[i + 1] = (x - F[i]) / a0;
                Δd = Bf1[i + 1] - Bf1[i];
                if (Δd < Math.Pow(10, -10))
                {
                    i = i + 1;
                    break;
                }
                
            }
            // tan(Bf)的值
            double tf = Math.Tan(Bf1[i]);
            // ηf的值
            double ηf = e2 * Math.Cos(Bf1[i]) * Math.Cos(Bf1[i]);
            //计算Mf的值
            double Mf = a * (1 - e1) / Math.Pow(1 - e1 * Math.Sin(Bf1[i]) * Math.Sin(Bf1[i]), 1.5);
            //计算Nf的值
            double Nf = a / Math.Sqrt(1 - e1 * Math.Sin(Bf1[i]) * Math.Sin(Bf1[i]));
            //计算y坐标的前2位
            int aa = Convert.ToInt32(Math.Truncate(y1 / Math.Pow(10, 6)));
            if (comboBox2.Text == "三度带")
            {
               
                L0 = 3 * aa;

            }
            if (comboBox2.Text == "六度带")
            {
              
                L0 = 6 * aa - 3;

            }
            //求大地经度L
            L = (Math.PI / 180) * L0 + y / (Nf * Math.Cos(Bf1[i])) - (1 + 2 * tf * tf + ηf ) * Math.Pow(y, 3) / (6 * Math.Pow(Nf, 3) * Math.Cos(Bf1[i])) + (5 + 28 * tf * tf + 24 * Math.Pow(tf, 4) + 6 * ηf + 8 * ηf  * Math.Pow(tf,4)) * Math.Pow(y, 5) / (120 * Math.Pow(Nf, 5) * Math.Cos(Bf1[i]));
         
          
            //转换经度
            double degrees = (180 / Math.PI) * L;//将弧度转化为度
            int d1 = Convert.ToInt32(Math.Truncate(degrees));//度
            int f1 = Convert.ToInt32(Math.Truncate((degrees - d1) * 60));//分
            double m1 = Math.Round(((degrees - d1) * 60 - f1) * 60,2);//秒
            if (m1 == 60)
            {
                m1 = 0;
                f1 += 1;
            }
            //求大地纬度B
            B = Bf1[i] - (tf * y * y) / (2 * Mf * Nf)+ tf * (5 + 3 * tf * tf + ηf  - 9 * ηf  * tf * tf) * Math.Pow(y, 4) / (24 * Mf * Math.Pow(Nf, 3)) + tf * (61 + 90 * tf * tf + 45 * Math.Pow(tf, 4)) * Math.Pow(y, 6) / (720 * Mf * Math.Pow(Nf, 5));
            double degrees1 = (180 / Math.PI) * B;//将弧度转化为度
            int d = Convert.ToInt32(Math.Truncate(degrees1));//度
            int f = Convert.ToInt32(Math.Truncate((degrees1 - d) * 60));//分
            double m = Math.Round(((degrees1 - d) * 60 - f) * 60,2);//秒
            if (m == 60)
            {
                m = 0;
                f += 1;
            }
            richTextBox1.AppendText(Environment.NewLine);
            richTextBox1.Text += "高斯平面坐标转大地坐标后:" + "\r\n";
            richTextBox1.Text +=  "大地坐标L:" + d1+"°   "+f1+"′  "+m1+"″   "+ "大地坐标B:" + d + "°   " + f + "′  " + m + "″   "+"\r\n";

四、结语

最开始写这个高斯正反算程序的时候,公式完全按照大地测量学实习指导书上的进行编写,写完过后进行数据验证,发现相互转换就不能实现,位就出现了偏差,说明正算公式或者反算公式出现了问题,经过检查,正算公式修改成了与https://blog.csdn.net/du12300/article/details/109307386所展示的公式。反算公式是对的,主要底点纬度的精度,我没在CSDN上找到相关的高斯反算文章,需要你自己发力了。
这个程序没有很困难的地方,就是公式的编写,可能就是需要注意double的精度丢失对数据结果带来的影响。
如果你需要批量处理,其实也简单,把我那个水准或者导线的程序里面的批量导入部分copy过来,设置几个变量,再写几个for语句就完事。
我的其他文章:

  1. 利用Python编写一个高斯正反算程序:https://blog.csdn.net/Zj1638/article/details/125740379
  2. 利用C#编写一个附和闭合导线简易平差程序:https://blog.csdn.net/Zj1638/article/details/125639541
  3. 利用C#编写一个水准测量近似平差程序:https://blog.csdn.net/Zj1638/article/details/119303957
  4. 利用C#编写一个GPS高程拟合(二次曲面拟合模型)程序:https://blog.csdn.net/Zj1638/article/details/125752243

相关下载链接:

  1. 利用C#编写一个水准测量近似平差程序下载链接:https://download.csdn.net/download/Zj1638/16732130
  2. 利用C#编写一个附和闭合导线简易平差程序下载链接:https://download.csdn.net/download/Zj1638/85928040
  3. 利用C#编写一个高斯正反算程序下载链接:https://download.csdn.net/download/Zj1638/85711234
  4. 利用Python编写一个高斯正反算程序下载链接:https://download.csdn.net/download/Zj1638/86059069
  5. 利用C#编写一个GPS高程拟合(二次曲面拟合模型)程序下载链接:https://download.csdn.net/download/Zj1638/85916113

需要的可以支持一下。如果有什么不懂的,可以私信,我看到了会回答的。

  • 14
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
### 回答1: 高斯投影坐标正是指根据大地坐标系中某一点的经纬度,计其在二维高斯投影坐标系中的坐标。高斯投影坐标正的过程如下: 首先,确定所使用的高斯投影投影带,即确定该区域的中央子午线经度。 然后,根据该点的经纬度,确定其与中央子午线的经度差。 接下来,根据经度差的大小,选择对应的高斯投影投影带参数,包括椭球体参数和投影带参数。 然后,根据选择的椭球体参数,计相关的参考椭球体参数,如椭球扁率、地球的极地半径、赤道半径等。 接着,通过一些公式计该点的X和Y坐标。计公式中包括经纬度差、椭球体参数以及相关的常数。 最后,根据出的X和Y坐标,即可得到该点在高斯投影坐标系中的坐标。 需要注意的是,在计过程中,可能需要进行一些单位转换和角度换,确保数据的一致性。 高斯投影坐标正是工程测绘和地理信息系统中常用的方法,可以将大地坐标系中的点转换为平面坐标系中的位置,方便地图制作和实际应用。 ### 回答2: 高斯投影坐标正是指根据给定的地理经纬度坐标点,通过高斯投影法计其对应的平面坐标,也称为平面直角坐标或高斯坐标。高斯投影坐标正的具体步骤如下: 1. 首先,根据给定的地理经纬度坐标点,需要确定所使用的高斯投影坐标系统的参数,包括中央子午线经度、假东偏移量和假北偏移量等。 2. 根据地理经纬度坐标点所在位置的所属投影带,确定该投影带的参数。 3. 根据高斯投影法的公式,将地理经纬度坐标点的经度和纬度转换为弧度制。 4. 根据经纬度的弧度值,结合投影带参数,使用高斯公式计出对应的平面坐标X和Y值。 5. 根据具体的坐标系统,可能会对计结果做一定的修正,如添加偏移量,使得计结果更加准确。 6. 最后,得到的平面坐标X和Y即为高斯投影坐标。 需要注意的是,高斯投影坐标正的准确性受到多种因素影响,包括所使用的投影坐标系统参数的准确性、地理经纬度坐标的准确性以及计过程中的近似误差等。因此,在进行高斯投影坐标正时,需要仔细选择和确定所使用的参数,并密切注意计过程中的准确性和误差控制。 ### 回答3: 高斯投影坐标正,简称高斯,是指根据给定的经纬度坐标求解对应的高斯投影坐标。高斯投影坐标正需要用到高斯投影的相关参数,包括中央经线、标准纬度、假东原点和椭球体参数等。 首先,需要明确所使用的高斯投影参数。这些参数可以通过地图或者相关数据库获取。例如,中国使用高斯克吕格投影,其中包括6度带和3度带两种参数。对于某个给定的经纬度坐标,需要确定所在的投影带,并获取对应的投影参数。 然后,将经纬度转换为弧度单位,以便进行计。经度的弧度值可以通过将度数乘以π/180获得。纬度的弧度值需要通过一些级数展开公式来计,这个过程较为复杂。 接下来,根据高斯投影的计公式,结合相应的参数和坐标数据,计出对应的高斯投影坐标。计的过程包括投影的平行圈半径、扁率因子、比例尺系数、点的投影坐标等。 最后,将计得到的高斯投影坐标转换为所需的单位,如米或千米。计结果即为所求的高斯投影坐标。 总而言之,高斯投影坐标正是一种将经纬度坐标转换为高斯投影坐标的过程。通过确定投影参数,计投影相关参数,并应用高斯投影公式,可以得到对应的高斯投影坐标。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

卤雅少年

有问题可以私信

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

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

打赏作者

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

抵扣说明:

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

余额充值