您的位置:首页 > 编程语言 > Go语言

Algorithm: 如何判断一个点是否在一个三角形内

2017-03-17 08:07 309 查看
昨日因为机缘巧合,做了一道阿里的实习生编程题。题目很有趣,其中涉及到了如何判断一个点是否在一个三角形内。

其中,判断这个问题最简单的方法是面积法。(图片来源: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):


所以,当它是平行四边形的两边的时候,它的模就是平行四边形的面积。

接下来看向量的点乘,就是求一个向量在另一个向量上的投影:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: