计算几何之线段性质(二):求线段交点

求线段的交点即求线段交点的坐标。若已确定两线段相交,可以通过解析几何中的直线方程来求解交点,这里介绍另外的一种方法。叉积multi(p1,p2,p0)可以看做是由点P1,P2,P0和P1+P2,这四个点围成的平行四边形的面积(如下图所示),及三角形P0P1P2的面积S=1/2 multi(P1,P2,P0)


在下图中,线段AB和CD相交于点P。



我们分别从D点和C点做AB的垂线DD1和CC1,由于△DD1P∽△CC1P,因此我们有|DD1| / |CC1|=|DP| / |CP|。又因为S△ABD=DD1*AB/2,S△ABC=CC1*AB/2,所以:

|DP| / |CP|=S△ABD/S△ABC=|AD × AB| / |AC × AB|=|multi(D,B,A)| / |multi(C,B,A)|

又因为|DP| / |CP|=(XD-XP)/(XP-XC)=(YD-YP)/(YP-YC)

所以有:

XP=(S△ABD * XC + S△ABC * XD)/(S△ABD + S△ABC)

    =(multi(D,B,A)* XC - multi(C,B,A)* XD)/(multi(D,B,A)- multi(C,B,A))

YP=(S△ABD * YC + S△ABC * YD)/(S△ABD + S△ABC)

    =(multi(D,B,A)* YC - multi(C,B,A)* YD)/(multi(D,B,A)- multi(C,B,A))

由此得出计算线段u和v交点的算法,参考代码如下:

#include <cstdio>
using namespace std;
typedef struct node
{
    double x,y;
}point;
typedef struct line
{
    point start,end;
}segment;
double multi(point p1,point p2,point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
point intersection(segment u,segment v)
{
    point p;
    p.x=(multi(v.end,u.end,u.start)*v.start.x-multi(v.start,u.end,u.start)*v.end.x)/(multi(v.end,u.end,u.start)-multi(v.start,u.end,u.start));
    p.y=(multi(v.end,u.end,u.start)*v.start.y-multi(v.start,u.end,u.start)*v.end.y)/(multi(v.end,u.end,u.start)-multi(v.start,u.end,u.start));
    return p;
}
int main()
{
    segment u,v;
    scanf("%lf%lf%lf%lf",&u.start.x,&u.start.y,&u.end.x,&u.end.y);
    scanf("%lf%lf%lf%lf",&v.start.x,&v.start.y,&v.end.x,&v.end.y);
    point p=intersection(u,v);
    printf("%lf  %lf\n",p.x,p.y);
    return 0;
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值