天天看點

個人項目作業

個人項目作業

寫在前面:

項目 内容
這個作業屬于哪個課程 2020年春季計算機學院軟體工程(羅傑 任建)
這個作業的要求在哪裡
教學班級 005
項目Github連結 https://github.com/ame-lm/SEC_HW_IndividualProject

項目PSP表格:

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

解題思路

按照直線和直線, 直線和圓, 圓和圓在平面上的關系分為下面三種情況考慮:

直線和直線:

  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;
}