Simple Adjustment Calculation Of Wires

UI设计(仅供参考)

用到的控件;

菜单栏,标签,列表,表格,tab容器,文本框,richbox,表格,图表。

在主界面放需要的初始变量;

public int  number;//未知点个数
        public List<PointF> points = new List<PointF>();//点的坐标
        public List<double> length= new List<Double>();//边长
        public List<double> angle = new List<Double>();//角度
        public string angle_type;//角度类型
        public string lenhth_type; //导线类型
        public bool model=false;    //手写模式是否打开

导入文件(需要写xls和txt两种格式);

我们先先封装好两个方法,它们接收文件路径。

excel的读取

 public void excel(string filename)//读取excel文件
        {
            Microsoft.Office.Interop.Excel.Application xlsApp = new Microsoft.Office.Interop.Excel.Application(); // Excel程序对象
            Microsoft.Office.Interop.Excel.Workbook Wb = null; // Exce 工作簿对象
            Microsoft.Office.Interop.Excel.Worksheet WSheet = null; // Exce工作表对象

            xlsApp.Visible = false; // Excel程序对象界面不可见
            xlsApp.DisplayAlerts = true; // 不显示系统提示
            Wb = xlsApp.Workbooks.Open(filename); // 打开Excel文件
            WSheet = Wb.Sheets[1]; // 指定工作表
            int XStart = 0;
            int XEnd = 0;
            //遍历所有有效行获取数据
            for(int i=1;i<=WSheet.UsedRange.Rows.Count;i++)
            {
               //获取当前遍历行的值
               string value =(string) WSheet.Cells[i,1].Value;
                if(value== "已知点信息")//
                {                  
                    //获取坐标起始行
                    XStart= i;
                }

                if (value == "夹角类型")//
                {
                    //获取坐标结束行
                    XEnd= i;
                    break;
                }
         
            }
            //开始赋值
            this.lenhth_type = WSheet.Cells[XStart - 1, 2].Value;//导线类型
            this.angle_type = WSheet.Cells[XEnd, 2].Value;//观测角类型
            this.angle_type = this.angle_type == "左角" ? "1" : "2";
            this.lenhth_type = this.lenhth_type == "附和导线" ? "1" : "2";
            //坐标获取
            //获取坐标有效行数
            int hang = XEnd - XStart - 2;
            for (int i = 0; i < hang; i++)
            {
                float temp_x = (float)WSheet.Cells[XStart+2+i,2].Value;
                float temp_y = (float)WSheet.Cells[XStart + 2+i, 3].Value;
                PointF n1=new PointF(temp_x, temp_y);
                this.points.Add(n1);

            }
            //获取角度有效行数
            int hang_angle = WSheet.UsedRange.Rows.Count - XEnd -4;
            //获取未知点个数
            this.number =hang_angle-2;
            for (int i=0;i<hang_angle;i++)
            {
                angle.Add(WSheet.Cells[XEnd+4+i,2].Value); 
            }
            for (int i = 0; i < hang_angle-1; i++)
            {
                length.Add(WSheet.Cells[XEnd + 5 + i, 3].Value);
            }



        }

 我们遍历有效行,获取“有已知点信息”,“夹角类型”,作为相对位置求出其他数据的位置。

以闭合导线的xls文件为参考,求出”已知点信息“这一列的位置就可以知道其他的信息。

已知点坐标的有效行数是;

 int hang = XEnd - XStart - 2;

以此类推;

txt文本的读取;

  public void txt(string filename)//读取txt文件
        {
            string[] data;
            data = File.ReadAllLines(filename, Encoding.Default);
            for (int i = 0; i < data.Length; i++)
            {
                if (data[i].Contains("数据"))
                {
                    int key = i;//获取开始的行
                    this.lenhth_type = data[i + 1];
                    this.angle_type = data[i + 2];
                    //读取已知点坐标

                    float[] po = Array.ConvertAll(data[i + 4].Split(','), float.Parse);
                    for (int j = 0; j < po.Length - 1; j += 2)
                    {
                        PointF temp = new PointF(po[j], po[j + 1]);
                        this.points.Add(temp);
                    }
                    //分别给角度,长度赋值
                    this.angle_type = data[i + 5];
                    this.number = angle.Count - 2;
                    this.angle = Array.ConvertAll(data[i + 6].Split(','), double.Parse).ToList();
                    this.length = Array.ConvertAll(data[i + 7].Split(','), double.Parse).ToList();
                }

            }


        }

这里我们用cotains方法判断从哪里开始读取数据,然后切割存储,没什么难度。

数据的展示;

       private void 文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "文本文件(*.txt)|*.txt|Excel表格文件(*.xls)|*.xls";
            openFileDialog.InitialDirectory = @"C:\";
            openFileDialog.Title = "Select a Text File";

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {            
                try
                {
                    //ToloWer是转小写的方法
                    string fileName = openFileDialog.FileName;
                    if (fileName.ToLower().Contains(".txt"))
                        txt(fileName); // 从文本文件中导入数据
                    if (fileName.ToLower().Contains(".xls"))
                        excel(fileName); // 从XLS文件中导入数据                                                   
                    //把数据打印在列表里面
                  
                    dataGridView1.Rows.Add();
                    inster_data(lenhth_type);

                    for (int i = 0; i <this.angle.Count; i++)
                    {
                        dataGridView1.Rows.Add();
                        dataGridView1.Rows[i].Cells[0].Value = angle[i];    
                    }
                    for (int i = 0; i < this.length.Count; i++)
                    {
                        dataGridView1.Rows.Add();
                        dataGridView1.Rows[i].Cells[1].Value = length[i];
                    }
                    //给listbox的选项赋值
                    if (this.lenhth_type== "1")
                    {
                        this.listBox1.SelectedIndex= 0; 
                    }
                    else { this.listBox1.SelectedIndex = 1; ; }

                    if (this.angle_type == "1")
                    {
                        this.listBox2.SelectedIndex = 0;
                    }
                    else { this.listBox2.SelectedIndex = 1; }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("An error occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("导入失败");
                return;


            }
        }

给文本框赋值;

 public void inster_data(string type)//初始化表格数据
        {

            if (type == "1")
            {
                textBox1.Text = Convert.ToString(points[0].X);
                this.textBox2.Text=Convert.ToString(points[0].Y);
                this.textBox3.Text= Convert.ToString(points[1].X);
                this.textBox4.Text= Convert.ToString(points[1].Y);
                this.textBox5.Text= Convert.ToString(points[2].X);
                this.textBox6.Text= Convert.ToString(points[2].Y);
                this.textBox7.Text= Convert.ToString(points[3].X);
                this.textBox8.Text= Convert.ToString(points[3].Y);

            }
            else
            {
                textBox1.Text = Convert.ToString(points[0].X);
                this.textBox2.Text = Convert.ToString(points[0].Y);
                this.textBox3.Text = Convert.ToString(points[1].X);
                this.textBox4.Text = Convert.ToString(points[1].Y);


            }

        }

手写和导入模式的切换;

我们开头已经设置的一个bool值,默认false为导入模式。

  private void 切换模式手写ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(model==false)
            {
                textBox1.Enabled = true;
                this.textBox2.Enabled = true;
                this.textBox3.Enabled = true;
                this.textBox4.Enabled = true;
                this.textBox5.Enabled = true;
                this.textBox6.Enabled = true;
                this.textBox7.Enabled = true;
                this.textBox8.Enabled = true;
                this.dataGridView1.Enabled = true;

                model= true;
                this.label7.Text = "手写模式";

            }
            else {
                     textBox1.Enabled = false;
                this.textBox2.Enabled = false;
                this.textBox3.Enabled = false;
                this.textBox4.Enabled = false;
                this.textBox5.Enabled = false;
                this.textBox6.Enabled = false;
                this.textBox7.Enabled = false;
                this.textBox8.Enabled = false;
                this.dataGridView1.Enabled = false;
                model= false;
                this.label7.Text = "读取模式";

            }
        }

不建议这样写,可以把这些控件放在一个大的控件块上,修改控件块的enabled属性即可。

但是我懒得改了。

算法部分

我们新建一个cs文件。将方法封装在里面。

并且设置以下需要用到的字段;


        public string angle_type;
        public string length_type;
        public int n;//未知点个数
        List<double> angle = new List<double>(); //角度
        List<double> length = new List<double>(); //长度
        List<double> calculateBearing = new List<double>(); //坐标方位角
        List<double> calculateBearing_rapir = new List<double>(); //修正后坐标方位角
        List<double> X = new List<double>(); //近似坐标X
        List<double> Y = new List<double>(); //近似坐标Y
        List<double> XRapir = new List<double>(); //修正X
        List<double> YRapir = new List<double>(); //修正Y
        double angle_start;//起始方位角
        double angle_end;//结束方位角
        double f_angle;//方位角闭合差
        double f_x;
        double f_y;
        double f_s;

用到的基础函数;

1.坐标方位角的计算

 public static double CalculateBearing(double x1, double y1, double x2, double y2)
        {
            double dx = x2 - x1;
            double dy = y2 - y1;
            double angle = Math.Atan(dy / dx);
            if (dx < 0 && dy > 0) { angle += Math.PI; }
            else if (dx < 0 && dy < 0) { angle += Math.PI; }
            else if (dx > 0 && dy < 0) { angle += 2 * Math.PI; }
            return angle;//这是弧度
        }

2,ddmmss格式转弧度


      // DMS转弧度
        public static double DMS2Hu(double dms)
        {
            int d, m;
            double s;
            d = (int)Math.Floor(dms);
            m = (int)Math.Floor((dms - d) * 100);
            s = ((dms - d) * 100 - m) * 100;
            double val;
            val = (d + m / 60.0 + s / 3600.0) * Math.PI / 180;
            return val;
        }

3,ddmmss转角度

 //ddmmss转换为角度
        public static double ConvertToDegree(double coordinate1)

        {
            string coordinate = Convert.ToString(coordinate1);
            int index= coordinate.IndexOf('.'); 
            double du = Convert.ToDouble(coordinate.Substring(0, index));
            double fen = Convert.ToDouble(coordinate.Substring(index+1, 2));
            double miao = Convert.ToDouble(coordinate.Substring(index+2, 2));
            double degree = (fen / 60);
            double minutes = miao / 3600;
            return du + degree + minutes;
        }

我们设置一个主函数计算

 public   void main(Form1 form1,RichTextBox rich)//将主界面的对象和文本框传过来
        {

//从表格和文本框获取数据
//计算起始和终止方位角
//计算近似方位角
//计算方位角闭合差
//分配方位角闭合差(注意迭代上一个闭合差)
//计算近似坐标
//计算平差后的坐标
//输出在界面的文本框







}

1.我们先获取表格和文本框数据

注意需要讲角度(ddmmss格式)转化为弧度

 //获取表格数据
            //边长
            foreach (DataGridViewRow row in form1.dataGridView1.Rows)
            {
                if (!row.IsNewRow) // 排除新行
                {
                    if(row.Cells[0].Value==null)
                    { continue; }
                    angle.Add( Convert.ToDouble(row.Cells[0].Value)); // 获取第一列数据,并添加到 List 中
                }
            }
            for(int i=0; i<angle.Count; i++) { angle[i] =DMS2Hu( angle[i]); }
            foreach (DataGridViewRow row in form1.dataGridView1.Rows)
            {
                if (!row.IsNewRow) // 排除新行
                {
                    if (row.Cells[0].Value == null)
                    { continue; }
                    length.Add(Convert.ToDouble(row.Cells[1].Value)); // 获取第一列数据,并添加到 List 中
                }
            }
            this.n = length.Count-1;//未知点个数
 
            //获取类型
           this.angle_type= form1.listBox2.SelectedItem.ToString();
            this.length_type = form1.listBox1.SelectedItem.ToString();

2,根据文本框内容计算起始和终止方位角

 //计算起终方位角

            if (length_type == "附和")
            {
                angle_start = CalculateBearing(Convert.ToDouble(form1.textBox1.Text), Convert.ToDouble(form1.textBox2.Text), Convert.ToDouble(form1.textBox3.Text), Convert.ToDouble(form1.textBox4.Text));
                angle_end = CalculateBearing(Convert.ToDouble(form1.textBox5.Text), Convert.ToDouble(form1.textBox6.Text), Convert.ToDouble(form1.textBox7.Text), Convert.ToDouble(form1.textBox8.Text));
            }
            else
            {
                angle_start = CalculateBearing(Convert.ToDouble(form1.textBox1.Text), Convert.ToDouble(form1.textBox2.Text), Convert.ToDouble(form1.textBox3.Text), Convert.ToDouble(form1.textBox4.Text));
                angle_end = Math.PI + angle_start;
            }

ps(闭合导线的终止角等于起始角加180度)

3.近似方位角的计算;

 public void angle_zhe()//遍历角度计算坐标方位角
        {
            if (length_type == "附和")

            {
                if (angle_type == "左角")//左角
                {
                    double temp = angle_start;
                    foreach (double x in angle)
                    {
                        temp = temp + x- Math.PI;
                        this.calculateBearing.Add(temp);
                    }
                }
                else//右角
                {
                    int i = 0;
                    double temp = angle_start;
                    foreach (double x in angle)
                    {
                        temp = temp - x + Math.PI;
                        temp = temp > 2 * Math.PI ? temp - 2 * Math.PI : temp;
                        temp = temp > 2 * Math.PI ? temp - 2 * Math.PI : temp;//判断是否大于360度,最多720度。判断两次    
                        this.calculateBearing.Add(temp);
                    }
                }
            }
            else
            {
                double temp = angle_start;
                if (angle_type == "左角")//左角
                {

                    //针对闭合切左角的情况需要对第一个角和最后一个进行改正
                    angle[0] = 2 * Math.PI - angle[0];
                    angle[angle.Count - 1] = angle[angle.Count - 1] + (2 * Math.PI - angle[0]);
                }
                    for (int j = 0; j < angle.Count; j++)
                    {                                        
                       temp = temp - angle[j] - Math.PI;
                        if (temp > 2 * Math.PI)
                        { temp -= 2 * Math.PI; }
                        if (temp <0)
                        { temp += 2 * Math.PI; }
                        if (temp < 0)
                        { temp += 2 * Math.PI; }
                        this.calculateBearing.Add(temp);
                    }
            }
                                           
        }

ps(闭合导线计算方法需要注意)。


4.计算角度闭合差

 public void Closure_error_angle()//计算角度闭合差
        {
            this.f_angle = calculateBearing[calculateBearing.Count - 1] - angle_end;
        }

5.计算是否超限

   public void limt()//计算是否超限
        { 



        }

不想写了。参考书p150页即可。

6.更新修正方位角

 public void upadat_angle()//更新方位角
        {
            int i = 1;
            double fb_ex = -this.f_angle / n;//闭合的均值
            foreach(double a in this.calculateBearing ) { calculateBearing_rapir.Add(a+i*fb_ex); i++; }
      
        }


7.计算坐标(注意迭代上一个值)

 public void Corrding(Form1 form1)//计算坐标增量和闭合差
        {
            //获取起始点坐标
           double x = Convert.ToDouble((form1.textBox3.Text));
           double y = Convert.ToDouble((form1.textBox4.Text));

            for (int i=0;i<form1.length.Count;i++)
            {
                x = (x + length[i] * Math.Cos(calculateBearing_rapir[i]));
                X.Add(x);
                y = (y + length[i] * Math.Sin(calculateBearing_rapir[i]));
                Y.Add(y);           
            }
            //计算坐标闭合差
            if(length_type=="闭合导线")
            {
                f_x = X[X.Count-1]-Convert.ToDouble( form1.textBox5.Text);
                f_y = Y[Y.Count - 1] - Convert.ToDouble(form1.textBox6.Text);
            }
            else
            {
                f_x = X[X.Count - 1] - Convert.ToDouble(form1.textBox3.Text);
                f_y = Y[Y.Count - 1] - Convert.ToDouble(form1.textBox4.Text);

            }
            double vx =0;
            double vy = 0;
            //分配并且计算坐标
            for (int i=0;i<X.Count;i++) 
            {
                vx += -f_x * length[i]  / length.Sum();
                vy += -f_y * length[i]  / length.Sum();
                double temp = X[i] + vx;
                double temp2 = Y[i] + vy;
                XRapir.Add(temp);   
                YRapir.Add(temp2);

            }
        }

Last,主函数就是这样的。

        public   void main(Form1 form1,RichTextBox rich, System.Windows.Forms.DataVisualization.Charting.Chart chart)
        {
            //获取表格数据
            //边长
            foreach (DataGridViewRow row in form1.dataGridView1.Rows)
            {
                if (!row.IsNewRow) // 排除新行
                {
                    if(row.Cells[0].Value==null)
                    { continue; }
                    angle.Add( Convert.ToDouble(row.Cells[0].Value)); // 获取第一列数据,并添加到 List 中
                }
            }
            for(int i=0; i<angle.Count; i++) { angle[i] =DMS2Hu( angle[i]); }
            foreach (DataGridViewRow row in form1.dataGridView1.Rows)
            {
                if (!row.IsNewRow) // 排除新行
                {
                    if (row.Cells[1].Value == null)
                    { continue; }
                    length.Add(Convert.ToDouble(row.Cells[1].Value)); // 获取第一列数据,并添加到 List 中
                }
            }
            this.n = length.Count-1;//未知点个数


            
            //获取类型
           this.angle_type= form1.listBox2.SelectedItem.ToString();
            this.length_type = form1.listBox1.SelectedItem.ToString();

            //计算起终方位角

            if (length_type == "附和")
            {
                angle_start = CalculateBearing(Convert.ToDouble(form1.textBox1.Text), Convert.ToDouble(form1.textBox2.Text), Convert.ToDouble(form1.textBox3.Text), Convert.ToDouble(form1.textBox4.Text));
                angle_end = CalculateBearing(Convert.ToDouble(form1.textBox5.Text), Convert.ToDouble(form1.textBox6.Text), Convert.ToDouble(form1.textBox7.Text), Convert.ToDouble(form1.textBox8.Text));
            }
            else
            {
                angle_start = CalculateBearing(Convert.ToDouble(form1.textBox1.Text), Convert.ToDouble(form1.textBox2.Text), Convert.ToDouble(form1.textBox3.Text), Convert.ToDouble(form1.textBox4.Text));
                angle_end = Math.PI + angle_start;
            }
            
            angle_zhe();
          
            calculateBearing.ForEach(n1 => rich.Text +=  (n1 * 180 / Math.PI).ToString("f4") + "\n");
            Closure_error_angle();
            
            calculateBearing_rapir.ForEach(n1 => rich.Text += (n1 * 180 / Math.PI).ToString("f4") + "\n");
            upadat_angle();
            Corrding(form1);
            rich.Text = "未知点个数;" + n + "\n";
            rich.Text += "起始方位角是;" + angle_start * 180 / Math.PI + "\n";
            rich.Text += "终止方位角是;" + angle_end * 180 / Math.PI + "\n";
            rich.Text += "近似方位角是;" + "\n";
            for(int i=0;i<calculateBearing.Count;i++)
            { rich.Text += (calculateBearing[i] * 180 / Math.PI).ToString("f4") + "\n"; }
            rich.Text += "改正方位角是;" + "\n";
            for (int i = 0; i < calculateBearing_rapir.Count; i++)
            { rich.Text += (calculateBearing_rapir[i] * 180 / Math.PI).ToString("f4") + "\n"; }

            rich.Text += "角度闭合差是" + this.f_angle+"\n";
            rich.Text += "近似坐标是" + "\n";
            for (int i=0;i<X.Count;i++)
            {
                rich.Text += "x;" + X[i].ToString("f4") + "  "+"y;" + Y[i].ToString("f4") + "\n";
            }
            rich.Text += "改正坐标是"  + "\n";
            for (int i = 0; i < X.Count; i++)
            {
                rich.Text += "x;" + XRapir[i].ToString("f4") + "  " + "y;" + YRapir[i].ToString("f4") + "\n";
            }
            paint(chart);
        }

把内容输出在界面的richbox上。

把主界面的计算事件补上

 private void 开始计算ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Method method = new Method();
            method.main(this,this.richTextBox1);
            tabControl1.SelectedIndex= 2;
        }

成果如下;

学废了吗?那就赶紧动手试试吧!!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值