C#进阶(一)——TXT文件处理:以导线网近似平差为例
生活随笔
收集整理的這篇文章主要介紹了
C#进阶(一)——TXT文件处理:以导线网近似平差为例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
引用及預處理方法的設計
引用
讀取方法
相關類及方法的設計
窗體類后續方法的設計及調用
完整的窗體類設計
首先展示一下此程序可讀取的.txt文件的正確格式
6,3,2 A,3143.237,5260.334 B,4609.361,5025.696 C,4157.197,8853.254 D,3822.911,9795.726 A B,L,0 P1,L,44.0545 P1,S,2185.070 B P1,L,0 A,L,93.1043 P1 A,L,0 B,L,42.4327 B,S,1522.853 P2,L,244.3218 P2,S,1500.017 P2 P1,L,0 C,L,201.5734 C,S,1009.021 C P2,L,0 D,L,168.0145引用及預處理方法的設計
引用
讀取.txt后綴文件,需要作引用,需要引用的內容如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;注意,這是程序能正常運行的完整引用,并不只是處理.txt文件所需的引用。
讀取方法
接下來就是讀取,這里在對應的窗體類中設計一個void函數來進行讀取:
/// <summary> /// 讀取文件 /// </summary> /// <returns></returns> private void ReadDoc() {observedDatas = new List<ObservedData>();OpenFileDialog open = new OpenFileDialog();if (open.ShowDialog() != DialogResult.OK){return;}StreamReader reader = new StreamReader(open.FileName);//讀取已知數據string[] s = reader.ReadLine().Split(',');knownData = new KnownData(Convert.ToDouble(s[0]), Convert.ToDouble(s[1]), Convert.ToDouble(s[2]));while (true){s = reader.ReadLine().Split(',');if (s.Length != 3) break;knownData.pointDatas.Add(new PointData(s[0], Convert.ToDouble(s[1]), Convert.ToDouble(s[2])));}while (!reader.EndOfStream){ObservedData observedData = new ObservedData(s[0]);while (!reader.EndOfStream){s = reader.ReadLine().Split(',');if (s.Length != 3) break;observedData.originalDatas.Add(new OriginalData(s[0], s[1], Convert.ToDouble(s[2])));}observedDatas.Add(observedData);}DataTable table = new DataTable(); }相關類及方法的設計
這個方法中,有自主設計的類,KnowData類、ObservedData類。此外還有需要在近似平差中使用的PointData類,其設計及內置方法如下所示:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 水平網平差程序 {/// <summary>/// 已知數據/// </summary>class KnownData{public double directionError, sideError, ratioError;public List<PointData> pointDatas;public KnownData(double directionError, double sideError, double ratioError){this.directionError = directionError;this.sideError = sideError;this.ratioError = ratioError;this.pointDatas = new List<PointData>();}}/// <summary>/// 已知點數據/// </summary>class PointData{public string id;public double x, y;public PointData(string id, double x, double y){this.id = id;this.x = x;this.y = y;}}/// <summary>/// 觀測數據/// </summary>class ObservedData{public string testSiteNum;public List<OriginalData> originalDatas;public ObservedData(string testSiteNum){this.testSiteNum = testSiteNum;this.originalDatas = new List<OriginalData>();}}/// <summary>/// 照準點數據/// </summary>class OriginalData{public string id;public string type;public double value;public OriginalData(string id, string type, double value){this.id = id;this.type = type;this.value = value;}} }之后設計角度等的簡單計算:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 水平網平差程序 {/// <summary>/// 基本運算/// 包括:角度弧度互化、坐標方位角計算/// </summary>class BasicCal{/// <summary>/// 角度轉弧度/// 適用于格式為dd.mmss/// </summary>/// <param name="dms"></param>/// <returns></returns>public static double Dms2rad(double dms){double d = Math.Floor(dms);double m = Math.Floor((dms - d) * 100.0);double s = (dms - d - m / 100.0) * 10000.0;return (d + m / 60.0 + s / 3600.0) * Math.PI / 180.0;}/// <summary>/// 弧度轉角度/// </summary>/// <param name="rad"></param>/// <returns></returns>public static double Rad2dms(double rad){double temp = rad * 180 / Math.PI;double d = Math.Floor(temp);double m = Math.Floor((temp - d) * 60);double s = Math.Floor((temp - d - m / 60.0) * 3600);return d + m / 100.0 + s / 10000.0;}/// <summary>/// 求坐標方位角/// </summary>/// <param name="xA"></param>/// <param name="yA"></param>/// <param name="xB"></param>/// <param name="yB"></param>/// <returns></returns>public static double CoordinateAzimuth(double xA, double yA, double xB, double yB){if (yB - yA < 0){return Math.Atan2(yB - yA, xB - xA) + 2.0 * Math.PI;}if (xB - xA == 0 && yB - yA >= 0){return Math.PI / 2.0;}if (xB - xA == 0 && yB - yA < 0){return Math.PI * 3.0 / 2.0;}return Math.Atan2(yB - yA, xB - xA);}} }最后是近似平差類及方法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 水平網平差程序 {/// <summary>/// 導線網近似坐標計算/// </summary>class ApproximateCoordinate{public List<PointData> points;public ApproximateCoordinate(KnownData knownData, List<ObservedData> observedDatas){this.points = new List<PointData>();foreach (ObservedData observedData in observedDatas){//從已知數據中尋找相應點號坐標PointData pA = knownData.pointDatas.Find(item => item.id == observedData.testSiteNum);if (pA == null){//若已知數據不存在相應點號,則到已算近似坐標中尋找pA = points.Find(item => item.id == observedData.testSiteNum);if (pA == null){//若已知數據和已算近視坐標均找不到則數據有誤MessageBox.Show("數據有誤");return;}}//同理查找第一個照準點PointData pB = knownData.pointDatas.Find(item => item.id == observedData.originalDatas[0].id);//points.Add(pB);if (pB == null){pB = points.Find(item => item.id == observedData.originalDatas[0].id);if (pB == null){MessageBox.Show("數據有誤");return;}}//計算AB的坐標方位角double alphaAB = BasicCal.CoordinateAzimuth(pA.x, pA.y, pB.x, pB.y) - observedData.originalDatas[0].value;//循環計算該組數據的其他照準點近似坐標for (int i = 1; i < observedData.originalDatas.Count; i++){//若為已知數據直接加入PointData tempP = knownData.pointDatas.Find(item => item.id == observedData.originalDatas[i].id);if (tempP != null){//points.Add(tempP);continue;}//只要角度觀測值if (knownData.pointDatas.Exists(item => item.id == observedData.originalDatas[i].id) || observedData.originalDatas[i].type == "S" || points.Exists(item => item.id == observedData.originalDatas[i].id)){continue;}//計算近似點坐標double xA = pA.x;double yA = pA.y;double sAP = observedData.originalDatas.Find(item => item.id == observedData.originalDatas[i].id && item.type == "S").value;double AlphaAP = alphaAB + BasicCal.Dms2rad(observedData.originalDatas[i].value);double cosAlphaAP = Math.Cos(AlphaAP);double sinAlphaAP = Math.Sin(AlphaAP);points.Add(new PointData(observedData.originalDatas[i].id, xA + sAP * cosAlphaAP, yA + sAP * sinAlphaAP));}}}} }窗體類后續方法的設計及調用
這里采取Datagridview控件儲存及處理數據
設計兩個Name屬性分別為 已知點 和 觀測值 的Datagirdview在窗體內,不做其他設計,之后在窗體中設計ShowTable方法,用于將數據讀入控件:
private void ShowTable() {//已知數據顯示DataTable table1 = new DataTable();table1.Columns.Add("已知點點號");table1.Columns.Add("X坐標");table1.Columns.Add("Y坐標");foreach (PointData p in knownData.pointDatas){DataRow row = table1.NewRow();row["已知點點號"] = p.id;row["X坐標"] = p.x;row["Y坐標"] = p.y;table1.Rows.Add(row);}已知點.DataSource = table1;//觀測數據顯示DataTable table2 = new DataTable();table2.Columns.Add("觀測點點號");table2.Columns.Add("照準點點號");table2.Columns.Add("觀測值類型");table2.Columns.Add("觀測值");foreach (ObservedData observedData in observedDatas){foreach (OriginalData P in observedData.originalDatas){DataRow row = table2.NewRow();row["觀測點點號"] = observedData.testSiteNum;row["照準點點號"] = P.id;row["觀測值類型"] = P.type;row["觀測值"] = P.value;table2.Rows.Add(row);}}已知點.DataSource = table1;觀測值.DataSource = table2; }在點擊 打開 按鈕時調用:
private void 打開_Click(object sender, EventArgs e) {try{ReadDoc();ShowTable();}catch{MessageBox.Show("文件格式不符");} }之后是在單擊某個控件時進行計算,這里使用Name為 計算 的 按鈕 控件:
private void 計算_Click(object sender, EventArgs e) {try{approximateCoordinate = new ApproximateCoordinate(knownData, observedDatas);ShowText();}catch{MessageBox.Show("計算錯誤");} }接下來,是將計算結果寫入某控件,這里采取的是 Name 屬性為 報告 的 richtextbox:
private void ShowText() {報告.Text += " 近似坐標值:\n";報告.Text += string.Format("{0,14}", "點名") + string.Format("{0,14}", "X坐標") + string.Format("{0,14}", "Y坐標") + "\n";foreach (PointData pointData in knownData.pointDatas){報告.Text += string.Format("{0,16}", pointData.id) + string.Format("{0,16}", pointData.x) + string.Format("{0,16}", pointData.y) + "\n";}foreach (PointData pointData in approximateCoordinate.points){報告.Text += string.Format("{0,16}", pointData.id) + string.Format("{0,16}", pointData.x.ToString("0.000")) + string.Format("{0,16}", pointData.y.ToString("0.000")) + "\n";} }最后則是將結果寫入.txt文件,同樣在單擊按鈕時進行:
private void 保存_Click(object sender, EventArgs e) {SaveFileDialog save = new SaveFileDialog();save.Filter = "(文本文件)|.txt";if (save.ShowDialog() == DialogResult.OK){StreamWriter sw = new StreamWriter(save.FileName);sw.Write(報告.Text);sw.Close();} }完整的窗體類設計
完整的窗體類設計如下所示:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 水平網平差程序 {public partial class 導線網近似平差 : Form{public 導線網近似平差(){InitializeComponent();StartPosition = FormStartPosition.CenterScreen;}KnownData knownData;List<ObservedData> observedDatas;ApproximateCoordinate approximateCoordinate;IndirectAdjustment indirectAdjustment;private void 打開_Click(object sender, EventArgs e){try{ReadDoc();ShowTable();}catch{MessageBox.Show("文件格式不符");}}private void 計算_Click(object sender, EventArgs e){try{approximateCoordinate = new ApproximateCoordinate(knownData, observedDatas);ShowText();展示框.SelectedTab = 報告頁;}catch{MessageBox.Show("計算錯誤");}}private void 保存_Click(object sender, EventArgs e){SaveFileDialog save = new SaveFileDialog();save.Filter = "(文本文件)|.txt";if (save.ShowDialog() == DialogResult.OK){StreamWriter sw = new StreamWriter(save.FileName);sw.Write(報告.Text);sw.Close();}}/// <summary>/// 讀取文件/// </summary>/// <returns></returns>private void ReadDoc(){observedDatas = new List<ObservedData>();OpenFileDialog open = new OpenFileDialog();if (open.ShowDialog() != DialogResult.OK){return;}StreamReader reader = new StreamReader(open.FileName);//讀取已知數據string[] s = reader.ReadLine().Split(',');knownData = new KnownData(Convert.ToDouble(s[0]), Convert.ToDouble(s[1]), Convert.ToDouble(s[2]));while (true){s = reader.ReadLine().Split(',');if (s.Length != 3) break;knownData.pointDatas.Add(new PointData(s[0], Convert.ToDouble(s[1]), Convert.ToDouble(s[2])));}while (!reader.EndOfStream){ObservedData observedData = new ObservedData(s[0]);while (!reader.EndOfStream){s = reader.ReadLine().Split(',');if (s.Length != 3) break;observedData.originalDatas.Add(new OriginalData(s[0], s[1], Convert.ToDouble(s[2])));}observedDatas.Add(observedData);}DataTable table = new DataTable();}private void ShowTable(){//已知數據顯示DataTable table1 = new DataTable();table1.Columns.Add("已知點點號");table1.Columns.Add("X坐標");table1.Columns.Add("Y坐標");foreach (PointData p in knownData.pointDatas){DataRow row = table1.NewRow();row["已知點點號"] = p.id;row["X坐標"] = p.x;row["Y坐標"] = p.y;table1.Rows.Add(row);}已知點.DataSource = table1;//觀測數據顯示DataTable table2 = new DataTable();table2.Columns.Add("觀測點點號");table2.Columns.Add("照準點點號");table2.Columns.Add("觀測值類型");table2.Columns.Add("觀測值");foreach (ObservedData observedData in observedDatas){foreach (OriginalData P in observedData.originalDatas){DataRow row = table2.NewRow();row["觀測點點號"] = observedData.testSiteNum;row["照準點點號"] = P.id;row["觀測值類型"] = P.type;row["觀測值"] = P.value;table2.Rows.Add(row);}}已知點.DataSource = table1;觀測值.DataSource = table2;}private void ShowText(){報告.Text += " 近似坐標值:\n";報告.Text += string.Format("{0,14}", "點名") + string.Format("{0,14}", "X坐標") + string.Format("{0,14}", "Y坐標") + "\n";foreach (PointData pointData in knownData.pointDatas){報告.Text += string.Format("{0,16}", pointData.id) + string.Format("{0,16}", pointData.x) + string.Format("{0,16}", pointData.y) + "\n";}foreach (PointData pointData in approximateCoordinate.points){報告.Text += string.Format("{0,16}", pointData.id) + string.Format("{0,16}", pointData.x.ToString("0.000")) + string.Format("{0,16}", pointData.y.ToString("0.000")) + "\n";}}} }總結
以上是生活随笔為你收集整理的C#进阶(一)——TXT文件处理:以导线网近似平差为例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 风压和功率计算公式轴流式_离心风机风压计
- 下一篇: hunt和sniffit 的一些用法(非