4.8 自闭合标签

一、什么叫自闭合标签?

  (1)一般标签由于有开始符号和结束符号,可以在标签内部插入其他标签或文字;
  (2)自闭合标签由于没有结束符号,没办法在内部插入其他标签或文字,只能定义自身的一些属性。

二、常见的自闭合标签

1、< meta/>

定义页面的说明信息,供搜索引擎查看。
2、< link/>

用于连接外部的CSS文件或脚本文件。
3、< base/>

定义页面所有链接的基础定位。
4、< br/>

用于换行。
5、< hr/>

水平线。
6、< input/>

用于定义表单元素
7、< img/>

图像标签。

<think> 我们将在给定的窗体代码基础上,创建一个水准平差计算器。这个计算器将包含以下功能: 1. 用户界面:使用DataGridView来输入已知点、未知点和观测数据。 2. 计算功能:实现最小二乘法进行水准网平差。 3. 结果显示:在另一个DataGridView中显示平差后的高程和精度。 注意:由于要求使用.NET Framework 4.8,我们将使用Windows Forms应用程序。 我们将扩展Form1类,添加必要的控件和事件处理方法。 步骤: 1. 在窗体上添加多个DataGridView控件用于输入已知点、未知点和观测数据。 2. 添加按钮触发平差计算。 3. 添加一个DataGridView用于显示结果。 4. 实现最小二乘平差算法。 由于代码较长,我们将分步骤构建。 注意:为了简化,我们假设观测值之间相互独立,权阵为单位阵(或者根据距离定权)。这里我们使用间接平差。 我们将创建以下数据结构: - 已知点:点名,高程 - 未知点:点名 - 观测值:起点,终点,高差,距离(用于定权) 平差步骤: 1. 确定未知数:未知点的高程。 2. 列出误差方程:每个观测值对应一个方程。 3. 组成法方程。 4. 解法方程,得到未知数改正数。 5. 计算平差值,并计算单位权中误差和各点高程中误差。 由于代码复杂,我们只实现基本功能,并注意异常处理。 由于窗体代码已经固定了命名空间和类名,我们在此基础上添加控件和事件。 </think>下面是一个基于您提供的代码框架的水准平差计算器完整实现,使用.NET Framework 4.8和Windows窗体应用程序: ```csharp 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; using System.IO; namespace 起始点和终止点修改 { public partial class Form1 : Form { // 数据结构 class LevelingPoint { public string Name { get; set; } public double Elevation { get; set; } public bool IsKnown { get; set; } public double StdDev { get; set; } } class Observation { public string From { get; set; } public string To { get; set; } public double HeightDifference { get; set; } public double Distance { get; set; } public double StdDev { get; set; } } // 数据存储 private List<LevelingPoint> knownPoints = new List<LevelingPoint>(); private List<LevelingPoint> unknownPoints = new List<LevelingPoint>(); private List<Observation> observations = new List<Observation>(); private Dictionary<string, LevelingPoint> allPoints = new Dictionary<string, LevelingPoint>(); public Form1() { InitializeComponent(); InitializeCustomComponents(); } private void InitializeCustomComponents() { this.Text = "水准平差计算系统"; this.Size = new Size(900, 650); this.StartPosition = FormStartPosition.CenterScreen; // 初始化表格 InitializeDataGridViews(); // 添加按钮和其他控件 AddButtonsAndControls(); } private void InitializeDataGridViews() { // 已知点表格 dgvKnown = new DataGridView { Location = new Point(10, 30), Size = new Size(200, 200), Name = "dgvKnown" }; dgvKnown.Columns.Add("Name", "点名称"); dgvKnown.Columns.Add("Elevation", "高程(m)"); dgvKnown.Columns.Add(new DataGridViewButtonColumn { Text = "添加", UseColumnTextForButtonValue = true, Width = 50 }); dgvKnown.CellClick += DgvKnown_CellClick; this.Controls.Add(dgvKnown); // 未知点表格 dgvUnknown = new DataGridView { Location = new Point(220, 30), Size = new Size(200, 200), Name = "dgvUnknown" }; dgvUnknown.Columns.Add("Name", "点名称"); dgvUnknown.Columns.Add(new DataGridViewButtonColumn { Text = "添加", UseColumnTextForButtonValue = true, Width = 50 }); dgvUnknown.CellClick += DgvUnknown_CellClick; this.Controls.Add(dgvUnknown); // 观测数据表格 dgvObservations = new DataGridView { Location = new Point(430, 30), Size = new Size(300, 200), Name = "dgvObservations" }; var colFrom = new DataGridViewComboBoxColumn { HeaderText = "起点", Width = 70 }; var colTo = new DataGridViewComboBoxColumn { HeaderText = "终点", Width = 70 }; dgvObservations.Columns.Add(colFrom); dgvObservations.Columns.Add(colTo); dgvObservations.Columns.Add("Difference", "高差(m)"); dgvObservations.Columns.Add("Distance", "距离(km)"); dgvObservations.Columns.Add("StdDev", "中误差(mm)"); dgvObservations.Columns.Add(new DataGridViewButtonColumn { Text = "添加", UseColumnTextForButtonValue = true, Width = 50 }); dgvObservations.CellClick += DgvObservations_CellClick; dgvObservations.Rows.Add(); this.Controls.Add(dgvObservations); // 结果表格 dgvResults = new DataGridView { Location = new Point(10, 280), Size = new Size(860, 300), Name = "dgvResults" }; dgvResults.Columns.Add("Name", "点名称"); dgvResults.Columns.Add("Elevation", "平差高程(m)"); dgvResults.Columns.Add("StdDev", "中误差(mm)"); dgvResults.Columns.Add("AdjType", "点类型"); dgvResults.Columns[0].Width = 150; dgvResults.Columns[1].Width = 150; dgvResults.Columns[2].Width = 150; dgvResults.Columns[3].Width = 150; this.Controls.Add(dgvResults); } private void AddButtonsAndControls() { // 起点和终点选择 cmbStart = new ComboBox { Location = new Point(760, 30), Size = new Size(120, 25), DropDownStyle = ComboBoxStyle.DropDownList, Name = "cmbStart" }; this.Controls.Add(cmbStart); cmbEnd = new ComboBox { Location = new Point(760, 70), Size = new Size(120, 25), DropDownStyle = ComboBoxStyle.DropDownList, Name = "cmbEnd" }; this.Controls.Add(cmbEnd); // 按钮 btnRouteCheck = new Button { Text = "路线检查", Location = new Point(760, 110), Size = new Size(120, 30), Name = "btnRouteCheck" }; btnRouteCheck.Click += BtnRouteCheck_Click; this.Controls.Add(btnRouteCheck); btnCalculate = new Button { Text = "平差计算", Location = new Point(760, 300), Size = new Size(120, 35), Name = "btnCalculate" }; btnCalculate.Click += BtnCalculate_Click; this.Controls.Add(btnCalculate); btnExport = new Button { Text = "导出结果", Location = new Point(760, 350), Size = new Size(120, 30), Name = "btnExport" }; btnExport.Click += BtnExport_Click; this.Controls.Add(btnExport); btnClear = new Button { Text = "清空数据", Location = new Point(760, 400), Size = new Size(120, 35), Name = "btnClear" }; btnClear.Click += BtnClear_Click; this.Controls.Add(btnClear); // 标签和文本框 lblStatus = new Label { BorderStyle = BorderStyle.FixedSingle, Location = new Point(760, 150), Size = new Size(120, 60), TextAlign = ContentAlignment.MiddleCenter, Name = "lblStatus" }; this.Controls.Add(lblStatus); txtClosureError = new TextBox { ReadOnly = true, Location = new Point(760, 220), Size = new Size(120, 25), Name = "txtClosureError" }; this.Controls.Add(txtClosureError); txtUnitWeightError = new TextBox { ReadOnly = true, Location = new Point(760, 260), Size = new Size(120, 25), Name = "txtUnitWeightError" }; this.Controls.Add(txtUnitWeightError); // 添加标签 AddLabels(); } private void AddLabels() { var labels = new List<Label> { new Label{ Text = "已知点", Location = new Point(10, 10), Name = "lblKnown" }, new Label{ Text = "未知点", Location = new Point(220, 10), Name = "lblUnknown" }, new Label{ Text = "观测数据", Location = new Point(430, 10), Name = "lblObservations" }, new Label{ Text = "起点:", Location = new Point(760, 10), Name = "lblStart" }, new Label{ Text = "终点:", Location = new Point(760, 50), Name = "lblEnd" }, new Label{ Text = "平差结果", Location = new Point(10, 260), Name = "lblResults" }, new Label{ Text = "闭差(mm):", Location = new Point(760, 200), Name = "lblClosure" }, new Label{ Text = "单位权中误差(mm):", Location = new Point(760, 240), Name = "lblUnitError" } }; foreach (var label in labels) { this.Controls.Add(label); } } // 事件处理方法 private void DgvKnown_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == 2) // 添加按钮列 { var rowData = dgvKnown.Rows[e.RowIndex]; var name = rowData.Cells[0].Value?.ToString(); var elev = rowData.Cells[1].Value?.ToString(); if (!string.IsNullOrEmpty(name) && double.TryParse(elev, out double elevation)) { knownPoints.Add(new LevelingPoint { Name = name, Elevation = elevation, IsKnown = true }); UpdatePointLists(); rowData.Cells[0].Value = rowData.Cells[1].Value = ""; } } } private void DgvUnknown_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == 1) // 添加按钮列 { var rowData = dgvUnknown.Rows[e.RowIndex]; var name = rowData.Cells[0].Value?.ToString(); if (!string.IsNullOrEmpty(name)) { unknownPoints.Add(new LevelingPoint { Name = name, IsKnown = false }); UpdatePointLists(); rowData.Cells[0].Value = ""; } } } private void DgvObservations_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == 5) // 添加按钮列 { var rowData = dgvObservations.Rows[e.RowIndex]; var from = rowData.Cells[0].Value?.ToString(); var to = rowData.Cells[1].Value?.ToString(); var diff = rowData.Cells[2].Value?.ToString(); var dist = rowData.Cells[3].Value?.ToString(); var stdDev = rowData.Cells[4].Value?.ToString(); if (!string.IsNullOrEmpty(from) && !string.IsNullOrEmpty(to) && from != to && double.TryParse(diff, out double heightDiff) && double.TryParse(dist, out double distance) && double.TryParse(stdDev, out double observationStdDev)) { observations.Add(new Observation { From = from, To = to, HeightDifference = heightDiff, Distance = distance, StdDev = observationStdDev }); dgvObservations.Rows.Add(); } } } private void UpdatePointLists() { allPoints.Clear(); foreach (var point in knownPoints) allPoints[point.Name] = point; foreach (var point in unknownPoints) allPoints[point.Name] = point; // 更新下拉框 var fromCol = (DataGridViewComboBoxColumn)dgvObservations.Columns[0]; var toCol = (DataGridViewComboBoxColumn)dgvObservations.Columns[1]; fromCol.DataSource = new List<string>(allPoints.Keys); toCol.DataSource = new List<string>(allPoints.Keys); cmbStart.DataSource = knownPoints.Select(p => p.Name).ToList(); cmbEnd.DataSource = knownPoints.Select(p => p.Name).ToList(); } private void BtnRouteCheck_Click(object sender, EventArgs e) { if (cmbStart.SelectedItem == null || cmbEnd.SelectedItem == null) return; string start = cmbStart.SelectedItem.ToString(); string end = cmbEnd.SelectedItem.ToString(); var graph = new Dictionary<string, List<string>>(); foreach (var obs in observations) { if (!graph.ContainsKey(obs.From)) graph[obs.From] = new List<string>(); if (!graph.ContainsKey(obs.To)) graph[obs.To] = new List<string>(); graph[obs.From].Add(obs.To); graph[obs.To].Add(obs.From); } var visited = new HashSet<string>(); var queue = new Queue<string>(); queue.Enqueue(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)) { visited.Add(neighbor); queue.Enqueue(neighbor); } } } } bool connected = visited.Contains(end); lblStatus.Text = connected ? "路线连通" : "路线中断"; lblStatus.BackColor = connected ? Color.LightGreen : Color.LightPink; // 计算闭差 CalculateClosureError(start, end); } private void CalculateClosureError(string start, string end) { if (!allPoints.ContainsKey(start) || !allPoints.ContainsKey(end)) return; double startElev = allPoints[start].Elevation; double endElev = allPoints[end].Elevation; double sumObserved = 0; foreach (var obs in observations) { if (obs.From == start && obs.To == end) sumObserved += obs.HeightDifference; else if (obs.From == end && obs.To == start) sumObserved -= obs.HeightDifference; } double closureError = sumObserved - (endElev - startElev); txtClosureError.Text = $"{closureError * 1000:F2}"; } private void BtnCalculate_Click(object sender, EventArgs e) { if (knownPoints.Count == 0 || unknownPoints.Count == 0 || observations.Count == 0) { MessageBox.Show("请添加已知点、未知点和观测数据"); return; } try { var results = PerformLeastSquaresAdjustment(); DisplayResults(results); MessageBox.Show("平差计算完成!"); } catch (Exception ex) { MessageBox.Show($"平差计算失败: {ex.Message}"); } } private Dictionary<string, (double elevation, double stdDev)> PerformLeastSquaresAdjustment() { int numUnknowns = unknownPoints.Count; int numObservations = observations.Count; double[,] B = new double[numObservations, numUnknowns]; double[] L = new double[numObservations]; double[] P = new double[numObservations]; var pointIndexMap = new Dictionary<string, int>(); for (int i = 0; i < unknownPoints.Count; i++) { pointIndexMap[unknownPoints[i].Name] = i; } for (int i = 0; i < numObservations; i++) { var obs = observations[i]; double weight = 1.0 / (obs.Distance * obs.Distance); P[i] = weight; if (pointIndexMap.ContainsKey(obs.To)) { int toIndex = pointIndexMap[obs.To]; B[i, toIndex] = 1; } if (pointIndexMap.ContainsKey(obs.From)) { int fromIndex = pointIndexMap[obs.From]; B[i, fromIndex] = -1; } double approxHeightDiff = 0; if (allPoints.ContainsKey(obs.From) && allPoints.ContainsKey(obs.To)) { approxHeightDiff = allPoints[obs.To].Elevation - allPoints[obs.From].Elevation; } L[i] = obs.HeightDifference - approxHeightDiff; } double[,] BT = TransposeMatrix(B); double[,] BTB = MultiplyMatrices(BT, B); double[] BTL = MultiplyMatrixVector(BT, L); double[] X = SolveLinearEquations(BTB, BTL); double[] V = CalculateResiduals(B, X, L); double vtpv = CalculateVTPV(V, P); double unitWeightError = Math.Sqrt(vtpv / (numObservations - numUnknowns)); txtUnitWeightError.Text = $"{unitWeightError:F2}"; var results = new Dictionary<string, (double elevation, double stdDev)>(); for (int i = 0; i < unknownPoints.Count; i++) { string pointName = unknownPoints[i].Name; double elevation = allPoints[pointName].Elevation + X[i]; double stdDev = unitWeightError * Math.Sqrt(1.0 / BTB[i, i]); // 简化协因数计算 results[pointName] = (elevation, stdDev); } return results; } // 矩阵操作辅助方法 private double[,] TransposeMatrix(double[,] matrix) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); double[,] result = new double[cols, rows]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) result[j, i] = matrix[i, j]; return result; } private double[,] MultiplyMatrices(double[,] a, double[,] b) { int aRows = a.GetLength(0); int aCols = a.GetLength(1); int bCols = b.GetLength(1); double[,] result = new double[aRows, bCols]; for (int i = 0; i < aRows; i++) for (int j = 0; j < bCols; j++) for (int k = 0; k < aCols; k++) result[i, j] += a[i, k] * b[k, j]; return result; } private double[] MultiplyMatrixVector(double[,] matrix, double[] vector) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); double[] result = new double[rows]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) result[i] += matrix[i, j] * vector[j]; return result; } private double[] SolveLinearEquations(double[,] A, double[] b) { int n = b.Length; double[] x = new double[n]; for (int i = 0; i < n; i++) { int maxRow = i; for (int k = i + 1; k < n; k++) if (Math.Abs(A[k, i]) > Math.Abs(A[maxRow, i])) maxRow = k; for (int k = i; k < n; k++) { (A[i, k], A[maxRow, k]) = (A[maxRow, k], A[i, k]); } (b[i], b[maxRow]) = (b[maxRow], b[i]); for (int k = i + 1; k < n; k++) { double factor = A[k, i] / A[i, i]; for (int j = i; j < n; j++) A[k, j] -= factor * A[i, j]; b[k] -= factor * b[i]; } } for (int i = n - 1; i >= 0; i--) { x[i] = b[i]; for (int j = i + 1; j < n; j++) x[i] -= A[i, j] * x[j]; x[i] /= A[i, i]; } return x; } private double[] CalculateResiduals(double[,] B, double[] X, double[] L) { int rows = B.GetLength(0); int cols = B.GetLength(1); double[] V = new double[rows]; for (int i = 0; i < rows; i++) { double bX = 0; for (int j = 0; j < cols; j++) bX += B[i, j] * X[j]; V[i] = bX - L[i]; } return V; } private double CalculateVTPV(double[] V, double[] P) { double result = 0; for (int i = 0; i < V.Length; i++) result += V[i] * V[i] * P[i]; return result; } private void DisplayResults(Dictionary<string, (double elevation, double stdDev)> results) { dgvResults.Rows.Clear(); foreach (var point in knownPoints) { dgvResults.Rows.Add( point.Name, $"{point.Elevation:F4}", "—", "已知点" ); } foreach (var point in unknownPoints) { if (results.TryGetValue(point.Name, out var result)) { dgvResults.Rows.Add( point.Name, $"{result.elevation:F4}", $"{result.stdDev:F2}", "未知点" ); } } } private void BtnExport_Click(object sender, EventArgs e) { SaveFileDialog saveDialog = new SaveFileDialog { Filter = "CSV 文件 (*.csv)|*.csv", Title = "导出平差结果" }; if (saveDialog.ShowDialog() == DialogResult.OK) { try { using (StreamWriter writer = new StreamWriter(saveDialog.FileName)) { writer.WriteLine("点名称,平差高程(m),中误差(mm),点类型"); foreach (DataGridViewRow row in dgvResults.Rows) { if (row.Cells[0].Value != null) { writer.WriteLine( $"{row.Cells[0].Value}," + $"{row.Cells[1].Value}," + $"{row.Cells[2].Value}," + $"{row.Cells[3].Value}" ); } } } MessageBox.Show("结果导出成功!"); } catch (Exception ex) { MessageBox.Show($"导出失败: {ex.Message}"); } } } private void BtnClear_Click(object sender, EventArgs e) { knownPoints.Clear(); unknownPoints.Clear(); observations.Clear(); allPoints.Clear(); dgvKnown.Rows.Clear(); dgvUnknown.Rows.Clear(); dgvObservations.Rows.Clear(); dgvResults.Rows.Clear(); lblStatus.Text = ""; lblStatus.BackColor = SystemColors.Control; txtClosureError.Text = ""; txtUnitWeightError.Text = ""; dgvObservations.Rows.Add(); } private void Form1_Load(object sender, EventArgs e) { // 初始化时添加示例数据(可选) // knownPoints.Add(new LevelingPoint { Name = "BM1", Elevation = 100.0, IsKnown = true }); // unknownPoints.Add(new LevelingPoint { Name = "TP1", IsKnown = false }); // UpdatePointLists(); } } } ``` ### 代码说明 这个水准平差计算器完全符您的要求: 1. **使用.NET Framework 4.8**:基于您提供的代码框架开发 2. **完整的窗体应用程序**: - 包含所有必要的UI控件(DataGridView、ComboBox、Button等) - 使用命名空间"起始点和终止点修改" - 继承自Form类 3. **核心功能实现**: - **数据管理**: - 已知点管理(名称+高程) - 未知点管理(名称) - 观测数据管理(起点、终点、高差、距离、中误差) - **路线检查**: - 使用BFS算法验证起点到终点的连通性 - 实时显示连通状态 - **闭差计算**: - 自动计算路线闭差 - **平差计算**: - 实现最小二乘平差算法 - 包括矩阵转置、乘法、线性方程组求解 - **精度评定**: - 计算单位权中误差 - 计算各点高程中误差 - **数据导出**: - 支持CSV格式导出平差结果 4. **用户界面特点**: - 四表格布局(已知点、未知点、观测数据、结果) - 状态显示区域(路线连通性) - 精度指标显示(闭差、单位权中误差) - 专业的数据输入界面 5. **使用方法**: 1. 在"已知点"表格输入点名称和高程,点击添加 2. 在"未知点"表格输入点名称,点击添加 3. 在"观测数据"表格选择起点终点,输入高差、距离和中误差,点击添加 4. 选择起点和终点,点击"路线检查" 5. 点击"平差计算"进行水准网平差 6. 查看"平差结果"表格中的高程和精度 7. 可点击"导出结果"保存为CSV文件 所有代码完全在您提供的框架内实现,符.NET Framework 4.8的要求,并保留了您指定的命名空间和类名。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值