toLeftTest

toLeftTest是判断一个点是否在有向直线左侧的算法。

当点s位于向量pq左侧时,toLeftTest返回true。当点s位于向量pq右侧时,toLeftTest返回false。

具体的算法可以根据三角形的有符号面积来计算

对应上图中的 2倍三角形面积area 的公式为

当pqs的方向为逆时针时,面积area为;当pqs的方向为顺时针时,面积area为负值。当area为0时,说明点s在直线pq上

下面的算法有效避免了除法的出现,减少了计算误差。

 bool toLeftTest(Point p, Point q, Point s){
return area2(p,q,s) > ;
} int area2(Point p, Point q, Point s){
return
p.x * q.y - p.y * q.x
+ q.x * s.y - q.y * s.x
+ s.x * p.y - s.y * p.x;
}

应用:

  1. 需要考察角度的最大最小值时

InTriangleTest

InTriangleTest用于判断一个点是否在给点的三角形内。

三角形的三条边所在直线将平面分成了7份,无论三角形三个顶点是逆时针还是顺时针的,位于三角形内的点对三边向量所做的toLeftTest结果都相同。

方法一:利用toLeftTest

 bool inTriangleTest(Point r, Point p, Point q, Point s){
int a = toLeftTest(p,q,r);
int b = toLeftTest(q,s,r);
int c = toLeftTest(s,p,r);
return ( a == b && b == c);
}

凸包的toLeftTest性质

给定一个逆时针的凸包,在平面上随意取一个点P。对于凸包上的点Q,以PQ为向量,对Q先前邻接的点Q-1之后邻接的点Q+1做 toLeftTest测试

  1. 当点P在凸包内时

对于凸包上任意的点Q,Q先前邻接的点Q-1之后邻接的点Q+1的 toLeftTest 结果分别为false和true,记为 FT

  1. 当点P在凸包外时

通过P可以在凸包上找到两个点T和S,向量PS和PT会与凸包相切。

2.1 点T和点S的前驱和后继点(T-1和T+1,S-1和S+1)的toLeftTest结果均为两个相同的值,要么都为true,要么都为false。记为 TT 和 FF
2.2 凸包TS之间的点(TS具有方向性),其前驱和后继的toLeftTest测试结果为true,false。 记为 TF
2.3 凸包ST之间的点(ST具有方向性),其前驱和后继的toLeftTest测试结果为false,true。 记为 FT

inConvexPolygonTest

inConvexPolygonTest是用来判断一个点是否在一个凸包多边形的内部。下面的算法要求输入的凸包点集是逆时针的。过程可看下图

算法的过程是需要将 inConvexPolygonTest 最终转化为 inTriangleTest。取凸包的第一个点作为InTriangleTest的三角形的一个点,通过二分找到中间点,然后通过不断的inLeftTest二分, 从而找到将判断点夹在中间的三角形,最后进行inTriangleTest,用inTriangleTest的结果作为inConvexPolygonTest的结果。

以上面的图作为inConvexPolygonTest算法的过程例子

  1. 取凸包的第一个点A中间的点D
  2. 用向量AD对点s进行toLeftTest。 toLeftTest(A,D,s)
  3. 上一步toLeftTest结果为false, 所以对右侧的点进行二分找到点B。
  4. 用向量AB对点s进行toLeftTest。 toLeftTest(A,B,s)
  5. 上一步toLeftTest结果为true, 所以对左侧的点进行二分找到点C。
  6. 用向量AC对点s进行toLeftTest。 toLeftTest(A,C,s)
  7. 由于toLeftTest(A,C,s)返回true,且D邻接在点C的左侧,所以确定进行inTriangleTest的为三角形 ACD。
  8. 用三角形ACD对点s进行inTriangleTest,返回true,所以点s在凸包内。

inPolygonTest

左右两个不相交凸包的两条公切线求法

graham scan 以O(nlogn)复杂度求平面点集的凸包

算法步骤为

  1. 找到 lowest then leftmost的点A(在笛卡尔坐标系中,y值最小的点。如果y值相同,则要求x值最小。)
  2. 以点A建立极角坐标系,对剩余的点以极角的大小进行从小到大排序,找出极角最小的点B。
  3. 建立堆栈S,将点A压栈,将点B压栈。
  4. 遍历剩余的点,记正在遍历的点为P。以堆栈S的次栈顶的点Q(最开始时为A点),栈顶的点R(最开始时为点B),和点P进行toLeftTest测试。
    4.1 如果toLeftTest测试结果为true,将点T压进堆栈S。
    4.2 如果toLeftTest测试结果为false
    4.2.1 如果堆栈S中的点的个数小于等于3,不做任何事情。
    4.2.2 如果堆栈S中点的个数大于3,将堆栈S中的栈顶的点推出(pop),然后返回到步骤4继续做toLeftTest测试。
  5. 直到遍历完所有的点。

算法结束后,堆栈S中从栈底到栈顶的点集及为凸包逆时针方向的点集。

Common tangle 左右两个子凸包的公切线

Geometry Interaction (线段相交)

Segments Interaction(线段集的求交)

线段集的求交是给定 线段的集合作为输入 求出这些 线段中的所有可能交点

一种与输出的交点数敏感的算法是平面扫描算法。以一条扫描线扫过所有的线段集,以线段集中的所有起点终点、和将来求出的交点作为所有事件点,当扫描线经过事件点时,则需要对与扫描线相交的线段中的部分线段进行相交检测,判断从而判断是否存在交点。

  1. 当扫描线经过一条线段的起点,即事件点为线段的起点。将线段放入与扫描线相交的线段的有序集合中,并与其前驱和后继的线段进行相交检测。
    1.1 如果有交点,记录交点。并把交点纳入事件点。
    1.2 如果没有交点,继续扫描,进入下一个事件点。
  2. 当事件点为交点。将交点的两条线段在与扫描线相交的线段的有序集合中交换顺序,并与其新前驱或新后继的线段进行相交检测。
    2.1 如果有交点,记录交点。并把交点纳入事件点。
    2.2 如果没有交点,继续扫描,进入下一个事件点。
  3. 当事件点为线段的终点。将该线段从与扫描线相交的线段的有序集合中移除,并对其移除之前的前驱和后继线段进行相交检测。
    3.1 如果有交点,记录交点。并把交点纳入事件点。
    3.2 如果没有交点,继续扫描,进入下一个事件点。

isTwoConvexPolygonIntersected

参考资料

学堂在线 清华大学 邓俊辉的 计算几何 课程+https://www.cnblogs.com/smallpi/p/7257762.html

计算几何-凸包-toleft test的更多相关文章

  1. 计算几何---凸包问题(Graham/Andrew Scan )

    概念 凸包(Convex Hull)是一个计算几何(图形学)中的概念.用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有点的.严谨的定义和相关概念参 ...

  2. 计算几何-凸包算法 Python实现与Matlab动画演示

    凸包算法是计算几何中的最经典问题之一了.给定一个点集,计算其凸包.凸包是什么就不罗嗦了 本文给出了<计算几何——算法与应用>中一书所列凸包算法的Python实现和Matlab实现,并给出了 ...

  3. 【BZOJ-1069】最大土地面积 计算几何 + 凸包 + 旋转卡壳

    1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 2707  Solved: 1053[Submit][Sta ...

  4. uva 10652 Board Wrapping (计算几何-凸包)

    Problem B Board Wrapping Input: standard input Output: standard output Time Limit: 2 seconds The sma ...

  5. Codeforces 1045E. Ancient civilizations 构造 计算几何 凸包

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045E.html 4K码量构造题,CF血腥残暴! 题解 首先,如果所有点颜色相同,那么直接连个菊花搞定. ...

  6. 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-I.html 题目传送门 - 2018牛客多校赛第三场 I ...

  7. POJ3348 Cows 计算几何 凸包

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3348 题意概括 求凸包面积(答案÷50) 题解 凸包裸题. 代码 #include <cstr ...

  8. POJ 1113 Wall(计算几何の凸包)

    Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall ...

  9. [hdu-4946] Area of Mushroom 计算几何 凸包

    大致题意: 平面上有n个人,给你每个人的坐标和一个速度v,如果某个人比其他所有人都先到达某点,则该点就被这个人掌控,求谁掌控者无限大的面积. 首先 速度最大的人,抛弃其他人,速度小的人必定无法得到无限 ...

随机推荐

  1. winform中获取当前周次

    /*方法一*/ var dt = DateTime.Now; //找到今年的第一天是周几 int firstWeekend = Convert.ToInt32(DateTime.Parse(dt.Ye ...

  2. System Center Configuration Manager 2016 必要条件准备篇(Part1)

    步骤4.创建系统管理容器 SCCM 2016 配置管理系列(Part 1- 4) 介绍AD01上配置了Active Directory域服务(ADDS),然后将Configuration Manag ...

  3. kubernetes发布解释型语言应用的最佳实践

    说明 k8s在发布编译型语言的应用时,几乎不用多考虑,就会选择将编译好jar/war包(java语言)或者二进制文件(golang/c++)直接打到镜像当中,生成新的应用镜像,然后将镜像推到镜像仓库, ...

  4. JS encodeURIComponent函数

    为了避免歧义,可以用JS 的encodeURIComponent函数  将有歧义的字符(?+=等)转换成对应的ASCII编码 for(var i=0;i<whichform.elements.l ...

  5. [VC]socket含义

    两个程序之间的通信方法.Socket 是一种识别码,应用程式可用此唯一识别通信端点.用户创建 Socket 地址与Socket 的关联性后,便可创建通信协议地址与Socket 的关联性.

  6. systemd初始化进程(转)

    Systemd初始化进程 Linux操作系统开机过程首先从BIOS开始→进入"Boot Loader"→加载内核→内核的初始化→启动初始化进程,初始化进程作为系统第一个进程,它需要 ...

  7. 【BZOJ1101】[POI2007] Zap(莫比乌斯反演)

    点此看题面 大致题意: 求\(\sum_{x=1}^N\sum_{y=1}^M[gcd(x,y)==d]\). 一道类似的题目 推荐先去做一下这道题:[洛谷2257]YY的GCD,来初步了解一下莫比乌 ...

  8. 【洛谷5358】[SDOI2019] 快速查询(模拟)

    点此看题面 大致题意: 有单点赋值.全局加法.全局乘法.全局赋值.单点求值.全局求和\(6\)种操作.现在给出操作序列,以及\(t\)对正整数\(a_i,b_i\).让你处理\(t*q\)次操作,每次 ...

  9. js 实现纯前端将数据导出excel两种方式,亲测有效

    由于项目需要,需要在不调用后台接口的情况下,将json数据导出到excel表格,兼容chrome没问题,其他还没有测试过 通过将json遍历进行字符串拼接,将字符串输出到csv文件,输出的文件不会再是 ...

  10. Jmeter后置处理器

    一.什么是关联? 将请求1的输出 作为 请求2 的输入,则称之为关联 例如:“用户登录”请求中服务器返回了token,“查询用户信息”请求需要把token返回给服务器进行验证 二.通过JSON Pat ...