【计算几何】确定两条连续线段向左转还是向右转

确定两条连续线段向左转还是向右转

目录

  • 一、说明
  • 二、算法
    • 2.1 两点的叉积
    • 2.2 两个段的叉积
  • 三、旋转方向判别
    • 3.1 左转
    • 3.2 右转
    • 3.3 共线判别

一、说明

   如果是作图,或者是判别小车轨迹。为了直观地了解,从当前点到下一个点过程中,什么是左转、什么是右转,或者方向不变,这在现场实时运算中是很重要的。本篇描述其快速算法。

   请考虑下面所示的示例。
在这里插入图片描述

   两图中,共有三点p1,p2和p3和两条线段 p 1 p 2 ‾ \overline{p_1p_2} p1p2 p 2 p 3 ‾ \overline{p_2p_3} p2p3。中途点 p 2 p_2 p2是两条线段共有的。在图(a)中,线段 p 2 p 3 ‾ \overline{p_2p_3} p2p3 p 2 p_2 p2该点右转而在图(b)中,段 p 2 p 3 ‾ \overline{p_2p_3} p2p3在公共点 p 2 p_2 p2左转。我们的眼睛更容易通过观察图形来快速识别路段是左转还是右转,因为您的眼睛天生具有快速识别事物的能力。在这篇文章中,我将讨论计算机如何使用几何算法来识别这一点。

二、算法

2.1 两点的叉积

   给定两点 p 1 ( x 1 , y 1 ) p_1(x_1,y_1) p1(x1,y1 p 2 ( x 2 , y 2 ) p_2(x_2,y_2) p2(x2,y2),我们首先需要判断点是否 p 1 p_1 p1从点开始是顺时针还是逆时针 p 2 p_2 p2就起源而言。解决这个问题的一种方法是计算两者所成的角度 p 1 ‾ \overline{p_1} p1 p 2 ‾ \overline{p_2} p2
和X轴和角度的差异可以判断一个点是顺时针还是逆时针。有一个比查找计算向量叉积的角度更简单有效的解决方案 p 1 ‾ \overline{p_1} p1 p 2 ‾ \overline{p_2} p2。数学上两个向量的叉积 p 1 ‾ \overline{p_1} p1 p 2 ‾ \overline{p_2} p2定义成:
p 1 × p 2 = x 1 y 2 − x 2 y 1 p_1×p_2=x_1y_2-x_2y_1 p1×p2=x1y2x2y1

   如果值p1×p2为正,则p1是沿逆时针到达p2,关于原点如下图所示。
在这里插入图片描述

   同样,如果p1×p2是负数,从p1到p2是顺时针过度。相对于原点,如果值为 0,则点p1,p2和原点共线。以下 python 代码实现了叉积。

class Point:def __init__(self, x, y):self.x = xself.y = ydef subtract(self, p):return Point(self.x - p.x, self.y - p.y)def __str__(self):return '(' + str(self.x) + ', ' + str(self.y) + ')'# calculates the cross product of vector p1 and p2
# if p1 is clockwise from p2 wrt origin then it returns +ve value
# if p2 is anti-clockwise from p2 wrt origin then it returns -ve value
# if p1 p2 and origin are collinear then it returs 0
def cross_product(p1, p2):return p1.x * p2.y - p2.x * p1.y

2.2 两个段的叉积

   考虑两个线段,其端点是p1(X1,y1),p2(X2,y2)和p1(X1,y1),p3(X3,y3)分别。为了计算两个线段的叉积,我们需要将它们转换为向量。这可以通过以下方式完成。

p 1 p 2 ‾ = ( x 2 − x 1 , y 2 − y 1 ) , p 1 p 3 ‾ = ( x 3 − x 1 , y 3 − y 1 ) \overline{p_1p_2} = (x_2 - x_1, y_2 - y_1), \overline{p_1p_3} = (x_3 - x_1, y_3 - y_1) p1p2=(x2x1,y2y1),p1p3=(x3x1,y3y1)

   一旦我们有了两个两个向量,我们就可以调用cross_product来计算叉积,如下面的代码所示。

# returns the cross product of vector p1p3 and p1p2
# if p1p3 is clockwise from p1p2 it returns +ve value
# if p1p3 is anti-clockwise from p1p2 it returns -ve value
# if p1 p2 and p3 are collinear it returns 0
def direction(p1, p2, p3):return  cross_product(p3.subtract(p1), p2.subtract(p1))

三、旋转方向判别

3.1 左转

   判断一个段是否 p 2 p 3 p_2p_3 p2p3从路段左转 p 1 p 2 p_1p_2 p1p2在点 p 2 p_2 p2,我们画下一个向量 p 1 p 3 ‾ \overline{p_1p_3} p1p3并检查新向量是否与向量逆时针方向 p 2 p 3 ‾ \overline{p_2p_3} p2p3。如下图所示。右图显示向量
在这里插入代码片在这里插入图片描述

   p 1 p 3 ‾ \overline{p_1p_3} p1p3从向量逆时针方向 p 1 p 2 ‾ \overline{p_1p_2} p1p2因此我们可以说该段p2p3
从路段左转p1p2在点p2。下面给出了 python 实现。

# checks if p3 makes left turn at p2
def left(p1, p2, p3):return direction(p1, p2, p3) < 0

3.2 右转

   这与左转相同,唯一的区别是向量 p 1 p 3 ‾ \overline{p_1p_3} p1p3从向量顺时针方向 p 2 p 3 ‾ \overline{p_2p_3} p2p3。下面给出了 python 实现。

# checks if p3 makes right turn at p2
def right(p1, p2, p3):return direction(p1, p2, p3) > 0

3.3 共线判别

   当该方法direction既不返回正值也不返回负值而是返回零时,就会出现一种特殊情况。在这种情况下,所有的点 p 1 p_1 p1, p 2 p_2 p2 p 3 p_3 p3位于同一条线上。在本例中段 p 2 p 3 p_2p_3 p2p3不转向任何方向。

# checks if p1, p2 and p3 are collinear
def collinear(p1, p2, p3):return direction(p1, p2, p3) == 0

参考
Cormen, TH、Leiserson, CE、Rivest, RL 和 Stein, C.(nd)。算法简介(第三版)。麻省理工学院出版社。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/466198.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【芯片设计- RTL 数字逻辑设计入门 12 -- verilog 有符号数加减法】

文章目录 多功能数据处理器描述verilog 无符号数与有符号数8d100 8d1558d100 8d1568d100 8d157verilog 代码实现TestBench 代码VCS 仿真结果 多功能数据处理器描述 根据指示信号select的不同&#xff0c;对输入信号a,b实现不同的运算。输入信号a,b为8bit有符号数&#xff1…

【后端高频面试题--Linux篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;后端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 后端高频面试题--Linux篇 Windows和Linux的区别&#xff1f;Unix和Linux有什么区别&#xff1f…

[Python进阶] 制作动态二维码

11.1 制作动态二维码 二维码&#xff08;QR code&#xff09;是一种二维条形码&#xff08;bar code&#xff09;&#xff0c;它的起源可以追溯到20世纪90年代初。当时&#xff0c;日本的汽车工业开始使用一种被称为QR码的二维条码来追踪汽车零部件的信息。 QR码是Quick Respo…

i.MX6ULL 嵌入式学习(一)

i.MX6ULL 嵌入式学习(一) i.MX6ULL理论知识 i.MX6ULL 嵌入式学习(一)进程psipc 进程间通信管道信号(类似中断)system-V 消息队列system-V 信号量system-V 共享内存 进程 创建进程(复制)&#xff0c;同程序 fork #include<unistd.h> a. 返回值 成功 0 或 非负非零整数( 父…

红队打靶练习:DEVGURU: 1

目录 信息收集 1、arp 2、nmap 3、dirsearch WEB web信息收集 8585端口 漏洞利用 提权 系统信息收集 横向渗透 get flag 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:50:56:20:80:1b, IPv4: 192.168.10…

【Linux学习】线程详解

目录 十八.多线程 18.1 线程与进程 18.2 内核视角看待创建线程与进程 18.3 线程优缺点总结 线程的优点&#xff1a; 线程的缺点&#xff1a; 线程的用途&#xff1a; 18.4 线程与进程的联系 十九.线程控制 19.1 POSIX线程库 19.2 线程创建 19.3 线程等待 19.4 线程终止 19.5 线…

python -m SimpleHTTPServer mac报错

错误内容&#xff1a; Traceback (most recent call last):File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 174, in _run_module_as_main"__main__", fname, loader, pkg_name)File "/System/Libra…

Uniapp真机调试:手机端访问电脑端的后端接口解决

Uniapp真机调试&#xff1a;手机端访问电脑端的后端接口解决 1、前置操作 HBuilderX -> 运行 -> 运行到手机或模拟器 -> 运行到Android App基座 少了什么根据提示点击下载即可 使用数据线连接手机和电脑 手机端&#xff1a;打开开发者模式 -> USB调试打开手机端&…

前端面试题——JS实现反转链式表

前言 反转单向链表就是将整个单链表的数据进行倒序的过程。 例如&#xff0c;如果反转之前的单链表是0->1->2->3&#xff0c;那么反转之后的单链表应该是3->2->1->0。这个操作通常是通过改变链表中每个节点的指针方向来实现的&#xff0c;即让每个节点的指…

HCIA-HarmonyOS设备开发认证V2.0-3.2.轻量系统内核基础-中断管理

目录 一、中断基础概念二、中断管理使用说明三、中断管理模块接口四、代码分析&#xff08;待续...&#xff09; 一、中断基础概念 在程序运行过程中&#xff0c;出现需要由 CPU 立即处理的事务时&#xff0c;CPU 暂时中止当前程序的执行转而处理这个事务&#xff0c;这个过程…

KingSCADA实现按钮点击效果

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 在做SCADA项目的时候&#xff0c;按钮是不可缺少的功能&#xff0c;但软件自带的按钮太丑&#xff0c;已经无法满足现如今客户对界面美观度的要求。 这时候就需要UI小姐姐设计美观大气的SCADA界面&#xff0c;但UI设计…