软工个人项目作业

项目 内容
北航2020软工 班级博客
作业要求 个人项目作业
项目GitHub地址 个人项目
教学班级 006

PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 10
· Estimate · 估计这个任务需要多少时间 10 10
Development 开发 270 280
· Analysis · 需求分析 (包括学习新技术) 20 30
· Design Spec · 生成设计文档 10 20
· Design Review · 设计复审 (和同事审核设计文档) 20 30
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 20
· Design · 具体设计 30 30
· Coding · 具体编码 100 80
· Code Review · 代码复审 20 20
· Test · 测试(自我测试,修改代码,提交修改) 50 50
Reporting 报告 80 90
· Test Report · 测试报告 20 20
· Size Measurement · 计算工作量 30 40
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 30
合计 360 380

解题思路

拿到题目后,首先想到的是两两直线组合,因为答案是有限个,只有相交和平行两种情况。

参考https://blog.csdn.net/u010177286/article/details/46226183

每条直线表示为一般式方程\(Ax+By+C=0\)

那么两条直线\(a_0x+b_0y+c_0=0\)\(a_1x+b_1y+c_1=0\)

的交点为

\(x=(b_0*c_1-b_1*c_0)/D\)

\(y=(a_1*c_0-a_0*c_1)/D\)

\(D=a_0*b_1-a_1*b_0\)

当D=0时两直线平行

估计复杂度为O(n^2)

:由于坐标范围为\((-10^5,10^5)\),相乘后可能溢出,因此使用long long。

设计实现

1.class dot:点类

bool dot::operator <(const  dot& d)const

重写比较方法

根据坐标判断两点是否重合

2.class line:直线类

dot* line::cross(line l)

求两直线交点,若平行则返回nullpointer

3.class Cross:相交类

long long Cross::getDifCrossDotsNum(vector lines)

计算非重合交点个数

4.单元测试

采用Assert测试了上述三个函数
软工个人项目作业_第1张图片

性能分析

思考了很多想法,都是复杂度为O(n^2),因此没有做过多优化。

性能分析图:
软工个人项目作业_第2张图片

消耗最大的函数为

Cross::getDifCrossDotsNum()

软工个人项目作业_第3张图片

代码说明

bool dot::operator<(const  dot& d)const
{
	if (x_top * d.x_bottom != x_bottom * d.x_top) {
		return x_top * d.x_bottom < x_bottom * d.x_top;
	}
	else {
		return y_top * d.y_bottom < y_bottom * d.y_top;
	}
}

因为交点可能是非整数点,因此利用分子分母交叉相乘的方法来判断两点是否重合。

dot* line::cross(line l) {
	long long D = A * l.B - B * l.A;
	long long x_top = B * l.C - C * l.B;
	long long y_top = l.A * C - A * l.C;
	dot* cross_dot = NULL;
	if (D != 0)cross_dot = new dot(x_top, D, y_top, D);
	return cross_dot;
}

根据前面的解题思路,若D==0则平行,返回NULL

否则返回交点的坐标

long long Cross::getDifCrossDotsNum(vector lines)
{
	
	
	for (unsigned int i = 0; i < lines.size() - 1; i++) {
		for (unsigned int  j = i + 1; j < lines.size(); j++) {
			dot* d = lines[i].cross(lines[j]);
			if (d != NULL) {
				dots.insert(*d);
				delete d;
			}
		}
	}
	
	return dots.size();
}

两两计算交点并存入dots;

		TEST_METHOD(TestMethod1)
		{
			dot* d1 = new dot(1, 2, 1, 2);
			dot* d2 = new dot(2, 4, 2, 4);
			Assert::IsFalse(d1->operator <(*d2));
		}
		TEST_METHOD(TestMethod2)
		{
			line* l1 = new line(100000, 0, 0, 100000);
			line* l2 = new line(-100000, 0, 0, -100000);
			Assert::IsNull(l1->cross(*l2));
		}
		TEST_METHOD(TestMethod3)
		{
			line l1(1, 1, 2, 3);
			line l2(2, 3, 4, 5);
			line l3(7, 4, 3, 1);
			vector lines;
			lines.push_back(l1);
			lines.push_back(l2);
			lines.push_back(l3);
			Cross* cross = new Cross();
			Assert::AreEqual(cross->getDifCrossDotsNum(lines),long long(3));
			
		}
                
                TEST_METHOD(TestMethod4)
		{
			line l1(1, 1, 2, 3);
			vector lines;
			lines.push_back(l1);			
			Cross* cross = new Cross();
			Assert::AreEqual(cross->getDifCrossDotsNum(lines), long long(0));

		}

			TEST_METHOD(TestMethod5)
		{
			line l1(1, 0, 1, 3);
			line l2(2, 0, 2, 3);
			vector lines;
			lines.push_back(l1);
			lines.push_back(l2);
			Cross* cross = new Cross();
			Assert::AreEqual(cross->getDifCrossDotsNum(lines), long long(0));

		}

		TEST_METHOD(TestMethod6)
		{
			line l1(100000, 0, 0, 100000);
			line l2(-100000, 0, 0, 100000);
			line l3(-100000, 0, 0, -100000);
			line l4(100000, 0, 0, -100000);
			vector lines; 
			lines.push_back(l1);
			lines.push_back(l2);
			lines.push_back(l3);
			lines.push_back(l4);
			Cross* cross = new Cross();
			Assert::AreEqual(cross->getDifCrossDotsNum(lines), long long(4));

		}

		}

一部分单元测试代码,测试了三个函数

Code Quality Analysis

软工个人项目作业_第4张图片

你可能感兴趣的:(软工个人项目作业)