线段与多边形的关系

转自周见智

介绍

最近项目中要用到有关几何(Geometry)方面的知识,程序需要判断给定的一条线段(Segment)与指定多边形(Polygon)的位置关系。这种关系分为三种:多边形包含线段、多边形与线段相交以及多边形与线段无关联。

起初我以为.NET类库中已经包含此种判定功能的API,比如类似System.Drawing.Region这些类型,后来等到实际要用的时候才发现根本就没这种“高级”算法。

没办法,只能自己去写代码实现。后来在stackoverflow(链接)上找到了一个解决方案,不过都是源代码,并没有详细的说明。本文参照原作者提供的源码,进行详细的说明。如果你只需要最终答案,可以不用阅读本文所有内容,文章最后会给出判断源代码,很简答使用,就一个方法,代入参数直接调用即可,但如果你想搞清楚怎么回事,那么可以静下心来看看本文全部内容,虽然比较复杂,但是相信一定会有所收获的。

 

解决思路

线段与多边形的关系只有三种:无关联、相交以及包含。我们可以分以下两步来进行分析:

  • 判断线段与多边形的各条边是否相交,若是,则线段与多边形属于“相交”关系;
  • 如果线段与多边形的任何边都不相交,那么我们接着判断线段的任意一个端点是否在多边形内部,若是,则整条线段肯定在多边形内(即“包含”关系);若不是,则整条线段肯定都在多边形外部(即“无关联”关系)。

上面两步看似简单,实质相当复杂。判断线段与多边形各条边的关系涉及到了“线段与线段关系的判断”、判断线段任意一个端点是否在多边形内部涉及到了“点与线段关系的判断”,总之,要解决大问题必须先解决一些小问题:

  • 点与线段的关系
  • 线段与线段的关系
  • 点与多边形的关系

下面依次介绍以上三个小问题的解决方法。

 

问题一:点与线段的关系

点与线段只有两种关系:

  • 点在线段上
  • 点与线段无关联

这种判断方法很简单,只要我们能确保给定点P的Y坐标在线段AB两个端点的Y坐标之间(或者点P的X坐标在两个端点的X坐标之间也行),并且点P与线段AB任意端点间的斜率与AB线段斜率相等即可说明点P在线段AB上。

如上图,如果Y2<Y<Y1且K==K1,则说明点P在线段AB上;否则,点P与线段AB无关联。

 

问题二:线段与线段的关系

线段与线段也只有两种关系:

  • 两线段相交
  • 两线段无关联

这种判断稍微复杂一些,为了更方便计算,涉及到了“平移”、“旋转”等操作。给定线段AB和CD,先将两线段整体平移(注意是整体),让线段AB的A端点与原点(0,0)重合,接着将两线段整体旋转(注意是整体),让线段AB与X轴的正方向重合。

如上图,将任意两线段AB和CD按照“先整体平移,再整体旋转”的顺序操作一遍,最终让线段AB的A端点与原点(0,0)重合,并让线段AB与X轴正方向重合。很显然,任意线段均可以进行以上操作。接下来,再在此基础上进行判断就比较简单了,如果线段CD的两个端点C和D的Y坐标均大于零(分布在第一、二象限)或者均小于零(分布在第三、四象限),那么AB与CD肯定不相交,换句话说,CD的两个端点必须一个在X轴上方另一个在X轴下方时,两条线段才有可能相交。如果线段CD的端点确实是一个在X轴上方一个在X轴下方,接下来再计算直线AB和直线CD(注意这里说的是直线)的交点(这时候两条直线一定有交点,并且交点在X轴上),这里暂定交点为P,如果P在X轴的负方向上(P.X<0),那么说明线段AB和CD不相交,如果P在X轴正方向但是P的X坐标大于线段AB的长度,那么说明线段AB和CD也不相交,其他情况下,线段AB和CD才属于“相交”关系。

 

问题三:点与多边形的关系

点与多边形有三种关系:

  • 点与多边形无关联
  • 点在多边形上(某条边上)
  • 点在多边形内部

判断点是否在多边形上需要用到解决问题一的方法,即判断点与线段的关系。如果点不在多边形上,那么需要判断它在多边形内部还是外部,这个判断方法说难也不难,说不难也挺难的。事实上,只需要判断点在多边形每条边的左边还是右边(注意这里的左边和右边定义,见下图)

如上图,多边形ABCDE在右侧光源的照射下,它的每条边(如AB、BC等)都会与Y轴上各自的投影(如A`B`、B`C`等)之间形成一个梯形区域,如ABB`A`、BCC`B`等。我们只需要统计给定点P在这些梯形区域中的次数,若点P在某条边对应的梯形区域内,那么计数N加1,最后看N是否为偶数,如果N为偶数(包括0),那么说明点P不在多边形内部;否则,点P在多边形内部。上图中P1的计数N==1(只在ABB`A`内部),所以点P1在多边形ABCDE内部,而点P2的计数N==2(同时在AEE`A`和BCC`B`内部),所以点P2不在多边形ABCDE内部,同理,点P3的计数N==0,所以它也不在多边形内部。

 

转载于:https://www.cnblogs.com/P3nguin/p/9379654.html

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

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

相关文章

解决,文件上传到 ftp 服务器,中文出现乱码问题

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 上传到 ftp 服务器&#xff0c;中文出现乱码解决&#xff0c;之前文件名 “ 网关信息 ” 始终不能正确显示&#xff0c;尝试了多种编码…

常用负载均衡策略分析

背景 一般生产环境单机所能承受的QPS压力为2w左右&#xff0c;过大的压力会导致服务器爆炸。即便是单机能够撑住2w QPS&#xff0c;一般也不会这么做&#xff0c;生产环境一般会预留50%的冗余能力&#xff0c;防止QPS因为某个热门的活动而爆炸。当QPS超过单机所能承受的压力时&…

解决- SecureCRT上运行 linux vim 命令中文出现乱码

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 乱码如图&#xff1a; 这个问题是CRT的编码设置造成的&#xff0c;改一下设置就可以了&#xff1a; 1. 在当前连接上右键选择最后一个 2…

linux中操作数据库的使用命令记录

1&#xff0c;mysql 查看数据库表编码格式&#xff1a; show create table widget; 修改数据库表编码格式&#xff1a; alter table widget default character set utf8; 修改数据库表中某字段的编码格式&#xff1a; alter table widget change widget_name widget_name varc…

ICC Scenario Definition

现代先进工艺下的后端设计都是在 MCMM 情况下设计的&#xff0c;所谓 MCMM 就是 muti-corner muti-mode&#xff0c;用于芯片的不同工作模式和工作条件。 后端设计过程中&#xff0c;需要保证芯片在所有工作模式和工作条件下都能正常工作&#xff0c;工作模式一般只有几种&…

持续集成与持续部署宝典Part 2:创建持续集成流水线

2019独角兽企业重金招聘Python工程师标准>>> 在本系列文章中&#xff0c;我们将探讨在容器时代如何在基于Docker的环境中创建连贯的工作流程和流水线来简化大规模项目的部署。另外&#xff0c;我们还将详细介绍如何利用Docker和Rancher自动化处理这些工作流。 在上文…

64 装饰器函数: 母版 csrf防御机制 cookie

主要内容: 1: 装饰器函数 a: 原理: 在不改变原函数的代码和调用方式的情况下, 给函数动态的添加功能 b: 实例: 装饰器的原理: def yue(tools):print(使用%s约一约 % tools) def wrapper(fn):def inner(*args, **kwargs):print(先准备好钱)fn(*args, **kwargs)return inner yue …

Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 方案一&#xff1a;用Eclipse自带的Export功能 步骤1&#xff1a;准备主清单文件 “MANIFEST.MF”&#xff0c; 由于是打包引用了第三…

一个判断session是否过期的小技巧

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Session一直是我们做web项目经常使用的&#xff0c;以前没太注意&#xff0c;这次又细致的看了下&#xff01; 1.session其实就是一个Ma…

jQuery基础-事件

只能添加一个处理函数&#xff0c;后面的会覆盖前面 会有兼容性差异 冒泡 会依次检查父元素 截获冒泡 或者 最大的缺陷 并且在IE和NetSpace里面分别为冒泡和捕获两种 多个处理函数 依次执行 捕获--->自己--->冒泡 true 只捕获&#xff0c;不冒泡 false 只冒泡 从父元素的…

别的AI还在打游戏,这个AI已经当上“超级马里奥”游戏策划了|GECCO最佳论文

AI打游戏已经不是什么新鲜事了&#xff0c;“沉迷”Dota 2、星际争霸、LOL的AI一个接一个的出现。 但是你也许不知道&#xff0c;相比这些“游戏玩家”AI&#xff0c;还有一位优秀的AI&#xff0c;直接当起了“游戏策划”&#xff0c;做的还是脍炙人口的“超级马里奥”。 &…

单点登录的三种实现方式

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 单点登录SSO&#xff08;Single Sign On&#xff09;说得简单点就是在一个多系统共存的环境下&#xff0c;用户在一处登录后&#xff0c;…

java对象占用内存大小?

一个不包含任何内部成员变量的空Object大约占33byte&#xff0c;若增加成员变量&#xff0c;则增加相应大小的内存占用。 测算方式&#xff1a;设置jvm的堆大小为1m&#xff0c;在堆中不停new不含任何成员变量的OOMObject对象&#xff0c;直到堆内存溢出。如下图&#xff0c;在…

Java程序员面试中的多线程问题

很多核心Java面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework)&#xff0c;理解核心线程概念时&#xff0c;娴熟的实际经验是必需的。这篇文章收集了 Java 线程方面一些典型的问题&#xff0c;这些问题经常被高级工程师所问到。 0.Java 中多线程同步是什…

单点登录原理与简单实现

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构&#xff0c;http作为通信协议。http是无状态协议&#xff0c;浏…

java接口类支持多继承

一个类只能extends一个父类&#xff0c;只能有一个父类&#xff0c;但可以implements多个接口。java通过使用接口的概念来取代C中多继承。与此同时&#xff0c;一个接口则可以同时extends多个接口&#xff0c;却不能implements任何接口。Java中的接口是支持多继承的。

xmind-HTTP协议

转载于:https://www.cnblogs.com/margot921/p/9764788.html

弹性布局

弹性布局 一、Flex布局是什么&#xff1f; Flex是Flexible Box的缩写&#xff0c;意为”弹性布局”&#xff0c;用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。 二、基本概念 采用Flex布局的元素&#xff0c;称为Flex容器&#xff08;flex container&…

解决dataTable 报错:cannot read property “style“ of undefined

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 其实这错&#xff0c;我之前也遇到过&#xff0c;只是太久了&#xff0c;没有记录下来&#xff0c; 今天看到群里朋友也遇到这个错误&a…

万恶之源 - Python基础数据类型一

整数 整数在Python中的关键字用int来表示; 整型在计算机中运于计算和比较 在32位机器上int的范围是: -2**31&#xff5e;2**31-1&#xff0c;即-2147483648&#xff5e;2147483647 在64位机器上int的范围是: -2**63&#xff5e;2**63-1&#xff0c;即-9223372036854775808&…