一个企图用代码偷懒计算测量学闭合导线各项数据的屑是否有错
最近的測(cè)量學(xué)。
真的是。越來越過分了。計(jì)算量超大超大超大超大,作業(yè)提交頻率賊高,啊這,每次計(jì)算的東西都恨不得能把計(jì)算器按出火星子。于是本懶人想出一個(gè)辦法,能不能利用程序,每次只輸入一堆數(shù)據(jù),就能自動(dòng)替我算結(jié)果?
答案是顯而易見的。而且我甚至在腦海里想出了那種及其簡(jiǎn)便的場(chǎng)景~
步驟一:輸入數(shù)據(jù)
步驟二:看答案
步驟三:美滋滋的看著同學(xué)還在按計(jì)算器焦頭爛額兒,時(shí)不時(shí)嘲諷下結(jié)果算錯(cuò)了。
理想永遠(yuǎn)是美好的,對(duì)吧。
沒錯(cuò),這確實(shí)太香了,由于之后的測(cè)量學(xué)實(shí)習(xí)是要站在大太陽下面做的,我只想盡快的完成一次計(jì)算然后飛奔到?jīng)隹斓牡胤健?#xff08;本人不耐熱)
所以一次好好蕩蕩的敲代碼環(huán)節(jié)就開始了。
運(yùn)用的語言是C語言,主要是按照測(cè)量學(xué)的計(jì)算步驟來劃分的函數(shù)模塊。
測(cè)量學(xué)的原理
這次計(jì)算的是導(dǎo)線閉合差,所以一切標(biāo)準(zhǔn)按照導(dǎo)線閉合差來算。
1、根據(jù)已知角以及各個(gè)觀測(cè)角(右角)計(jì)算出各個(gè)點(diǎn)的坐標(biāo)方位角a=a后+180°?a右a=a_后+180^{\degree}-a_右a=a后?+180°?a右?。
2、根據(jù)閉合多邊形內(nèi)角和原理,計(jì)算出實(shí)際測(cè)量值和理論值之間的誤差f=∑a?∑a理f=\sum{a}-\sum{a_理}f=∑a?∑a理?,然后得到改正數(shù)v=?f/nv=-f/nv=?f/n,再重新分配到每個(gè)角上,得到正確的角值。當(dāng)然,不排除會(huì)有測(cè)量的角值誤差超過限差的情況,因?yàn)楝F(xiàn)在是作業(yè)所需嘛,所以…
3、再由各個(gè)邊的長(zhǎng)度和坐標(biāo)方位角知道各個(gè)點(diǎn)之間的坐標(biāo)偏移值Δx=lcosa,Δy=lsina\Delta x=lcosa,\Delta y=lsinaΔx=lcosa,Δy=lsina。但是,這個(gè)坐標(biāo)偏移值同樣需要矯正。∑Δx理=∑Δy理=0\sum{\Delta x_理}=\sum{\Delta y_理}=0∑Δx理?=∑Δy理?=0。所以根據(jù)這個(gè)我們就可以獲得誤差值fx,fyf_x,f_yfx?,fy?。改正數(shù)vxi=?fx?li/∑lv_{xi}=-f_x*l_i/\sum{l}vxi?=?fx??li?/∑l,vyi=?fy?li/∑lv_{yi}=-f_y*l_i/\sum{l}vyi?=?fy??li?/∑l,根據(jù)權(quán)重分配的誤差值。同樣再加上,才是真正的坐標(biāo)偏移值。
4、通過起始點(diǎn)加上各個(gè)坐標(biāo)偏移值得到各點(diǎn)坐標(biāo)。
數(shù)據(jù)結(jié)構(gòu)的提取
通過以上的問題,提取出了三種數(shù)據(jù):
點(diǎn),距離,角度。
尤其是角度,度分秒制轉(zhuǎn)換賊頭疼。給出以下幾種數(shù)據(jù)結(jié)構(gòu),皆為帶表頭的單鏈表。
點(diǎn):
距離:
typedef struct DistNode {double dist;DistNode* Next; }DistNode;typedef struct Dist {DistNode* Head;int Length; }Dist;角度(度分秒制):
typedef enum {Left,Right} Dir; typedef struct Angle {double Origin;int Degree;int Min;int Sec; }Angle;typedef struct AngleNode {Angle A;Dir dir;AngleNode* Next; }AngleNode;typedef struct Angles {AngleNode* Head;int Length; }Angles;接下來就是把上面的步驟變成函數(shù)分解了。再次我直接把我做的三個(gè)頭文件按照順序給出。
點(diǎn)
線
#ifndef _DIST_H #define _DIST_H #include<stdio.h> #include<stdlib.h>typedef struct DistNode {double dist;DistNode* Next; }DistNode;typedef struct Dist {DistNode* Head;int Length; }Dist;Dist* InitDist() {Dist *p;DistNode* q;p=(Dist*)malloc(sizeof(Dist));q=(DistNode*)malloc(sizeof(DistNode));p->Head=q;q->dist=0;q->Next=NULL;p->Length=0;return p; }bool InsertDists(Dist* DS,double D)//插入邊長(zhǎng) {DistNode* p=(DistNode*)malloc(sizeof(DistNode));DistNode* q;p->dist=D;q=DS->Head;while(q->Next){q=q->Next;}p->Next=q->Next;q->Next=p;DS->Length++;printf("Inserted.\n");return true; }bool GetDists(Dist* DS)//從鍵盤獲取若干邊長(zhǎng) {double* D;printf("Input Dists.Stop by input Dist smaller than 0\n");while(true){D=(double*)malloc(sizeof(double));scanf("%lf",D);if(*D<=0){free(D);break;}InsertDists(DS,*D);}printf("GetDists...\n");return true; }bool SumDist(Dist* DS) {DistNode* d;d=DS->Head->Next;while(d){DS->Head->dist+=d->dist;d=d->Next;}printf("Summed Dist\n");return true; } #endif角度(不要問我為什么角度會(huì)有這么多,其實(shí)我自己實(shí)現(xiàn)的時(shí)候變復(fù)雜了,本來只需要做出度分秒和小數(shù)點(diǎn)制互換就好了的)
#include<stdio.h> #include<stdlib.h> #include<math.h> #include"Dist.h" #include"Point.h" #define RAD 3.1415936/180 //涉及到的是觀測(cè)角的計(jì)算和矯正,同時(shí)涉及到坐標(biāo)方位角的計(jì)算 //其中觀測(cè)角的和會(huì)放入帶表頭的鏈表的第一個(gè),坐標(biāo)方位角的已知角也會(huì)放在第一個(gè) typedef enum {Left,Right} Dir; typedef struct Angle {double Origin;int Degree;int Min;int Sec; }Angle;typedef struct AngleNode {Angle A;Dir dir;AngleNode* Next; }AngleNode;typedef struct Angles {AngleNode* Head;int Length; }Angles;Angle CreateAngle(int Degree,int Min,int Sec) {Angle angle;angle.Degree=Degree;angle.Min=Min;angle.Sec=Sec;angle.Origin=angle.Degree+((double)angle.Min)/60+((double)angle.Sec)/3600;return angle; }Angle Aadd(Angle A,Angle B)//角度加法 {Angle angle;angle.Degree=A.Degree+B.Degree;angle.Min=A.Min+B.Min;if(angle.Min>=60){angle.Degree++;angle.Min-=60;}angle.Sec=A.Sec+B.Sec;if(angle.Sec>=60){angle.Min++;angle.Sec-=60;if(angle.Min>=60){angle.Degree++;angle.Min-=60;}}angle.Origin=A.Origin+B.Origin;if(angle.Origin>360){angle.Origin-=360;angle.Degree-=360;}if(angle.Origin>0){if(angle.Sec<0){angle.Sec+=60;angle.Min--;}if(angle.Min<0){angle.Min+=60;angle.Degree--;}}return angle; }Angle Amin(Angle A,Angle B)//角度減法 {Angle angle;if(A.Origin>B.Origin){angle.Sec=A.Sec-B.Sec;if(angle.Sec<0){angle.Sec+=60;A.Min--;}angle.Min=A.Min-B.Min;if(angle.Min<0){angle.Min+=60;A.Degree--;}angle.Degree=A.Degree-B.Degree;}else{angle.Sec=B.Sec-A.Sec;if(angle.Sec<0){angle.Sec+=60;B.Min--;}angle.Min=B.Min-A.Min;if(angle.Min<0){angle.Min+=60;B.Degree--;}angle.Degree=B.Degree-A.Degree;angle.Degree=0-angle.Degree;angle.Min=0-angle.Min;angle.Sec=0-angle.Sec;}angle.Origin=A.Origin-B.Origin;return angle; }Angle ADiv(Angle A,int D) {Angle angle;angle.Sec=((A.Min+A.Degree%D*60)%D*60+A.Sec)/D;angle.Min=(A.Min+A.Degree%D*60)/D;angle.Degree=A.Degree/D;angle.Origin=A.Origin/D;return angle; }Angles* InitAngles()//初始化角鏈表 {AngleNode* p=(AngleNode*)malloc(sizeof(AngleNode));Angles* AS=(Angles*)malloc(sizeof(Angles));p->Next=NULL;AS->Head=p;AS->Length=0;printf("Init Angles.\n");return AS; }bool InsertAngles(Angles* AS,Angle A)//插入角度 {AngleNode* p=(AngleNode*)malloc(sizeof(AngleNode));AngleNode* q;p->A=A;q=AS->Head;while(q->Next){q=q->Next;}p->Next=q->Next;q->Next=p;AS->Length++;printf("Inserted.\n");return true; }bool GetAngles(Angles* AS)//從鍵盤獲取若干角度 {Angle* angle;printf("Input Angles.Stop by input Degree larger than 360\n");while(true){angle=(Angle*)malloc(sizeof(Angle));scanf("%d,%d,%d",&angle->Degree,&angle->Min,&angle->Sec);if(angle->Degree>360){free(angle);break;}angle->Origin=angle->Degree+((double)angle->Min)/60+((double)angle->Sec)/3600;InsertAngles(AS,*angle);}printf("GetAngles...\n");return true; }bool CountSum(Angles* AS)//計(jì)算總角和 {AngleNode* p=AS->Head->Next;Angle angle;angle.Degree=0;angle.Min=0;angle.Sec=0;angle.Origin=0;while(p){angle.Degree+=p->A.Degree;angle.Min+=p->A.Min;if(angle.Min>=60){angle.Min-=60;angle.Degree++;}angle.Sec+=p->A.Sec;if(angle.Sec>=60){angle.Sec-=60;angle.Min++;if(angle.Min>=60){angle.Min-=60;angle.Degree++;}}angle.Origin+=p->A.Origin;p=p->Next;}AS->Head->A=angle;printf("Counted AngleSum\n");return true; }Angle CountModA(Angles* AS)//計(jì)算改正數(shù) {Angle A;Angle B;B.Degree=(AS->Length-2)*180;B.Min=0;B.Sec=0;B.Origin=B.Degree;CountSum(AS);A=Amin(AS->Head->A,B);return ADiv(A,AS->Length); }bool CountModAngle(Angles* AS)//計(jì)算改正后的各個(gè)角度 {AngleNode* p;p=AS->Head->Next;Angle Mod=CountModA(AS);while(p){p->A=Amin(p->A,Mod);p=p->Next;}printf("Get Modified Angles\n");return true; } bool CountDirectAngle(Angles* AS,Angles* LOCA)//計(jì)算方位角 {if(LOCA->Head->A.Degree<0||LOCA->Head->A.Degree>360){printf("You didn't init the locationangles.\n");exit(1);}AngleNode* p,*q;Angle n;Angle B;//180常量角B.Degree=180;B.Min=0;B.Sec=0;B.Origin=B.Degree;q=LOCA->Head;p=AS->Head->Next;while(p)//把計(jì)算出來的方位角插入{n=Amin(Aadd(q->A,B),p->A);//后角加180減去右角,適用于右角if(n.Degree>=360){n.Degree-=360;n.Origin-=360;}if(n.Origin<0){Angle a;a.Degree=360;a.Min=0;a.Sec=0;a.Origin=a.Degree;n=Aadd(n,a);}//printf("%d°%d′%d″ %lf\n",n.Degree,n.Min,n.Sec,n.Origin);InsertAngles(LOCA,n);q=q->Next;p=p->Next;}printf("Counted dir.\n");return true; } bool CountLOCbyAngle(Angles* AS,Dist* D,Points* PC)//計(jì)算各點(diǎn)坐標(biāo)值增量 {AngleNode* angle;DistNode* dist;Point* point,*p;angle=AS->Head->Next;dist=D->Head->Next;while(angle){point=(Point*)malloc(sizeof(Point));point->x=D->Head->Next->dist*cos(angle->A.Origin*RAD);point->y=D->Head->Next->dist*sin(angle->A.Origin*RAD);InsertPoints(PC,point);angle=angle->Next;dist=dist->Next;}printf("Counted Location Change\n");return true; }bool DisplayAngles(Angles* AS) {AngleNode* p;p=AS->Head->Next;while(p){printf("%d°%d′%d″ %lf\n",p->A.Degree,p->A.Min,p->A.Sec,p->A.Origin);p=p->Next;}return true; }以上就是已經(jīng)親測(cè)過使用的頭文件,大概可以被稱作api了吧hhh。
然后在主函數(shù)的使用部分:
這就很簡(jiǎn)單的完成了上面的步驟(指做了一天一夜,昨晚凌晨三點(diǎn)睡的)。
很慶幸學(xué)過數(shù)據(jù)結(jié)構(gòu),對(duì)指針計(jì)算各種值都可以有很好的理解,不然面對(duì)這么恐怖的數(shù)據(jù),我也不可能做下去了.jpg。
學(xué)生黨的樂趣或許就在這里吧,這一套API可以繼續(xù)擴(kuò)建,畢竟基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)完成,剩下的只是算法的實(shí)現(xiàn)了,每次實(shí)現(xiàn)都會(huì)比上次簡(jiǎn)單不少,隨著時(shí)間不斷完善。而我現(xiàn)在只是吧最艱難的開頭先擺出來了,至于后其的完善,或許會(huì)更新在這里的吧hhh。就這樣了,我要睡了(不是)。
總結(jié)
以上是生活随笔為你收集整理的一个企图用代码偷懒计算测量学闭合导线各项数据的屑是否有错的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简述导线平差计算的五个步骤_结点导线如何
- 下一篇: 闭合导线平差计算(表面)