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 AOP Aspect的简单实现(基于注解)
第1步:声明使用注解 <!-- 配置扫描注解--> 扫描包的位置<context:component-scan base-package="com.zz"/> ...
- Java字符串常量池及字符串判等解析
一.理解"=="的含义 "=="常用于两个对象的判等操作,在Java中,"=="主要有以下两种用法: 1.基础数据类型:比较的是他们的值是否 ...
- Jenkins教程(七)实现 GitLab 提交/合并代码触发构建
楔子 最近公司推行统一构建平台(基于 Jenkins + Kubernetes 插件创建 slave),原来部门自建的 Jenkins 不让用了. 迁移上统一构建平台的最大阻力是前端模块发布的问题: ...
- 洛谷P1088——火星人(全排列+数学模拟)
题目描述 人类终于登上了火星的土地并且见到了神秘的火星人.人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法.这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学 ...
- linux7可以通过远程和localhost访问mysql,但是127.0.0.1不能访问
网上搜索的其他方法都试过,不行 比如设置权限,开放端口,配置数据库... 最好偶然一个搜索查看可能原因是防火墙端口问题: vim /etc/sysconfig/iptables 在文件中添加下面语句 ...
- Shell系列(13)- read
前言 作用是往脚本中传递参数,之前文章的位置参数变量也有此功能,但是只适用于脚本的作者,为什么?第三方用户不知道这个脚本要传递哪些参数,这些参数分别是什么.本篇随笔read就可以实现上述功能,别且该命 ...
- 传说中 VUE 的“语法糖”到底是啥?
一.什么是语法糖? 语法糖也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语.指的是计算机语言中添加的一种语法,在不影响功能的情况下,添加某种简单的语 ...
- LeetCode2-链表两数和
目录 LeetCode2-链表两数和 题目描述 示例提示 经验教训 参考正解 题目描述 示例提示 经验教训 链表题的判空条件不是万能的,有时候示例会极其复杂,根本难以通过判空来区分不同情况. /** ...
- 由浅入深了解cookie
什么是 Cookie "cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用 JavaScript 来创建和取回 c ...
- P5437-[XR-2]约定【拉格朗日差值,数学期望】
正题 题目链接:https://www.luogu.com.cn/problem/P5437 题目大意 \(n\)个点的完全图,连接\(i,j\)的边权值为\((i+j)^k\).随机选出一个生成树, ...