个人项目作业
个人项目作业
项目 | 内容 |
---|---|
这个作业属于那个课程 | 班级博客 |
这个作业的要求在哪里 | 作业要求 |
我在这个课程的目标是 | 学习软件工程相关知识,锻炼软件开发能力。 |
这个作业在哪个具体方面帮我实现目标 | 完成个人项目,体会单元测试和PSP流程 |
作业正文 | 作业正文 |
1.About(1')
- 教学班级:005
- 项目地址:https://github.com/Pandapan-Buaa/IntersectProject
2.在开始实现程序之前,在下述 PSP 表格记录下你估计将在程序的各个模块的开发上耗费的时间。(0.5' + 0.5')
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
·Estimate | 估计这个任务需要多少时间 | 60(7.2%) | 40(阅读具体要求,完成了博客框架) |
Development | 开发 | ||
·Analysis | 需求分析 (包括学习新技术) | 120(14.5%) | 90(c++复习,相关插件资料阅读) |
·Design Spec | 生成设计文档 | 60(7.2%) | 30 |
·Design Review | 设计复审 (和同事审核设计文档) | 10(1.2%) | 10 |
·Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10(1.2%) | 10 |
·Design | 具体设计 | 60(7.2%) | 30 |
·Coding | 具体编码 | 180(21.6%) | 90 |
·Code Review | 代码复审 | 60(7.2%) | 60 |
·Test | 测试(自我测试,修改代码,提交修改) | 120(14.5%) | 90 |
Reporting | 报告 | ||
·Test Report | 测试报告 | 60(7.2%) | 30 |
·Size Measurement | 计算工作量 | 30(3.6%) | 20 |
·Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60(7.2%) | 30 |
合计 | 830 | 530 |
由于对C++的诸多特性没有很好的掌握,预估时对每个部分的时间估计都过于宽松。实际完成时间大致会比预估少1/3-1/2。
3.解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。(3')
刚拿到题目时,考虑如何计算两条直线的交点。模拟解方程的过程过于复杂,且不够简便,于是考虑其他方法,搜索资料后发现可以采用计算几何的方法,利用向量求解交点。
4.设计实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?单元测试是怎么设计的?(4')
整体结构如上,开始设计时基本决定分两类,Point(点类,包含点的减法,叉乘与点乘方法)/Line(线类,包含求该对象与另一线对象交点的方法),并决定采取map/queue分别存放交点与已读入的直线。
完成第一版后,为了改进性能对原始设计进行了一些修改,最终的类结构如下所示
class Point
{
public:
double x;
double y;
Point();
Point(double _x, double _y);
Point operator -(const Point& b)const;
double operator *(const Point& b)const;
double operator ^(const Point& b)const;
bool operator <(const Point& b)const;
bool operator ==(const Point& b)const;
};
#pragma once
#include "Point.h"
#include <vector>
#include <set>
#include<iostream>
using namespace std;
class Line
{
public:
Point s;
Point e;
Line();
Line(Point _s, Point _e);
void intersect(set<Point>* pointset, const Line& b);
};
由于整体逻辑比较简单,并未对关键函数绘制流程图。
单元测试方面,则是对点类与线类的每个方法分别进行测试,确保在给定数据范围内的正确性。着重测试了求交点的intersect方法,利用随机数生成数据,并利用Geogebra画图求得交点的数值解,进而保证了intersect方法的正确性。
5.记录在改进程序性能上所花费的时间,描述你改进的思路,并展示一张性能分析图(由 VS 2019 的性能分析工具自动生成),并展示你程序中消耗最大的函数。(3')
性能改进与单元测试编写共150分钟,
通过性能分析工具,对原始代码进行分析,发现原本使用的交点map插入前需要调用find方法判断是否已存在该交点。因此放弃map转而使用set+trycatch块,将消耗时间大量减少。
最终的性能分析图如图所示,其中Intersect方法占用时间最多(90.45%)
6.代码说明。展示出项目关键代码,并解释思路与注释说明。(3')
void Line::intersect(set<Point>* pointset, const Line& b)
{
Point res = s;
if (sgn((s - e) ^ (b.s - b.e)) == 0)
{
return;
}
//判断平行(本应判断是否重合,由于本题不会出现重合情况,故舍去部分代码)
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
//计算几何求交点过程
try {
pointset->insert(res);
}catch (exception e){}
//利用set的不重复特性,添加交点结果至set中
}
关键代码为Line的intersect方法,说明在注释中。
for (int i = 0; i < n; i++) {
if (cmdin) in >> sub >> x1 >> y1 >> x2 >> y2;
else cin >> sub >> x1 >> y1 >> x2 >> y2;
Line tempLine = Line(Point(x1, y1), Point(x2, y2));
if (i != 0) {
for (Line b : lineVector) {
tempLine.intersect(&points,b);
}
}
lineVector.push_back(tempLine);
}
if (cmdout) out << points.size() << endl;
else cout << points.size() << endl;
外部调用则集成在IntersectLine函数中,如上所示,其主要部分是一个二重循环,对每一个读入的Line,与之前读入并存在lineVector中的Line依次求交点。
7.程序评分规则要求截图
消除 Code Quality Analysis 中的所有警告
单元测试数目:
覆盖率:
查看后添加了一部分单元测试,但没有增长,由于覆盖率与代码正确性无必然关系,因此没有再添加单元测试内容