Algorithm Design——求两条线段的交点

  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)\n", intersection.x, intersection.y);
126     }
127 
128     return 0;
129 }

 

posted @ 2013-12-01 11:09  yiyi_xuechen  Views(301)  Comments(0Edit  收藏  举报