2020BUAA软工个人项目作业
2020BUAA软工个人项目作业
17373010 杜博玮
项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2020春季计算机学院软件工程(罗杰 任健) |
这个作业的要求在哪里 | 个人项目作业 |
我在这个课程的目标是 | 学习软件工程,培养工程开发能力、团队协作能力,开阔视野 |
这个作业在哪个具体方面帮助我实现目标 | 通过个人尝试对软件工程构建一定认识 |
教学班级 005
项目地址 https://github.com/Cuogeihong/IntersectProject
PSP表格:
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
Estimate | 估计这个任务需要多少时间 | 15 | 10 |
Development | 开发 | ||
Analysis | 需求分析 (包括学习新技术) | 80 | 90 |
Design Spec | 生成设计文档 | 45 | 40 |
Design Review | 设计复审 | 15 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 15 | 10 |
Design | 具体设计 | 60 | 75 |
Coding | 具体编码 | 240 | 200 |
Code Review | 代码复审 | 15 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 150 |
Reporting | 报告 | ||
Test Reporting | 测试报告 | 45 | 40 |
Size Measurement | 计算工作量 | 15 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 15 | 20 |
合计 | 680 | 675 |
解题思路:
我的思路主要是暴力求解。通过处理输入数据,将直线表示为\(ax+by+c=0\)的形式,将圆表示为\((x-a)^2+(y-b)^2=r^2\)的形式,使用vector数组储存。计算时分为三种情况,直线与直线之间,圆与直线之间,圆与圆之间,对这三种情况分别利用已经推导好的公式计算得出结果,将结果去重后得到答案。
通过数学知识我分析了暴力求交点的方法。
计算两直线之间的交点时先判断是否平行,之后直接代入两个二元一次方程联立后的解即可得到结果。
计算直线与圆之间的交点时首先判断直线是否垂直于x轴,如果是,则直接求出\(x\),此后解一元二次方程得到\(y\)。否则通过直线将\(y\)从圆的方程组消掉,求解一元二次方程得到\(x\),再代回直线求得\(y\)。
计算圆与圆之间交点直接将两圆相减得到直线方程,之后按照计算直线与圆之间的交点的方法求出圆与圆之间交点。此时需注意直线的\(a\)与\(b\)均为0的情况。
在后来优化代码时我发现了使用向量法求交点的方法,但是程序已经比较完善了,使用向量法需要几乎重写程序,因此我没有采用向量法。
设计实现过程:
主要功能在Image类中实现。main函数主要处理命令行参数以及接受输入并传给Image类。
Image类中主要有6个函数,其中addLine函数和addCircle函数处理输入数据并存储,getNum函数接受main函数调用并总领计算,getLineAndLinePoint,getLineAndCirclePoint,getCircleAndCirclePoint三个函数分别计算两直线之间的交点、直线与圆之间的交点、圆与圆之间交点。
此外程序定义了line、circle、point数据类型方便程序编写。
整体而言程序实现并不复杂。
单元测试主要测试以下功能。
两直线相交
两直线平行
三条直线相交于同一点
三条直线其中两直线平行
直线与圆相交
直线与圆相切
直线与圆相离
圆与圆外切
圆与圆相交
圆与圆外离
圆与圆内切
圆与圆内含
TEST_METHOD(TestMethod1)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addLine(0, 0, 1, 1);
img->addLine(1, -1, 0, 0);
Assert::AreEqual(img->getNum(), 1);
}
TEST_METHOD(TestMethod2)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addLine(0, 0, 1, 1);
img->addLine(3, 4, 4, 5);
Assert::AreEqual(img->getNum(), 0);
}
TEST_METHOD(TestMethod3)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addLine(0, 0, 1, 1);
img->addLine(-1, 1, 1, -1);
img->addLine(3, 4, -3, -4);
Assert::AreEqual(img->getNum(), 1);
}
TEST_METHOD(TestMethod4)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addLine(0, 0, 1, 1);
img->addLine(-1, 1, 1, -1);
img->addLine(3, 4, -4, -3);
Assert::AreEqual(img->getNum(), 2);
}
TEST_METHOD(TestMethod5)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 1);
img->addLine(0, 0, 1, 1);
Assert::AreEqual(img->getNum(), 2);
}
TEST_METHOD(TestMethod6)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 1);
img->addLine(0, 1, 1, 1);
Assert::AreEqual(img->getNum(), 1);
}
TEST_METHOD(TestMethod7)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 1);
img->addLine(2, 2, 2, 0);
Assert::AreEqual(img->getNum(), 0);
}
TEST_METHOD(TestMethod8)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 1);
img->addCircle(2, 0, 1);
Assert::AreEqual(img->getNum(), 1);
}
TEST_METHOD(TestMethod9)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 1);
img->addCircle(1, 0, 1);
Assert::AreEqual(img->getNum(), 2);
}
TEST_METHOD(TestMethod10)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 1);
img->addCircle(3, 0, 1);
cout << img->getNum() << endl;
Assert::AreEqual(img->getNum(), 0);
}
TEST_METHOD(TestMethod11)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 4);
img->addCircle(3, 0, 1);
cout << img->getNum() << endl;
Assert::AreEqual(img->getNum(), 1);
}
TEST_METHOD(TestMethod12)
{
// TODO: 在此输入测试代码
Image *img = new Image();
img->addCircle(0, 0, 4);
img->addCircle(0, 1, 1);
cout << img->getNum() << endl;
Assert::AreEqual(img->getNum(), 0);
}
单元测试运行结果:
性能分析与优化:
此前我采用set进行去重工作,通过性能分析我们可以看到,set花费了超过80%的CPU时间,因此需要对set进行优化。这样我找到了unordered_set,它利用hash来实现set的功能,不会对集合内数据进行排序,在修改后性能得到了大幅度的提高。
代码说明:
求两直线交点
for (int i = 0; i < linesLength; i++) {
for (int j = i + 1; j < linesLength; j++) {//避免重复运算
line lineA, lineB;
lineA = lines[i];
lineB = lines[j];
double judgeNum = lineA.a * lineB.b - lineA.b * lineB.a;//判断两直线是否平行
if (fabs(judgeNum) < 1e-8) {//防止因为浮点数以无限逼近于0代表0
continue;
}
double x, y;
x = (lineB.c * lineA.b - lineA.c * lineB.b) / judgeNum;//计算交点x
y = (lineB.a * lineA.c - lineA.a * lineB.c) / judgeNum;//计算交点y
point cur(x, y);
points.insert(cur);//将交点放入集合中去重
}
}
求直线与圆交点
for (int i = 0; i < linesLength; i++) {
for (int j = 0; j < circlesLength; j++) {
line curLine;
circle curCircle;
curLine = lines[i];
curCircle = circles[j];
if (curLine.b == 0) {//当直线垂直于x轴时
double distanceLC = curLine.c / curLine.a + curCircle.x;
if (fabs(fabs(distanceLC) - abs(curCircle.r)) < 1e-8) {
point cur(-1 * curLine.c / curLine.a, curCircle.y);
points.insert(cur);//将交点放入集合中去重
}
else if (fabs(distanceLC) - abs(curCircle.r) < 0) {
double sqrtTmp = sqrt(curCircle.r * curCircle.r -
distanceLC * distanceLC);
point cur1(-1 * curLine.c / curLine.a, curCircle.y + sqrtTmp);
point cur2(-1 * curLine.c / curLine.a, curCircle.y + sqrtTmp);
points.insert(cur1);//将交点放入集合中去重
points.insert(cur2);//将交点放入集合中去重
}
}
else {
//用x表示y的值 y=kx+b
double k = -1 * curLine.a / curLine.b, b = -1 * curLine.c / curLine.b;
double equationA, equationB, equationC;//表示化简得到的一元二次方程
equationA = k * k + 1;
equationB = 2 * (k * b - k * curCircle.y - curCircle.x);
equationC = curCircle.x * curCircle.x - curCircle.r * curCircle.r +
(b - curCircle.y) * (b - curCircle.y);
double judge = equationB * equationB - 4 * equationA * equationC;//判别式
if (fabs(judge) < 1e-8) {
//一元二次方程只有一个根时
double answerX = -1 * equationB / 2 / equationA;
point cur(answerX, answerX * k + b);
points.insert(cur);//将交点放入集合中去重
}
else if (judge > 0) {
//计算x的两个根并推出y的值
double answerX1 = (-1 * equationB + sqrt(judge)) / 2 / equationA;
point cur1(answerX1, answerX1 * k + b);
points.insert(cur1);//将交点放入集合中去重
double answerX2 = (-1 * equationB - sqrt(judge)) / 2 / equationA;
point cur2(answerX2, answerX2 * k + b);
points.insert(cur2);//将交点放入集合中去重
}
}
}
}
两圆之间交点的计算与直线与圆计算相同,不再放出。
消除 Code Quality Analysis 中的所有警告:
2020BUAA软工个人项目作业的更多相关文章
- 2020BUAA软工结伴项目作业
2020BUAA软工结伴项目作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结伴项目作业 我在这个课程的目标是 学 ...
- 【BUAA 软工个人项目作业】玩转平面几何
BUAA 软件工程个人项目作业 项目 内容 课程:2020春季软件工程课程博客作业(罗杰,任健) 博客园班级链接 作业:BUAA软件工程个人项目作业 作业要求 课程目标 学习大规模软件开发的技巧与方法 ...
- BUAA 软工 结对项目作业
1.相关信息 Q A 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目作业 我在这个课程的目标是 系统地学习软件工程开发知识,掌握相关流程和技术,提升 ...
- BUAA软工-结对项目作业
结对项目作业 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目作业 我在这个课程的目标是 通过这门课锻炼软件开发能力和经验,强化与他人合作 ...
- python简单实现论文查重(软工第一次项目作业)
前言 软件工程 https://edu.cnblogs.com/campus/gdgy/informationsecurity1812 作业要求 https://edu.cnblogs.com/cam ...
- 2020BUAA软工提问回顾和个人总结作业
2020BUAA软工提问回顾和个人总结作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 提问回顾和个人总结作业 我在 ...
- 2020BUAA软工个人博客作业-软件案例分析
2020BUAA软工个人博客作业-软件案例分析 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业-软件案例分 ...
- 2020BUAA软工个人博客作业
2020BUAA软工个人博客作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业 我在这个课程的目标是 学 ...
- 2020BUAA软工热身作业
2020BUAA软工热身作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 热身作业 我在这个课程的目标是 学习软件工 ...
随机推荐
- Spring Boot 入门系列(二十八) JPA 的实体映射关系,一对一,一对多,多对多关系映射!
前面讲了Spring Boot 使用 JPA,实现JPA 的增.删.改.查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用.JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层 ...
- .NET5修改配置不重启自动生效
.NET Core,.NET5默认配置都是只加载一次,修改配置时都需要重启才能生效,如何能修改即时生效呢,下面来演示一遍. 一.设置配置文件实时生效 1.1配置 在Program.cs的CreateH ...
- [第五篇]——Docker 镜像加速之Spring Cloud直播商城 b2b2c电子商务技术总结
Docker 镜像加速 国内从 DockerHub 拉取镜像有时会遇到困难,此时可以配置镜像加速器.Docker 官方和国内很多云服务商都提供了国内加速器服务,例如: 科大镜像: 网易: 阿里云: 你 ...
- 管理后台界面 详细分析(内含代码 |【前端】)RuoYi
最近在做的一个后台管理 因为关于隐私原因 只方便展示个别页面代码 不会上传项目 注意是前端代码 我把项目代码地址放在最后了 如有需要可自取学习 我会为各位兄弟详细的介绍其中各个属性的含义和用法,记 ...
- TP5路由的位置导致错误
// 测试 '[js]' => [ ':id' => ['test/test/js', ['method' => 'get'], ['id' => '\d+']], ':id/ ...
- Docker系列(19)- 数据卷之Dockerfile
初识Dockerfile Dockerfile就是用来构建docker镜像的构建文件!命令脚本! 通过这个脚本生成镜像,镜像是一层一层的,脚本与一个个的命令,每个命令都是一层! # 创建一个docke ...
- Linux系列(2) - 命令提示符
命令提示符 起始符 [root@localhost ~]# root:当前登录用户 localhost:主机名 ~:当前所在目录(家目录);管理员为 /root ,user用户为 /home/user ...
- Linux系列(23) - echo
作用:打印 格式:echo [选项] [输出内容] 选项:-e :支持反斜线控制的字符转换 前置条件:必须加选项-e才能使用 控制字符 作用 \a 输出警告音 \b 退格符,也就是向左删除键 \n 换 ...
- Xftp乱码问题
Xftp出现乱码 修改编码
- vue 改变路由参数
更改路由传递的参数: const query = JSON.parse(JSON.stringify(this.$route.query)) // 获取路由参数信息 query.id = Name / ...