文章目录

  • 算法一:快速排斥+跨立试验
    • 代码
  • 算法二:参数方程求解
    • 代码
  • 算法三:凸多边形
  • 算法四:点在线的哪一侧

算法一:快速排斥+跨立试验

重点掌握

【原理】利用矢量的叉乘

【图解】

代码

#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
typedef struct{double x;double y;
}Point;
typedef struct{Point A,B;
}Line;
// 线段L与C的位置关系
// 返回值:>0即C在L的顺时针方向(下方);<0即C在L的逆时针方向(上方);=0同线
double PointLineLocation(Point &C, Line &L) {double AB_x,AB_y; //矢量ABdouble AC_x,AC_y; //矢量ACAB_x=L.A.x-L.B.x; AB_y=L.A.y-L.B.y; //矢量A->BAC_x=L.A.x-C.x;   AC_y=L.A.y-C.y;   //矢量A->Creturn AB_x*AC_y-AB_y*AC_x; //矢量AB、AC叉乘
}
int Intersection(Line &L1, Line &L2) { //L1和L2是否相交//快速排斥if ( max(L1.A.x, L1.B.x)<min(L2.A.x, L2.B.x) ) return 0;if ( max(L1.A.y, L1.B.y)<min(L2.A.y, L2.A.y) ) return 0;if ( max(L2.A.x, L2.B.x)<min(L1.A.x, L1.A.x) ) return 0;if ( max(L2.A.y, L2.B.y)<min(L1.A.y, L1.A.y) ) return 0;//跨立实验if ( PointLineLocation(L1.A, L2)*PointLineLocation(L1.B, L2)>0 ) //L1的两端点都在L2的同侧return 0;if ( PointLineLocation(L2.A, L1)*PointLineLocation(L2.B, L1)>0 ) //L2的两端点都在L1的同侧return 0;return 1; //相交
}

算法二:参数方程求解

线段AB、线段CD是否相交

【定义】线段的参数方程:

  1. AD = A + r(b-A),r∈[0,1] (用r描述AB线段上的每个点,不再是x,y)
  2. CD = C + s(D-c),s∈[0,1]

【推算】Ax,Ay表示A的横坐标、纵坐标
如果AB、CD相交 => A+r(B-A)=C+s(D-c) => Ax+r(Bx-Ax)=Cx+s(Dx-Cx),Ay+r(By-Ay)=Cy+s(Dy-Cy), r、s∈[0,1] => 解方程,得到r,s

【判断方法】设P为AB、CD的交点 => P=A+r(B-A) => Px=Ax+r(Bx-Ax),Py=Ay+r(By-Ay)

  1. 如果(0≤r≤1)and(0≤s≤1) => AB、CD交点存在
  2. 如果(Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)=0 => AB和CD平行
  3. 如果2成立,(Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cx)也为0 => AB和CD共线
  4. 如果AB和CD相交,而交点不位于线段AB、CD之间,则交点位置可以通过以下条件判断
    • r>1 => P位于AB的延长线上
    • r<0 => P位于BA的延长线上
    • s>1 => P位于CD的延长线上
    • s<0 => P位于DC的延长线上

代码

bool IsIntersection(Point a,Point  b,Point c,Point d) {//AB = A + r(B-A), r 在[0,1]//CD = C + t(D-C),s 在[0,1]double r, s;double deno = (b.X - a.X) * (d.Y - c.Y) - (b.Y - a.Y) * (d.X - c.X);double mem1 = (a.Y - c.Y) * (d.X - c.X) - (a.X - c.X) * (d.Y - c.Y);double mem2 = (a.Y - c.Y) * (b.X - a.X) - (a.X - c.X) * (b.Y - a.Y);r = mem1 / deno;s = mem2 / deno;if (r > 1 || r < 0)return false;if (s > 1 || s < 0)return false;return true;
}

算法三:凸多边形

判断是否为凸多边形 --> 凸多边形 --> 线段相交

  1. 凸多边形:当从某个点开始绕一周,要么全顺时针拐弯,要么全逆时针

typedef struct vector{double x,y;
}Vector; //向量
/** 由两个点构造一个向量*/
Vector VectorConstruct(Point A, Point B) {Vector v;v.x = B.x - A.x;v.y = B.y - A.y;return v;
}
// 向量的叉积
double CrossProduct(Vector a, Vector b) {return a.x * b.y - a.y * b.x;
}
/** 判断两线段(线段AB和CD)是否相交,是返回1,否0*   判断四边形ACBD是否是一个凸四边形*/
int SegmentIntersection(Point A, Point B, Point C, Point D) {double c[4];Vector AC = VectorConstruct(A, C);Vector CB = VectorConstruct(C, B);Vector BD = VectorConstruct(B, D);Vector DA = VectorConstruct(D, A);c[0] = CrossProduct(AC, CB);c[1] = CrossProduct(CB, BD);c[2] = CrossProduct(BD, DA);c[3] = CrossProduct(DA, AC);int f1=0, f2=0;  // 计算正数,负数的个数int i;for (i=0; i<4; i++) {if (c[i] > 0) f1++;if (c[i] < 0) f2++;}if (f1 > 0 && f2 > 0)   // 有正,有负,返回无交集return 0;elsereturn 1;
}

算法四:点在线的哪一侧

//功能:求 点(x,y) 在 有向直线ab 的左边还是右边
//返回:0共线、1左边、-1右边
int   left_right(point   a,point   b,double   x,double   y)  {double   t;  a.x -= x;b.x -= x;  a.y -= y;b.y -= y;  t = a.x*b.y-a.y*b.x;  return t==0 ? 0 : (t>0?1:-1);  //注意:double类型t==0应该改成fabs(t)<10e-6
}  //功能:直线ab 与 线段cd 是否相交
bool   intersect1(point   a,point   b,point   c,point   d)   {return   left_right(a,b,c.x,c.y) ^ left_right(a,b,d.x,d.y) == -2;
}  //功能:判断线段c,d和线段a,b是否相交
bool   intersect(point   a,point   b,point   c,point   d)  {  return   intersect1(a,b,c,d)  //直线ab 与 线段cd 相交   &&intersect1(c,d,a,b);   //直线cd 与 线段ab 相交
}

[GIS算法] 判断两线段是否相交的四种方案(快速排斥+跨立实验、参数方程求解、凸多边形、点在线的哪一侧)-附C语言实现相关推荐

  1. python判断两线段是否相交_c语言 判断两直线段是否相交

    转了多人的放到一起比较!! //功能:求点在有向直线左边还是右边 //返回:0共线.1左边.-1右边 intleft_right(pointa,pointb,doublex,doubley) { do ...

  2. 判断线段是否相交:快速排斥+跨立

    矢量 如果一条线段的端点是有次序之分的话,那么这种线段就称为 有向线段,如果有向线段p1p2的起点p1在坐标的原点,则可以把它称为矢量p2 矢量的加减 设二维矢量 P = (x1, y1), Q = ...

  3. hdu 1086(判断两线段是否相交)

    题意:给出一些线段,问有多少个交点. 解题思路:这里实际就是一个线段相交的模型,下面这个图给出了思路. 如果两线段相交,则两线段必然相互跨立对方.若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ...

  4. 判断两线段是否相交——快速排斥与跨立实验

    如何判断两条线段是否相交呢?如果是我们去解决这个问题,用眼睛很容易就看出来了,但是如果用计算机来解决这个问题,该怎么办呢?下面介绍两个方法,这两个方法结合起来就能完美解决这个问题了. 一.快速排斥 对 ...

  5. java判断两线段是否相交

    首先推荐java的Line2D类自带方法linesIntersect java.awt.geom.Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y ...

  6. 判断两线段是否相交,并求交点

    首先, 上个示意图. 根据图示, 线段a表示为端点a1和a2, 线段b表示为端点b1和b2. 为了利用向量的叉乘关系, 将线段的端点看成四个向量, 下面用粗体表示向量. 根据向量运算可知 a=a2-a ...

  7. nyoj1016德莱联盟【判断两线段是否相交】

    德莱联盟 时间限制:1000ms  |  内存限制:65535KB 难度:1 描述 欢迎来到德莱联盟.... 德莱文... 德莱文在逃跑,卡兹克在追.... 我们知道德莱文的起点和终点坐标,我们也知道 ...

  8. 判断三维空间两线段是否相交(附代码)

    文章目录 一.推导过程 二.MATLAB代码   博文: 计算几何--判断两线段是否相交,提供了判断两线段是否相交的方法以及代码.然而,只是考虑了平面的情况.本博文提供一种简单有效的方法判断三维空间两 ...

  9. 快速排斥实验amp;跨立实验 判断两直线是否相交

    两条线段有且仅有一个公共点,且这个点不是任何一条线段的端点时,称这两条线段是严格相交的. 也就是说线段不严格相交时可以将端点作为交点,但本文不讨论不严格相交,只讨论严格相交的情况(即使它们在算法实现上 ...

最新文章

  1. 【opencv】(13) 案例:停车场空余车位检测,附python完整代码
  2. linux监控平台搭建-内存
  3. 2022王道操作系统名词解释概念题
  4. 《Spring Cloud Netflix官方文档》1.服务发现:Eureka客户端
  5. P6365 众数出现的次数(水)
  6. UE4移动平台上基于物理的着色
  7. shell:概述、脚本编写、变量的简单基础
  8. @Import-给容器中加载bean的第三种方式
  9. python100爬取
  10. CentOS 7 配置花生壳(phddns)自启动
  11. svn中文路径 权限设定
  12. Python:实现zellers congruence泽勒一致算法(附完整源码)
  13. c语言写的exe文件怎么改图标,c/c++修改exe文件图标
  14. php数据库操作类库doctrine使用全攻略
  15. 计算机任务管理器设置软件启动,电脑软件开机自动启动,教你一招禁止启动,能够有效提升开机速度...
  16. git stash暂存操作
  17. 百度、快手、商汤、旷视等重磅嘉宾确认出席AI ProCon 2019,你还剩1天早鸟票特权!...
  18. 逻辑思维能力选择题30道
  19. java根据url获取pdf流_从URL获取动态创建的PDF
  20. 怎么用MindManager将导图导出为HTML5交互式导图

热门文章

  1. 面试准备之redis
  2. 约束条件(constraint)
  3. 修改 Surface Pro 3 无线网卡的 MAC 地址
  4. git 无法push远程仓库 Note about fast-forwards 问题解决
  5. Android开发仿位置分享功能基于高德地图
  6. beego tag详解
  7. 2018.11.04-3988-地理课(geography)
  8. Java工具 :SQL解析
  9. Linux | 补天01
  10. Salesforce 2023财年逆风增长,现金流达历史最高!