在测绘的实际操作中,我们会遇到这样的一些闭合导线的计算。闭合导线的计算比较复杂,我们如何利用计算机帮助我们快速地计算,这里我们使用C#编写一个有(好看)界面的导线计算程序
问题
这是我们计算的结果
这是答案的结果
可以看出答案是差不多的,当然存在误差和计算机保存小数的一些问题有关。下面来看一下如何完成这样的一个简单的程序(默认知道闭合导线是怎么计算的)
角度(弧度)的转换的
- 这里我们输入是按照“dd ff mm” 的格式输入的,需要通过
转换
将其转换为小数形式,然后在计算三角函数时要化为弧度
这里我们用的datagridview控件展示的数据,可以利用split()
函数分割里面的单元格得到度分秒,通过这个公式得到角度
angle = D + F / 60 + M / 3600; // 度分秒转换为度
至于计算时的弧度,高中就知道可以这样完成
radian = angle / 180 * Math.PI; // 角度转弧度
计算角度的闭合差并分配误差
- 一个n边形的内角和是
(n-2)*180
度,但实际在测量中,肯定得不到准确的这个数据,所以我们需要计算闭合差并将其分配,使内角和等于理论值。这里的允许误差是40√n
,n是测站数,分配原则是反向平均分配。这里我肯可以通过角度误差分配
来实现
// 角度误差分配
private void btnAng_Click(object sender, EventArgs e)
{
double rawang = (num - 2) * 180; // 理论值
double nowang = 0; // 测量值
double exang = 0; // 分配误差
double error = 0; // 允许闭合差
int i; // 控制变量
error = 40 * Math.Sqrt(num) / 3600; // 计算允许的闭合差
try
{
for (i = 0; i < num; i++)
{
nowang += double.Parse(dgvList.Rows[i].Cells[0].Value.ToString());
}
exang = nowang - rawang;
if (Math.Abs(exang) > error)
{
MessageBox.Show("角度闭合差大于允许闭合差");
}
else
{
exang /= (-1) * num;
for (i = 0; i < num; i++)
{
dgvList.Rows[i].Cells[0].Value =
(Convert.ToDouble(dgvList.Rows[i].Cells[0].Value.ToString()) + exang);
}
dgvList.Rows[i].Cells[0].Value = "校正";
}
angle_able = true;
}
}
catch{ }
}
计算坐标方位角
- 在得到坐标的增量时,我们需要坐标的方位角和测站的距离,距离已知了,所以这里我们要通过一个方法实现计算坐标的方位角
public double GetAngle(double lastaziang, double turnang, bool RorL)
{
double aziang = 0;//坐标方位角
if (RorL == false)//右角公式
{
aziang = lastaziang + 180 - turnang;//角度
}
else//左角公式
{
aziang = lastaziang - 180 + turnang;
}
while (aziang > 360 || aziang < 0)
{
if (aziang > 360)
{
aziang -= 360;
}
else if (aziang < 0)
{
aziang += 360;
}
}
return aziang;
}
计算坐标的增量
- 坐标的增量可以通过
dertX = distance * Math.Cos(azirad)
和dertY = distance * Math.Sin(azirad)
求得,这个azirad就是坐标方位角的弧度形式 - 这里的写法比较简单,其中是在datagridview的单元格中直接先计算放上去的,后面的改正将会在原来的基础数据上改正
public void GetVariateDistance(DataGridView dgvList, int num)
{
int i;
for (i = 0; i < num; i++)
{
dgvList.Rows[i].Cells[4].Value =
double.Parse(dgvList.Rows[i].Cells[1].Value.ToString()) * Math.Cos(double.Parse(dgvList.Rows[i].Cells[3].Value.ToString()) / 180 * Math.PI);
dgvList.Rows[i].Cells[5].Value =
double.Parse(dgvList.Rows[i].Cells[1].Value.ToString()) * Math.Sin(double.Parse(dgvList.Rows[i].Cells[3].Value.ToString()) / 180 * Math.PI);
}
}
坐标增量的简单平差
- 因为这是一个闭合导线,所以理论上坐标增量的和应该为零(又回到最初的起点),然而因为误差的存在并不是这样的,所以我们要把闭合差(
√((∑dertX)^ 2)+ (∑dertY)^ 2))
)按照边长的比例反其符号分配给每个坐标增量,量距导线和测距导线的闭合差一般都小于1/2000
,这里我们可以使用这样处理
public void ExVariateDistance(DataGridView dgvList, int num, double xVariate, double yVariate, double distance)
{
int i = 0;
for (i = 0; i < num; i++)
{
xVariate += double.Parse(dgvList.Rows[i].Cells[4].Value.ToString());
yVariate += double.Parse(dgvList.Rows[i].Cells[5].Value.ToString());
distance += double.Parse(dgvList.Rows[i].Cells[1].Value.ToString());
}
xVariate /= ((-1) * distance);
yVariate /= ((-1) * distance);
for (i = 0; i < num; i++)
{
dgvList.Rows[i].Cells[4].Value =
(Convert.ToDouble(dgvList.Rows[i].Cells[4].Value.ToString()) + (xVariate * Convert.ToDouble(dgvList.Rows[i].Cells[1].Value.ToString())));
dgvList.Rows[i].Cells[5].Value =
(Convert.ToDouble(dgvList.Rows[i].Cells[5].Value.ToString()) + (yVariate * Convert.ToDouble(dgvList.Rows[i].Cells[1].Value.ToString())));
}
dgvList.Rows[i].Cells[4].Value = "校正";
dgvList.Rows[i].Cells[5].Value = "校正";
}
最后就是求坐标
- 这个就是从已知的那个起点坐标开始加坐标增量,得到每一个导线点的坐标,也就是第二个点的X坐标就是
X = startX + dertX
,Y坐标是Y = startY + dertY
。后面的点依次加dert。代码如下,这里使用(x|y)
这样的格式显示
public void GetPoint(double BX, double BY, DataGridView dgvList, int num)
{
double X;
double Y;
try
{
X = BX + double.Parse(dgvList.Rows[0].Cells[4].Value.ToString());
Y = BY + double.Parse(dgvList.Rows[0].Cells[5].Value.ToString());
dgvList.Rows[0].Cells[6].Value = "(" + X + "|" + Y + ")";
for (int i = 1; i < num; i++)
{
X += double.Parse(dgvList.Rows[i].Cells[4].Value.ToString());
Y += double.Parse(dgvList.Rows[i].Cells[5].Value.ToString());
dgvList.Rows[i].Cells[6].Value = "(" + X + "|" + Y + ")";
}
}
catch
{ }
}
做后就完成了,只在豆丁上找了一个题测试了一下(见开头)。完整的代码没有贴出来,界面的设计也没说了,还有一些其他的杂七杂八的功能。这是很早之前写的,中间一些细节现在也忘了,之前的代码写的不好,但能提供一些参考作用,所以还是记录下来