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字的设计报告