個人項目作業
項目 | 内容 |
---|---|
這個作業屬于那個課程 | 班級部落格 |
這個作業的要求在哪裡 | 作業要求 |
我在這個課程的目标是 | 學習軟體工程相關知識,鍛煉軟體開發能力。 |
這個作業在哪個具體方面幫我實作目标 | 完成個人項目,體會單元測試和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 | 生成設計文檔 | 30 | |
·Design Review | 設計複審 (和同僚稽核設計文檔) | 10(1.2%) | 10 |
·Coding Standard | 代碼規範 (為目前的開發制定合适的規範) | ||
·Design | 具體設計 | ||
·Coding | 具體編碼 | 180(21.6%) | 90 |
·Code Review | 代碼複審 | 60 | |
·Test | 測試(自我測試,修改代碼,送出修改) | ||
Reporting | 報告 | ||
·Test Report | 測試報告 | ||
·Size Measurement | 計算工作量 | 30(3.6%) | 20 |
·Postmortem & Process Improvement Plan | 事後總結, 并提出過程改進計劃 | ||
合計 | 830 | 530 |
由于對C++的諸多特性沒有很好的掌握,預估時對每個部分的時間估計都過于寬松。實際完成時間大緻會比預估少1/3-1/2。
3.解題思路描述。即剛開始拿到題目後,如何思考,如何找資料的過程。(3')
剛拿到題目時,考慮如何計算兩條直線的交點。模拟解方程的過程過于複雜,且不夠簡便,于是考慮其他方法,搜尋資料後發現可以采用計算幾何的方法,利用向量求解交點。
參考1:直線交點
參考2:圓交點
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 中的所有警告
單元測試數目:
覆寫率:
檢視後添加了一部分單元測試,但沒有增長,由于覆寫率與代碼正确性無必然關系,是以沒有再添加單元測試内容