1. 程式人生 > >Algorithm: 如何判斷一個點是否在一個三角形內

Algorithm: 如何判斷一個點是否在一個三角形內

昨日因為機緣巧合,做了一道阿里的實習生程式設計題。題目很有趣,其中涉及到了如何判斷一個點是否在一個三角形內。

其中,判斷這個問題最簡單的方法是面積法。(圖片來源:http://www.cnblogs.com/TenosDoIt/p/4024413.html)


如果一個點在三角形內,其與三角形的三個點構成的三個子三角形的面積等於大三角形的面積。否則,大於大三角形的面積。

所以,這個問題就轉化成如何在知道三角形的三個點的情況下,求這個三角形的面積的問題了。

這個問題,比較好理解的方法是使用向量法:先求出這個三角形的對應的平行四邊形的面積。然後這個面積的1/2就是三角形的面積了。

先隨意選擇兩個點,如B、C通過其座標相減得向量(B,C)。記得誰減另一個就是指向誰。然後求出其中一個點和剩下一個點的向量。這兩個向量的叉乘的便是平行四邊形的面積。除以2就是三角形的面積。(注意這裡是叉乘 (cross product),而非內積(dot product))

程式碼如下:

private static final double ABS_DOUBLE_0 = 0.0001;
	
private static double getTriangleArea(Point p0, Point p1, Point p2) {
	Point ab, bc;
	ab = new Point(p1.x - p0.x, p1.y - p0.y);
	bc = new Point(p2.x - p1.x, p2.y - p1.y);
	return Math.abs((ab.x * bc.y - ab.y * bc.x) / 2.0);
}
	
private static boolean isInTriangle(Point a, Point b, Point c, Point d) {
	double sabc, sadb, sbdc, sadc;
	sabc = getTriangleArea(a, b, c);
	sadb = getTriangleArea(a, d, b);
	sbdc = getTriangleArea(b, d, c);
	sadc = getTriangleArea(a, d, c);
		
	double sumSuqar = sadb + sbdc + sadc;
		
	if (-ABS_DOUBLE_0 < (sabc - sumSuqar) && (sabc - sumSuqar) < ABS_DOUBLE_0) {
		return true;
	} else {
		return false;
	}
}

向量之間的積分為兩種:叉乘和點乘。叉乘求面積,點乘求投影。這是兩者的意義。而且,叉乘理論得到的是一個向量,而點乘得到的是一個標量。

公式如下(參考連結:https://zh.wikipedia.org/wiki/%E5%90%91%E9%87%8F%E7%A7%AF; https://zh.wikipedia.org/wiki/%E6%95%B0%E9%87%8F%E7%A7%AF):


所以,當它是平行四邊形的兩邊的時候,它的模就是平行四邊形的面積。

接下來看向量的點乘,就是求一個向量在另一個向量上的投影: