基本算法
- 坐标方位角计算
- 内插点高程计算
- 断面面积计算
内容
- 道路纵断面计算
- 道路横断面计算
步骤
1 读取散点数据、关键点数据
数据结构:
- 散点类 DicretePoint
- 关键点类 KeyPoint
- 插值点类 InsertPoint
- 中心点类 CenterPoint
class DiscretePoint
{
public double X, Y, H;
public string id;
public double D;//用于记录与待插点的距离
public DiscretePoint(string id, double x, double y, double h)
{
this.id = id;
X = x;
Y = y;
H = h;
}
public DiscretePoint()
{
}
}
class KeyPoint
{
public double X, Y, H;
public string id;
public KeyPoint(string id , double x,double y,double h)
{
this.id = id;
X = x;
Y = y;
H = h;
}
public KeyPoint()
{
}
}
class InsertPoint
{
public double X, Y, H;
KeyPoint start = new KeyPoint();//起始的点
public List<DiscretePoint> nearpoint = new List<DiscretePoint>();//最邻近的点
public InsertPoint(List<DiscretePoint> Qs,KeyPoint start,double L,double alpha)
{
//X,Y坐标计算
this.start = start;//起始点
this.X = start.X + L * Math.Cos(alpha);
this.Y = start.Y + L * Math.Sin(alpha);
//H计算
//内插高程计算,检索最邻近的5个点进行高程计算
List<DiscretePoint> ps = new List<DiscretePoint>();
ps.AddRange(Qs);
for (int i = 0; i < ps.Count; i++)
{
ps[i].D = Math.Sqrt(Math.Pow(ps[i].Y-this.Y,2)+Math.Pow(ps[i].X-this.X,2));
}
//根据距离排序进行高程插值
ps.Sort((p1,p2)=>p1.D.CompareTo(p2.D));
double total_h = 0;
double total_d = 0;
for (int i = 0; i < 5; i++)//最近的五个点
{
nearpoint.Add(ps[i]);
total_d += 1.0 / ps[i].D;
total_h += ps[i].H / ps[i].D;
}
this.H = total_h / total_d;
}
public InsertPoint()
{
}
}
class CenterPoint
{
public double X, Y;
public string id;
public List<InsertPoint> Ps = new List<InsertPoint>();
public CenterPoint(string id, double Xa, double Ya, double Xb, double Yb)
{
this.id = id;
X = (Xa + Xb) / 2;
Y = (Ya + Yb) / 2;
}
public CenterPoint()
{
}
}
定义变量
DiscretePoint A = new DiscretePoint();
DiscretePoint B = new DiscretePoint();//测试点A,B
double H0;//参考面高程
List<string> Ks_name = new List<string>();//关键点点名
List<DiscretePoint> Qs = new List<DiscretePoint>();//离散点点集
List<KeyPoint> Ks = new List<KeyPoint>();//关键点点集
List<InsertPoint> Ps = new List<InsertPoint>();//插值点集
List<InsertPoint> KPs = new List<InsertPoint>();//加入关键点的内插点集合,用于计算面积
List<CenterPoint> Cps = new List<CenterPoint>();//横断面中心点
List<double> Di = new List<double>();//纵断面各段长度
Draw draw = new Draw();
数据读取
private void toolStripButton1_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog open = new OpenFileDialog();
if (open.ShowDialog() == DialogResult.OK)
{
StreamReader read = new StreamReader(open.FileName);
H0 = Convert.ToDouble(read.ReadLine().Split(',')[1]);
string[] s1 = read.ReadLine().Split(',');//关键点点名
string[] sa = read.ReadLine().Split(',');
string[] sb = read.ReadLine().Split(',');//A,B点
A.X = double.Parse(sa[1]); A.Y = double.Parse(sa[2]);
B.X = double.Parse(sb[1]); B.Y = double.Parse(sb[2]);
read.ReadLine();
while (!read.EndOfStream)
{
string[] sts = read.ReadLine().Split(',');
string id = sts[0];
double X = double.Parse(sts[1]);
double Y = double.Parse(sts[2]);
double H = double.Parse(sts[3]);
if (Regex.IsMatch(id, @"K\d+"))//关键点
{
KeyPoint K = new KeyPoint(id,X,Y,H);
Ks.Add(K);
}
else//离散点
{
DiscretePoint Q = new DiscretePoint(id,X,Y,H);
Qs.Add(Q);
}
}
}
2 道路纵断面计算
2.1计算断面长度
分段计算两关键点间距离
2.2计算内插点坐标
private void insertpoint()
{
double L = 10;
for (int i = 0; i < Ks.Count-1; i++)//遍历关键点对(K0,K1)(K1,K2)
{
InsertPoint k = new InsertPoint();//起始点,用于面积计算
k.X = Ks[i].X;
k.Y = Ks[i].Y;
k.H = Ks[i].H;
KPs.Add(k);
double xita = CalAzimuth(Ks[i + 1].X, Ks[i + 1].Y, Ks[i].X, Ks[i].Y);
for (int j = 0; j < Di[i] / 10-1; j++)//每一对关键点
{
InsertPoint p = new InsertPoint(Qs,Ks[i],L,xita);
Ps.Add(p);
KPs.Add(p);
L += 10;
}
L -= Di[i];
}
2.3计算面积
private double calzarea()
{
double area = 0;
for (int i = 0; i < KPs.Count-1; i++)
{
area += (KPs[i].H+KPs[i+1].H-2*H0) / 2 * 10;
}
return area;
}
3 道路横断面计算
3.1计算断面中心点
private void Calcenter()
{
richTextBox1.Text += "所有中心点坐标:\n";
for (int i = 0; i < Ks.Count-1; i++)
{
CenterPoint cp = new CenterPoint();
cp.X = (Ks[i].X+Ks[i+1].X) / 2;
cp.Y = (Ks[i].Y + Ks[i + 1].Y) / 2;
Cps.Add(cp);
richTextBox1.Text += cp.X.ToString("0.000") + "," + cp.Y.ToString("0.000") + ";\n";
}
}
3.2根据断面中心点进行插值
private void Insert2()
{
double L = 25;
double l = 5;
for (int i = 0; i < Cps.Count; i++)
{
double alpha = CalAzimuth(Ks[i].X, Ks[i].Y, Ks[i+1].X, Ks[i+1].Y) +Math.PI/2;
KeyPoint k = new KeyPoint();
k.X = Cps[i].X;k.Y = Cps[i].Y;
for (int j = 0; j < 2*25/l; j++)
{
InsertPoint inp = new InsertPoint(Qs, k, -L, alpha);
Cps[i].Ps.Add(inp);
L += l;
}
}
}
3.3计算横断面面积
private List<double> calharea()
{
richTextBox1.Text += "横断面面积:\n";
List<double> areas = new List<double>();
for (int i = 0; i < Cps.Count; i++)
{
double area = 0;
for (int j = 0; j < Cps[i].Ps.Count-1; j++)
{
area += (Cps[i].Ps[j+1].H+ Cps[i].Ps[j].H-2*H0) / 2 * 5;
}
areas.Add(area);
richTextBox1.Text += "第"+i+1+"个横断面:"+area.ToString("0.000")+"\n";
}
return areas;
}