天天看點

個人項目作業

個人項目作業

項目 内容
作業所屬課程 2020春季計算機學院軟體工程(羅傑,任健)
作業要求
教學班級 005
項目位址 個人項目位址

PSP表格

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃
· Estimate · 估計這個任務需要多少時間 15 10
Development 開發
· Analysis · 需求分析 (包括學習新技術) 60 120
· Design Spec · 生成設計文檔 20
· Design Review · 設計複審 (和同僚稽核設計文檔)
· Coding Standard · 代碼規範 (為目前的開發制定合适的規範)
· Design · 具體設計
· Coding · 具體編碼 90 100
· Code Review · 代碼複審 30
· Test · 測試(自我測試,修改代碼,送出修改)
Reporting 報告
· Test Report · 測試報告
· Size Measurement · 計算工作量
· Postmortem & Process Improvement Plan · 事後總結, 并提出過程改進計劃
合計 310 475

解題思路

對于給定的N條直線,詢問平面中有多少點在至少2條給定的直線上,即求出N條直線有多少不重複的交點。

首先我分析到輸入部分,每條直線對應線上不同的兩點,我首先根據這兩點計算得到直線的标準方程式,記得到三個重要參數:a, b, c:

$$

ax + by + c = 0, a = y2 - y1, b = x1 - x2, c = y1x2 - x1y2;

同時我們保證a始終大于0。

得到每個直線的标準方程式後,我們就可以進行兩兩比較得到交點數了,若兩條直線的斜率不等,則說明兩條直線有交點,同時記錄交點的坐标資訊:

x = (b1c2 - c1b2)/(a1b2 - a2b1), y = (a2c1 - a1c2)/(a1b2 - a2b1);

在比對所有直線的相交情況後,我們就可以去掉計數了重複的點了,最後得到就是所有直線不重複的交點,即平面中至少在2條給點直線上的點數。

設計實作

程式中有四個函數,設計了兩個結構體:

直線标準式資訊(LINE):

記錄了每條直線的a, b, c相應的值,采用double資料類型。

交點坐标資訊(Point2d):

記錄每個交點的坐标軸資訊,包括x, y,采用double資料類型。

主函數(main):

主要用于指令行的輸入輸出,首先對指令行進行處理得到所要的資料,将每個直線的兩點坐标資訊讀取傳遞給調用函數,傳回得到直線标準方程式資訊,然後調用計算交點數函數得到無重複的交點個數,傳回到輸出檔案中。

直線标準方程式函數(makeline):

根據所給的直線兩點坐标,計算得到直線标準式a, b, c值,其中保證a值大于0,,傳回一個LINE資料結構體。

計算交點函數(calculateCrossPointsNum):

周遊每條直線,檢視兩兩直線是否相交,統計并記錄交點坐标資訊,然後周遊交點資訊,取出重複的交點。

判斷直線是否相交函數(lineintersect):

通過比較所給兩條直線的斜率,分析兩條直線是否平行,若直線相交計算并記錄交點的坐标資訊。

函數之間的關系:

主函數main通過調用makeline來根據點的坐标資訊得到直線的标準式資訊,然後通過calculateCrossPointsNum計算得到交點個數,calculateCrossPointsNum函數調用lineintersect來判斷兩兩直線是否相交:

個人項目作業

單元測試主要根據樣例分析多種不同情況,考慮一條直線,多條直線相交一點,多條平行線等問題,均可實作。

個人項目作業

性能分析表

性能分析圖(由 VS 2019 的性能分析工具自動生成) :

個人項目作業
個人項目作業

程式中消耗最大的是比較斜率過程。

代碼說明

通過指令行輸入直線資料:

int main(int argc, char* argv[])
{
	ifstream in;
	ofstream out;
	for (int i = 0; i < argc; i++) {
		if ((string)argv[i] == "-i") {
			in.open(argv[i + 1]);
		}
		else if ((string)argv[i] == "-o") {
			out.open(argv[i + 1]);
		}
	}

    int N; // 直線個數
	in >> N;
           

根據已知兩點坐标,求過這兩點的直線解析方程:a*x + b * y + c = 0:

LINE makeline(double x1,double y1,double x2,double y2)
{
    LINE tl;
    int sign = 1;
    tl.a = y2 - y1;
    if (tl.a < 0) {
        sign = -1;
        tl.a = sign * tl.a;
    }
    tl.b = sign * (x1 - x2);
    tl.c = sign * (y1 * x2 - x1 * y2);
    return tl;
}
           

如果兩條直線 l1(a1x+b1y+c1 = 0), l2(a2x+b2y+c2 = 0)相交,傳回true,且傳回交點p:

bool lineintersect(LINE l1, LINE l2, Point2d &p)
{
    double d = l1.a * l2.b - l2.a * l1.b;
    if (abs(d) < EP)
    {
        return false;
    }
    p.x = (l2.c * l1.b - l1.c * l2.b) / d;
    p.y = (l2.a * l1.c - l1.a * l2.c) / d;
    return true;
}

           

去掉重複點:

for (int i = 0; i < pnts.size() - 1; i++)
    {
        for (int j = i + 1; j < pnts.size(); j++)
        {
            if (pnts[i].x == pnts[j].x && pnts[i].y == pnts[j].y)
            {
                pnts.erase(pnts.begin() + j);
                j--;
            }
        }
    }
           

Code Quality Analysis分析

個人項目作業