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春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 热身作业 我在这个课程的目标是 学习软件工 ...
随机推荐
- CSS002. 字体穿透蒙层(用img设置字体的color)
之前在逛Apple Store时看到了下面的UI: 交互图标非常圆滑上手也很舒服,虽然背景底色本就是白底,但是只依赖css能不能使 "+" 穿透背景看到底色 ? 大致思路如下: ...
- 运行FreeSWITCH的命令行参数
一般来说,FreeSWITCH 不需要任何命令行参数就可以启动,但在某些情况下,你需要以一些特殊的参数启动.在此,仅作简单介绍.如果你知道是什么意思,那么你就可以使用,如果不知道,多半你用不到. 使用 ...
- Spring Boot 2.x 之 Spring Data JPA, Hibernate 5
1. Spring Boot常用配置项 基于Spring Boot 2.0.6.RELEASE 1.1 配置属性类 spring.jpa前缀的相关配置项定义在JpaProperties类中, 1.2 ...
- (未完)Java集合框架梳理(基于JDK1.8)
Java集合类主要由两个接口Collection和Map派生出来的,Collection派生出了三个子接口:List.Set.Queue(Java5新增的队列),因此Java集合大致也可分成List. ...
- POJ 2509 Peter's smokes(Peter的香烟)
POJ 2509 Peter的香烟 描述 Peter抽烟.他抽烟一个个地抽着烟头.从 k (k>1) 个烟头中,他可以抽一根新烟.彼得可以抽几支烟? 输入 输入是一系列行.每行包含两个给出n和k ...
- PHP设计模式之享元模式
享元模式,"享元"这两个字在中文里其实并没有什么特殊的意思,所以我们要把它拆分来看."享"就是共享,"元"就是元素,这样一来似乎就很容易理解 ...
- TP5缩放图片加水印
// 给图片增加水印文字 试验缩放图片,放大图片,加水印,加文字功能 public function doCreateImage1($data,$path) { $basePath = ROOT_PA ...
- 超详细unittest单元测试框架总结
unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果.今天笔者 ...
- 替代jquery中的几个函数
// https://open.alipay.com/developmentAccess/developmentAccess.htm var $ = window.jQuery; (function( ...
- pyqt5无边框拖动
from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * import sys class ...