个人项目作业

个人项目作业

写在前面:

项目 内容
这个作业属于哪个课程 2020年春季计算机学院软件工程(罗杰 任建)
这个作业的要求在哪里 个人项目作业
教学班级 005
项目Github链接 https://github.com/ame-lm/SEC_HW_IndividualProject

项目PSP表格:

PSP2.1 预估耗时(分钟) 实际耗时(分钟)
Planning 60 60
· Estimate 30 30
Development 420 600
· Analysis 20 20
· Design Spec 20 20
· Design Review 20 20
· Coding Standard 20 20
· Design 40 100
· Coding 240 300
· Code Review 30 60
· Test 60 120
Reporting 40 40
· Test Report 20 20
· Size Measurement 10 10
· Postmortem & Process Improvement Plan 10 10

解题思路

按照直线和直线, 直线和圆, 圆和圆在平面上的关系分为下面三种情况考虑:

直线和直线:

  1. 判断直线是否相交: \(A_1*B_2-A_2*B_1!=0\)则相交.
  2. 若相交则求交点: \((\frac{B_1*C_2-B_2*C_1}{A_1*B_2-A_2*B_1},\frac{A_2*C_1-A_1*C_2}{A_1*B_2-A_2*B_1})\)

直线和圆:

  1. 联立直线和圆方程(为了起见简便, 若\(B!=0\), 化为斜截式再联立), 求得系数\(tA\), \(tB\), \(tC\).
  2. 根据\(Delta=tB^2-4*tA*tC\)判断交点个数
  3. \(Delta\ge0\) , 根据求根公式求得交点横坐标, 进而求出交点.

圆和圆:

  1. 计算圆心距\(dis=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\).
  2. 比较圆心距\(dis\) 和半径和\(r_1+r_2\), 半径差\(|r_1-r_2|\) .
  3. 若有交点则两圆相减求出相交弦方程, 进而转化为直线和圆得交点.

程序设计

对象建模:

平面: Class PlaneContainer

几何图形: Class Figure

交点: Class Point

直线: Class Line: Figure

圆: Class Circle: Figure

交互逻辑:

Class Point重载<, ==以适应set模板.

Class Figure子类均需实现set<Point> ClassName::intersect(Figure* figure)方法用于计算交点.

Class PlaneContainer实现void PlaneContainer::insert(Figure* figure)方法用于添加Figure, 每次添加均需和平面内已有图形求交点.

Class PlaneContainer每次添加Figure得到的点放入set<Point> intersectionPoints中, 借助set类型过滤相同点.

单元测试

分成两类测试:

测试简单几何对象:

TEST_METHOD(Test1) {//for Circle.cpp, Line.cpp, Figure.cpp, Point.cpp
		Point* p1 = new Point(1, 0);
		Point* p2 = new Point(100000, 0);
		Point* p3 = new Point(1, -100000);
		Point* p4 = new Point(-100000, 100000);
		Assert::AreNotEqual((int)p1, NULL);
		Assert::AreNotEqual((int)p2, NULL);
		Assert::AreNotEqual((int)p3, NULL);
		Assert::AreNotEqual((int)p4, NULL);

		Circle* c1 = new Circle(0, 0, 1);
		Circle* c2 = new Circle(-100000, 100000, 100000);
		Assert::AreNotEqual((int)c1, NULL);
		Assert::AreNotEqual((int)c2, NULL);

		Line* l1 = new Line(0, 0, 1, 100000);
		Line* l2 = new Line(100000, 0, 1, 100000);
		Line* l3 = new Line(0, 0, -100000, 100000);
		Line* l4 = new Line(0, -334, 1, 100000);
		Assert::AreNotEqual((int)l1, NULL);
		Assert::AreNotEqual((int)l2, NULL);
		Assert::AreNotEqual((int)l3, NULL);
		Assert::AreNotEqual((int)l4, NULL);
	}

测试几何对象在平面上相交情况:

包括直线与圆相离, 相交, 相切等测试.

TEST_METHOD(Test2) {//for PlaneContainer.cpp
		//test for condition1: all objs are lines
		PlaneContainer* pc1 = new PlaneContainer();
		Assert::AreEqual(pc1->countIntersectionPoints(), 0);
		Line* l1 = new Line(0, 1, 0);
		pc1->insert(l1);
		Assert::AreEqual(pc1->countIntersectionPoints(), 0);
		Line* l2 = new Line(1, 0, 0);
		pc1->insert(l2);
		Assert::AreEqual(pc1->countIntersectionPoints(), 1);
		Line* l3 = new Line(1, 1, 1);
		pc1->insert(l3);
		Assert::AreEqual(pc1->countIntersectionPoints(), 3);
		Line* l4 = new Line(1, 1, -1);
		pc1->insert(l4);
		Assert::AreEqual(pc1->countIntersectionPoints(), 5);
		Line* l5 = new Line(1, -1, 1);
		pc1->insert(l5);
		Assert::AreEqual(pc1->countIntersectionPoints(), 5);
		Line* l6 = new Line(1, -1, -1);
		pc1->insert(l6);
		Assert::AreEqual(pc1->countIntersectionPoints(), 5);

		//test for condition2: all objs are circles
		PlaneContainer* pc2 = new PlaneContainer();
		Assert::AreEqual(pc2->countIntersectionPoints(), 0);
		Circle* c1 = new Circle(0, 0, 1);
		pc2->insert(c1);
		Assert::AreEqual(pc2->countIntersectionPoints(), 0);
		Circle* c2 = new Circle(1, 0, 1);
		pc2->insert(c2);
		Assert::AreEqual(pc2->countIntersectionPoints(), 2);
		Circle* c3 = new Circle(0, 1, 1);
		pc2->insert(c3);
		Assert::AreEqual(pc2->countIntersectionPoints(), 6);
		Circle* c4 = new Circle(-1, 0, 1);
		pc2->insert(c4);
		Assert::AreEqual(pc2->countIntersectionPoints(), 9);
		Circle* c5 = new Circle(0, -1, 1);
		pc2->insert(c5);
		Assert::AreEqual(pc2->countIntersectionPoints(), 13);
		Circle* c6 = new Circle(0, 0, 2);
		pc2->insert(c6);
		Assert::AreEqual(pc2->countIntersectionPoints(), 17);

		//test for condition3: objs contains lines and circles
		PlaneContainer* pc3 = new PlaneContainer();
		pc3->insert(l1);
		pc3->insert(l2);
		pc3->insert(l3);
		pc3->insert(l4);
		pc3->insert(l5);
		pc3->insert(l6);
		Assert::AreEqual(pc3->countIntersectionPoints(), 5);

		pc3->insert(c1);
		Assert::AreEqual(pc3->countIntersectionPoints(), 5 + 0);

		pc3->insert(c2);
		Assert::AreEqual(pc3->countIntersectionPoints(), 5 + 2 + 5);
	}

关键代码

Class Line求解相交:

set<Point> Line::intersect(Figure* figure) {
	double x, y;
	set<Point> points;
	if (typeid(*figure) == typeid(Line)) {//line-line condition 
		Line* line = (Line*)figure;
		double A1, B1, C1, A2, B2, C2;
        //line1 cofficient 
		A1 = this->A; B1 = this->B; C1 = this->C;
        //line2 cofficient 
		A2 = line->getA(); B2 = line->getB(); C2 = line->getC();
		//cordinate formula:((B1*C2-B2*C1)/(A1*B2-A2*B1),(A2*C1-A1*C2)/(A1*B2-A2*B1))
		if (A1 * B2 != A2 * B1) {//not paralell
			x = (B1 * C2 - B2 * C1) / (A1 * B2 - A2 * B1);
			y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
			points.insert(Point(x, y));
		}
	} else if (typeid(*figure) == typeid(Circle)) {//line-circle condition 
		Circle* circle = (Circle*)figure;
		double tA, tB, tC, a, b, r, k, m, Delta;
        //circle cofficient
		a = circle->getX();
		b = circle->getY();
		r = circle->getR();
		if (B != 0) {//if line slope exists
             //line slope and intercept
			k = -A / B;
			m = -C / B;
			//body equation cofficients 
			//tA=1+k^2
			tA = 1 + k * k;
			//tB=2(km-bk-a)
			tB = 2 * (k * m - b * k - a);
			//tC=a^2+(b-m)^2-r^2
			tC = a * a + (b - m) * (b - m) - r * r;
            
			Delta = tB * tB - 4 * tA * tC;
			if (Delta > 0) {//intersection
				x = (-tB + sqrt(Delta)) / (2 * tA);
				y = k * x + m;
				points.insert(Point(x, y));

				x = (-tB - sqrt(Delta)) / (2 * tA);
				y = k * x + m;
				points.insert(Point(x, y));
			} else if (Delta == 0) {//tangent
				x = -tB / (2 * tA);
				y = k * x + m;
				points.insert(Point(x, y));
			}
		} else {//line slope not exists
			x = m = -C / A;
			y = b + sqrt(r * r - (m - a) * (m - a));
			points.insert(Point(x, y));

			y = b - sqrt(r * r - (m - a) * (m - a));
			points.insert(Point(x, y));
		}
	}
	return points;
}

Class Circle求解相交:

set<Point> Circle::intersect(Figure* figure) {
	double x, y;
	set<Point> points;
	if (typeid(*figure) == typeid(Line)) {
         //transform circle-line condition into line-circle conditon
		Line* line = (Line*)figure;
		points = line->intersect(this);
	} else if (typeid(*figure) == typeid(Circle)) {
		Circle* circle = (Circle*)figure;
		double x1, x2, y1, y2, r1, r2;
		double D1, D2, E1, E2, F1, F2, dis;
         //circle1 cofficient
		x1 = this->x;
		y1 = this->y;
		r1 = this->r;
         //circle2 cofficient
		x2 = circle->getX();
		y2 = circle->getY();
		r2 = circle->getR();
         //center distance
		dis = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
		dis = sqrt(dis);
         //normal formula of circle
		D1 = -2 * x1;
		E1 = -2 * y1;
		F1 = x1 * x1 + y1 * y1 - r1 * r1;
		D2 = -2 * x2;
		E2 = -2 * y2;
		F2 = x2 * x2 + y2 * y2 - r2 * r2;
		if (dis <= r1 + r2 && dis >= abs(r1 - r2)) {
             //quation about the intersection string and then transformed into line-circle condition
			points = Line(D1 - D2, E1 - E2, F1 - F2).intersect(this);
		}
	}
	return points;
}
posted @ 2020-03-10 17:05  燈心  阅读(231)  评论(1编辑  收藏  举报