天天看點

個人項目作業

個人項目作業

項目 内容
這個作業屬于那個課程 班級部落格
這個作業的要求在哪裡 作業要求
我在這個課程的目标是 學習軟體工程相關知識,鍛煉軟體開發能力。
這個作業在哪個具體方面幫我實作目标 完成個人項目,體會單元測試和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 中的所有警告

個人項目作業

單元測試數目:

個人項目作業

覆寫率:

檢視後添加了一部分單元測試,但沒有增長,由于覆寫率與代碼正确性無必然關系,是以沒有再添加單元測試内容

個人項目作業