BUAA软件工程个人项目
写在前面
项目 | 内容 |
---|---|
所属课程 | 2020春季计算机学院软件工程(罗杰 任健) (北航) |
作业要求 | [个人项目作业](<https://edu.cnblogs.com/campus/buaa/BUAA_SE_2020_LJ/homework/10429) |
课程目标 | 培养软件开发能力 |
本作业对实现目标的具体作用 | 锻炼个人开发项目的能力 |
教学班级 | 006 |
github项目地址 | https://github.com/LiuZH-19/SE_IntersectProject |
PSP表格记录
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 5 | 10 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 180 | 220 |
· Design Spec | · 生成设计文档 | 10 | 20 |
· Design Review | · 设计复审 (和同事审核设计文档) | 15 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 5 | 5 |
· Design | · 具体设计 | 30 | 60 |
· Coding | · 具体编码 | 120 | 160 |
· Code Review | · 代码复审 | 20 | 20 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | ||
· Test Report | · 测试报告 | 30 | 30 |
· Size Measurement | · 计算工作量 | 5 | 5 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 30 |
合计 | 550 | 700 |
解题思路描述
大体思路:
看了题目之后,想到的方法是:
利用数学的方法,解出两直线L1,L2存在交点的条件和其存在的交点的公式。
然后对输入中的任意两条直线,进行判断。若存在交点,则取出放入容器中(避免容器中元素的重复性)
最后输出容器中交点的个数
但考虑到需对输入中的直线两两求解,复杂度为\(\O(n^2)\)。我打算上网查一查,看看有没有更巧妙的算法。
查询无果,与小伙伴们讨论了一下,也没有更好的算法。就打算按这个算法,仔细想想细节部分。
为了避免直线的一些特殊情况的分析,我即将直线表示为一般式:Ax+By+C=0
附加题,也是类似的思路:
直线两两求解交点,再求解直线之前的交点情况,再求解两圆之间的交点情况。
在求解交点前,先判断是满足具有交点的条件,避免不必要的计算
细节考量:
直线与直线的交点比较好算,所以自己手算出来了算式关系。
直线与圆的公式也是手算的。
圆与圆之前的交点的公式,解得我头大,也不确定自己算出来的对不对,所以参考了网上的算法。详见
设计实现过程
代码组织:
期初设想:
类的设计:
- Line 类
- 直线用 Ax+By+C=0 表示 ,其中A,B,C为x1,y1,x2,y2的 函数
- 属性为 A,B,C
- 成员函数为 getA(), getB(), getC()
- Circle类
- 圆用\(\(x-X)^{2}+(y-Y)^{2}=R^2\)表示
- 属性为 X, Y, R
- 成员函数为 getX(), getY(),getR()
- Line 类
用 vector 存放 所有的直线
交点为Pair类型,用set存放所有的交点
三个函数,分别计算两直线之间,直线与圆之间,两圆之间的交点情况。
按照上述思路实现后,我发现Line 和 Circle类有点多余。教材中也说,只是封装数据的话,不用class用struct。所以我打算将直线和圆的参数用结构体来存。将原先计算交点情况的三个函数封装成一个Calculator类。又考虑到计算中的精度损失问题,构造了point 类,重写了operator <。具体情况如下:
后来改进:
Calculator 类
重载了三个成员函数class Calculator
{
public:
Calculator();
int haveIntersection(Line l1, Line l2, set<Point>& nodeSet);
int haveIntersection(Circle c, Line l, set<Point>& nodeSet);
int haveIntersection(Circle c1, Circle c2, set<Point>& nodeSet);
};Point类
自定义了运算符bool Point::operator < (const Point& p)const {
//return x==p.x?y<p.y:x<p.x;
return dcmp(x - p.x) == 0 ? dcmp(y - p.y) < 0 : dcmp(x - p.x) < 0; } bool Point::operator ==(const Point& p)const {
if (dcmp(x-p.x)==0&&dcmp(y-p.y)==0)
return true;
return false;
}
Line 和Circle的架构体
main中的函数 countALLinsect()
分别计算 直线之间,直线与圆之间,圆与圆之间的交点情况
单元测试设计
- 测试Calculator类,具体包括以下几个方面:
- 直线直线的交点情况
- 平行
- 三线交于一点
- 直线平行于x轴
- 直线 平行于y轴
- 一般情况
- 直线与圆的交点情况
- 直线的特殊情况
- 线圆关系
- 相切
- 相离
- 相交
- 圆与圆的交点关系
- 相离
- 相交
- 外切
- 内切
- 内含(同心)
- 复杂情况(两圆与一直线)
- 有一交点重叠
- 有两个交点重叠
- 一般情况
- 直线直线的交点情况
- 测试point类
检测 重写的operator < 是否正确 - 整体测试
- 大量数据测试 ,检测时间是否符合题意
- 检测 set 是否去重
测试均通过,且交点为8000000左右时,用时7s,也没有超时。
性能改进相关
图中可以看出,采用set容器后,构建红黑树占用了绝大部分CPU时间。在建树过程中,用到了我在Point类里面 重写的operator <,故其占用时间也较多。除去set的相关操作外,接下来去看了下 Calculator中的函数。
其中 CPU绝大部分的占用时间依然是 set的insert操作。所以在没能想到更优的算法下,性能改进工作可做的很少。我将一些常用的计算式先算出来,避免之后的重复计算。例如下图:
消除 Code Quality Analysis 中的所有警告
采用的是“Microsoft建议”的风格。
关键代码说明
求解所有的交点情况:直线之前、直线与圆、两圆之间
int countAllinsect(vector<Line> lVec, vector<Circle> cVec, set<Point> &nodeSet){
Calculator* calc = new Calculator();
size_t i, j;
//计算两条直线间的交点
for (i = 0; i < lVec.size(); i++) {
for (j = i + 1; j < lVec.size(); j++) {
calc->haveIntersection(lVec[i], lVec[j], nodeSet);
}
}
//计算直线与圆之间的交点
for (i = 0; i < cVec.size(); i++) {
for (j = 0; j < lVec.size(); j++) {
calc->haveIntersection(cVec[i], lVec[j], nodeSet);
}
}
//计算两圆之间的交点
for (i = 0; i < cVec.size(); i++) {
for (j = i + 1; j < cVec.size(); j++) {
calc->haveIntersection(cVec[i], cVec[j], nodeSet);
}
}
return nodeSet.size();
}
方法很暴力,就是循环遍历。
困惑
本次项目涉及到浮点数运算的精度问题。由于公式中存在开方以及除法运算,导致最终算出来的点只是近似值。因此我重写了 比较函数 ,EPS最终取的是0.0000001。虽然这个EPS是经过我多番测试选出来的值,但我任然无法保证他的实用性。所以在判断点是否重合的时候,可能会存在误差。
下面是关于精确度问题的相关代码:
#define EPS 0.0000001
int dcmp(double x) {
if (fabs(x) < EPS) return 0;
return x < 0 ? -1 : 1;
}
bool Point::operator < (const Point& p)const {
//return x==p.x?y<p.y:x<p.x;
return dcmp(x - p.x) == 0 ? dcmp(y - p.y) < 0 : dcmp(x - p.x) < 0;
}
BUAA软件工程个人项目的更多相关文章
- BUAA软件工程结对项目作业
BUAA软件工程结对项目 小组成员:16005001,17373192 1.教学班级和项目地址 项目 内容 这个作业属于哪个课程 博客园班级连接 这个作业的要求在哪里 结对项目作业 我在这个课程的目标 ...
- BUAA软件工程个人项目作业
BUAA软件工程个人项目作业 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 学习软件开发的流程 这个作业在哪 ...
- BUAA 软件工程个人作业
BUAA 软件工程 个人项目作业 Author: 17373015 乔玺华 教学班级 :005 项目地址:https://github.com/JordenQiao/SE_Homework_Perso ...
- BUAA 2020 软件工程 个人项目作业
BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...
- 【BUAA软件工程】第一次阅读作业
BUAA软件工程 第一次阅读作业 项目 内容 这个作业属于哪个课程? 北航软工 这个作业的要求在哪里? 第一次个人作业 我在这个课程的目标是? 学习高效严谨的软件工程开发过程,建立团队意识 这个作业在 ...
- BUAA软件工程:软件案例分析
BUAA软件工程:软件案例分析 Author:17373015 乔玺华 项目 内容 这个作业属于哪个课程 2020计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 软件案例分析博客作业 我在这个 ...
- 2021S软件工程——结对项目第一阶段
# 2021S软件工程--结对项目第一阶段 2021春季软件工程(罗杰 任健) 项目地址 1020 1169 --- ## 1 结对感受 总体来说,结对编程与之前的个人编程感觉有很大的不同.有如下几个 ...
- 2021S软件工程——结对项目第三阶段
2021S软件工程--结对项目第三阶段 2021春季软件工程(罗杰 任健) 项目地址 1020 1169 1 实践反思 1.1 问题分析 两人习惯不一致 没有具体制定时间节点 写完代码才开始" ...
- BUAA 2020 软件工程 结对项目作业
Author: 17373051 郭骏 3.28添加:4.计算模块接口的设计与实现过程部分,PairCore实现的细节 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) ...
随机推荐
- 攻防世界 reverse SignIn
SignIn 2019_SUCTF __int64 __fastcall main(__int64 a1, char **a2, char **a3) { char mod; // [rsp+0 ...
- 攻防世界 reverse evil
这是2017 ddctf的一道逆向题, 挑战:<恶意软件分析> 赛题背景: 员工小A收到了一封邮件,带一个文档附件,小A随手打开了附件.随后IT部门发现小A的电脑发出了异常网络访问请求,进 ...
- OpenGL 绘制你的 github skyline 模型
前言 好久没更新博客了,上一篇文章还是在去年6月份,乍一看居然快要过去一年了,不时还能看到粉丝数和排名在涨,可是却一直没有内容更新,怪不好意思的- -(主要是一直没想好要写些什么,中间也有过一些想法, ...
- Python基础之:Python中的内部对象
目录 简介 内置函数 内置常量 内置类型 逻辑值检测 逻辑值的布尔运算 比较运算 数字类型 整数类型的位运算 整数类型的附加方法 浮点类型的附加方法 迭代器 序列类型 集合类型 映射类型 字典视图对象 ...
- CVE-2020-1472 Zerologon
CVE-2020-1472 Zerologon 漏洞简介 CVE-2020-1472是继MS17010之后一个比较好用的内网提权漏洞,影响Windows Server 2008R 2至Windows ...
- 第25 章 : Kubernetes 网络模型进阶
Kubernetes 网络模型进阶 本文将主要分享以下五个方面的内容: Kubernetes 网络模型来龙去脉 Pod 究竟如何上网? Service 究竟怎么工作? 啥?负载均衡还分内部外部? 思考 ...
- [SpringCloud教程]3. Eureka服务注册中心集成
新微服务项目多半采用Nacos作为服务注册与发现中心,但是旧项目可能使用Eureka.zookeeper.Consul.Nacos作为服务注册中心. 新项目建议使用Nacos作为服务注册中心 Spri ...
- 学习笔记-git 上传
0.git add * (如果你需要修改源码需要在 1 之前使用,然后再回到 1) 1.git commit -m '提交文字描述' 2.git push -u origin master (上传到主 ...
- 学习笔记-vue.js快捷登录 enter
一般监听在输入密码的input监听keyup事件,加enter修饰符.如果input是组件,加上.native修饰符.<div id="app"> <input ...
- BUAA_2020_OO_UNIT1_REVIEW
OO第一单元总结 一.程序结构分析 总的来说,这一学期我才开始正式的接触面向对象的思想,直到pre才开始正式的实践,所以这次作业可能写的有一些混乱,第三次作业也进行了大量重构. 1. 第一次作业 关于 ...