读取道路关键点数据和散点数据,进行道路纵断面、横断面的相关点位计算,以及断面面积计算,将输出成果保存到指定的文件中。
1.类的定义
class KeyPoint
{
public string Name;
public double X;
public double Y;
public double H;
public KeyPoint(string name, double x, double y, double h)
{
this.Name = name;
this.X = x;
this.Y = y;
this.H = h;
}
}
class DiscretePoint
{
public string Name;
public double X;
public double Y;
public double H;
public double dis;
public DiscretePoint(string name, double x, double y, double h)
{
this.Name = name;
this.X = x;
this.Y = y;
this.H = h;
}
}
class InsertPoint
{
public string[] index;
public double X;
public double Y;
public double H;
public InsertPoint(List<DiscretePoint> Dp, double X, double Y, double L, double alpha)
{
this.X = X + L * Math.Cos(alpha);
this.Y = Y + L * Math.Sin(alpha);
index = SelectIndex(Dp, this.X, this.Y, 5);
H = InsertHeigh(Dp, this.X, this.Y, 5);
}
public double InsertHeigh(List<DiscretePoint> Dp, double X, double Y, int num)
{
double d = 0;
for (int i = 0; i < Dp.Count(); i++)
{
Dp[i].dis = Math.Sqrt(Math.Pow(X - Dp[i].X, 2) + Math.Pow(Y - Dp[i].Y, 2));
}
Dp = Dp.OrderBy(o => o.dis).ToList();
double total_h = 0, total_1 = 0;
for (int j = 0; j < num; j++)
{
d = Math.Sqrt(Math.Pow(X - Dp[j].X, 2) + Math.Pow(Y - Dp[j].Y, 2));
total_h += Dp[j].H / d;
total_1 += 1 / d;
}
return total_h / total_1;
}
public string[] SelectIndex(List<DiscretePoint> Dp, double X, double Y, int num)
{
string[] ind = new string[num];
for (int i = 0; i < Dp.Count(); i++)
{
Dp[i].dis = Math.Sqrt(Math.Pow(X - Dp[i].X, 2) + Math.Pow(Y - Dp[i].Y, 2));
}
Dp = Dp.OrderBy(o => o.dis).ToList();
for (int k = 0; k < num; k++)
{
ind[k] = Dp[k].Name;
}
return ind;
}
}
class CenterPoint
{
public double X;
public double Y;
public List<InsertPoint> insert = new List<InsertPoint>();
public CenterPoint(double X, double Y)
{
this.X = X;
this.Y = Y;
}
}
class ABpoint
{
public string Name;
public double X;
public double Y;
}
2.计算部分实现
class Cal
{
//方位角计算
public static double amuzith(double deltaY,double deltaX)
{
if (deltaX > 0)
{
return Math.Atan(deltaY / deltaX);
}
else
{
return Math.Atan(deltaY / deltaX) + Math.PI;
}
}
//纵断面分段长度计算
public static double[] divideLenth(List<KeyPoint> Kp)
{
double[] Lenth = new double[Kp.Count() - 1];
for(int i = 0; i < Kp.Count()-1; i++)
{
Lenth[i]= Math.Sqrt(Math.Pow(Kp[i + 1].X - Kp[i].X, 2) + Math.Pow(Kp[i + 1].Y - Kp[i].Y, 2));
}
return Lenth;
}
//纵断面总长度计算
public static double totalLenth(double[] Lenth)
{
double totalLenth = 0;
for(int i = 0; i < Lenth.Count(); i++)
{
totalLenth += Lenth[i];
}
return totalLenth;
}
//添加内插点
public static List<InsertPoint> Insertpoint(List<KeyPoint> Kp,List<DiscretePoint> Dp,double[] Lenth)
{
List<InsertPoint> Ip = new List<InsertPoint>();
double L = 10;
for(int i = 0; i < Kp.Count() - 1; i++)
{
double deltaY = Kp[i + 1].Y - Kp[i].Y;
double deltaX = Kp[i + 1].X - Kp[i].X;
double sigma = amuzith(deltaY, deltaX);
for(int j = 0; j < Lenth[i] / 10 - 1; j++)
{
InsertPoint Inp = new InsertPoint(Dp, Kp[i].X, Kp[i].Y, L, sigma);
Ip.Add(Inp);
L += 10;
}
L -= Lenth[i];
}
return Ip;
}
//断面面积计算
public static double Area(List<InsertPoint> Ip,List<KeyPoint> Kp,double L,double h0,double[] Lenth)
{
double S = 0;
for (int i = 0; i < Ip.Count(); i++)
{
if (i == 0)
S += (Ip[0].H + Kp[0].H - 2 * h0) / 2 * 10;
if (i == 3)
S += (Kp[1].H + Ip[3].H - 2 * h0) / 2 * (Lenth[0] % 10);
if (i == 4)
S += (Kp[1].H + Ip[4].H - 2 * h0) / 2 * (10 - Lenth[0] % 10);
if (i == Ip.Count() - 1)
S += (Kp[2].H + Ip[i].H - 2 * h0) / 2 * (Lenth[1] % 10);
else
S += (Ip[i].H + Ip[i + 1].H - 2 * h0) / 2 * 10;
}
return S;
}
//横断面中心点坐标
public static List<CenterPoint> Centerpoint(List<KeyPoint> Kp)
{
List<CenterPoint> Cp = new List<CenterPoint>();
double x = 0, y = 0;
for(int i = 0; i < Kp.Count()-1; i++)
{
x = (Kp[i].X + Kp[i + 1].X) / 2;
y = (Kp[i].Y + Kp[i + 1].Y) / 2;
CenterPoint cp = new CenterPoint(x, y);
Cp.Add(cp);
}
return Cp;
}
//横断面内插点
public static List<CenterPoint> InsertPoint2(List<CenterPoint> Cp,List<KeyPoint> Kp,List<DiscretePoint> Dp)
{
for(int i = 0; i < Cp.Count(); i++)
{
double distance = -25;
double deltaY = Kp[i + 1].Y - Kp[i].Y;
double deltaX = Kp[i + 1].X - Kp[i].X;
double alaph = amuzith(deltaY, deltaX) + Math.PI / 2;
for(int j = 0; j <= 25 * 2 / 5; j++)
{
InsertPoint insertpoint = new InsertPoint(Dp, Cp[i].X, Cp[i].Y, distance, alaph);
Cp[i].insert.Add(insertpoint);
distance += 5;
}
}
return Cp;
}
//横断面面积
public static double[] crossArea(List<CenterPoint> Cp,double h0)
{
double[] S = new double[Cp.Count()];
for(int i = 0; i < Cp.Count(); i++)
{
for(int j = 0; j < Cp[i].insert.Count() - 1; j++)
{
S[i] += (Cp[i].insert[j].H + Cp[i].insert[j + 1].H - 2 * h0) / 2 * 5;
}
}
return S;
}
}
这里纵断面的计算个人感觉有些问题,使用了比较呆的办法,最后算出来的结果也不一定正确。
3.Form.cs
public partial class Form1 : Form
{
List<DiscretePoint> Dp = new List<DiscretePoint>();
List<KeyPoint> Kp = new List<KeyPoint>();
List<InsertPoint> Ip = new List<InsertPoint>();
List<CenterPoint> Cp = new List<CenterPoint>();
List<ABpoint> AB = new List<ABpoint>();
double H0;
string report = null;
public Form1()
{
InitializeComponent();
}
private void 读取文件数据ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog op = new OpenFileDialog();
op.Filter = "文本文件(*.txt)|*.txt";
if (op.ShowDialog() == DialogResult.OK)
{
string filepath = op.FileName;
StreamReader sr = new StreamReader(filepath);
string[] Info = sr.ReadLine().Split(',');
H0 = Convert.ToDouble(Info[1]);
sr.ReadLine();
//A B
for (int i = 0; i < 2; i++)
{
ABpoint ab = new ABpoint();
Info = sr.ReadLine().Split(',');
ab.Name = Convert.ToString(Info[0]);
ab.X = Convert.ToDouble(Info[1]);
ab.Y = Convert.ToDouble(Info[2]);
AB.Add(ab);
}
sr.ReadLine();
//提取离散点数据和关键点
while (!sr.EndOfStream)
{
Info = sr.ReadLine().Split(',');
string Name = Info[0];
double X = Convert.ToDouble(Info[1]);
double Y = Convert.ToDouble(Info[2]);
double H = Convert.ToDouble(Info[3]);
if (Regex.IsMatch(Name, @"K\d"))
{
KeyPoint K = new KeyPoint(Name, X, Y, H);
Kp.Add(K);
}
else
{
DiscretePoint D = new DiscretePoint(Name, X, Y, H);
Dp.Add(D);
}
}
MessageBox.Show("读取成功!");
ShowData(Kp, Dp);
}
}
catch
{
throw;
}
}
private void 纵断面计算ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
double[] Lenth = Cal.divideLenth(Kp);
double total = Cal.totalLenth(Lenth);
report += "\t----------------------------纵断面长度----------------------------\n";
foreach (var item in Lenth)
{
report += "\t分长度:" + item.ToString("0.000") + "\t";
}
report += "\n\t总长度:" + total.ToString("0.000") + "\t\n";
Ip = Cal.Insertpoint(Kp, Dp, Lenth);
report += "\t-----------------------------内插点-----------------------------\n";
report += "\t关键点\n " + "\t" + "X坐标(m)" + "\t" + "Y坐标(m)" + "\t" + "H坐标(m)\n";
foreach (InsertPoint item in Ip)
{
report += "\t" + item.X.ToString("0.000") + "\t" + item.Y.ToString("0.000") + "\t" + item.H.ToString("0.000") + "\n";
}
double S = Cal.Area(Ip, Kp, 10, H0, Lenth);
report += "\t---------------------------纵断面面积-----------------------------\n";
report += "\t" + S.ToString("0.000") + "\n";
richTextBox2.Text = report;
tabControl1.SelectedIndex = 1;
}
catch
{
throw;
}
}
private void 横断面计算ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
Cp = Cal.Centerpoint(Kp);
report += "\t-----------------------------中心点-----------------------------\n";
report += "\tX坐标(m)" + "\t" + "Y坐标(m)" + "\t" + "\n";
foreach (CenterPoint item in Cp)
{
report += "\t" + item.X.ToString("0.000") + "\t" + item.Y.ToString("0.000") + "\t" + "\n";
}
Cp = Cal.InsertPoint2(Cp, Kp, Dp);
report += "\t----------------------------横断内插点----------------------------\n";
report += "\tX坐标(m)" + "\t" + "Y坐标(m)" + "\t" + "H坐标(m)\n";
foreach (CenterPoint item in Cp)
{
for (int j = 0; j < item.insert.Count(); j++)
{
report += "\tP" + j.ToString("0") + "\t" + item.insert[j].X.ToString("0.000") + "\t" + item.insert[j].Y.ToString("0.000") + "\t" + item.insert[j].H.ToString("0.000") + "\t最近五个离散点点号:";
report += "\t" + item.insert[j].index[0] + " " + item.insert[j].index[1] + " " + item.insert[j].index[2] + " " + item.insert[j].index[3] + " " + item.insert[j].index[4] + "\n";
}
report += "\n";
}
double[] S = Cal.crossArea(Cp, H0);
report += "\t----------------------------横断面面积----------------------------\n";
foreach (double item in S)
{
report += "\t分断面面积:" + item.ToString("0.000") + "\t";
}
richTextBox2.Text = report;
tabControl1.SelectedIndex = 1;
}
catch
{
throw;
}
}
private void 导出RToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
SaveFileDialog sf = new SaveFileDialog();
sf.Filter = "文本文件(*.txt)|*.txt";
if (sf.ShowDialog() == DialogResult.OK)
{
string filepath = sf.FileName;
StreamWriter sw = new StreamWriter(filepath);
sw.Write(report);
sw.Close();
}
MessageBox.Show("导出成功!");
}
catch
{
}
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
读取文件数据ToolStripMenuItem_Click(sender, e);
}
private void toolStripButton2_Click(object sender, EventArgs e)
{
try
{
纵断面计算ToolStripMenuItem_Click(sender, e);
横断面计算ToolStripMenuItem_Click(sender, e);
}
catch
{
throw;
}
}
private void toolStripButton3_Click(object sender, EventArgs e)
{
MessageBox.Show("按提示进行操作!");
}
private void toolStripButton4_Click(object sender, EventArgs e)
{
导出RToolStripMenuItem_Click(sender, e);
}
private void toolStripButton5_Click(object sender, EventArgs e)
{
Close();
}
private void ShowData(List<KeyPoint> Ks,List<DiscretePoint> Ds)
{
try
{
string report = null;
report = "\t----------------------------读取结果----------------------------\n";
report += "\t关键点\n\t点名 \tX坐标(m)\tY坐标(m)\tH坐标(m)\n";
foreach (KeyPoint item in Ks)
{
report += "\t" + item.Name + "\t" + item.X.ToString("0.000") + "\t" + item.Y.ToString("0.000") + "\t" + item.H.ToString("0.000") + "\n";
}
report += "\t离散点\n\t点名 \tX坐标(m)\tY坐标(m)\tH坐标(m)\n";
foreach (DiscretePoint item in Ds)
{
report += "\t" + item.Name + "\t" + item.X.ToString("0.000") + "\t" + item.Y.ToString("0.000") + "\t" + item.H.ToString("0.000") + "\n";
}
richTextBox1.Text = report;
toolStripStatusLabel1.Text = "状态:读取成功!";
}
catch
{
}
}
}
运行过程如图所示
附带功能是计算以及保存,由于赛制的变更以及自身实力有限所以没有做相关的绘图功能,欢迎各位探讨,源码我会放在资源里。