BUAA软件工程个人项目
写在前面
| 项目 | 内容 |
|---|---|
| 所属课程 | 2020春季计算机学院软件工程(罗杰 任健) (北航) |
| 作业要求 | [个人项目作业](<https://edu.cnblogs.com/campus/buaa/BUAA_SE_2020_LJ/homework/10429) |
| 课程目标 | 培养软件开发能力 |
| 本作业对实现目标的具体作用 | 锻炼个人开发项目的能力 |
| 教学班级 | 006 |
| github项目地址 | https://github.com/LiuZH-19/SE_IntersectProject |
PSP表格记录
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | ||
| · Estimate | · 估计这个任务需要多少时间 | 5 | 10 |
| Development | 开发 | ||
| · Analysis | · 需求分析 (包括学习新技术) | 180 | 220 |
| · Design Spec | · 生成设计文档 | 10 | 20 |
| · Design Review | · 设计复审 (和同事审核设计文档) | 15 | 20 |
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 5 | 5 |
| · Design | · 具体设计 | 30 | 60 |
| · Coding | · 具体编码 | 120 | 160 |
| · Code Review | · 代码复审 | 20 | 20 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 120 | 120 |
| Reporting | 报告 | ||
| · Test Report | · 测试报告 | 30 | 30 |
| · Size Measurement | · 计算工作量 | 5 | 5 |
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 30 |
| 合计 | 550 | 700 |
解题思路描述
大体思路:
看了题目之后,想到的方法是:
利用数学的方法,解出两直线L1,L2存在交点的条件和其存在的交点的公式。
然后对输入中的任意两条直线,进行判断。若存在交点,则取出放入容器中(避免容器中元素的重复性)
最后输出容器中交点的个数
但考虑到需对输入中的直线两两求解,复杂度为\(\O(n^2)\)。我打算上网查一查,看看有没有更巧妙的算法。
查询无果,与小伙伴们讨论了一下,也没有更好的算法。就打算按这个算法,仔细想想细节部分。
为了避免直线的一些特殊情况的分析,我即将直线表示为一般式:Ax+By+C=0
附加题,也是类似的思路:
直线两两求解交点,再求解直线之前的交点情况,再求解两圆之间的交点情况。
在求解交点前,先判断是满足具有交点的条件,避免不必要的计算
细节考量:
直线与直线的交点比较好算,所以自己手算出来了算式关系。
直线与圆的公式也是手算的。
圆与圆之前的交点的公式,解得我头大,也不确定自己算出来的对不对,所以参考了网上的算法。详见
设计实现过程
代码组织:
期初设想:
类的设计:
- Line 类
- 直线用 Ax+By+C=0 表示 ,其中A,B,C为x1,y1,x2,y2的 函数
- 属性为 A,B,C
- 成员函数为 getA(), getB(), getC()
- Circle类
- 圆用\(\(x-X)^{2}+(y-Y)^{2}=R^2\)表示
- 属性为 X, Y, R
- 成员函数为 getX(), getY(),getR()
- Line 类
用 vector 存放 所有的直线
交点为Pair类型,用set存放所有的交点
三个函数,分别计算两直线之间,直线与圆之间,两圆之间的交点情况。
按照上述思路实现后,我发现Line 和 Circle类有点多余。教材中也说,只是封装数据的话,不用class用struct。所以我打算将直线和圆的参数用结构体来存。将原先计算交点情况的三个函数封装成一个Calculator类。又考虑到计算中的精度损失问题,构造了point 类,重写了operator <。具体情况如下:
后来改进:
Calculator 类
重载了三个成员函数class Calculator
{
public:
Calculator();
int haveIntersection(Line l1, Line l2, set<Point>& nodeSet);
int haveIntersection(Circle c, Line l, set<Point>& nodeSet);
int haveIntersection(Circle c1, Circle c2, set<Point>& nodeSet);
};Point类
自定义了运算符bool Point::operator < (const Point& p)const {
//return x==p.x?y<p.y:x<p.x;
return dcmp(x - p.x) == 0 ? dcmp(y - p.y) < 0 : dcmp(x - p.x) < 0; } bool Point::operator ==(const Point& p)const {
if (dcmp(x-p.x)==0&&dcmp(y-p.y)==0)
return true;
return false;
}
Line 和Circle的架构体
main中的函数 countALLinsect()
分别计算 直线之间,直线与圆之间,圆与圆之间的交点情况
单元测试设计
- 测试Calculator类,具体包括以下几个方面:
- 直线直线的交点情况
- 平行
- 三线交于一点
- 直线平行于x轴
- 直线 平行于y轴
- 一般情况
- 直线与圆的交点情况
- 直线的特殊情况
- 线圆关系
- 相切
- 相离
- 相交
- 圆与圆的交点关系
- 相离
- 相交
- 外切
- 内切
- 内含(同心)
- 复杂情况(两圆与一直线)
- 有一交点重叠
- 有两个交点重叠
- 一般情况
- 直线直线的交点情况
- 测试point类
检测 重写的operator < 是否正确 - 整体测试
- 大量数据测试 ,检测时间是否符合题意
- 检测 set 是否去重

测试均通过,且交点为8000000左右时,用时7s,也没有超时。
性能改进相关

图中可以看出,采用set容器后,构建红黑树占用了绝大部分CPU时间。在建树过程中,用到了我在Point类里面 重写的operator <,故其占用时间也较多。除去set的相关操作外,接下来去看了下 Calculator中的函数。

其中 CPU绝大部分的占用时间依然是 set的insert操作。所以在没能想到更优的算法下,性能改进工作可做的很少。我将一些常用的计算式先算出来,避免之后的重复计算。例如下图:

消除 Code Quality Analysis 中的所有警告
采用的是“Microsoft建议”的风格。

关键代码说明
求解所有的交点情况:直线之前、直线与圆、两圆之间
int countAllinsect(vector<Line> lVec, vector<Circle> cVec, set<Point> &nodeSet){
Calculator* calc = new Calculator();
size_t i, j;
//计算两条直线间的交点
for (i = 0; i < lVec.size(); i++) {
for (j = i + 1; j < lVec.size(); j++) {
calc->haveIntersection(lVec[i], lVec[j], nodeSet);
}
}
//计算直线与圆之间的交点
for (i = 0; i < cVec.size(); i++) {
for (j = 0; j < lVec.size(); j++) {
calc->haveIntersection(cVec[i], lVec[j], nodeSet);
}
}
//计算两圆之间的交点
for (i = 0; i < cVec.size(); i++) {
for (j = i + 1; j < cVec.size(); j++) {
calc->haveIntersection(cVec[i], cVec[j], nodeSet);
}
}
return nodeSet.size();
}
方法很暴力,就是循环遍历。
困惑
本次项目涉及到浮点数运算的精度问题。由于公式中存在开方以及除法运算,导致最终算出来的点只是近似值。因此我重写了 比较函数 ,EPS最终取的是0.0000001。虽然这个EPS是经过我多番测试选出来的值,但我任然无法保证他的实用性。所以在判断点是否重合的时候,可能会存在误差。
下面是关于精确度问题的相关代码:
#define EPS 0.0000001
int dcmp(double x) {
if (fabs(x) < EPS) return 0;
return x < 0 ? -1 : 1;
}
bool Point::operator < (const Point& p)const {
//return x==p.x?y<p.y:x<p.x;
return dcmp(x - p.x) == 0 ? dcmp(y - p.y) < 0 : dcmp(x - p.x) < 0;
}
BUAA软件工程个人项目的更多相关文章
- BUAA软件工程结对项目作业
BUAA软件工程结对项目 小组成员:16005001,17373192 1.教学班级和项目地址 项目 内容 这个作业属于哪个课程 博客园班级连接 这个作业的要求在哪里 结对项目作业 我在这个课程的目标 ...
- BUAA软件工程个人项目作业
BUAA软件工程个人项目作业 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 学习软件开发的流程 这个作业在哪 ...
- BUAA 软件工程个人作业
BUAA 软件工程 个人项目作业 Author: 17373015 乔玺华 教学班级 :005 项目地址:https://github.com/JordenQiao/SE_Homework_Perso ...
- BUAA 2020 软件工程 个人项目作业
BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...
- 【BUAA软件工程】第一次阅读作业
BUAA软件工程 第一次阅读作业 项目 内容 这个作业属于哪个课程? 北航软工 这个作业的要求在哪里? 第一次个人作业 我在这个课程的目标是? 学习高效严谨的软件工程开发过程,建立团队意识 这个作业在 ...
- BUAA软件工程:软件案例分析
BUAA软件工程:软件案例分析 Author:17373015 乔玺华 项目 内容 这个作业属于哪个课程 2020计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 软件案例分析博客作业 我在这个 ...
- 2021S软件工程——结对项目第一阶段
# 2021S软件工程--结对项目第一阶段 2021春季软件工程(罗杰 任健) 项目地址 1020 1169 --- ## 1 结对感受 总体来说,结对编程与之前的个人编程感觉有很大的不同.有如下几个 ...
- 2021S软件工程——结对项目第三阶段
2021S软件工程--结对项目第三阶段 2021春季软件工程(罗杰 任健) 项目地址 1020 1169 1 实践反思 1.1 问题分析 两人习惯不一致 没有具体制定时间节点 写完代码才开始" ...
- BUAA 2020 软件工程 结对项目作业
Author: 17373051 郭骏 3.28添加:4.计算模块接口的设计与实现过程部分,PairCore实现的细节 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) ...
随机推荐
- java例题_12 奖金问题(暴力破解)
1 /*12 [程序 12 计算奖金] 2 题目:企业发放的奖金根据利润提成. 3 利润I低于或等于 10 万元时,奖金可提 10%: 4 利润高于 10 万元,低于 20 万元时,低于 10 万元的 ...
- 图文详解Java对象内存布局
作为一名Java程序员,我们在日常工作中使用这款面向对象的编程语言时,做的最频繁的操作大概就是去创建一个个的对象了.对象的创建方式虽然有很多,可以通过new.反射.clone.反序列化等不同方式来创建 ...
- 20182217_刘洪宇 后门原理与实践 EXP2
1.后门概念 后门就是不经过正常认证流程而访问系统的通道. 哪里有后门呢? 编译器留后门 操作系统留后门 最常见的当然还是应用程序中留后门 还有就是潜伏于操作系统中或伪装为特定应用的专用后门程序. - ...
- 《环形队列》游戏高《TPS》模式下减少cpu线程切换
序言 什么高TPS?QPS,其实很多人都知道,还有人说大数据,大流量这些关键词夜以继日的出现在我们眼前: 针对高TPS,QPS这些词汇还有一个次可能比较陌生那就是CCU,tps,qps接受满天飞,CC ...
- Java 时间日期系列
Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(1) Calendar Java Calendar,Date,DateFormat ...
- Hadoop完整搭建过程(二):伪分布模式
1 伪分布模式 伪分布模式是运行在单个节点以及多个Java进程上的模式.相比起本地模式,需要进行更多配置文件的设置以及ssh.YARN相关设置. 2 Hadoop配置文件 修改Hadoop安装目录下的 ...
- Magicodes.IE.ASPNETCore之多样化接口使用
1.安装包 Install-Package Magicodes.IE.AspNetCore 2.开始配置 在Startup.cs的Configure()方法中,在UseRouting()中间件之后,注 ...
- C语言-字符串函数的实现(二)之strcpy
C语言中的字符串函数有如下这些 获取字符串长度 strlen 长度不受限制的字符串函数 strcpy strcat strcmp 长度受限制的字符串函数 strncpy strncat strncmp ...
- Mybatis3源码笔记(二)SqlSession
1. 核心层次 2. SqlSession 先从顶层的SqlSession接口开始说起.SqlSession是MyBatis提供的面向用户的API,表示和数据库的会话对象,用于完成对数据库的一系列CR ...
- istio1.2.2 安装及使用示例
前言 本文介绍istio的安装及使用 dashboard,grafana,prometheus,kiali,jaeger的配置示例.演示通过istio的ingressgateway统一访问入口 Ist ...