面试题 16.03. 交点--计算几何

面试题 16.03. 交点

给定两条线段(表示为起点start = {X1, Y1}和终点end = {X2, Y2}),如果它们有交点,请计算其交点,没有交点则返回空值。

要求浮点型误差不超过10^-6。若有多个交点(线段重叠)则返回 X 值最小的点,X 坐标相同则返回 Y 值最小的点。

示例 1:

输入:
line1 = {0, 0}, {1, 0}
line2 = {1, 1}, {0, -1}
输出: {0.5, 0}

示例 2:

输入:
line1 = {0, 0}, {3, 3}
line2 = {1, 1}, {2, 2}
输出: {1, 1}

示例 3:

输入:
line1 = {0, 0}, {1, 1}
line2 = {1, 0}, {2, 1}
输出: {},两条线段没有交点

提示:

坐标绝对值不会超过 2^7
输入的坐标均是有效的二维坐标

题解

题目不难,先把线段看成直线,那么直线无非两种情况:平行或者相交。
如果两条线段所在的直线是平行的,那么直接返回空,如果不平行,需要判断是否是在同一条直接,如果在同一条直线,并且相交了,就是有多个交点。如果所在的直线是相交的,直接算出相交的点,判断这个点是否同时在两条线段上,就得到了答案。

感觉我的代码写的比较冗余,思路能理解就好。

AC代码

class Solution {
public:
    typedef long long ll;
    vector <double>fun(double x1,double y1,double x2,double y2)//计算直线的k和b
    {
        double k=(y1-y2)/(x1-x2);
        double b=y1-k*x1;
        vector<double>q;
        q.push_back(k);
        q.push_back(b);
        return q;
    }
    vector<double> intersection(vector<int>& start1, vector<int>& end1, vector<int>& start2, vector<int>& end2) {
        ll ans1=(start1[0]-end1[0])*(start2[1]-end2[1]);
        ll ans2=(start2[0]-end2[0])*(start1[1]-end1[1]);
        if(ans1==ans2)//两条直线斜率一样
        {
            ll ans3=(start1[0]-end1[0])*(start1[1]-start2[1]);
            ll ans4=(start1[0]-start2[0])*(start1[1]-end1[1]);
            if(ans3==ans4)//说明两条线段属于同一条直线
            {
                int mix=min(start2[0],end2[0]);
                int mxx=max(start2[0],end2[0]);
                int miy=min(start2[1],end2[1]);
                int mxy=max(start2[1],end2[1]);
                double x=1e9,y=1e9;
                if(start1[0]>=mix&&start1[0]<=mxx&&start1[1]>=miy&&start1[1]<=mxy)
                {
                    if(start1[0]<x)
                    {
                        x=start1[0];
                        y=start1[1];
                    }
                }
                if(end1[0]>=mix&&end1[0]<=mxx&&end1[1]>=miy&&end1[1]<=mxy)
                {
                    if(end1[0]<x)
                    {
                        x=end1[0];
                        y=end1[1];
                    }
                }
                mix=min(start1[0],end1[0]);
                mxx=max(start1[0],end1[0]);
                miy=min(start1[1],end1[1]);
                mxy=max(start1[1],end1[1]);
                if(start2[0]>=mix&&start2[0]<=mxx&&start2[1]>=miy&&start2[1]<=mxy)
                {
                    if(start2[0]<x)
                    {
                        x=start2[0];
                        y=start2[1];
                    }
                }
                if(end2[0]>=mix&&end2[0]<=mxx&&end2[1]>=miy&&end2[1]<=mxy)
                {
                    if(end2[0]<x)
                    {
                        x=start2[0];
                        y=start2[1];
                    }
                }
                vector<double>q;
                if(x>1e8)return q;//说明这两条线段没有交点
                q.push_back(x);
                q.push_back(y);
                return q;
            }
            else//说明两条线段平行
            {
                vector<double>q;
                return q;
            }
        }
        else//直线不平行必然相交
        {
            double x1,x2,y1,y2,x3,x4,y3,y4;            
            if(start2[0]==end2[0])
            {
                swap(start1,start2);
                swap(end1,end2);
            }
            x1=min(start1[0],end1[0]);
            x2=max(start1[0],end1[0]);
            y1=min(start1[1],end1[1]);
            y2=max(start1[1],end1[1]);
            x3=min(start2[0],end2[0]);
            x4=max(start2[0],end2[0]);
            y3=min(start2[1],end2[1]);
            y4=max(start2[1],end2[1]);

            if(start1[0]==end1[0])
            {
                vector<double>q;
                double x=start1[0];
                double y=double((end2[0]-x)*start2[1]+(x-start2[0])*end2[1])/double(end2[0]-start2[0]);
                if(x>=x1&&x<=x2&&x>=x3&&x<=x4&&y>=y1&&y<=y2&&y>=y3&&y<=y4)
                {
                    
                    q.push_back(x);
                    q.push_back(y);
                    return q;
                }
                else
                {
                    return q;
                }
            }
            else
            {
                vector<double>f1=fun(start1[0],start1[1],end1[0],end1[1]);
                vector<double>f2=fun(start2[0],start2[1],end2[0],end2[1]);
                
                double x=(f2[1]-f1[1])/(f1[0]-f2[0]);
                double y=f1[0]*x+f1[1];
                vector<double>q;
                if(x>=x1&&x<=x2&&x>=x3&&x<=x4&&y>=y1&&y<=y2&&y>=y3&&y<=y4)
                {
                    
                    q.push_back(x);
                    q.push_back(y);
                    return q;
                }
                else
                {
                    return q;
                }
            }
        }
        vector<double>q;
        return q;
    }
};

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值