线段交点(图解)

线段交点

线段交点问题,通常给出4个点的坐标,求出交点坐标,我们通过交点构造出向量,利用向量的知识求解。

图示

在这里插入图片描述

从图中可以看到,4个端点p1,p2,p3,p4,交点x,以及向量p1p2、p1p3、p2p4、p3p4,以及通过p3到直线p1p2的距离h1,p4到p1p2的距离h2,以及通过向量p1p2、p1p3所围成的平行四边形。

推导交点坐标

1、先求出h1、h2的长度,进而求出h1比h2

我们利用外积模的几何意义:|axb|=|a|x|b|sinθ=所围成平行四边形面积,在求出向量p1p2的模长,用所围成平行四边形面积➗p1p2模长,求出h1高度,同理求出h2高度!

再看下一幅图

在这里插入图片描述

从图中可以看到直角坐标系,以及向量ox,op3,p3x

2、求出ox向量,即x点坐标

当有了h1比h2后,我们可以求出向量p3x,用p3p4✖(h1➗(h1+h2))

(因为两个三角形h1p3x、p2p4x全等,所以对应的边成比例)

向量p3x=ox-op3推导出ox=p3x+op3,从而求得x点坐标!

对上述过程的化简

我们可以不用求出h1h2,只需要求出两个向量积,因为我们需要的是h1比h2,在求h1、h2的过程中,所对应的平行四边形为同一个底边p1p2,所以在h1比h2的时候会约去!

实现代码

测试用例

输入

3
0 0 2 0 1 1 1 -1
0 0 1 1 0 1 1 0
0 0 1 1 1 0 0 1

输出

(1,1)
(0.5,0.5)
(0.5,0.5)

#include <bits/stdc++.h>

using namespace std;

class Point
{

public:
    double x,y;

    Point(double x=0,double y=0):x(x),y(y) {}

    //向量加法
    Point operator+(Point p)
    {
        return Point(x+p.x,y+p.y);
    }
    //向量减法
    Point operator-(Point p)
    {
        return Point(x-p.x,y+p.y);
    }
    //向量伸缩
    Point operator*(double a)
    {
        return Point(x*a,y*a);
    }
    Point operator/(double a)
    {
        return Point(x/a,y/a);
    }
    //向量大小
    double abs()
    {
        return sqrt(norm());
    }
    //向量范数
    double norm()
    {
        return x*x+y*y;
    }
};

typedef Point Vector;

//向量内积
double dot(Vector a,Vector b)
{
    return a.x*b.x+a.y*b.y;
}

//向量外积
double cross(Vector a,Vector b)
{
    return a.x*b.y-a.y*b.x;
}

Point getCrossPoint(Point p1,Point p2,Point p3,Point p4)
{
    Vector p12(p2.x-p1.x,p2.y-p1.x);
    Vector p13(p3.x-p1.x,p3.y-p1.y);
    Vector p24(p4.x-p2.x,p4.y-p2.y);
    Vector p34(p4.x-p3.x,p4.y-p3.y);
    double d1=abs(cross(p13,p12));
    double d2=abs(cross(p24,p12));
    double h=d1/(d1+d2);
    Point x=p34*h+p3;
    return  x;
}
int main()
{

    int t;
    cin>>t;//t组测试数据
    int x1,y1,x2,y2,x3,y3,x4,y4;
    while(t--)
    {
        cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
        Point p1(x1,y1);
        Point p2(x2,y2);
        Point p3(x3,y3);
        Point p4(x4,y4);
        cout<<"("<<getCrossPoint(p1,p2,p3,p4).x<<","<<getCrossPoint(p1,p2,p3,p4).y<<")"<<endl;
    }


    return 0;
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值