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春季计算机学院软件工程(罗杰 任健) ...
随机推荐
- 数据库SQL查询作业
--设有三个关系 --S(S#,SNAME,AGE,SEX) --SC(S#,C#,GRADE) --C(C#,CNAME,TEACHER) --(1)检索LIU老师所授课程的课程号.课程名 sele ...
- 数数字(JAVA语言)
package 第三章习题; /* * 把前n(n<=10000)个整数顺次写在一起: * 89101112... * 数一数0-9各出现多少次 * (输出10个整数,分别是09出现的次 ...
- 《逆向工程核心原理》——通过调试方式hook Api
1.附加目标进程, 2.CREATE_PROCESS_DEBUG_EVENT附加事件中将目标api处设置为0xcc(INT 3断点) 3.EXCEPTION_DEBUG_EVENT异常事件中,首先判断 ...
- Maven项目中resources配置总结
目录 背景 第一部分 基本配置介绍 第二部分 具体配置和注意事项 第三部分 读取resources资源 参考文献及资料 背景 通常Maven项目的文件目录结构如下: # Maven项目的标准目录结构 ...
- 冒泡算法(BubbleSort)
/*冒泡排序原理 比较相邻的元素.如果前一个元素比后一个元素大,就交换这两个元素的位置. 对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素.最终最后位置的元素就是最大值.实现步骤 1 ...
- 深度学习---1cycle策略:实践中的学习率设定应该是先增再降
深度学习---1cycle策略:实践中的学习率设定应该是先增再降 本文转载自机器之心Pro,以作为该段时间的学习记录 深度模型中的学习率及其相关参数是最重要也是最难控制的超参数,本文将介绍 Lesli ...
- SpringCloudAlibaba—微服务概念及SpringCloudAlibaba介绍
目录 1.1 系统架构演变 1.1.1 单体应用架构 1.1.2垂直应用架构 1.1.3 分布式架构 1.1.4 SOA架构 1.1.5 微服务架构 1.2 微服务架构介绍 1.2.1 微服务架构的常 ...
- oo第二单元——多线程魔鬼电梯
在初步认识了面向对象思想后,立刻进入了多线程的学习,本单元的难点主要是锁的理解,需要保证线程安全的同时防止死锁的发生,也要尽可能缩小锁的范围,提高性能.这一单元以电梯为载体,让我们从生活出发,从电梯运 ...
- springboot项目整合mybatis
记录创建springboot项目并配置mybatis中间件: 资源准备及版本说明 编程工具:IDEA JDK版本:1.8 Maven版本:Apache Maven 3.6.3 springboot版本 ...
- 解决SQLPLUS无法使用上下箭头
1 问题描述 SQLPLUS中使用上下箭头无法获取历史命令,如下图所示: 按上下箭头会显示^[[A/^[[B. 2 解决方案 需要安装rlwrap,可以的话可以用包管理器安装,笔者环境CentOS,这 ...