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. MyBatis的Mapper代理笔记

    MaBatis--Mapper代理 目前使用SqlSession进行增删改查的缺点: 没有办法实现多参传值 书写的时候没有接口,后期的维护低 使用Mapper的动态代理方式来解决问题 具体实现 首先我 ...

  2. 记一次《C语言踩内存》问题定位有感

    踩内存问题,个人认为算是比较容易出现但是有很难定位的问题,被踩者轻者功能瘫痪,重者一命呜呼,直接诱发死机.产生踩内存的的原因也比较多样,比较典型的有如下几种: 数组越界访问 字符串越界操作 直接操作野 ...

  3. minix3使用轻快入门

    minix3是一款迷你的unix作业系统,但又不在at&t代码的基础上构建.当年开发这款作业系统的作者仅仅是拿来自用,给学生上课使用的. 如果你已经安装了minix3,你还需要安装openss ...

  4. mac php安装扩展 如 seoole apcu

    //下载 --安装 --复制扩展文件到对应目录 wget https://pecl.php.net/get/apcu-5.1.7.tgz tar -zvcf pcu-5.1.7.tgz cd 到解压目 ...

  5. ORACLE 坏块的模拟和查看

    坏块的模拟和查看使用bbed工具修改数据文件的块,然后使用dbv和rman工具查看坏块. 1.创建数据:根据dbv查看没有坏块Total Pages Marked Corrupt : 0create ...

  6. 利用Conda尝鲜Python 3.10

    1 简介 就在几天前,Python3.10的第一个正式版本3.10.0发布,之前我们只是从其各个测试版本中捕风捉影地知晓了一些可能加入的新特性,而在正式版本中,我们得以一睹其正式加入的诸多新特性. 本 ...

  7. 11.5.1 LVS-DR 实验

    lvs-server VIP:10.211.55.99 DIP:10.211.55.23 负载均衡器   rs01 RIP:10.211.55.24 后端服务器   rs02 RIP:10.211.5 ...

  8. 10.7 URI

    URI:   Uniform Resource Identifier  统一资源标识符 URL:  Uniform Resource Locator    统一资源定位符 URN: Uniform R ...

  9. 从零搭建基于webpack的Electron-Vue3项目(1)——基于webpack的Vue3项目搭建

    从零搭建基于webpack的Electron-Vue3项目(1)--基于webpack的Vue3项目搭建 前言 本篇文章内容,主要是基于webpack的Vue3项目开发环境进行搭建,暂时还不涉及到El ...

  10. 怎样将.h文件添加到项目中

    作为C++的初学者,在运行别人的程序时,第一个遇到的问题就是无法将程序中写到的.h文件包含到项目中来.下面来写一下处理方法.本文以easyx.h为例进行说明 首先右键你的工程 选择Properties ...