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春季计算机学院软件工程(罗杰 任健) ...
随机推荐
- IPFS挖矿必须要托管吗?
IPFS 本质上只是一个人人使用的协议,而 Filecoin 是 IPFS 的激励层,大家平时说的 IPFS 挖矿,其实就是挖 Filecoin.而提到IPFS 就不得不说到矿机托管的问题. 点击了解 ...
- Hexagon HDU - 6862
题目链接:https://vjudge.net/problem/HDU-6862 题意: 由六边形组成的圆形图案,要求不重复走遍历每一个小六边形. 思路:https://www.cnblogs.com ...
- 循环3n加1问题
package 第二章; import java.util.Scanner; //int 32位整数 /* * 猜想:对于任意大于一的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半 经过 ...
- matplotlib常规使用方法
1,指定图片大小和像素 Python绘图问题:Matplotlib中指定图片大小和像素 2,绘图命令的基本架构及其属性设置 绘图与可视化 3,python基础语法(二)--- plt的一些函数使用 p ...
- java例题_08 输入特定数字求和(n个a位数递增求和问题)
1 /*8 [程序 8 输入数字求和] 2 题目:求 s=a+aa+aaa+aaaa+aa...a 的值,其中 a 是一个数字.例如 2+22+222+2222+22222(此时共有 5 个数相加), ...
- pgrep - 命令
pgrep 命令格式:pgrep [选项] [模式] 选项 含义 -d <string> 指定输出分隔符 -l PID和进程名称 -a 列出PID和完整的命令行 -v 取反 -c 统计进程 ...
- EfficientNet & EfficientDet 论文解读
概述 总体而言,这两篇论文都在追求一件事,那就是它们名字中都有的 efficient.只是两篇文章的侧重点不一样,EfficientNet 主要时研究如何平衡模型的深度 (depth).宽度 (wid ...
- 【Prolog - 1.0 基础语法与概念】
[概述] Prolog的语法与其它常用语言(如C,JAVA等)不同,它更接近于自然语言. [实例] 当我想表示"Mia是以女人"这个事实(之后会提到事实这个概念)的时候,我可以这么 ...
- 自动化kolla-ansible部署ubuntu20.04+openstack-victoria之镜像制作centos7.8-15
自动化kolla-ansible部署ubuntu20.04+openstack-victoria之镜像制作centos7.8-15 欢迎加QQ群:1026880196 进行交流学习 制作OpenS ...
- (十二)docker --privileged
1. privileged参数作用 --privileged Give extended privileges to this container 大约在0.6版,privileged被引入docke ...