第五讲 测量窗体代码撰写2

本文是系列教程的第五部分,主要介绍如何在C#程序中实现串口通信功能。首先,读取待检测图像库;然后,通过串口发送按钮进行串口设置;接着,展示串口窗口的代码,包括打开串口和使用串口助手进行通信测试。文章提供了串口通信的详细步骤,并提到了串口助手的源码分享。

接着上一讲,完成了测量矩形,这一讲开始完成串口的模块。

1.打开待检测图库

首先读取一个图像文件夹,里面存放的是需要检测的图像。

       //打开待检测图库
        private void button6_Click(object sender, EventArgs e)
        {
            //创建读取文件夹的对话框类
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.SelectedPath = "D:\\File\\c# code\\ce liang\\bin\\Debug\\图像";
            //提示信息
            dialog.Description = "请选择图片文件路径";
           
            string Path1 ;
            //获取文件夹下的文件
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                Path1 = dialog.SelectedPath;     //获取文件夹路径
                path = Directory.GetFiles(Path1, "*.*");    //获取文件夹下的所有文件的路径
                HOperatorSet.ReadImage(out ho_image, path[Index]);
           
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace jiaruluxianchangdu { public partial class Form1 : Form { public class LevelPoint { public string Name { get; set; } public double Elevation { get; set; } public bool IsKnown { get; set; } public int Index { get; set; } = -1; } private List<LevelPoint> KnownPoints = new List<LevelPoint>(); private List<LevelPoint> UnknownPoints = new List<LevelPoint>(); private List<Tuple<LevelPoint, LevelPoint, double>> ObservationData = new List<Tuple<LevelPoint, LevelPoint, double>>(); private Panel pnlKnown, pnlUnknown, pnlObs, pnlResult, pnlControl; private DataGridView dgvKnown, dgvUnknown, dgvObs, dgvResult; private Button btnCalculate, btnClear, btnCheckRoute; private Label lblPrecision, lblRouteStatus, lblRouteLength; private NumericUpDown nudPrecision, nudRouteLength; private ComboBox cmbStartPoint, cmbEndPoint; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 窗体基础设置 this.Text = "水准高程平差计算器"; this.Size = new Size(1000, 700); this.StartPosition = FormStartPosition.CenterScreen; // 已知点面板 pnlKnown = new Panel { Location = new Point(10, 10), Size = new Size(280, 250), BorderStyle = BorderStyle.FixedSingle, Text = "已知点数据" }; dgvKnown = new DataGridView { Location = new Point(10, 30), Size = new Size(260, 190), Columns = { new DataGridViewTextBoxColumn { Name = "Name", HeaderText = "点名称", Width = 100 }, new DataGridViewTextBoxColumn { Name = "Elevation", HeaderText = "已知高程", Width = 100 }, new DataGridViewButtonColumn { Text = "添加", UseColumnTextForButtonValue = true, Name = "AddKnown", Width = 60 } } }; dgvKnown.CellContentClick += DgvKnown_CellContentClick; pnlKnown.Controls.Add(dgvKnown); // 未知点面板 pnlUnknown = new Panel { Location = new Point(300, 10), Size = new Size(280, 250), BorderStyle = BorderStyle.FixedSingle, Text = "未知点数据" }; dgvUnknown = new DataGridView { Location = new Point(10, 30), Size = new Size(260, 190), Columns = { new DataGridViewTextBoxColumn { Name = "Name", HeaderText = "点名称", Width = 160 }, new DataGridViewButtonColumn { Text = "添加", UseColumnTextForButtonValue = true, Name = "AddUnknown", Width = 60 } } }; dgvUnknown.CellContentClick += DgvUnknown_CellContentClick; pnlUnknown.Controls.Add(dgvUnknown); // 观测数据面板 pnlObs = new Panel { Location = new Point(590, 10), Size = new Size(280, 250), BorderStyle = BorderStyle.FixedSingle, Text = "观测数据录入" }; dgvObs = new DataGridView { Location = new Point(10, 30), Size = new Size(260, 190), Columns = { new DataGridViewComboBoxColumn { Name = "FromPoint", HeaderText = "起始点", Width = 100 }, new DataGridViewComboBoxColumn { Name = "ToPoint", HeaderText = "终止点", Width = 100 }, new DataGridViewTextBoxColumn { Name = "Difference", HeaderText = "高差", Width = 80 }, new DataGridViewButtonColumn { Text = "添加", UseColumnTextForButtonValue = true, Name = "AddObs", Width = 60 } } }; dgvObs.CellContentClick += DgvObs_CellContentClick; pnlObs.Controls.Add(dgvObs); // 添加默认行(解决下拉框为空的关键修改) dgvObs.Rows.Add(); // 控制按钮面板 pnlControl = new Panel { Location = new Point(880, 10), Size = new Size(280, 400), // 增加高度 BorderStyle = BorderStyle.FixedSingle, Text = "计算控制" }; lblPrecision = new Label { Text = "平差精度(mm):", Location = new Point(20, 30), Size = new Size(120, 20) }; nudPrecision = new NumericUpDown { Location = new Point(140, 30), Size = new Size(120, 20), Minimum = 0.1M, Maximum = 100M, Increment = 0.1M, Value = 1M }; // 路线长度控件 lblRouteLength = new Label { Text = "路线长度(公里):", Location = new Point(20, 70), Size = new Size(120, 20) }; nudRouteLength = new NumericUpDown { Location = new Point(140, 70), Size = new Size(120, 20), Minimum = 0.1M, Maximum = 100M, Increment = 0.1M, DecimalPlaces = 2, Value = 1M }; // 路线检查控件 Label lblStartPoint = new Label { Text = "路线起点:", Location = new Point(20, 110), Size = new Size(80, 20) }; cmbStartPoint = new ComboBox { Location = new Point(100, 110), Size = new Size(160, 20), DropDownStyle = ComboBoxStyle.DropDownList }; Label lblEndPoint = new Label { Text = "路线终点:", Location = new Point(20, 150), Size = new Size(80, 20) }; cmbEndPoint = new ComboBox { Location = new Point(100, 150), Size = new Size(160, 20), DropDownStyle = ComboBoxStyle.DropDownList }; btnCheckRoute = new Button { Text = "检查水准路线", Location = new Point(40, 190), Size = new Size(200, 30), Font = new Font("微软雅黑", 9, FontStyle.Bold) }; btnCheckRoute.Click += BtnCheckRoute_Click; lblRouteStatus = new Label { Location = new Point(20, 230), Size = new Size(240, 80), BorderStyle = BorderStyle.FixedSingle, TextAlign = ContentAlignment.MiddleCenter }; btnCalculate = new Button { Text = "平差计算", Location = new Point(40, 320), Size = new Size(200, 40), Font = new Font("微软雅黑", 10, FontStyle.Bold) }; btnCalculate.Click += BtnCalculate_Click; btnClear = new Button { Text = "清空数据", Location = new Point(40, 370), Size = new Size(200, 40), Font = new Font("微软雅黑", 10, FontStyle.Bold) }; btnClear.Click += BtnClear_Click; pnlControl.Controls.Add(lblPrecision); pnlControl.Controls.Add(nudPrecision); pnlControl.Controls.Add(lblRouteLength); pnlControl.Controls.Add(nudRouteLength); pnlControl.Controls.Add(lblStartPoint); pnlControl.Controls.Add(cmbStartPoint); pnlControl.Controls.Add(lblEndPoint); pnlControl.Controls.Add(cmbEndPoint); pnlControl.Controls.Add(btnCheckRoute); pnlControl.Controls.Add(lblRouteStatus); pnlControl.Controls.Add(btnCalculate); pnlControl.Controls.Add(btnClear); // 计算结果面板 pnlResult = new Panel { Location = new Point(10,270), Size = new Size(1150, 400), BorderStyle = BorderStyle.FixedSingle, Text = "平差结果" }; dgvResult = new DataGridView { Location = new Point(10, 30), Size = new Size(1130, 350), Columns = { new DataGridViewTextBoxColumn { Name = "Name", HeaderText = "点名称", Width = 150 }, new DataGridViewTextBoxColumn { Name = "Elevation", HeaderText = "平差高程", Width = 150 }, new DataGridViewTextBoxColumn { Name = "Residual", HeaderText = "残差(mm)", Width = 120 }, new DataGridViewTextBoxColumn { Name = "Accuracy", HeaderText = "精度(mm)", Width = 120 } } }; pnlResult.Controls.Add(dgvResult); // 将所有控件添加到窗体 this.Controls.Add(pnlKnown); this.Controls.Add(pnlUnknown); this.Controls.Add(pnlObs); this.Controls.Add(pnlControl); this.Controls.Add(pnlResult); // 初始化下拉列表 RefreshPointLists(); } // 刷新点列表(用于下拉框) private void RefreshPointLists() { var allPoints = KnownPoints.Concat(UnknownPoints).Select(pt => pt.Name).ToList(); // 更新观测数据表格下拉框 if (dgvObs.Columns["FromPoint"] is DataGridViewComboBoxColumn fromColumn) { fromColumn.Items.Clear(); foreach (var pt in allPoints) fromColumn.Items.Add(pt); } if (dgvObs.Columns["ToPoint"] is DataGridViewComboBoxColumn toColumn) { toColumn.Items.Clear(); foreach (var pt in allPoints) toColumn.Items.Add(pt); } // 更新路线起点和终点下拉框 cmbStartPoint.Items.Clear(); cmbEndPoint.Items.Clear(); foreach (var pt in KnownPoints.Select(p => p.Name)) { cmbStartPoint.Items.Add(pt); cmbEndPoint.Items.Add(pt); } // 默认选择第一个已知点 if (cmbStartPoint.Items.Count > 0) cmbStartPoint.SelectedIndex = 0; if (cmbEndPoint.Items.Count > 0) cmbEndPoint.SelectedIndex = Math.Min(1, cmbEndPoint.Items.Count - 1); } // 已知点添加按钮事件 private void DgvKnown_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == dgvKnown.Columns["AddKnown"].Index && e.RowIndex >= 0) { string name = dgvKnown.Rows[e.RowIndex].Cells["Name"].Value?.ToString(); string elev = dgvKnown.Rows[e.RowIndex].Cells["Elevation"].Value?.ToString(); if (string.IsNullOrEmpty(name)) { MessageBox.Show("请输入点名称!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } if (double.TryParse(elev, out double elevation)) { KnownPoints.Add(new LevelPoint { Name = name, Elevation = elevation, IsKnown = true, Index = KnownPoints.Count }); RefreshPointLists(); dgvKnown.Rows[e.RowIndex].Cells["Name"].Value = ""; dgvKnown.Rows[e.RowIndex].Cells["Elevation"].Value = ""; } else { MessageBox.Show("高程格式错误,请输入数字!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } } // 未知点添加按钮事件 private void DgvUnknown_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == dgvUnknown.Columns["AddUnknown"].Index && e.RowIndex >= 0) { string name = dgvUnknown.Rows[e.RowIndex].Cells["Name"].Value?.ToString(); if (string.IsNullOrEmpty(name)) { MessageBox.Show("请输入点名称!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } UnknownPoints.Add(new LevelPoint { Name = name, IsKnown = false, Index = UnknownPoints.Count }); RefreshPointLists(); dgvUnknown.Rows[e.RowIndex].Cells["Name"].Value = ""; } } // 观测数据添加按钮事件 private void DgvObs_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == dgvObs.Columns["AddObs"].Index && e.RowIndex >= 0) { string from = dgvObs.Rows[e.RowIndex].Cells["FromPoint"].Value?.ToString(); string to = dgvObs.Rows[e.RowIndex].Cells["ToPoint"].Value?.ToString(); string diff = dgvObs.Rows[e.RowIndex].Cells["Difference"].Value?.ToString(); if (string.IsNullOrEmpty(from)) { MessageBox.Show("请选择起始点!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); dgvObs.CurrentCell = dgvObs.Rows[e.RowIndex].Cells["FromPoint"]; return; } if (string.IsNullOrEmpty(to)) { MessageBox.Show("请选择终止点!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); dgvObs.CurrentCell = dgvObs.Rows[e.RowIndex].Cells["ToPoint"]; return; } if (from == to) { MessageBox.Show("起始点和终止点不能相同!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } if (double.TryParse(diff, out double difference)) { var fromPoint = KnownPoints.Concat(UnknownPoints).FirstOrDefault(pt => pt.Name == from); var toPoint = KnownPoints.Concat(UnknownPoints).FirstOrDefault(pt => pt.Name == to); if (fromPoint != null && toPoint != null) { ObservationData.Add(Tuple.Create(fromPoint, toPoint, difference)); dgvObs.Rows[e.RowIndex].Cells["FromPoint"].Value = ""; dgvObs.Rows[e.RowIndex].Cells["ToPoint"].Value = ""; dgvObs.Rows[e.RowIndex].Cells["Difference"].Value = ""; // 添加新行用于输入下一条观测数据 dgvObs.Rows.Add(); } } else { MessageBox.Show("高差格式错误,请输入数字!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } } // 检查水准路线 private void BtnCheckRoute_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(cmbStartPoint.Text) || string.IsNullOrEmpty(cmbEndPoint.Text)) { MessageBox.Show("请选择起点和终点!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } if (ObservationData.Count == 0) { MessageBox.Show("请先录入观测数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 创建图结构存储点之间的关系 var graph = new Dictionary<string, List<Tuple<string, double>>>(); var allPoints = new HashSet<string>(); foreach (var obs in ObservationData) { string from = obs.Item1.Name; string to = obs.Item2.Name; double diff = obs.Item3; if (!graph.ContainsKey(from)) graph[from] = new List<Tuple<string, double>>(); if (!graph.ContainsKey(to)) graph[to] = new List<Tuple<string, double>>(); graph[from].Add(Tuple.Create(to, diff)); // 正向边:从起点到终点 graph[to].Add(Tuple.Create(from, -diff)); // 反向边:从终点到起点 allPoints.Add(from); allPoints.Add(to); } string start = cmbStartPoint.Text; string end = cmbEndPoint.Text; // 检查起点和终点是否在图中 if (!allPoints.Contains(start) || !allPoints.Contains(end)) { lblRouteStatus.Text = "起点或终点不在观测数据中!"; lblRouteStatus.BackColor = Color.Yellow; return; } // 使用BFS检查路径是否存在 var visited = new HashSet<string>(); var queue = new Queue<string>(); queue.Enqueue(start); visited.Add(start); while (queue.Count > 0) { var current = queue.Dequeue(); if (current == end) break; if (graph.ContainsKey(current)) { foreach (var neighbor in graph[current]) { if (!visited.Contains(neighbor.Item1)) { visited.Add(neighbor.Item1); queue.Enqueue(neighbor.Item1); } } } } if (!visited.Contains(end)) { lblRouteStatus.Text = "路线不连通:起点和终点之间没有路径!"; lblRouteStatus.BackColor = Color.Red; return; } // 计算闭合差 double totalDifference = 0; double knownDifference = 0; try { // 获取起点和终点的高程 double startElevation = KnownPoints.First(p => p.Name == start).Elevation; double endElevation = KnownPoints.First(p => p.Name == end).Elevation; knownDifference = endElevation - startElevation; // 计算观测高差总和 foreach (var obs in ObservationData) { totalDifference += obs.Item3; } // 计算闭合差(毫米) double closureError = (totalDifference - knownDifference) * 1000; // 读取用户输入的路线长度L(公里) double routeLength = (double)nudRouteLength.Value; // 按40√L mm公式计算允许闭合差 double allowableError = 40 * Math.Sqrt(routeLength); // 显示结果 if (Math.Abs(closureError) <= allowableError) { lblRouteStatus.Text = $"路线符合要求!\n闭合差: {closureError:F4} mm\n允许值: {allowableError:F4} mm"; lblRouteStatus.BackColor = Color.LightGreen; } else { lblRouteStatus.Text = $"路线超限!\n闭合差: {closureError:F4} mm\n允许值: {allowableError:F4} mm"; lblRouteStatus.BackColor = Color.Red; } } catch (Exception ex) { lblRouteStatus.Text = $"计算错误: {ex.Message}"; lblRouteStatus.BackColor = Color.Yellow; } } // 平差计算核心逻辑(简化版间接平差) private void BtnCalculate_Click(object sender, EventArgs e) { if (KnownPoints.Count == 0 || ObservationData.Count == 0) { MessageBox.Show("请先录入已知点和观测数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 初始化平差参数 double precision = (double)nudPrecision.Value / 1000.0; // 转换为米 var result = new Dictionary<string, double>(); var residuals = new Dictionary<Tuple<LevelPoint, LevelPoint, double>, double>(); var pointAccuracy = new Dictionary<string, double>(); // 步骤1:初始化已知点高程 KnownPoints.ForEach(p => result[p.Name] = p.Elevation); // 步骤2:初步计算未知点高程(简化传递) foreach (var obs in ObservationData) { if (result.ContainsKey(obs.Item1.Name)) { result[obs.Item2.Name] = result[obs.Item1.Name] + obs.Item3; } else if (result.ContainsKey(obs.Item2.Name)) { result[obs.Item1.Name] = result[obs.Item2.Name] - obs.Item3; } } // 步骤3:计算残差(简化逻辑,实际需用最小二乘法) foreach (var obs in ObservationData) { double calcDiff = result[obs.Item2.Name] - result[obs.Item1.Name]; double residual = obs.Item3 - calcDiff; residuals[obs] = residual; } // 步骤4:计算点位精度(简化逻辑) UnknownPoints.ForEach(pt => { int count = ObservationData.Count(obs => obs.Item1.Name == pt.Name || obs.Item2.Name == pt.Name); double accuracy = precision * Math.Sqrt(1 + count); pointAccuracy[pt.Name] = accuracy * 1000; }); // 显示结果 dgvResult.Rows.Clear(); foreach (var point in KnownPoints.Concat(UnknownPoints)) { double residual = 0; double accuracy = 0; if (UnknownPoints.Contains(point)) { residual = residuals.Values.Where(r => Math.Abs(r) < 1e-6).FirstOrDefault(); accuracy = pointAccuracy[point.Name]; } dgvResult.Rows.Add( point.Name, Math.Round(result[point.Name], 4), Math.Round(residual * 1000, 2), Math.Round(accuracy, 2) ); } MessageBox.Show("平差计算完成!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } // 清空数据按钮事件 private void BtnClear_Click(object sender, EventArgs e) { if (MessageBox.Show("确定要清空所有数据吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { KnownPoints.Clear(); UnknownPoints.Clear(); ObservationData.Clear(); dgvKnown.Rows.Clear(); dgvUnknown.Rows.Clear(); dgvObs.Rows.Clear(); dgvResult.Rows.Clear(); lblRouteStatus.Text = ""; lblRouteStatus.BackColor = SystemColors.Control; RefreshPointLists(); // 添加默认行到观测数据表格 dgvObs.Rows.Add(); } } } }结合这个代码,请给我生成6000字的设计报告
11-29
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猪猪派对

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

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

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

打赏作者

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

抵扣说明:

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

余额充值