清华计算几何-ConvexHull(凸包)-极点InTriangle/ToLeft Test

ConvexHull(凸包)的基本概念

给定一个点集, 求出最外围的点所形成的几何, 就是凸包。如下所示

凸包在计算几何是一个非常基础和核心的一个概念, 很多几何计算算法都围绕凸包展开。

极点和非极点

如上图所示, 蓝图圈圈住的点都是极端点, 极端点具备一个重要的特性:

极点(extremity point): 存在一条经过此点的线L, 把其他所有点列在线L的同一端。

非极点:与极点相反不具备这样的线L.

凸组合(Convex Combination)

也就是说给定一个点集合S,数量为N, 每个点都存在一个权重R(x),

当保证 每个R >= 0 并且 R1 + R2... Rn = 1.0

由计算公式: P = Point1 * R1 +  Point2 * R2 + ... PointN * Rn

求出的点集合为S的凸组合.

凸相关 

某个点加入后,S集合依然不变,则该点和S凸组合是凸相关的,也就是该点原本就在S组合里。

对于1和4构成的S集合, 2和3是凸相关。

凸无关

某个点加入后,S集合发生改变, 则该点和S凸组合是凸无关的。也就是该点原本不在S组合里。

点4的加入使用"1-2-3" S凸组合的范围变大了,因为点4和"1-2-3"凸组合是凸无关的。

ConvexHull(凸包)的求解

流程分解

总结:遍历所有三角形,判断每个点是否在任意一个三角形内。用In-Trignle|InLeft|Determinant叉积。算法复杂度:O(n4)

伪代码全流程

InTrianle测试

ToLeft测试

这里2*S的[1, 1, 1]理解为三维空间中,三个点为同一Z平面。叉积就是带正负的面积。

代码实现求凸包-极点集合(2D)

InTrianleTest + ToLeftTest

给定一个点的集合求所有极点

#include <iostream>
#include <vector>using namespace std;struct Point
{float x;float y;
};float Area2(const Point& inPointA, const Point& inPointB, const Point& inPointC)
{float value =inPointA.x * inPointB.y - inPointA.y * inPointB.x+ inPointB.x * inPointC.y - inPointB.y * inPointC.x+ inPointC.x * inPointA.y - inPointC.y * inPointA.x;return value;
}bool IsLeftTest(const Point& inPointA, const Point& inPointB, const Point& inPointC)
{return Area2(inPointA, inPointB, inPointC) > 0;
}bool IsInTrianle(const Point& inPoint, const Point& triangleA, const Point& triangleB, const Point& triangleC)
{bool bLeftA = IsLeftTest(triangleA, triangleB, inPoint);bool bLeftB = IsLeftTest(triangleB, triangleC, inPoint);bool bLeftC = IsLeftTest(triangleC, triangleA, inPoint);// 取决于CCW/CWreturn (bLeftA == bLeftB) && (bLeftB == bLeftC);
}void GetConvexPointSet(const vector<Point>& inPoints, vector<Point>& outPoints)
{int pointNum = inPoints.size();vector<bool> extrmeFlags;extrmeFlags.resize(pointNum);for (int index = 0; index < pointNum; index++){extrmeFlags[index] = true;}// O(n4)for (int idxA = 0; idxA < pointNum; idxA++){for (int idxB = idxA + 1; idxB < pointNum; idxB++){for (int idxC = idxB + 1; idxC < pointNum; idxC++){for (int s = 0; s < pointNum; s++){if (s == idxA || s == idxB || s == idxC || !extrmeFlags[s])continue;if (IsInTrianle(inPoints[s], inPoints[idxA], inPoints[idxB], inPoints[idxC])){extrmeFlags[s] = false;}}}}}for (int index = 0; index < pointNum; index++){if (extrmeFlags[index]){outPoints.push_back(inPoints[index]);}}}int main()
{std::cout << "Hello World!\n";// point set contructvector<Point> inPoints ={{0, 0},{-1, -1},{5, 2},{4, 5},{3, 3},{-1, 3},{2, 2},{-3, 2},};vector<Point> outPoints;GetConvexPointSet(inPoints, outPoints);for (int index = 0; index < outPoints.size(); index++){printf("(%f, %f)\n", outPoints[index].x, outPoints[index].y);}}
测试结果 

很显然,求的凸包存在问题,遗漏了(-1, -1)

按照InTriangle-ToLeft测试,(-1, -1)(0,0)(2, 2)(3, 3)四个点刚好是位于一条线上,(-1, -1) In-Triangle三次ToLeft都是相同结果,(-1, -1)被认定在三角形[(0,0)(2, 2)(3, 3)]内.

所以得改进In-Triangle测试,判断四点共线的情况。

改进InTrianleTest,消除四点共线

bool IsInTrianle(const Point& inPoint, const Point& triangleA, const Point& triangleB, const Point& triangleC)
{float a_area2 = Area2(triangleA, triangleB, inPoint);float b_area2 = Area2(triangleB, triangleC, inPoint);float c_area2 = Area2(triangleC, triangleA, inPoint);if (a_area2 == 0 && b_area2 == 0 && c_area2 == 0)return false;bool bLeftA = a_area2 > 0;bool bLeftB = b_area2 > 0;bool bLeftC = c_area2 > 0;// 取决于CCW/CWreturn (bLeftA == bLeftB) && (bLeftB == bLeftC);
}
测试结果

资料参考

[1]清华计算几何课程 P1-P13

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

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

相关文章

Vue 3 组合式 API 指南:响应式状态管理与跨组件通信

引言 随着 Vue 3 的发布&#xff0c;Vue 引入了一个新的编程范式——组合式 API&#xff08;Composition API&#xff09;。这一新特性旨在解决 Options API 在处理复杂逻辑时的一些局限性&#xff0c;并提供了一种更灵活、更可重用的方式来组织和重用代码 组合式 API 基础 …

YOLOv10改进 | 特殊场景检测篇 | 单阶段盲真实图像去噪网络RIDNet辅助YOLOv10图像去噪(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是单阶段盲真实图像去噪网络RIDNet&#xff0c;RIDNet&#xff08;Real Image Denoising with Feature Attention&#xff09;是一个用于真实图像去噪的卷积神经网络&#xff08;CNN&#xff09;&#xff0c;旨在解决现有去噪方法在处理…

c# 容器变换

List<Tuple<int, double, bool>> 变为List<Tuple<int, bool>>集合 如果您有一个List<Tuple<int, double, bool>>并且您想要将其转换为一个List<Tuple<int, bool>>集合&#xff0c;忽略double值&#xff0c;您可以使用LINQ的S…

卷积神经网络-猫狗识别实战

课程来自bilibiliMomodel平台 全长只有两个小时&#xff0c;理论部分讲得很粗糙 1 人的视觉和计算机视觉 人的大脑&#xff1a;神经元细胞&#xff0c;轴突发送信号&#xff0c;树突接收信号&#xff0c;互相连接&#xff0c;连接的强度和状态会随着新的经历刺激而变化。 用…

server nat表和会话表的作用及NAT地址转换详细

本章节主要讲nat技术的基础 -会话表的建立也是看5元组 -状态检测技术的回包一样也看5元组&#xff0c;但是状态检测技术会看的除开5元组还有更多东西 老哥&#xff0c;你真的应该好好注意一个东西&#xff1a;我们的会话表只是为了后续包的转发&#xff0c;会话表是记录的首…

【机器学习】和【人工智能】在航空航天中的应用

作者主页: 知孤云出岫 目录 引言机器学习和人工智能在航空航天中的应用1. 预测性维护2. 飞行路径优化3. 自动驾驶飞行器 未来展望1. 增强人机协作2. 更智能的空中交通管理3. 高效的航空制造 结论参考文献 引言 随着科技的迅猛发展&#xff0c;机器学习和人工智能&#xff08;…

【python报错已解决】 “Invalid Array Index“

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法&#xff1a;2.1 方法一&#xff1a;检查索引范…

win32:第一个窗口程序-应用程序入口点(part.6)

第一个窗口程序的最后一部分&#xff1a;应用程序入口函数wWinMain&#xff1b;这是Windows应用程序的主函数&#xff0c;负责初始化应用程序、注册窗口类、创建主窗口并进入消息循环处理消息。 int APIENTRY wWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInst…

pytorch说明

深度学习中的重要概念&#xff1a; 激活函数&#xff1a; 激活函数的必要性&#xff1a;激活函数不是绝对必须的&#xff0c;但在深度学习中&#xff0c;它们几乎总是被使用。激活函数可以引入非线性&#xff0c;这使得神经网络能够学习更复杂的模式。 激活函数的位置&#x…

Linux C++ 053-设计模式之模板方法模式

Linux C 053-设计模式之模板方法模式 本节关键字&#xff1a;Linux、C、设计模式、模板方法模式 相关库函数&#xff1a; 概念 模板方法模式定义了一个算法的步骤&#xff0c;并允许子类别为一个或多个步骤提供其实践方式。让子类别在不改变算法架构的情况下&#xff0c;重新…

用HTML和CSS实现提示工具(tooltip)及HTML元素的定位

所谓提示工具&#xff0c;是指将鼠标移动到某个HTML元素&#xff08;工具&#xff09;时会显示一些提示内容&#xff08;提示文本&#xff09;&#xff0c;而鼠标移出工具元素的范围时提示文本就消失了。考虑到提示文本元素应当在鼠标进入工具元素时显示&#xff0c;鼠标离开工…

Mac安装stable diffusion 工具

文章目录 1.安装 Homebrew2.安装 stable diffusion webui 的依赖3.下载 stable diffusion webui 代码4.启动 stable diffusion webui 本体5.下载模型6.这里可能会遇到一个clip-vit-large-patch14报错 参考&#xff1a;https://brew.idayer.com/install/stable-diffusion-webui/…

Docker 部署 Nginx 并在容器内配置申请免费 SSL 证书

文章目录 dockerdocker-compose.yml申请免费 SSL 证书请求头参数带下划线 docker https://hub.docker.com/_/nginx docker pull nginx:1.27注&#xff1a; 国内网络原因无法下载镜像&#xff0c;nginx 镜像文件下载链接 https://pan.baidu.com/s/1O35cPbx6AHWUJL1v5-REzA?pw…

STM32入门开发操作记录(二)——LED与蜂鸣器

目录 一、工程模板二、点亮主板1. 配置寄存器2. 调用库函数 三、LED1. 闪烁2. 流水灯 四、蜂鸣器 一、工程模板 参照第一篇&#xff0c;新建工程目录ProjectMould&#xff0c;将先前打包好的Start&#xff0c;Library和User文件^C^V过来&#xff0c;并在Keil5内完成器件支持包的…

从零开始实现大语言模型(六):因果注意力机制

1. 前言 因果注意力机制(causal attention)是一种特殊的自注意力机制,其在计算context向量 z i z_i zi​

jenkins系列-01.docker安装jenkins

进入官网&#xff1a;https://www.jenkins.io/ 使用LONG term support版本&#xff1a;2.387.1 docker pull jenkins/jenkins:2.387.1-lts 拉取镜像&#xff1a; 编写docker-compose文件&#xff1a; 启动jenkins: 查看启动日志&#xff1a; 默认生成的密码&#xff1a;…

基于springboot+vue+uniapp的超市购物系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

LeetCode 142.环形链表2 C写法

LeetCOde 142.环形链表2 C写法 思路1&#x1f914;&#xff1a; ​ 用环形链表的方法&#xff0c;快慢指针找到slow和fast的相遇点&#xff0c;此时头到入口点的位置与相遇点到入口点的距离一样。 ​ 我们假设头到入口点的长度为L&#xff0c;环的长度为C&#xff0c;相遇点到入…

Rust 测试的组织结构

测试的组织结构 本章一开始就提到&#xff0c;测试是一个复杂的概念&#xff0c;而且不同的开发者也采用不同的技术和组织。Rust 社区倾向于根据测试的两个主要分类来考虑问题&#xff1a;单元测试&#xff08;unit tests&#xff09;与 集成测试&#xff08;integration test…

负荷预测 | Matlab基于Transformer-LSTM多变量时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于Transformer-LSTM多变量时间序列多步预测&#xff1b; 2.多变量时间序列数据集&#xff08;负荷数据集&#xff09;&#xff0c;采用前96*2个时刻预测的特征和负荷数据预测未来96个时刻的负荷数据&#x…