BUAA软件工程个人项目作业
BUAA软件工程个人项目作业
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2020春季计算机学院软件工程(罗杰 任健) |
| 这个作业的要求在哪里 | 个人项目作业 |
| 我在这个课程的目标是 | 学习软件开发的流程 |
| 这个作业在哪个具体方面帮助我实现目标 | 体会个人写项目的流程 |
| 教学班级 | 006 |
| 项目地址 | https://github.com/monokuma-zhuo/Intersect |
PSP项目表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | ||
| · Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
| Development | 开发 | ||
| · Analysis | · 需求分析 (包括学习新技术) | 30 | 60 |
| · Design Spec | · 生成设计文档 | 20 | 30 |
| · Design Review | · 设计复审 (和同事审核设计文档) | 20 | 20 |
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 5 | 5 |
| · Design | · 具体设计 | 30 | 15 |
| · Coding | · 具体编码 | 120 | 100 |
| · Code Review | · 代码复审 | 15 | 30 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 60 | 120 |
| Reporting | 报告 | ||
| · Test Report | · 测试报告 | 10 | 30 |
| · Size Measurement | · 计算工作量 | 5 | 10 |
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 15 |
| 合计 | 335 | 445 |
解题思路描述
读懂题目后,明白题目要求是平面内求直线和圆的交点总数。思路大概分为如何求解该问题和用代码如何实现
如何求解
很显然用解析几何知识,对于所有曲线两两求交点。因此我查找并复习了一些解析几何知识,并确定解题方法。
直线方程最常用的形式有点斜式y=kx+b和标准式Ax+By+C=0。点斜式虽然在运算时方便,但由于要考虑斜率等于0和斜率不存在的情况比较麻烦,故直线方程选择了标准式。
圆方程有标准式(x-a)2+(y-b)2=r2和一般式x2+y2+Dx+Ey+F=0两种形式,由于输入数据直接给出了圆心坐标和半径,我也没有多考虑直接选择了第一种形式。
直线与直线有平行和相交两种情况(重合不考虑),平行则A1*B2=A2*B1,否则直接联立求解即可。
直线与圆有相交相切相离三种情况,可以利用圆心到直线的距离是否大于半径来判断位置关系,也可以直接联立方程组根据解的个数判断,并得到交点坐标。
圆与圆有内含、内切、相交、外切、相离5种情况,可以利用两个圆心之间的距离判断位置关系,在求解时需要用到圆的一般式,相减去掉平方项后得到一个直线方程,之后用该直线方程和任意一个圆联立即可得到交点坐标。
代码实现
首先考虑到如何存储直线、圆、点,查找并学习了许多c++的容器,比如这次用到的vector,set,pair。
最初是想把点封装为一个类,但由于本题目只需要点的数量,放弃了封装类,仅存在了vector容器中。每个点由横坐标和纵坐标组成,故想到利用pair将x和y组合在一起,所以需要vector<pair>这样的容器。由于可能会有交点重复的情况,所以还需要对vector中的元素去重,将vector排序后用unique和erase进行去重。此外了解到set容器使用红黑树的结构并且不支持重复元素,故也可以直接用set进行存储。
线需要创建一个类,其中包含A,B,C三个参数的值,以及一个求交点坐标的intersect方法,返回值是pair类型。由于该方法我希望直接返回交点的坐标,所以我又写了一个方法判断两直线是否相交,如果相交则再调用intersect方法求坐标,这样也省去了一些不必要的计算。
同理圆也创建一个类,其中包含圆心坐标(a,b)和半径r三个参数。方法借鉴了线类的思想,先判断圆和直线是否有交点,如果有则调用line_cycle_instere方法求得交点坐标。返回值是一个pair<pair,pair>的形式,返回两个交点(如果相切,则相当于两个交点是同一点)。同理,判断两圆是否有交点,如果有则调用cycle_cycle_instere方法求得交点坐标。
设计与测试

如图共有两个类,Line类有2个构造函数和2个方法,Cycle类有1个构造函数和4个方法。这里我说一下为什么Line类为什么会多一个构造函数,因为根据两圆相交求交点的方法,是会直接得到Ax+By+C=0形式的直线方程。而输入的直线方程是两个点的坐标,二者不同,所以我重载了构造函数,得到直线后再调用line_cycle_instere方法即可。二者之间仅在圆和直线有交点时,Cycle对象会传入一个Line对象并进行求交点的运算。
这次题目比较简单,所以没有画流程图。大致说一下main函数的流程,读入数据后判断是直线还是圆并建立相应的对象存到vector容器中,之后判断该直线或圆有没有和已有的直线和圆相交,如果有则计算交点坐标并存入set容器。最后输出set容器的size即可。
单元测试根据之前分析的情况,针对直线和圆的不同位置关系构造不同的数据。包括:直线与直线相交、平行;直线与圆相交、相切、相离;圆与圆内含、内切、相交、外切、相离。其中还夹杂着直线斜率为0,直线斜率不存在以及重复点的情况。

性能分析与改进
在进行性能分析时发现消耗最大的是set容器的insert方法。随着交点增多,树的深度也逐渐加深,这样每进行一次insert就要消耗log数深的复杂度。所以我想到改用vector,毕竟vector的push_back方法是O(1)的复杂度。但经实际测试发现效果并不好,原因是vector在空间不够时,会讲整个数组拷贝到另一份新空间中。这样在数据量大的情况下会经常出现空间不够的情况,就需要反复进行O(n)的操作,代价也非常大,所以权衡之下还是选择了set容器。


如图这是我随机生成的10000条直线和圆的结果,消耗最大的地方为set容器的insert方法(上图数据仅供参考,实际的交点数已远大于题目要求)
代码说明
pair<double,double> intersect(Line l)
{
double x = (l.C * B - C * l.B) / (A * l.B - B * l.A);
double y = (C * l.A - l.C * A) / (A * l.B - B * l.A);
pair<double, double> dot(x, y);
return dot;
}
求两直线交点坐标,联立解方程组即可。
bool isteresect(Line l)
{
if (A * l.B - B * l.A == 0)
{
return false;
}
else
{
return true;
}
}
判断两直线是否平行。
bool line_cycle_pos(Line l)
{
double length = abs((l.A * x + l.B * y + l.C)) / (sqrt(l.A * l.A + l.B * l.B));
if (length > r)
{
return false;
}
else
{
return true;
}
}
判断圆和直线的位置关系,利用点到直线距离公式求圆心到直线的距离。
pair<pair<double, double>, pair<double, double>> line_cycle_instere(Line l)
{
if (l.A == 0)
{
double y_point = -1.0 * l.C / l.B;
double temp = sqrt((r * r - (y - y_point) * (y - y_point)));
pair<double, double> dot1(x + temp, y_point);
pair<double, double> dot2(x - temp, y_point);
return make_pair(dot1, dot2);
}
else if (l.B == 0)
{
double x_point = -1.0 * l.C / l.A;
double temp = sqrt((r * r - (x - x_point) * (x - x_point)));
pair<double, double> dot1(x_point, y + temp);
pair<double, double> dot2(x_point, y - temp);
return make_pair(dot1, dot2);
}
else
{
double k = -1.0 * l.A / l.B;
double b = -1.0 * l.C / l.B;
double a1 = 1.0 + k * k;
double b1 = 2.0 * (k * b - k * y - x);
double c1 = (b - y) * (b - y) -(r * r)+(x*x);
double x1 = (-1.0 * b1 + sqrt(b1 * b1 - 4 * a1 * c1)) / (2.0 * a1);
double y1 = k * x1 + b;
double x2 = (-1.0 * b1 - sqrt(b1 * b1 - 4 * a1 * c1)) / (2.0 * a1);
double y2 = k * x2 + b;
pair<double, double> dot1(x1, y1);
pair<double, double> dot2(x2, y2);
return make_pair(dot1, dot2);
}
}
求直线和圆交点坐标。分别判断了斜率等于0,斜率不存在的情况。然后将直线方程转化为y=kx+b的形式与圆方程进行联立求解。最后利用一元二次方程的求根公式得到x1和x2,带回到直线方程中即可求得y1和y2
bool cycle_cycel_pos(Cycle c)
{
double length = sqrt((c.x - x) * (c.x - x) + (c.y - y) * (c.y - y));
if (length > r + c.r||length<abs(r-c.r))
{
return false;
}
else
{
return true;
}
}
判断两圆的位置关系,求得圆心之间的距离,如果距离大于半径加和则外离;小于半径差则内含,都没有交点,其他情况均有交点。
pair<pair<double, double>, pair<double, double>> cycle_cycle_instere(Cycle c)
{
double D = -2.0 * x;
double E = -2.0 * y;
double F = (x * x) + (y * y) - (r * r);
double D1 = -2.0 * c.x;
double E1 = -2.0 * c.y;
double F1 = (c.x * c.x) + (c.y * c.y) - (c.r * c.r);
Line temp_l(D - D1, E - E1, F - F1);
return line_cycle_instere(temp_l);
}
求两圆的交点坐标,将圆转化为一般式后相减即得到一个直线方程,然后调用直线与圆求交点的方法即可。

最后附上代码已无任何警告的截图。
BUAA软件工程个人项目作业的更多相关文章
- BUAA软件工程结对项目作业
BUAA软件工程结对项目 小组成员:16005001,17373192 1.教学班级和项目地址 项目 内容 这个作业属于哪个课程 博客园班级连接 这个作业的要求在哪里 结对项目作业 我在这个课程的目标 ...
- BUAA 2020 软件工程 个人项目作业
BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...
- BUAA 2020 软件工程 结对项目作业
Author: 17373051 郭骏 3.28添加:4.计算模块接口的设计与实现过程部分,PairCore实现的细节 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) ...
- BUAA软件工程个人项目
写在前面 项目 内容 所属课程 2020春季计算机学院软件工程(罗杰 任健) (北航) 作业要求 [个人项目作业](<https://edu.cnblogs.com/campus/buaa/BU ...
- BUAA SE 个人项目作业
项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 通过个人项目实践熟悉个人开发流程 一.在文章开头给出教学班级和 ...
- 软件工程个人项目作业 Individual Project
利用Junit4进行程序模块的测试,回归测试 源码 https://github.com/dpch16303/test/blob/master/%E5%9B%9E%E5%BD%92%E6%B5%8B% ...
- 【BUAA 软工个人项目作业】玩转平面几何
BUAA 软件工程个人项目作业 项目 内容 课程:2020春季软件工程课程博客作业(罗杰,任健) 博客园班级链接 作业:BUAA软件工程个人项目作业 作业要求 课程目标 学习大规模软件开发的技巧与方法 ...
- BUAA 软件工程个人作业
BUAA 软件工程 个人项目作业 Author: 17373015 乔玺华 教学班级 :005 项目地址:https://github.com/JordenQiao/SE_Homework_Perso ...
- 【BUAA软件工程】第一次阅读作业
BUAA软件工程 第一次阅读作业 项目 内容 这个作业属于哪个课程? 北航软工 这个作业的要求在哪里? 第一次个人作业 我在这个课程的目标是? 学习高效严谨的软件工程开发过程,建立团队意识 这个作业在 ...
随机推荐
- Java-Bean Validation后端校验总结
Validation Information resource: SpringBoot Docs: 2.8.9. @ConfigurationProperties Validation url: ht ...
- vue-cli-service build 环境设置
zhidao zhouzongshuo的那个是使用vue-cli3打包项目,通过配置不同的指令给项目设置不一样的配置. npm run serve时会把process.env.NODE_ENV设置为' ...
- Linux没有/var/log/messages日志文件
1.新安装的CentOS8没有/var/log/messages日志文件: 安装rsyslog: dnf install -y rsyslog 或 yum install -y rsys ...
- 利用 Nginx 搭建小型的文件服务器
利用 Nginx 搭建小型的文件服务器 1.查看 Nginx 配置 android@localhost:/etc/nginx/conf.d$ nginx -hnginx version: nginx/ ...
- win10系统移动热点使用技巧
win10系统是自动移动热点功能,在平时测试的时候,有时需要进行手机抓包,需要手机和电脑处于同一网络当中,这时可以开启热点使用. 如何开启移动热点? 直接搜索"移动热点" 但是如果 ...
- centos7安装sonarqube与使用
https://www.cnblogs.com/mascot1/p/11179767.html https://blog.csdn.net/superbfly/article/details/1039 ...
- git 报错 gitThere is no tracking information for the current branch. Please specify which branch you w
新建本地分支后将本地分支推送到远程库, 使用git pull 或者 git push 的时候报错gitThere is no tracking information for the current ...
- lua文件修改为二进制文件
注意:lua编译跟luajit编译的二进制文件是不兼容,不能运行的 如果是使用luajit,请直接使用luajit直接编译二进制 第一种:luajit编译(以openresty为例,跟luac是相反的 ...
- ios web 媒体查询兼容
原文:https://blog.csdn.net/dear_zx/article/details/82785250 防止链接丢失,复制一下 兼容iphone4/4s: @media (device-h ...
- Fiddler抓包(以谷歌浏览器、安卓手机为例)
fiddler抓包流程与whistle相同,所以本章内容会相对简洁.如果需要详细说明,可参考whistle抓包. 这里以谷歌浏览器.安卓手机为例. 1.fiddler安装 下载安装包,默认安装. 2. ...