最近的测量学。
真的是。越来越过分了。计算量超大超大超大超大,作业提交频率贼高,啊这,每次计算的东西都恨不得能把计算器按出火星子。于是本懒人想出一个办法,能不能利用程序,每次只输入一堆数据,就能自动替我算结果?
答案是显而易见的。而且我甚至在脑海里想出了那种及其简便的场景~
步骤一:输入数据

步骤二:看答案

步骤三:美滋滋的看着同学还在按计算器焦头烂额儿,时不时嘲讽下结果算错了。

理想永远是美好的,对吧。
没错,这确实太香了,由于之后的测量学实习是要站在大太阳下面做的,我只想尽快的完成一次计算然后飞奔到凉快的地方。(本人不耐热)
所以一次好好荡荡的敲代码环节就开始了。
运用的语言是C语言,主要是按照测量学的计算步骤来划分的函数模块。
测量学的原理
这次计算的是导线闭合差,所以一切标准按照导线闭合差来算。
1、根据已知角以及各个观测角(右角)计算出各个点的坐标方位角a=a后+180°−a右a=a_后+180^{\degree}-a_右a=a后​+180°−a右​。
2、根据闭合多边形内角和原理,计算出实际测量值和理论值之间的误差f=∑a−∑a理f=\sum{a}-\sum{a_理}f=∑a−∑a理​,然后得到改正数v=−f/nv=-f/nv=−f/n,再重新分配到每个角上,得到正确的角值。当然,不排除会有测量的角值误差超过限差的情况,因为现在是作业所需嘛,所以…
3、再由各个边的长度和坐标方位角知道各个点之间的坐标偏移值Δx=lcosa,Δy=lsina\Delta x=lcosa,\Delta y=lsinaΔx=lcosa,Δy=lsina。但是,这个坐标偏移值同样需要矫正。∑Δx理=∑Δy理=0\sum{\Delta x_理}=\sum{\Delta y_理}=0∑Δx理​=∑Δy理​=0。所以根据这个我们就可以获得误差值fx,fyf_x,f_yfx​,fy​。改正数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,根据权重分配的误差值。同样再加上,才是真正的坐标偏移值。
4、通过起始点加上各个坐标偏移值得到各点坐标。
数据结构的提取
通过以上的问题,提取出了三种数据:
点,距离,角度。
尤其是角度,度分秒制转换贼头疼。给出以下几种数据结构,皆为带表头的单链表。

typedef struct Point
{double x;double y;Point* Next;
}Point;typedef struct Points
{Point* Head;int Length;
}Points;

距离

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;

接下来就是把上面的步骤变成函数分解了。再次我直接把我做的三个头文件按照顺序给出。

#include<stdio.h>
#include<stdlib.h>
#include"Dist.h"
typedef struct Point
{double x;double y;Point* Next;
}Point;typedef struct Points
{Point* Head;int Length;
}Points;Points* InitPoints()
{Points *p;Point* q;p=(Points*)malloc(sizeof(Points));q=(Point*)malloc(sizeof(Point));q->x=0;q->y=0;p->Head=q;q->Next=NULL;p->Length=0;return p;
}bool InsertPoints(Points* PS,Point *p)
{Point* point;Point* q;point=p;q=PS->Head;while(q->Next){q=q->Next;}point->Next=q->Next;q->Next=point;PS->Length++;printf("Inserted Point.\n");return true;
}bool GetPoints(Points* PS)//从键盘获取若干点
{Point* D;printf("Input Points.Stop by input x or y larger than 10000\n");while(true){D=(Point*)malloc(sizeof(Point));scanf("%lf,%lf",&D->x,&D->y);if(D->x>10000){free(D);break;}InsertPoints(PS,D);}printf("GetPoints...\n");return true;
}bool CountModP(Points *PS)//计算闭合导线坐标偏差
{Point* q=PS->Head->Next;double x=0;double y=0;while(q){x+=q->x;y+=q->y;q=q->Next;}PS->Head->x=x;PS->Head->y=y;return true;
}bool CountModPoints(Points *PS,Dist* DS)//改正坐标增量
{Point* p=PS->Head->Next;DistNode* d=DS->Head->Next;while(d){p->x-=(d->dist*PS->Head->x)/DS->Head->dist;p->y-=(d->dist*PS->Head->y)/DS->Head->dist;p=p->Next;d=d->Next;}return true;
}bool CountPointsByPC(Points *PS,Points *Change)//通过坐标增量计算坐标值
{Point *p,*q,*point;point=PS->Head->Next;q=Change->Head->Next;while(q){p=(Point*)malloc(sizeof(Point));p->x=point->x+q->x;p->y=point->y+point->y;InsertPoints(PS,p);q=q->Next;point=point->Next;}printf("Counted Location\n");return true;
}bool DisplayPoints(Points* PS)
{Point* p;p=PS->Head->Next;while(p){printf("x:%lf,y:%lf\n",p->x,p->y);p=p->Next;}return true;
}

线

#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)//插入边长
{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)//从键盘获取若干边长
{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

角度(不要问我为什么角度会有这么多,其实我自己实现的时候变复杂了,本来只需要做出度分秒和小数点制互换就好了的)

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include"Dist.h"
#include"Point.h"
#define RAD 3.1415936/180
//涉及到的是观测角的计算和矫正,同时涉及到坐标方位角的计算
//其中观测角的和会放入带表头的链表的第一个,坐标方位角的已知角也会放在第一个
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)//计算总角和
{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)//计算改正数
{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)//计算改正后的各个角度
{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)//计算方位角
{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)//把计算出来的方位角插入{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)//计算各点坐标值增量
{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;
}

以上就是已经亲测过使用的头文件,大概可以被称作api了吧hhh。
然后在主函数的使用部分:

#include<stdio.h>
#include<stdlib.h>
#include"Angle.h"
int main()
{Angles* AS,*LOCA;//Angle angle;//angle.Degree=100;//angle.Min=23;//angle.Sec=23;Angle angle;Dist *DS;Points *PS,*PC;AS=InitAngles();LOCA=InitAngles();DS=InitDist();PS=InitPoints();PC=InitPoints();LOCA->Head->A=CreateAngle(123,2,33);LOCA->Length++;//InsertAngles(AS,angle);GetAngles(AS);GetDists(DS);GetPoints(PS);//angle=Aadd(AS->Head->Next->A,AS->Head->Next->Next->A);//InsertAngles(AS,angle);DisplayAngles(AS);CountModAngle(AS);DisplayAngles(AS);CountDirectAngle(AS,LOCA);DisplayAngles(LOCA);CountLOCbyAngle(LOCA,DS,PC);printf("Origin Location Change:\n");DisplayPoints(PC);CountModP(PC);SumDist(DS);CountModPoints(PC,DS);   printf("Modified Location Change:\n");DisplayPoints(PC);CountPointsByPC(PS,PC);printf("Modified Location:\n");DisplayPoints(PS);return 0;
}

这就很简单的完成了上面的步骤(指做了一天一夜,昨晚凌晨三点睡的)。
很庆幸学过数据结构,对指针计算各种值都可以有很好的理解,不然面对这么恐怖的数据,我也不可能做下去了.jpg。
学生党的乐趣或许就在这里吧,这一套API可以继续扩建,毕竟基础的数据结构完成,剩下的只是算法的实现了,每次实现都会比上次简单不少,随着时间不断完善。而我现在只是吧最艰难的开头先摆出来了,至于后其的完善,或许会更新在这里的吧hhh。就这样了,我要睡了(不是)。

一个企图用代码偷懒计算测量学闭合导线各项数据的屑是否有错相关推荐

  1. [简单题]换一个思维,代码简洁度就完全变了(Python实现)

    题目名字: Human readable duration format 原题链接: https://www.codewars.com/kata/human-readable-duration-for ...

  2. 小数据量计算最大lyapunov代码_Software | 计算Lyapunov指数的GUI工具箱及函数包汇总...

    二十年前读书时用过的Lyapunov Exponents Toolbox,推荐给做非线性动力学入门的同学们.那个时候不会编写程序,做分支图.算连续或者离散系统的Lyapunov指数,极其困难,还好有这 ...

  3. java订单类_基于Java创建一个订单类代码实例

    这篇文章主要介绍了基于Java创建一个订单类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 需求描述 定义一个类,描述订单信息 订单id 订 ...

  4. calendar获取月份少一个月_VBA 技巧:计算一个月有多少天?

    VBA 技巧:计算一个月有多少天? 问题: 有时我们需要知道一个月有多少天,或者知道最后一天是31号还是30号 我们可以通过VBA代码来计算 Sub nb_days_month()'将日期传入变量,月 ...

  5. java订单类_使用Java创建一个订单类代码实例

    这篇文章主要简介了使用Java创建一个订单类代码实例,文中通过示例代码简介的非常具体,对大家的学习或者工作具有一定的参考学习网上卖,需要的朋友可以学习下 需求描述 定义一个类,描述订单信息 订单id ...

  6. php 字符串进行计算_PHP eval() 函数把字符串按照 PHP 代码来计算

    eval() 函数把字符串按照 PHP 代码来计算. 该字符串必须是合法的 PHP 代码,且必须以分号结尾. 如果没有在代码字符串中调用 return 语句,则返回 NULL.如果代码中存在解析错误, ...

  7. 编写一个简单Java程序,计算银行年存款的本息

    编写一个简单Java程序,计算银行年存款的本息 要求:程序运行后要求用户输入存款本金.年利率和存款年限,最后程序计算并输出相应年限后存款的金额.相应的计算公式为:存款总额=本金 * (1 + 利率)存 ...

  8. 对DES中的第一个S盒子S1,计算随机变量 X2⊕Y1⊕Y2⊕Y3⊕Y4 的偏差

    对DES中的第一个S盒子S1,计算随机变量 X2⊕Y1⊕Y2⊕Y3⊕Y4 的偏差 什么是偏差: S盒是DES中连接Bi和Ci的桥梁: 每个Bi都是6bits,每个Ci都是4bits,S盒是一个6bit ...

  9. 建立student类,在此类中所有数据定义为私有数据变量。并建立一个student对象数组,用附件中的数据进行初始化。计算每个学生三门课程的总分和平均成绩(C++实验)

    一.实验目的: (1)掌握类的创建,成员数据和成员函数的构建. (2)掌握构造函数的重载. (3)掌握静态成员函数和静态成员函数的使用. 二.实验内容和要求: (1)按照附件"成绩表.txt ...

  10. 公司停电,程序员去网吧写代码;iPhone 14将于北京时间9月8日发布;GitLab修复一个关键远程代码执行漏洞|极客头条

    「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 整理 | 梦依丹 出品 | CSDN(ID:CSDNnews ...

最新文章

  1. 征战全球16年:中国手机出海简史
  2. 代码实现UISlider 和 UISwitch
  3. 详解Adorner Layer(zz)
  4. 计算机java语言教程,计算机JAVA教程二讲Java语言基础知识.doc
  5. ux和ui_阅读10个UI / UX设计系统所获得的经验教训
  6. Android入门简书,android ndk开发入门随笔(一)
  7. Facebook 游戏开发更新文档 API 参考文档 v6.0
  8. 划重点丨详解Java流程控制语句知识点
  9. 第17章 高级数据表示 17.7 二叉搜索树(第一部分ADT 和 接口)
  10. MATLAB中施密特正交化的实现
  11. Arduino蓝牙无线自动下载程序 Arduino无线下载
  12. 自建DDNS配置教程(dynu)
  13. 移动云迁移工具:物理服务器迁移到移动云
  14. python从入门到精通-张子夜-专题视频课程
  15. Matlab的eval函数
  16. C++的双缓冲队列机制
  17. 企业微信如何提高用户粘性防止粉丝流失
  18. HDOJnbsp;nbsp;2048nbsp;nbsp;nbsp;神、上帝以及老天爷
  19. chatGPT与逆向的相遇,快速解决sslpinning抓包问题
  20. Linux 批量杀掉进程 kill -9

热门文章

  1. ESET NOD32 Antivirus – 免费 3个月/ 3PC
  2. 用python 代码写一个表白I love you
  3. 教你免费轻松下载百度文库的文件
  4. McAfee企业版8.8——病毒库的备份与还原
  5. CSND如何转载别人的文章
  6. 使用apache.commons.fileupload 进行文件上传
  7. 计算机开机b00t设置,电脑boot启动项设置的具体方法
  8. 标准工时管理软件VIOOVI助力企业数字化转型
  9. WebRTC 之 RTX
  10. 啦啦外卖独立版七牛云配置失败解决方案