ACM 几何基础(2)

判断两条线段是否相交:

矢量

      如果一条线段的端点是有次序之分的话,那么这种线段就称为 有向线段,如果有向线段p1p2的起点p1在坐标的原点,则可以把它称为矢量p2

矢量的加减

      设二维矢量 P = (x1, y1), Q = (x2, y2),则P + Q = (x1 + x2, y1 + y2), P - Q = (x1 - x2, y1 - y2),且有P + Q = Q + P, P - Q = -(Q - P)

矢量叉积

      设矢量 P = (x1, y1), Q = (x2, y2),则P * Q = x1 * y2 - x2 * y1;其结果是一个由(0, 0), P, Q, P + Q所组成的平行四边形的 带符号的面积,P * Q = -(Q * P), P * (- Q) = -(P * Q)

      叉积的一个非常重要的性质是可以通过它的符号来判断两矢量相互之间的顺逆时针关系:

             P * Q > 0,则 P Q的顺时针方向

             P * Q < 0, P Q的逆时针方向

             P * Q = 0,则 P Q共线,但不确定P, Q的方向是否相同

折线段的拐向判断

      如图,假设有折线段p0p1p2,要确定p1p2相对于p0p1是向左拐还是向右拐,可以通过计算(p2 - p0)*(p1 - p0)的符号来确定折线的拐向(点p2 - p0实际上就是向量p2,但这里要注意线段和矢量的区别)

判断点是否在线段上

      设点 Q = (x, y), P1 = (x1, y1), P2 = (x2, y2),若(Q - P1)*(P2 - P1) = 0min(x1, x2) <= x <= max(x1, x2) && min(y1, y2) <= y <= max(y1, y2),则点Q在线段P1P2

判断两线段是否相交
1)快速排斥试验

      设以线段 P1P2 为对角线的矩形为R,设以线段Q1Q2为对角线的矩形为T,若RT不相交,则两线段不可能相交

      假设 P1 = (x1, y1), P2 = (x2, y2), Q1 = (x3, y3), Q2 = (x4, y4),设矩形Rx 坐标的最小边界为minRX = min(x1, x2),以此类推,将矩形表示为R = (minRX, minRY, maxRX, maxRY)的形式,若两矩形相交,则相交的部分构成了一个新的矩形F,如图所示,我们可以知道FminFX = max(minRX, minTX), minFY = max(minRY, minTY), maxFX = min(maxRX, maxTX), maxFY = min(maxRY, maxTX),得到F的各个值之后,只要判断矩形F是否成立就知道RT 到底有没有相交了,若minFX > maxFXminFY > maxFyF无法构成,RT不相交,否则RT相交

 

 
 
2)跨立试验

       P1P2 跨立 Q1Q2,则 P1,P2 分别在 Q1Q2 所在直线的两端,则有(P1 - Q1)*(Q2 - Q1) * (Q2 - Q1)*(P2 - Q1) > 0,当(P1 - Q1)*(Q2 - Q1) = 0 时,说明(P1 - Q1)(Q2 - Q1)共线,但由于已经经过快速排斥试验,所以Q1必为P1P2Q1Q2的交点,依然满足线段相交的条件,则跨立试验可改为:

       (P1 - Q1)*(Q2 - Q1) * (Q2 - Q1)*(P2 - Q1) >= 0,则P1P2跨立Q1Q2,当Q1Q2也跨立P1P2的时候,则P1P2相交

      (注意式子中被隔开的*代表两个叉积的值的相乘,而另外的两个*则代表计算矢量叉积)

 

 

 

 

判断线段与直线是否相交:

首先在直线上随便取两点做为线段l1;

再与线段L2进行判断,因为是直线所以现在只需判断L2是否跨立l1就行了。

 

代码如下:

bool inter_line(line l1,line l2)//判断直线与线段是否相交

{

    return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0;

}

 


 

代码实现:

再这之前可以先去学下,C++的运算符重载部分

运算符重载详解  http://blog.chinaunix.net/uid-21411227-id-1826759.html

#include <iostream>

#include <cstdio>

#include <cmath>

using namespace std;

const double eps=1e-8;

const double PI=acos(-1.0);

int sgn(double x)

{

    if(fabs(x)<eps) return 0;

    if(x < 0) return -1;

    else return 1;

}

 

struct point

{

    double x,y;

    point(){}

    point (double _x,double _y)

    {

        x=_x,y=_y;

    }

    point operator -(const point &b)const

    {

        return point(x-b.x,y-b.y);

    }

    point operator +(const point &b)const

    {

        return point (x+b.x,y+b.y);

    }

    double operator ^(const point &b)const //叉积

    {

        return x*b.y-y*b.x;

    }

    double operator *(const point &b)const //点积

    {

        return x*b.x+y*b.y;

    }

    void transxy(double B)  //绕原点旋转角度B(弧度值),后的xy

    {

        double tx=x,ty=y;

        x= tx*cos(B) - ty*sin(B);

        y= tx*sin(B) + ty*cos(B);

    }

};

 

struct line//线

{

    point s,e;

    line(){}

    line(point _s,point _e)

    {

        s=_s,e=_e;

    }

};

 

double dist(point a,point b)//两点间距离

{

    return sqrt((a-b)*(a-b));

}

 

bool inter(line l1,line l2)//判断线段相交

{

    return max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&

    max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&

    max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&

    max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&

    sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0&&

    sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e))<=0;

}

 

bool inter_line(line l1,line l2)//判断直线与线段是否相交

{

    return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0;

}

 

int main()

{

    double ax,ay,bx,by,cx,cy,dx,dy;

    while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy)!=EOF)//分别输入两条线段的首尾端点

    {

        point k1(ax,ay);

        point k2(bx,by);

        point k3(cx,cy);

        point k4(dx,dy);

        line l1(k1,k2);

        line l2(k3,k4);

        if(inter(l1,l2))

            printf("Yes\n");

        else

            printf("No\n");

}

return 0;

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值