Qt判断一个点在多边形内还是外(支持凸边形和凹变形)
这里实现的方法是转载于https://blog.csdn.net/trj14/article/details/43190653和https://blog.csdn.net/WilliamSun0122/article/details/77994526
来实现的,并且按照Qt的规则进行了调整。
以下实现方法有四种,每种方法的具体讲解在转载的博客中有说明,这里不做重复阐述。
这里只说下代码的具体实现和每种方法的时间复杂度。
强烈推荐第一种方法,其它三种针对一些特殊图形或多或少都有一些问题。
方法一:射线法
时间复杂度:O(n) 。
适用范围:任意多边形。
优点:不需考虑精度误差和多边形点给出的顺序。
算法思想:以被测点Q为端点,向任意方向作射线(一般水平向右作射线),统计该射线与多边形的交点数。如果为奇数,Q在多边形内;如果为偶数,Q在多边形外。计数的时候会有一些特殊情况,如图
//判断点P在多边形内-射线法
bool Widget::InsidePolygon( QVector<QPointF> polygon,QPointF pt )
{int i,j;bool inside,redo;int N = polygon.size();redo = true;for (i = 0;i < N;++i){// 是否在顶点上if (polygon[i].x() == pt.x() && polygon[i].y() == pt.y()){redo = false;inside = true;break;}}while (redo){redo = false;inside = false;for (i = 0,j = N - 1;i < N;j = i++){if ( (polygon[i].y() < pt.y() && pt.y() < polygon[j].y()) ||(polygon[j].y() < pt.y() && pt.y() < polygon[i].y()) ){if (pt.x() <= polygon[i].x() || pt.x() <= polygon[j].x()){double _x = (pt.y()-polygon[i].y())*(polygon[j].x()-polygon[i].x())/(polygon[j].y()-polygon[i].y())+polygon[i].x();if (pt.x() < _x) // 在线的左侧inside = !inside;else if (pt.x() == _x) // 在线上{inside = true;break;}}}else if ( pt.y() == polygon[i].y()){if (pt.x() < polygon[i].x()) // 交点在顶点上{if (polygon[i].y() > polygon[j].y())pt.setY(pt.y() - 1);elsept.setY(pt.y() + 1);redo = true;break;}}else if ( polygon[i].y() == polygon[j].y() && pt.y() == polygon[i].y() &&((polygon[i].x() < pt.x() && pt.x() < polygon[j].x()) ||(polygon[j].x() < pt.x() && pt.x() < polygon[i].x())) )// 在水平的边界线上{inside = true;break;}}}return inside;
}
方法二:面积和判别法
时间复杂度:大于O(n)。
适用范围:所有凸边形,部分凹变形。
优点:算法简单。
缺点:有精度要求,强调多边形点给出的方向(逆时针)。
算法思想:如果点在多边形内部或者边上,那么点与多边形所有边组成的三角形面积和等于多边形面积。多边形的面积可以用叉积计算即连接坐标原点和各顶点形成向量,所有向量叉积的0.5的和即为多边形面积。不过计算面积是会有一定误差的,需要设置精度的误差范围。
//面积和判别法
bool InsidePolygon3( QVector<QPointF> polygon,QPointF pt )
{int i,j;bool inside = false;double polygon_area = 0;double trigon_area = 0;int N = polygon.size();for (i = 0,j = N - 1;i < N;j = i++){polygon_area += polygon[i].x() * polygon[j].y() - polygon[j].x() * polygon[i].y();trigon_area += abs(pt.x() * polygon[i].y() -pt.x() * polygon[j].y() -polygon[i].x() * pt.y() +polygon[i].x() * polygon[j].y() +polygon[j].x() * pt.y() -polygon[j].x() * polygon[i].y());}trigon_area *= 0.5;polygon_area = abs(polygon_area * 0.5);if ( fabs(trigon_area - polygon_area) < 1e-7 )inside = true;return inside;
}
方法三:点线判别法
时间复杂度:O(n)。
适用范围:所有凸边形,部分凹变形。
算法思想:对于多边形(正向,即逆时针),如果一个点它的所有有向边的左边,那么这个点一定在多边形内部。利用叉积正好可以判断点与给定边的关系,即点是在边的左边右边还是边上。
//点线判别法
bool InsidePolygon4( QVector<QPointF> polygon,QPointF p )
{int i,j;bool inside = false;int count1 = 0;int count2 = 0;int N = polygon.size();for (i = 0,j = N - 1;i < N;j = i++){double value = (p.x() - polygon[j].x()) * (polygon[i].y() - polygon[j].y()) - (p.y() - polygon[j].y()) * (polygon[i].x() - polygon[j].x());if (value > 0)++count1;else if (value < 0)++count2;}if (0 == count1 ||0 == count2){inside = true;}return inside;
}
方法四:角度和判别法
时间复杂度:O(n)。
适用范围:所有凸边形,部分凹变形。
优点:不强调多边形点给出顺序。
缺点:这个算法对精度的要求很高(会造成很大精度误差)。
算法思想:连接被测点与多边形所有顶点所形成的所有角的角度和在精度范围内等于则该点在多边形内,否则在多边形外。
// 根据需要不判断顶点
bool IsPointInLine( QPointF &pt,QPointF &pt1,QPointF &pt2 )
{bool inside = false;if (pt.y() == pt1.y() &&pt1.y() == pt2.y() &&((pt1.x() < pt.x() && pt.x() < pt2.x()) ||(pt2.x() < pt.x() && pt.x() < pt1.x())) ){inside = true;}else if (pt.x() == pt1.x() &&pt1.x() == pt2.x() &&((pt1.y() < pt.y() && pt.y() < pt2.y()) ||(pt2.y() < pt.y() && pt.y() < pt1.y())) ){inside = true;}else if ( ((pt1.y() < pt.y() && pt.y() < pt2.y()) ||(pt2.y() < pt.y() && pt.y() < pt1.y())) &&((pt1.x() < pt.x() && pt.x() < pt2.x()) ||(pt2.x() < pt.x() && pt.x() < pt1.x())) ){if (0 == (pt.y()-pt1.y())/(pt2.y()-pt1.y())-(pt.x() - pt1.x()) / (pt2.x()-pt1.x())){inside = true;}}return inside;
}//角度和判别法
bool InsidePolygon2( QVector<QPointF> polygon,QPointF p)
{int i,j;double angle = 0;bool inside = false;int N = polygon.size();for (i = 0,j = N - 1;i < N;j = i++){if (polygon[i].x() == p.x() && // 是否在顶点上polygon[i].y() == p.y()){inside = true;break;}else if (IsPointInLine(p,polygon[i],polygon[j])) // 是否在边界线上{inside = true;break;}double x1,y1,x2,y2;x1 = polygon[i].x() - p.x();y1 = polygon[i].y() - p.y();x2 = polygon[j].x() - p.x();y2 = polygon[j].y() - p.y();double radian = atan2(y1,x1) - atan2(y2,x2);radian = abs(radian);if (radian > M_PI) radian = 2* M_PI - radian;angle += radian; // 计算角度和}if ( fabs(6.28318530717958647692 - angle) < 1e-7 )inside = true;return inside;
}
相关文章:

Qt判断一个点在多边形内还是外(支持凸边形和凹变形)
这里实现的方法是转载于https://blog.csdn.net/trj14/article/details/43190653和https://blog.csdn.net/WilliamSun0122/article/details/77994526 来实现的,并且按照Qt的规则进行了调整。 以下实现方法有四种,每种方法的具体讲解在转载的博客中有说明&…...
MySQL导入数据库出现 Got error 168 from storage engine错误
“Got error 168 from storage engine” 是 MySQL 数据库的一个错误,通常是由于存储引擎发生了一些问题导致的。这个错误可能有多种原因引起。以下是一些可能的解决方法: 检查硬盘空间:确保目标数据库的服务器有足够的硬盘空间来执行导入操作…...

使用 VS Code 作为 VC6 的编辑器
使用 VS Code 作为 VC 6.0 的编辑器 由于一些众所周知的原因,我们不得不使用经典(过时)的比我们年龄还大的已有 25 年历史的 VC 6.0 来学习 C 语言。而对于现在来说,这个经典的 IDE 过于简陋,并且早已不兼容新的操作系…...

Peter算法小课堂—蠕动区间
蠕动区间 蠕动区间(尺取法、双游标)是一个经典的优化算法。 我们以毛毛虫🐛举例说明 具体的,我们看题目 例题 最小区间 这一题,我们用暴力法,复杂度O(N^2) 先给出暴力法代码 int ansn1; for(int tail…...

Vant和ElementPlus在vue的hash模式的路由下路由离开拦截使用Dialog和MessageBox失效
问题复现 ElementPlus:当点击返回或者地址栏回退时,MessageBox无效 <template><div>Element Plus Dialog 路由离开拦截测试</div><el-button type"primary" click"$router.back()">返回</el-button>…...

上海市通过区块链技术攻关 构建数字经济可信安全技术底座
日前,上海市印发《上海区块链关键技术攻关专项行动方案(2023—2025年)》(以下简称《行动方案》),提出到2025年,在区块链体系安全、密码算法等基础理论以及区块链专用处理器、智能合约、跨链、新…...
Java 面试题
昨天面试了两个Java开发程序员,问了一些问题,回答的不是很好,看看大家的回答如何,可以在评论区回复,测试下自己的水平。 A程序员: 1. 自我介绍一下; 2. 企业级和互联网行业都有那些项目经验,简…...

layui 表格 展开
一、表格嵌套表格(手风琴打开) <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>设备上下线统计</title><script type"text/javascript" src"../../../l…...

[尚硅谷React笔记]——第4章 React ajax
目录: 脚手架配置代理_方法一 server1.js开启服务器server1:App.js解决跨域问题:脚手架配置代理_方法二 server2.js开启服务器server2第一步:创建代理配置文件编写setupProxy.js配置具体代理规则:App.js运行结果&a…...

Richard Stallman 正在与癌症作战
导读为了纪念 GNU 项目成立 40 周年,自由软件基金会(FSF)已计划在 10 月 1 日(即GNU 40)为家庭、学生以及美国的其他人群组织一场黑客马拉松活动。 活动之前,GNU 项目于 9 月 27 日迎来了 40 岁生日&#…...

MathType7.4最新免费版(公式编辑器)下载安装包附安装教程
MathType是一款专业的数学公式编辑器,理科生专用的必备工具,可应用于教育教学、科研机构、工程学、论文写作、期刊排版、编辑理科试卷等领域。可视化公式编辑器轻松创建数学方程式和化学公式。兼容Office Word、PowerPoint、Pages、Keynote、Numbers 等7…...
如何支持h.265视频
前言 略 h.265视频 h.265是一种视频编码格式。 随着视频编码技术的发展,相比H.264, H.265同等画质体积仅为一半、带宽占用省一半、画质更细腻等诸多优势。 但Web浏览器还不支持H.265的解码播放,因此基于Web Assembly(封装FFmpeg)、JS解封装、Canvas投…...
vue 放大镜(简易)
目录 zoom组件 <template><div class"pic-img"><div class"img-container"><img ref"img" load"imgLoaded" :src"url" :style"overlayStyle" error"imgerrorfun"/><div cl…...

【计算机网络】第一章——概述
个人主页直达:小白不是程序媛 系列专栏:计算机网络基础 目录 前言 计算机网络概述 概念 功能 组成 分类 标准化工作 性能指标 速率 带宽 吞吐量 时延 时延带宽积 往返时延RTT 利用率 分层 为什么要分层? 分层的基本原则&am…...

vue实现在页面拖拽放大缩小div并显示鼠标在div的坐标
1、功能要求: 实现在一个指定区域拖拽div,并可以放大缩小,同时显示鼠标在该div里的坐标,如图可示 缩小并拖动 2、实现 <div class"div_content" ref"div_content"><div class"div_image" id"…...
LuatOS-SOC接口文档(air780E)-- io - io操作(扩展)
示例 -- io模块是lua原生模块,LuatOS增加了一些API -- 请配合os模块一起使用-- 只读模式, 打开文件 local fd io.open("/xxx.txt", "rb") -- 读写默认,打开文件 local fd io.open("/xxx.txt", "wb") -- 写入文件,且截断为0字节 loc…...

【数据结构】线性表(六)堆栈:顺序栈及其基本操作(初始化、判空、判满、入栈、出栈、存取栈顶元素、清空栈)
文章目录 一、堆栈1. 定义2. 基本操作 二、顺序栈0. 顺序表1. 头文件和常量2. 栈结构体3. 栈的初始化4. 判断栈是否为空5. 判断栈是否已满6. 入栈7. 出栈8. 查看栈顶元素9. 清空栈10. 主函数11. 代码整合 堆栈Stack 和 队列Queue是两种非常重要的数据结构,两者都是特…...
父组件可以监听到子组件的生命周期吗?
在 Vue 中,父组件是可以监听到子组件的生命周期的。Vue 提供了一些特殊的钩子函数,可以在父组件中监听子组件的生命周期事件。 以下是一些常用的方法来监听子组件的生命周期: 1:使用$emit: 在子组件的生命周期钩子函数中,使用 $emit 方法触发自定义事件,向父组件发送通…...

[开源]MIT开源协议,基于Vue3.x可视化拖拽编辑,页面生成工具
一、开源项目简介 AS-Editor 基于 Vue3.x 可视化拖拽编辑,页面生成工具。提升前端开发效率,可集成至移动端项目作为通过定义 JSON 直接生成 UI 界面。 二、开源协议 使用MIT开源协议 三、界面展示 四、功能概述 基于Vue可视化拖拽编辑,…...
【C++ Primer Plus学习记录】数组的替代品
目录 1.模板类vector 2.模板类array(C11) 3.比较数组、vector对象和array对象 模板类vector和array是数组的替代品。 1.模板类vector 模板类vector类似于string类,也是一种动态数组。您可以在运行阶段设置vector对象的长度,可…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...