UI的搭建(参考)
注意其中文本框和列表需要用groupBox1框住。
在第二页放一个charts控件。
listbox的item属性如下;
由于需要导入xls文件,我们需要引用Microsoft Office 16.0 Object Library
引用方法如下;右键添加引用,搜索excel安装即可
准备工作完成
接下来是主界面的字段
public List<System.Windows.Forms.TextBox> tb = new List<System.Windows.Forms.TextBox>();//输入框
public bool model=false; //手写模式是否打开
手写模式的判定
private void 切换模式手写ToolStripMenuItem_Click(object sender, EventArgs e)
{
if(model==false)
{
this.groupBox1.Enabled= true;
model= true;
this.label7.Text = "手写模式";
}
else {
this.groupBox1.Enabled= false;
model= false;
this.label7.Text = "读取模式";
}
}
两种读取文件方法的封装;
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("数据"))
{
this.listBox1.SelectedIndex = data[i + 1] == "1" ? 0 : 1;//导线类型
//读取已知点坐标
string[] po = data[i + 4].Split(',');
//给文本框赋值
for (int j = 0; j < po.Length - 1; j += 2)
{
tb[j].Text = po[j];
tb[j+1].Text = po[j+1];
}
//分别给角度,长度赋值
this.listBox2.SelectedIndex = data[i + 5] == "1" ? 0 : 1;//导线类型
string[] angleTemp = data[i + 6].Split(',');
string[] LengthTemp = data[i + 7].Split(',');
for (int j = 0;j<angleTemp.Length;j++)
{
dataGridView1.Rows.Add();
dataGridView1.Rows[j].Cells[0].Value = angleTemp[j];
}
for (int j = 0; j < LengthTemp.Length; j++)
{ dataGridView1.Rows[j].Cells[1].Value = LengthTemp[j]; }
}
}
}
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.listBox1.SelectedIndex= WSheet.Cells[XStart - 1, 2].Value=="附和导线"?0:1;//导线类型
this.listBox2.SelectedIndex = WSheet.Cells[XEnd, 2].Value == "左角" ? 0:1 ;//观测角类型
//坐标获取
//获取坐标有效行数
int hang = XEnd - XStart - 2;
for (int i = 0; i < hang; i++)
{
tb[i].Text = (string)WSheet.Cells[XStart+2+i,2].Value;
tb[i].Text = (string)WSheet.Cells[XStart + 2+i, 3].Value;
}
//获取角度有效行数
int hang_angle = WSheet.UsedRange.Rows.Count - XEnd -4;
//获取未知点个数
for (int i=0;i<hang_angle;i++)
{
dataGridView1.Rows.Add();
dataGridView1.Rows[i].Cells[0].Value = WSheet.Cells[XEnd + 4 + i, 2].Value;
}
for (int i = 0; i < hang_angle-1; i++)
{
dataGridView1.Rows[i].Cells[1].Value = WSheet.Cells[XEnd + 5 + i, 3].Value;
}
}
则导入文件的代码就写完了。
最后判断调用即可。
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文件中导入数据
}
catch (Exception ex)
{
MessageBox.Show("An error occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("导入失败");
return;
}
}
---------------------------------------------------------------------------------------------------------------------------------
MethodL类
我们新建一个类,用于计算。
它具有以下字段
public string angle_type;
public string length_type;
public PointF startPointF1;//起始点坐标
public PointF startPointF2;//起始点坐标
public PointF endPointF1;//结束点坐标
public PointF endPointF2;//结束点坐标
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;
写一个读取控件属性给类的字段赋值初始化的函数
代码如下;
foreach (DataGridViewRow row in form1.dataGridView1.Rows)
{
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 == "附和")
{
//获取已知点坐标
this.startPointF1 = new PointF(float.Parse(form1.textBox1.Text), float.Parse(form1.textBox2.Text));
this.startPointF2 = new PointF(float.Parse(form1.textBox3.Text), float.Parse(form1.textBox4.Text));
this.endPointF1 = new PointF(float.Parse(form1.textBox5.Text), float.Parse(form1.textBox6.Text));
this.endPointF1 = new PointF(float.Parse(form1.textBox7.Text), float.Parse(form1.textBox8.Text));
angle_start = CalculateBearing(startPointF1.X, startPointF1.Y, startPointF2.X, startPointF2.Y);
angle_end = CalculateBearing(endPointF1.X,endPointF1.Y,endPointF2.X,endPointF2.Y);
}
else
{
//获取已知点坐标
this.startPointF1 = new PointF(float.Parse(form1.textBox1.Text), float.Parse(form1.textBox2.Text));
this.startPointF2 = new PointF(float.Parse(form1.textBox3.Text), float.Parse(form1.textBox4.Text));
angle_start = CalculateBearing(startPointF1.X, startPointF1.Y, startPointF2.X, startPointF2.Y);
angle_end = Math.PI + angle_start;
}
它的基础计算函数如下
角度转换
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;
}
绘图函数
public void paint (Form1 form1,System.Windows.Forms.DataVisualization.Charting.Chart chart)//绘图方法
{
List<PointF> list = new List<PointF>();//附和部分
for (int i = 0; i < XRapir.Count;i++)
{
PointF pointF=new PointF((float)XRapir[i], (float)YRapir[i]);
list.Add(pointF);
}
if (length_type == "附和")
{
list.Insert(0, this.startPointF2);
list.Insert(0, this.startPointF1);
list.Add(this.endPointF2);
}
else
{
list.Insert(0, this.startPointF2);
list.Insert(0, this.startPointF1);
}
//开始绘图
// 清空所有的数据点和系列
chart.Series.Clear();
chart.ChartAreas.Clear();
// 添加一个新的 ChartArea
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea = chart.ChartAreas.Add("ChartArea");
chartArea.AxisX.Title = "Y";
chartArea.AxisY.Title = "X";
// 添加2个新的 Series 并设置其属性
chart.Titles.Add("Closed Curve");
chart.ChartAreas.Add(new System.Windows.Forms.DataVisualization.Charting.ChartArea("Default"));
chart.Series.Add(new System.Windows.Forms.DataVisualization.Charting.Series("Curve"));
chart.Series["Curve"].ChartType = SeriesChartType.Line;
chart.Series["Curve"].BorderWidth = 3;
chart.Series["Curve"].MarkerStyle = MarkerStyle.Circle;
chart.Series["Curve"].MarkerSize = 8;
chart.Series["Curve"].MarkerColor = Color.Red;
chart.Series["Curve"].Color = Color.Blue;
// 添加数据点
for (int i = 0; i < list.Count; i++)
{
chart.Series["Curve"].Points.AddXY(list[i].X, list[i].Y);
}
// 更新图表
chart.Invalidate();
}
方位角计算函数
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;//这是弧度
}
1,计算近似坐标方位角的函数
闭合导线的比较特殊,首末点需要修正后用另一个公式计算。
还有注意判断两次值的大小是否为负值和大于180.
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);
}
}
}
2,计算是否超限(很简单自己加,略)
3,根据闭合差更新坐标方位角()
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++; }
}
4,计算近似坐标和改正坐标
ps,还需要检测fs是否超限!!
public void Corrding(Form1 form1)//计算坐标增量和闭合差
{
//获取起始点坐标
double x = Convert.ToDouble((form1.textBox3.Text));
double y = Convert.ToDouble((form1.textBox4.Text));
for (int i=0;i<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.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 == "附和")
{
//获取已知点坐标
this.startPointF1 = new PointF(float.Parse(form1.textBox1.Text), float.Parse(form1.textBox2.Text));
this.startPointF2 = new PointF(float.Parse(form1.textBox3.Text), float.Parse(form1.textBox4.Text));
this.endPointF1 = new PointF(float.Parse(form1.textBox5.Text), float.Parse(form1.textBox6.Text));
this.endPointF1 = new PointF(float.Parse(form1.textBox7.Text), float.Parse(form1.textBox8.Text));
angle_start = CalculateBearing(startPointF1.X, startPointF1.Y, startPointF2.X, startPointF2.Y);
angle_end = CalculateBearing(endPointF1.X,endPointF1.Y,endPointF2.X,endPointF2.Y);
}
else
{
//获取已知点坐标
this.startPointF1 = new PointF(float.Parse(form1.textBox1.Text), float.Parse(form1.textBox2.Text));
this.startPointF2 = new PointF(float.Parse(form1.textBox3.Text), float.Parse(form1.textBox4.Text));
angle_start = CalculateBearing(startPointF1.X, startPointF1.Y, startPointF2.X, startPointF2.Y);
angle_end = Math.PI + angle_start;
}
angle_zhe();
calculateBearing.ForEach(n1 => rich.Text += (n1 * 180 / Math.PI).ToString("f4") + "\n");
this.f_angle = calculateBearing[calculateBearing.Count - 1] - angle_end;
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(form1,chart);
}
完结