1 /** 2 给出线段AB以及线段CD,只要判断A、B两点在直线CD的两端,并且C、D两点在直线AB的两端即可。 3 用叉乘进行判断。 4 5 问题描述 6 下面给出的是一个判断线段相交的次数 7 8 输入: 9 n:线段的个数 10 seg.begin.x,seg.begin.y,seg.end.x,seg.end.y:分别表示线段p1p2的点坐标 11 12 输出: 13 n个线段中两两相交的次数 14 15 样例输入 16 2 17 1 0 0 0 18 0 1 0 0 19 样例输出: 20 1 21 */ 22 23 #include<cstdio> 24 using namespace std; 25 26 struct point 27 { 28 double x, y; 29 }; 30 31 struct segment 32 { 33 point begin, end; 34 }; 35 36 double min(double x, double y) 37 { 38 return (x < y) ? x : y; 39 } 40 41 double max(double x, double y) 42 { 43 return (x > y) ? x : y; 44 } 45 46 //判断pk是否在线段<pi, pj>上 47 bool onsegment(point pi, point pj, point pk) 48 { 49 if(min(pi.x, pj.x) <= pk.x && pk.x <= max(pi.x, pj.x)) 50 { 51 if(min(pi.y, pj.y) <= pk.y && pk.y <= max(pi.y, pj.y)) 52 { 53 return true; 54 } 55 } 56 return false; 57 } 58 59 //计算向量<pk, pi>与向量<pj, pi>的叉乘 60 double direction(point pi, point pj, point pk) 61 { 62 return (pi.x - pk.x) * (pi.y - pk.y) - (pi.x - pj.x) * (pi.y - pk.y); 63 } 64 65 //判断p1p2以及p3p4是否相交 66 bool judge(point p1, point p2, point p3, point p4) 67 { 68 double d1 = direction(p3, p4, p1); 69 double d2 = direction(p3, p4, p2); 70 double d3 = direction(p1, p2, p3); 71 double d4 = direction(p1, p2, p4); 72 73 if((d1 * d2 < 0) && (d3 * d4 < 0))//如果p1、p2在线段p3p4的两侧并且p3、p4在线段p1p2的两侧 74 return true; 75 76 77 if((d1 == 0) && onsegment(p3, p4, p1))//p1在线段p3p4上 78 return true; 79 if((d2 == 0) && onsegment(p3, p4, p2))//p2在线段p3p4上 80 return true; 81 if((d3 == 0) && onsegment(p1, p2, p3))//p3在线段p1p2上 82 return true; 83 if((d4 == 0) && onsegment(p1, p2, p4))//p4在线段p1p2上 84 return true; 85 86 return false; 87 } 88 89 //求直线p1p2与直线p3p4之间的交点,纯粹性的数学公式求解了 90 point getIntersection(point p1, point p2, point p3, point p4) 91 { 92 /*根据两点式化为标准式,进而求线性方程组*/ 93 point crossPoint; 94 double tempLeft,tempRight; 95 //求x坐标 96 tempLeft = (p4.x - p3.x) * (p1.y - p2.y) - (p2.x - p1.x) * (p3.y - p4.y); 97 tempRight = (p1.y - p3.y) * (p2.x - p1.x) * (p4.x - p3.x) + p3.x * (p4.y - p3.y) * (p2.x - p1.x) - p1.x * (p2.y - p1.y) * (p4.x - p3.x); 98 crossPoint.x =tempRight / tempLeft ; 99 100 //求y坐标 101 tempLeft = (p1.x - p2.x) * (p4.y - p3.y) - (p2.y - p1.y) * (p3.x - p4.x); 102 tempRight = p2.y * (p1.x - p2.x) * (p4.y - p3.y) + (p4.x- p2.x) * (p4.y - p3.y) * (p1.y - p2.y) - p4.y * (p3.x - p4.x) * (p2.y - p1.y); 103 crossPoint.y = tempRight / tempLeft ; 104 105 return crossPoint; 106 } 107 108 int main() 109 { 110 int n; 111 segment seg[2];//两个线段 112 point intersection; 113 114 scanf_s("%d", &n); 115 while(n --)//测试次数 116 { 117 for(int i = 1 ; i <= 2 ; i ++) 118 { 119 scanf_s("%lf%lf%lf%lf", &seg[i].begin.x, &seg[i].begin.y, &seg[i].end.x, &seg[i].end.y); 120 } 121 122 if(judge(seg[1].begin, seg[1].end, seg[2].begin, seg[2].end)) 123 intersection = getIntersection(seg[1].begin, seg[1].end, seg[2].begin, seg[2].end); 124 125 printf_s("(%lf, %lf) ", intersection.x, intersection.y); 126 } 127 128 return 0; 129 }