判断一个点是否在一个多边形内部

1 原理

如下图所示, 四边形ABCD, P在四边形内部,Q在四边形外部。

在这里插入图片描述
通过观察可以发现, 当点在四边形内部时, 如果按顺时针方向的话, 点P在四条边AB, BC, CD, DA的右侧。 当然如果按逆时针的话, 点P在四条边的左侧。
点Q在AB,BC和CD的右侧, 但在DA的左侧。因此可以通过方向的一致性判断点是否位于多边形内部。

判断方向可以通过向量的叉积运算。

A B ⃗ \vec{AB} AB x A P ⃗ \vec{AP} AP , B C ⃗ \vec{BC} BC x B P ⃗ \vec{BP} BP , C D ⃗ \vec{CD} CD x C P ⃗ \vec{CP} CP , D A ⃗ \vec{DA} DA x D P ⃗ \vec{DP} DP 如果同方向, 那么P点就在多边形内部,否则就不在内部。

向量叉乘的结果是一个向量, 二维向量叉乘时, 结果向量的方向垂直于这2个向量。
其实不必要求是顺时针方向, 逆时针也可以, 逆时针顺序时4个向量叉积就都是小于0了。 因此只要4个向量叉乘是同时为正, 或同时为负就行。

2 向量叉积

假设有2个向量 a ⃗ = ( x 1 , y 1 ) \vec{a}=(x_1, y_1) a =(x1,y1), b ⃗ = ( x 2 , y 2 ) \vec{b}=(x_2,y_2) b =(x2,y2), a ⃗ \vec{a} a b ⃗ \vec{b} b 的叉积是一个向量,方向垂直于 a ⃗ \vec{a} a b ⃗ \vec{b} b 所在的平面, 遵循右手法则。

a ⃗ \vec{a} a x b ⃗ \vec{b} b = 0 i ⃗ + 0 j ⃗ + ( x 1 y 2 − x 2 y 1 ) k ⃗ 0\vec{i}+0\vec{j}+(x_1y_2-x_2y_1)\vec{k} 0i +0j +(x1y2x2y1)k

在这里插入图片描述

3 一些思考

其实最开始观察时, 发现了另外一个规律仿佛也奏效, 那就是 A B ⃗ \vec{AB} AB A P ⃗ \vec{AP} AP , B C ⃗ \vec{BC} BC B P ⃗ \vec{BP} BP , C D ⃗ \vec{CD} CD C P ⃗ \vec{CP} CP , D A ⃗ \vec{DA} DA D P ⃗ \vec{DP} DP 夹角都是小于90度的, 对Q点对应的向量夹角, 有些是小于90度, 有些是大于90度的, 那么通过向量的内积也可以判断。其实这个规律不是普世的, 可以举出反例, P点在多边形内部时, 也会出现同时有大于90度和小于90度的角。
如下图所示:
在这里插入图片描述
D A ⃗ \vec{DA} DA D P ⃗ \vec{DP} DP 夹角是大于90度的, 而其他向量夹角是小于90度的。

上面的判断方法(指的是根据向量外积), 只适用于任意的凸多边形, 对非凸多边形是不适用的。
在这里插入图片描述
如上图所示, 对于非凸多边形, C D ⃗ \vec{CD} CD x C P ⃗ \vec{CP} CP 的方向与其他向量就不同。

4 代码实现

import numpy as npdef isPointInArea(point, area):""":param point: [x,y]:param area: [[x1,y1],[x2,y2],[x3,y3],...]:return: if point is in area, return True, else False"""area_point_num = len(area)if area_point_num < 3:raise ValueError(f"the point number of the area must >=3, but get {area_point_num}")area.append(area[0])area = np.asarray(area)orientations = []xp, yp = point[0], point[1]for index in range(area_point_num):a = area[index + 1] - area[index]b = (xp - area[index, 0], yp - area[index, 1])ori = a[0] * b[1] - b[0] * a[1]orientations.append(ori)orientations = np.asarray(orientations)flags = orientations > 0if flags.sum() == area_point_num or flags.sum() == 0:return Trueelse:return Falseif __name__ == "__main__":point = [0.5, 1.5]area = [[0, 0], [0, 2], [2, 2], [2, 0]]flag = isPointInArea(point, area)print(flag)

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

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

相关文章

为什么客户跟踪对客户成功很重要?如何正确做到这一点?

如果您想以客户为中心&#xff0c;了解您的客户就非常重要。您可以利用客户沟通管理平台&#xff0c;例如SaleSmartly&#xff08;SS客服&#xff09;查看各种指标来了解客户对您的实际体验以及他们对您的期望。您需要长时间跟踪它们&#xff0c;注意它们的变化并找出原因&…

vue-elementPlus自动按需导入和主题定制

elementPlus自动按需导入 装包 -> 配置 1. 装包&#xff08;主包和两个插件包&#xff09; $ npm install element-plus --save npm install -D unplugin-vue-components unplugin-auto-import 2. 配置 在vite.config.js文件中配置&#xff0c;配置完重启&#xff08;n…

[国产MCU]-W801开发实例-MQTT客户端通信

MQTT客户端通信 文章目录 MQTT客户端通信1、MQTT介绍2、W801的MQTT客户端相关API介绍3、代码实现本文将详细介绍如何在W801中使用MQTT协议通信。 1、MQTT介绍 MQTT 被称为消息队列遥测传输协议。它是一种轻量级消息传递协议,可通过简单的通信机制帮助资源受限的网络客户端。 …

【笔试强训选择题】Day36.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01; 文章目录 前言一、Day…

【每日运维】RockyLinux8.6升级OpenSSH9.4p1

为什么需要升级openssh呢&#xff0c;因为很多项目进行漏扫结果都会涉及到这个服务器核心组件&#xff0c;一想到以前升级openssh带来的各种依赖性问题就头疼&#xff0c;不管是什么发行版&#xff0c;升级这个东西真的很烦&#xff0c;这次发现可能还会有好一点的通用一点的升…

GUIslice Builder 安装及使用

GUIslice Builder是一个可视化UI设计工具&#xff0c;可以简化GUIslice的UI设计流程。下面是GUIslice Builder的安装和使用步骤&#xff1a; 首先&#xff0c;下载GUIslice Builder并解压缩文件。 然后&#xff0c;进入解压后的文件夹&#xff0c;并运行GUIsliceBuilder.exe。…

SpringBoot项目--电脑商城【用户注册】

1.创建数据表 1.1 创建t_user表 CREATE TABLE t_user (uid INT AUTO_INCREMENT COMMENT 用户id,username VARCHAR(20) NOT NULL UNIQUE COMMENT 用户名,password CHAR(32) NOT NULL COMMENT 密码,salt CHAR(36) COMMENT 盐值,phone VARCHAR(20) COMMENT 电话号码,email VARCH…

自然语言处理(七):来自Transformers的双向编码器表示(BERT)

来自Transformers的双向编码器表示&#xff08;BERT&#xff09; BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种预训练的自然语言处理模型&#xff0c;由Google于2018年提出。它是基于Transformer模型架构的深度双向&#xff0…

Linux学习之MySQL连接查询

接上一篇 连接查询 连接查询也中多表查询&#xff0c;常用于查询来自于多张表的数据&#xff0c;通过不同的连接方式把多张表组成一张新的临时表&#xff0c;再对临时表做数据处理。 #表基础信息&#xff0c;内容可从上一篇博客中查看 mysql> desc departments; ---------…

方案展示 | RK3588开发板Linux双摄同显方案

iTOP-RK3588开发板使用手册更新&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 RK3588开发板载4路MIPI CAMERA摄像头接口、MIPI CSI DPHY的4.5Gbps、2.5Gops的MIPI CSI CPHY&#xff0c;四路同时输入&#xf…

Java“牵手”唯品会商品列表数据,关键词搜索唯品会商品数据接口,唯品会API申请指南

唯品会商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取唯品会商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问唯品会商城的网页来获取商品详情信息。以下是两种常用方法的介…

生成式人工智能能否使数字孪生在能源和公用事业行业成为现实?

推荐&#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 克服障碍&#xff0c;优化数字孪生优势 要实现数字孪生的优势&#xff0c;您需要数据和逻辑集成层以及基于角色的演示。如图 1 所示&#xff0c;在任何资产密集型行业&#xff08;如能源和公用事业&#xff09;中&…