附合导线平差程序设计报告.docx
《附合导线平差程序设计报告.docx》由会员分享,可在线阅读,更多相关《附合导线平差程序设计报告.docx(18页珍藏版)》请在冰豆网上搜索。
附合导线平差程序设计报告
《测量平差程序》课程设计
(报告)
学生姓名:
罗正材
学号:
1108030128
专业:
2011级测绘工程
指导教师:
肖东升
一、前言…………………………………………………………3
二、平差程序的基本要求………………………………………3
三、平差程序模块化……………………………………………3
四、平差中的重要函数…………………………………………4
五、结论…………………………………………………………7
六、部分源代码…………………………………………………7
一、前言
随着测绘科学技术的不断发展,在测量数据的处理中产生很多种平差的方法。
在本文中,附合导线近似平差程序是利用C++编程实现的,我们需要将导线网的已知数据信息按照特定的规则输入到.txt文本中,利用C++程序读取文本数据信息后,对其进行一系列的平差计算,最终获得平差后的结果,并以.txt文本的形式输出且保存,这样就可为测量工作提供一定的参考,还能为测绘数据的管理带来帮助。
二、平差程序的基本要求
平差程序设计与其它程序设计相同,应当满足一定的要求。
(1)程序逻辑结构简单,清晰易读,符合结构化程序设计要求,便于扩展;
(2)运算速度快,占用内存小,内外存之间的交换不宜过于频繁;
(3)数学模型及计算方法正确、先进,计算结果精度高;
(4)适应性强,便于移植,充分考虑各种可能形式,尽量满足不同要求与需要;
(5)方便用户,操作简便。
数据输入与用户作业方式与习惯相统一,输出明了、齐全;尽量减少手工处理工作量,操作简便;人机交互性要强。
上述要求,既体现在平差程序的总体设计中,也贯穿于平差程序设计的各个环节中。
三、平差程序模块化
图1
四、平差中的重要函数
(一)、角度制与弧度制的相互转化
C/C++程序设计中,关于角度的计算以弧度制为单位,而在测量以及具体工作中我们通常习惯以角度制为单位。
这样,在数据处理中,经常需要在角度制与弧度制之间进行相互转化。
这里,我们利用C/C++数学函数库math.h中的相关函数完成这两种功能。
这里,我们使用double类型数据表示角度制数和弧度制数。
例如:
123度44分58.445秒,用double类型表示为123.4458445,其中分、秒根据小数位确定。
在角度制与弧度制的转化中,涉及如下图2所示的两个环节。
图2
1.角度化弧度函数
doubled_h(doubleangle)//角度化弧度
{doublea,b;
angle=modf(angle,&a);//a为提取的度值(int类型),angle为分秒值(小数)
angle=modf(angle*100.0,&b);//b为提取的分值(int类型),angle为秒值(小数)
return(a+b/60.0+angle/36.0)*(PI+3.0E-16)/180.0;
}
2.弧度化角度函数
doubleh_d(doubleangle)//弧度化角度
{doublea,b,c;
angle=modf(angle*180.0/(PI-3.0E-16),&a);
angle=modf(angle*60.0,&b);
angle=modf(angle*60.0,&c);
returna+b*0.01+c*0.0001+angle*0.0001;
}
其中,函数modf(angle,&a)为C语言数学库函数,返回值有两个,以引用类型定义的a返回angle的整数部分,函数直接返回值为angle的小数部分。
(二)近似坐标计算
在平面网间接平差计算中,近似坐标计算是非常重要的一项基础工作。
近似坐标是否计算成功是间接平差是否可以进行的必要条件。
1.两方向交会
已知条件:
两个点的近似坐标,这两个点到未知点的方位角,如图3所示
图3两方向交会
根据图4.2,设
,
,则很容易写出
整理该式,得两方向交会的的计算公式
(4.1)
对(4.1)式计算,即可得到未知点的近似坐标。
应用中需要注意的是,若两方向值相同或相反,则该式无解。
程序中,定义该问题的函数为:
intxy0ang(obser&a1,obser&a2)
2.三边交会
如图4所示,为排除两边长交会的二义性,给出如下三边交会的模型,已知条件:
三个点的近似坐标,这三个点到未知点的距离测量值。
图4三边交会
对每条边长测量值,可列出边长条件
计算上式中(a)与(b)和(c)三式的差,消去未知参数的平方项,整理得三边交会的计算公式
(4.2)
对(4.2)式计算,即可得到未知点的近似坐标。
应用中需要注意的是,若三点位于同一条直线,则该式无解。
程序中,定义该问题的函数为:
intxy0dist(obser&a,obser&b,obser&c)。
3.坐标正算
使用测量正算公式计算控制网的近似坐标。
程序中,定义该问题的函数为:
intzheng(obser&a)
4.角度后方交会
使用测量后方交会计算公式计算控制网的近似坐标。
程序中,定义该问题的程序函数为:
inthouj(obser&a,obser&b,obser&c)
5.测角网无定向导线计算
无定向导线,主要应用于计算已知控制点不相邻的三角网的近似坐标。
基本思想为:
先由一个已知点开始,假设一条边的边长与方位角,根据三角网的角度观测值推算其它边的边长与方位角,然后,由任一导线计算,直到计算至另一个已知点为止。
假设导线的起点为A,终点为B。
这时,计算出的B点坐标必然与已知坐标不同,设A与B的已知坐标为(
),B点的计算坐标为B’(
),则用这些数据可以计算边长的放大系数k和假设方位角的改正数da
其中,
为计算方位角的函数。
这时,对网中的假设边长和所有由假设边长推算的近似边长进行k倍的放大,对假设方位角和所有由假设方位角推算的近似方位角进行方位角改正。
然后应用坐标正算法可以计算三角网中所有点的近似坐标。
五、结论:
C++在导线平差中的应用
在‘导线网的间接平差程序设计与实现’中,通过使用C++编程,采用测量平差中的间接平差的方法,实现了导线网的间接平差,最终得到了导线网中待定数据。
在‘导线网平差的程序应用’中,利用已经编好的导线网间接平差程序,对边角网、三角网的实例进行了平差,最终得到导线网的待定数据以及相关的精度评定,通过对这些平差结果的检查,最后,认为此导线网的间接平差程序可以为测量的平差工作提供一些服务。
虽然此程序可以完成导线网平差一些工作,但是它还有很多的不足地方需要改进以及完善。
平差程序的实现定义了五个结构体(间接平差结构、平面网、平面点、测站、观测值),通过一系列的函数将这五个结构体联系起来,最终完成平差任务。
下面阐述一下导线网的间接平差程序实现的基本流程:
(1)以DAT文件的形式输入导线网中的已知控制点、测站信息、观测值、测角中误差、测距加、乘常数等所有的已知数据,并且这些数据的输入必须符合前面所提到的数据输入格式;
(2)运用程序读取输入数据文件,通过相应的函数求得待定点的近似坐标;
(3)通过相应函数,求取间接平差的结构:
误差方程系数阵A、观测权阵P、误差方程常数项l;
(4)通过间接平差函数,实现对已经得到的间接平差结构的平差工作。
(5)最后,以DAT文件的格式输出并保存平差处理结果,为以后的测量工作提供参考。
六、部分源代码:
//"度分秒"化成弧度
doubleDMStoRAD(doubledms)
{
intd,m,f;doubles;
f=dms>=0?
1:
-1;
//0.001秒=4.8481368110953599358991410235795e-9弧度
dms+=f*0.0000001;
d=(int)dms;
dms=(dms-d)*100.0;
m=(int)dms;
s=(dms-m)*100.0;
return(d+m/60.0+s/3600.0)*_TORAD
-f*4.8481368110953599358991410235795e-9;
}
//弧度转“度分秒”
doubleRADtoDMS(doublerad)
{
intf=rad>=0?
1:
-1;//符号+-
//加0.001秒(用弧度表示),化为度
rad=(rad+f*4.8481368110953599358991410235795e-9)*_TODEG;
intd=(int)rad;
rad=(rad-d)*60.0;
intm=(int)rad;
doubles=(rad-m)*60.0;
returnd+m/100.0+s/10000.0-f*0.0000001;
}
//读入已知点的坐标
voidReadKnwData(FILE*in,DyArray*array)
{
charbuffer[256];
doubledx,dy;
SurPntpnt;
while(!
feof(in))
{
fgets(buffer,sizeof(buffer),in);
if(sscanf(buffer,"%s%lf%lf",pnt.name,&pnt.x,&pnt.y)==3)
{
Add(array,pnt);
}
else
break;
}
dx=array->elem[1].x-array->elem[0].x;
dy=array->elem[1].y-array->elem[0].y;
adj.azi0=atan2(dy,dx)+(dy<0?
1:
0)*_2PI;//alfa-0
dx=array->elem[3].x-array->elem[2].x;
dy=array->elem[3].y-array->elem[2].y;
adj.azin=atan2(dy,dx)+(dy<0?
1:
0)*_2PI;//alfa-n
adj.x1=array->elem[1].x;
adj.y1=array->elem[1].y;
adj.xn=array->elem[2].x;
adj.yn=array->elem[2].y;
Destroy(array);//
}
//观测值信息写到动态数组
voidReadObsValue(FILE*in,DyArray*array)
{
charbuffer[256];
doubledir0,dir1,dist0,dist1;
SurPntpnt;//用于临时保存点的坐标
while(!
feof(in))
{
fgets(buffer,sizeof(buffer),in);
if(feof(in))return;
if(sscanf(buffer,"%s%s%lf%lf%s%lf%lf",pnt.name,pnt.dir0.name,
&dir0,&dist0,pnt.dir1.name,&dir1,&dist1)==7)
{
pnt.dir0.dv=DMStoRAD(dir0);
pnt.dir0.dist=dist0;
pnt.dir1.dv=DMStoRAD(dir1);
pnt.dir1.dist=dist1;
pnt.b=pnt.dir1.dv-pnt.dir0.dv+(pnt.dir1.dv-pnt.dir0.dv<0?
1:
0)*_2PI;
Add(array,pnt);//观测值信息写到动态数组
}
else
break;//退出读观测值的循环
}
}
//求角度闭合差fb
voidFb(DyArray*array)
{
doublesumb=0.0;//beta求和
for(inti=0;ilength;i++)
{
sumb+=array->elem[i].b;
}
adj.fb=adj.azi0+sumb-_PI*array->length-adj.azin;
adj.v=-adj.fb/array->length;
adj.fb=adj.fb/_PI*180*3600;
adj.fr=2*8*sqrt(array->length);
if(abs(adj.fb)>=adj.fr)
strcpy(adj.judge,"方位角闭合差超限了!
");
else
strcpy(adj.judge,"方位角闭合差没超限");
}
//角度改正
voidCorrectAngle(DyArray*array)
{
for(inti=0;ilength;i++)
{
array->elem[i].b+=adj.v;
}
adj.v=adj.v/_PI*180*3600;
}
//推算方位角
voidDirect(DyArray*array)
{
SurPntpnt;
//第一个未知边
pnt.dir1.alfa=adj.azi0+array->elem[0].b-_PI;
pnt.dir1.dist=(array->elem[0].dir1.dist+array->elem[1].dir0.dist)/2;
pnt.dir1.dx=pnt.dir1.dist*cos(pnt.dir1.alfa);
pnt.dir1.dy=pnt.dir1.dist*sin(pnt.dir1.alfa);
AddDir(array,pnt,0);
for(inti=1;ilength-1;i++)
{
pnt.dir1.alfa=array->elem[i-1].dir1.alfa+array->elem[i].b-_PI;
pnt.dir1.dist=(array->elem[i].dir1.dist+array->elem[i+1].dir0.dist)/2;
pnt.dir1.dx=pnt.dir1.dist*cos(pnt.dir1.alfa);
pnt.dir1.dy=pnt.dir1.dist*sin(pnt.dir1.alfa);
AddDir(array,pnt,i);
}
for(i=0;ilength-1;i++)
{
array->elem[i].dir1.alfa=RADtoDMS(array->elem[i].dir1.alfa);//alfa转为角度
}
}
//坐标增量改正
voidCorrectDirect(DyArray*array)
{
doublesumx=0.0;
doublesumy=0.0;
doublesums=0.0;
for(inti=0;ilength-1;i++)
{
sumx+=array->elem[i].dir1.dx;
sumy+=array->elem[i].dir1.dy;
sums+=array->elem[i].dir1.dist;
}
adj.fx=adj.x1+sumx-adj.xn;
adj.fy=adj.y1+sumy-adj.yn;
adj.fs=sqrt(adj.fx*adj.fx+adj.fy*adj.fy);
adj.f=int(sums/adj.fs);//导线全长相对闭合差分母
for(i=0;ilength-1;i++)
{
array->elem[i].dir1.dx-=adj.fx*array->elem[i].dir1.dist/sums;//坐标增量改正
array->elem[i].dir1.dy-=adj.fy*array->elem[i].dir1.dist/sums;
}
}
//解算近似平差坐标
voidCoordinate(DyArray*array)
{
SurPntpnt;
array->elem[0].x=adj.x1;
array->elem[0].y=adj.y1;
for(inti=0;ilength-2;i++)
{
//strcpy(pnt.name,array->elem[i+1].name);
pnt.x=array->elem[i].x+array->elem[i].dir1.dx;//
pnt.y=array->elem[i].y+array->elem[i].dir1.dy;
AddCor(array,pnt,i+1);
}
}
//输出
voidPrint(DyArray*array,FILE*out)
{
doubled,m,s;
fprintf(out,"方位角闭合差fb=%.0lf秒%s角度改正v=%.0lf秒\n",adj.fb,adj.judge,adj.v);
fprintf(out,"坐标增量闭合差fx=%.0lfmmfy=%.0lfmmfs=%.0lfmm\n",adj.fx*1000,adj.fy*1000,adj.fs*1000);
fprintf(out,"导线全长相对闭合差fs/∑S=1/%d\n\n",adj.f);
fprintf(out,"坐标方位角\n");
for(inti=0;ilength-1;i++)
{
d=array->elem[i].dir1.alfa;
m=(d-(int)d)*100;
s=(m-(int)m)*100;
fprintf(out,"α%s-%s=%.0lf°%.0lf′%.0lf″\n",array->elem[i].name,array->elem[i+1].name,
d,m,s);
}
fprintf(out,"\n近似平差坐标\n");
for(i=1;ilength-1;i++)
{
fprintf(out,"%sx=%.3lfmy=%.3lfm\n",array->elem[i].name,array->elem[i].x,
array->elem[i].y);
}
}
intmain(intargc,char*argv[])
{
DyArraypnts;
Init(&pnts);
charinfile[255],outfile[255];
if(argc<2)
{
printf("Enterinfilename:
\n");
scanf("%s",infile);
}
else
strcpy(infile,argv[1]);
FILE*in=fopen(infile,"r");
if(in==NULL)
{
printf("File%scann'topen!
",infile);
return-1;
}
if(argc<3)
{
printf("Enteroutfilename:
\n");
scanf("%s",outfile);
}
else
strcpy(outfile,argv[2]);
FILE*out=fopen(outfile,"w");
if(out==NULL)
{
printf("File%scann'topen!
",outfile);
return-1;
}
//读入已知点的坐标
ReadKnwData(in,&pnts);
Init(&pnts);
//观测值信息写到动态数组
ReadObsValue(in,&pnts);
//求角度闭合差fb
Fb(&pnts);
//角度改正
CorrectAngle(&pnts);
//推算方位角
Direct(&pnts);
//坐标增量改正
CorrectDirect(&pnts);
//解算近似平差坐标
Coordinate(&pnts);
fclose(in);
//输出
Print(&pnts,out);
fclose(out);
Destroy(&pnts);
return0;
}