计算几何 经典题,求线段交点个数
首先大体思路,遍历的方式去寻找交点,如果有交点,计数+1
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++)
接下来就是判断线段是否有交点了
首先以线段作为对角线,构造矩形,先判断两个矩形是否有重叠,如果有重叠,则线段可能有交点,否则不可能有交点。
判断矩形有重叠部分
对于线段1 P1 (x1,y1) ,P2(x2,y2) 和线段2 P3(x3,y3), P4(x4,y4).
矩形重叠的条件是 x方向上
(max(x1,x2)>=min(x3,x4)&&min(x1,x2)<=max(x3,x4))
在y方向上同理。 只需把上式x替换成y即可。
接下来就是判断两条线段是否相交,
如果线段1和线段2有交叉,
则向量 (P1,P3)和(P1,P4) 肯定在(P1,P2)两侧,
根据叉积 ,他们和(P1,P2)的叉肯定异号,即叉积之积<=0
同时,以(P3,P4)作为基准线,(p1,p3),(p2,p3)与(p3,p4)的叉积之积也是异号,<=0
详细分析参考博客 http://www.cnblogs.com/–ZHIYUAN/p/6074676.html
#include <iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define MAX 105
double nodex1[MAX],nodey1[MAX];
double nodex2[MAX],nodey2[MAX];
int main()
{
int n;
int ans;
double x1,x2,y1,y2;
while(cin>>n){
if(n==0)break;
ans=0;
for(int i=0;i<n;i++){
scanf("%lf%lf%lf%lf",&nodex1[i],&nodey1[i],&nodex2[i],&nodey2[i]);
}
// serach
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
//rectangel charge
if(!(max(nodex1[i],nodex2[i])>=min(nodex1[j],nodex2[j])&&
min(nodex1[i],nodex2[i])<=max(nodex1[j],nodex2[j])&&
max(nodey1[i],nodey2[i])>=min(nodey1[j],nodey2[j])&&
min(nodey1[i],nodey2[i])<=max(nodey1[j],nodey2[j])
))
continue;
x1=nodex2[i]-nodex1[i];
y1=nodey2[i]-nodey1[i];
x2=nodex2[j]-nodex1[i];
y2=nodey2[j]-nodey1[i];
double tem1=x2*y1-x1*y2;
x2=nodex1[j]-nodex1[i];
y2=nodey1[j]-nodey1[i];
double tem2=x2*y1-x1*y2;
//
x1=nodex2[j]-nodex1[j];
y1=nodey2[j]-nodey1[j];
x2=nodex2[i]-nodex1[j];
y2=nodey2[i]-nodey1[j];
double tem3=x2*y1-x1*y2;
x2=nodex1[i]-nodex1[j];
y2=nodey1[i]-nodey1[j];
double tem4=x2*y1-x1*y2;
if(tem1*tem2<=0&&tem3*tem4<=0)ans++;
}
}
cout<<ans<<endl;
}
return 0;
}