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软件工程个人项目作业的更多相关文章

  1. BUAA软件工程结对项目作业

    BUAA软件工程结对项目 小组成员:16005001,17373192 1.教学班级和项目地址 项目 内容 这个作业属于哪个课程 博客园班级连接 这个作业的要求在哪里 结对项目作业 我在这个课程的目标 ...

  2. BUAA 2020 软件工程 个人项目作业

    BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...

  3. BUAA 2020 软件工程 结对项目作业

    Author: 17373051 郭骏 3.28添加:4.计算模块接口的设计与实现过程部分,PairCore实现的细节 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) ...

  4. BUAA软件工程个人项目

    写在前面 项目 内容 所属课程 2020春季计算机学院软件工程(罗杰 任健) (北航) 作业要求 [个人项目作业](<https://edu.cnblogs.com/campus/buaa/BU ...

  5. BUAA SE 个人项目作业

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 通过个人项目实践熟悉个人开发流程 一.在文章开头给出教学班级和 ...

  6. 软件工程个人项目作业 Individual Project

    利用Junit4进行程序模块的测试,回归测试 源码 https://github.com/dpch16303/test/blob/master/%E5%9B%9E%E5%BD%92%E6%B5%8B% ...

  7. 【BUAA 软工个人项目作业】玩转平面几何

    BUAA 软件工程个人项目作业 项目 内容 课程:2020春季软件工程课程博客作业(罗杰,任健) 博客园班级链接 作业:BUAA软件工程个人项目作业 作业要求 课程目标 学习大规模软件开发的技巧与方法 ...

  8. BUAA 软件工程个人作业

    BUAA 软件工程 个人项目作业 Author: 17373015 乔玺华 教学班级 :005 项目地址:https://github.com/JordenQiao/SE_Homework_Perso ...

  9. 【BUAA软件工程】第一次阅读作业

    BUAA软件工程 第一次阅读作业 项目 内容 这个作业属于哪个课程? 北航软工 这个作业的要求在哪里? 第一次个人作业 我在这个课程的目标是? 学习高效严谨的软件工程开发过程,建立团队意识 这个作业在 ...

随机推荐

  1. IPSec协议框架

    文章目录 1. IPSec简介 1.1 起源 1.2 定义 1.3 受益 2. IPSec原理描述 2.1 IPSec协议框架 2.1.1 安全联盟 2.1.2 安全协议 报文头结构 2.1.3 封装 ...

  2. weblogic漏洞分析之CVE-2017-10271

    weblogic漏洞分析之CVE-2017-10271 一.环境搭建 1)配置docker 这里使用vulhub的环境:CVE-2017-10271 编辑docker-compose.yml文件,加入 ...

  3. [第十篇]——Docker 容器连接之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker 容器连接 前面我们实现了通过网络端口来访问运行在 docker 容器内的服务. 容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过  -P 或  -p 参数来指定端口映射. ...

  4. jdbc核心技术-宋红康

    视频地址 JDBC核心技术 第1章:JDBC概述 1.1 数据的持久化 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应用,数据持久化意味着将 ...

  5. 小Z的袜子 & 莫队

    莫队学习 & 小Z的袜子 引入 莫队 由莫涛巨佬提出,是一种离线算法 运用广泛 可以解决广大的离线区间询问题 莫队的历史 早在mt巨佬提出莫队之前 类似莫队的算法和莫队的思想已在Codefor ...

  6. 跨 Docker 宿主机 macvlan 类型

    跨 Docker 宿主机 macvlan 类型 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 三台 CentOS 7.0 虚拟机 (Vmware Workstation 15 ...

  7. PHP中的PDO对象操作学习(一)初始化PDO及原始SQL语句操作

    PDO 已经是 PHP 中操作数据库事实上的标准.包括现在的框架和各种类库,都是以 PDO 作为数据库的连接方式.基本上只有我们自己在写简单的测试代码或者小的功能时会使用 mysqli 来操作数据库. ...

  8. PHP的zlib压缩工具扩展包学习

    总算到了我们压缩相关扩展的最后一篇文章了,最后我们要学习的也是 Linux 下非常常用的一种压缩格式:.gz 的压缩扩展.作为 PHP 的自带扩展,就像 zip 一样,zlib 扩展是随着 PHP 的 ...

  9. httprunner版本没有更新问题

    使用命令行创建虚拟环境,创建脚手架目录后,使用pycharm打开所创建的脚手架目录. 执行:hrun demo_testcase_request.yml 提示: E:\hrun_ven\test_hr ...

  10. P3293-[SCOI2016]美味【主席树】

    正题 题目链接:https://www.luogu.com.cn/problem/P3293 题目大意 给出一个长度为\(n\)的序列,\(m\)次询问给出\(b,x,l,r\)表示询问在\([l,r ...