线段相交 叉积

判断两条线断是否相交

首先,判断两条线段的 x , y 区间在坐标轴上的投影有没有重合

设两条线段 A-B, C-D


若     max(A.y,B.y) < min(C.y,D.y)||

        max(A.x,B.x) < min(C.x,D.x)||

        max(C.y,D.y) < min(A.y,B.y)||

        max(C.x,D.x) < min(A.x,B.x)

          则两条线断必定不相交

 

否则,用叉积判断;

P(x1,y1), Q(x2,y2)

P\times Q= x1*y2-x2*y1

若P×Q > 0,则P在Q的顺时针方向

若P×Q < 0,则P在Q的逆时针方向

若P×Q == 0,则P与Q平行

 

对于线段A-B, C-D

若 (A-C × C-D )*(B-C × C-D) <= 0, 则A和B在C-D的异侧,等号表示临界情况

若 A和B在C-D的异侧&&C和D在A-B的异侧,则 A-C 和 B-D 相交

否则不相交

题目:https://cn.vjudge.net/contest/296602#problem/C

判断线段之间的交点数量(不同线段间的相同交点视为不同交点)

 

#include
using namespace std;

struct node
{
    double x1,y1,x2,y2;
} a[120];

double cross(double x1,double y1,double x2,double y2)
{
    return x1*y2-x2*y1;
}
bool is_intersect(node a, node b)
{
   //判断两条线段的 x , y 区间在坐标轴上的投影有没有重合
    if(max(a.x1,a.x2) < min(b.x1,b.x2)||max(a.y1,a.y2) < min(b.y1,b.y2)||max(b.y1,b.y2) < min(a.y1,a.y2)||max(b.x1,b.x2) < min(a.x1,a.x2))
    {
        return 0;
    }
    //用叉积判断
    if(cross(a.x1-b.x1,a.y1-b.y1,b.x2-b.x1,b.y2-b.y1)*cross(a.x2-b.x1,a.y2-b.y1,b.x2-b.x1,b.y2-b.y1)>0||cross(b.x1-a.x1,b.y1-a.y1,a.x2-a.x1,a.y2-a.y1)*cross(b.x2-a.x1,b.y2-a.y1,a.x2-a.x1,a.y2-a.y1)> 0)
    {

        return 0;
    }
    return 1;
}

int main()
{
    int i,j,m,n,ans;
    while(scanf("%d",&n) !=EOF&&n)
    {
        ans = 0;
        for(i = 0; i < n; i ++)
        {
            scanf("%lf %lf %lf %lf",&a[i].x1, &a[i].y1, &a[i].x2,&a[i].y2);
        }

        for(i = 0; i < n; i ++)
        {
            for(j = i+1; j < n; j ++)
            {
                if(is_intersect(a[i],a[j]))
                {
                    ans ++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

你可能感兴趣的:(线段相交 叉积)