华为oj 之 判断点是否在三角形内
/*
* 任意顶点为A、B、C的三角形,如果点P在三角形内,那么
* 1)点P和点C在AB边的同一侧 2)点P和点A在BC边的同一侧 3)点P和点B在AC边的同一侧
* 反之亦然(充要条件)
*
* 关键:如何判断某两个点在某条直线的同一侧
* 参考图示发现:
* 对于点P: AB*BC的方向 和 AB*BP的方向相同
* 对于点P1: AB*BC的方向 和 AB*BP1的方向不同
* 故:对于边AB,以及点C、P,如果AB*BC的方向 和 AB*BP的方向相同,
* 那么点P和C在边AB的同一侧。
*/
1 public class POINT { 2 int x; 3 int y; 4 public POINT(int x,int y) 5 { 6 this.x=x; 7 this.y=y; 8 } 9 }
1 public class Main { 2 3 /* 4 * 求叉积 正:Z轴正向 ;负:Z轴负向;绝对值:叉积的模(以两个向量为边的平行四边形的面积) 5 * eg : 求a*b 向量a = (x1, y1, z1) 向量b = (x2, y2, z2) 6 * 因为a和b在三角形中,所以z1 = 0、z2 = 0, 7 * 所以 |a*b| = |x1·y2 - x2·y1| 8 * 详见:https://zh.wikipedia.org/zh/%E5%90%91%E9%87%8F%E7%A7%AF 9 */ 10 private static int crossProduct(POINT A, POINT B, POINT C, POINT D) { 11 int x1 = B.x - A.x; 12 int y1 = B.y - A.y; 13 14 int x2 = D.x - C.x; 15 int y2 = D.y - C.y; 16 17 return (x1*y2 - x2*y1); 18 } 19 20 // 叉积得到的方向是否相同 true:方向相同;false:方向不同 21 private static boolean isSameDirection(POINT A, POINT B, POINT C, POINT P) { 22 int Direction1 = crossProduct(A, B, B, C); 23 int Direction2 = crossProduct(A, B, B, P); 24 if (Direction1*Direction2 >= 0) { // 等于0:两个向量平行 (说明P点在三角形的AB边上) 25 return true; 26 } 27 return false; 28 } 29 30 // 判断P点是否在顶点为A、B、C的三角形内(在三角形的边上,也视作在三角形中) 31 public static boolean isInTriangle(POINT A, POINT B, POINT C, POINT P) 32 { 33 if (isSameDirection(A, B, C, P) && isSameDirection(B, C, A, P) && isSameDirection(C, A, B, P)) { 34 return true; 35 } 36 return false; 37 } 38 39 public static void main(String[] args) { 40 41 POINT A=new POINT(0,0); 42 POINT B=new POINT(0,80); 43 POINT C=new POINT(80,0); 44 POINT P=new POINT(20,60); 45 boolean b1 = isInTriangle(A, B, C, P); // true 46 47 POINT A2=new POINT(0,0); 48 POINT B2=new POINT(0,80); 49 POINT C2=new POINT(80,0); 50 POINT P2=new POINT(21,60); 51 boolean b2 = isInTriangle(A2, B2, C2, P2); // false 52 53 54 String result = null; 55 System.out.println(result); 56 } 57 }