当前位置:

首页 > 编程开发 > C++如何判断两个不规则多边形是否发生几何相交 (SAT 算法)

C++如何判断两个不规则多边形是否发生几何相交 (SAT 算法)

SAT算法通过检测两凸多边形所有边法向量轴的投影区间是否重叠来判断相交。非凸多边形需先分解为凸多边形才能应用。实现中要注意浮点容差比较、退化边过滤及轴去重,避免错误判定。

本文目录

    SAT算法实战:判断凸多边形相交的黄金法则

    判断两个不规则多边形是否发生几何相交,这是计算机图形学里一个基础但容易踩坑的问题。先说几个核心判断:SAT(分离轴定理)是解决这个问题的利器,但它不是万能的,你得知道它的边界在哪里。

    C++如何判断两个不规则多边形是否发生几何相交 (SAT 算法)

    两个凸多边形用SAT判断相交,只需检查边法向量轴

    对两个凸多边形A和B来说,分离轴其实就是它们所有边的法向量方向——这里必须强调,不是边本身,也不是任意随机方向。每条边 e = v1 - v0 对应一个候选轴 glm::vec2(-e.y, e.x)(2D场景)或者归一化后的垂直向量(3D场景)。A有n条边、B有m条边,所以最多检查 n + m 条轴,不是 n×m。

    实践中最容易踩的坑有两个。第一,直接把“边向量”当成轴来用,或者漏掉某个多边形的一条边;第二,没做去重处理——平行边产生的法向量可能完全相同或反向,glm::all(glm::epsilonEqual(a, b, 1e-6f)) 或 glm::all(glm::epsilonEqual(a, -b, 1e-6f)) 必须检查到位。

    几点经验之谈:2D场景下用 glm::vec2 就足够了,不要升维引入冗余计算;轴完全不需要归一化——投影区间只依赖点积的相对大小,归一化纯属浪费计算资源;如果某条边的长度 ,直接跳过它的法向量计算,防止除零或NaN传播。

    非凸多边形不能直接套SAT,必须先分解

    SAT只对凸形状有效,这一点必须刻在脑子里。遇到凹多边形或带孔多边形,硬上SAT会漏判——举个典型例子:两个“U”形多边形开口相对,投影在所有边法向上都重叠,但实际它们根本就不相交。

    真实工程场景中,建模导出的多边形常含凹点。有人试图用“顶点凹凸性检测+局部修正”来绕开这个问题,但从实践来看,稳定性很差,不推荐。稳妥的做法是用耳切法(ear clipping)或单调链剖分,先把原始多边形拆成若干个凸多边形,然后再两两做SAT。

    • 如果只是粗筛阶段,可以先用AABB包围盒快速排除:!aabb_intersect(aabb_a, aabb_b) 直接返回false
    • 推荐轻量库如 poly2tri,或者手写耳切——但要注意处理共线顶点和极小面积三角形
    • 当拆出的凸片数量爆炸时(比如百顶点多边形),可以考虑降级为边-边穷举:对所有边对调用 segment_intersect()

    投影区间计算必须覆盖全部顶点,且带浮点容差

    在每个轴上,必须对多边形所有顶点计算 glm::dot(p, axis),取min和max得到 [min, max]。一个常见的低级错误:只投影前三个点,或者误以为三角形就只投三个点,忽略了其他顶点——多边形顶点数是不固定的。

    区间比较这条红线绝对不能碰:不能用 proj_a_max < proj_b_min 这种裸比较,浮点误差会让本该重叠的区间被判为分离。正确的写法是:

    if (proj_a_max + 1e-6f < proj_b_min || proj_b_max + 1e-6f < proj_a_min) {
        return false; // 分离
    }
    • epsilon值选 1e-6f 就足够了,比 FLT_EPSILON(约1e-7)更鲁棒,因为累积误差往往更大
    • 不要用 std::minmax_element——它对 size
    • 投影值本身不需要 clamp 或 abs,点积可正可负,min/max自然能捕获范围

    退化边与共线顶点必须前置过滤,不能等crash再处理

    真实输入数据经常带着“惊喜”:三点近似共线的扁平三角形、重复顶点、或者导出时精度丢失导致的微小边长。这些情况会直接让 glm::normalize() 返回 vec3(0,0,0),后续点积全变成NaN,整个检测瞬间失效。

    防护措施必须在SAT主循环之前就到位:对每条边,先算长度;对每个面(3D场景),先算叉积模长。面积 就视为退化,跳过对应轴或整个多边形。

    • 2D边长检查:glm::length(v1 - v0) < 1e-6f
    • 3D面积检查:0.5f * glm::length(glm::cross(v1-v0, v2-v0)) < 1e-6f
    • 退化多边形可以降级为线段集:提取所有非退化边,再做O(n²)边相交检测

    还有一个经常被忽略的细节:共面但非共线的多边形,在3D空间中仍然要走3D SAT流程——哪怕z坐标全为0。强行降维到2D只适用于明确已知共面且没有z噪声的场景,否则会埋下隐患。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 C++
    相关文章 更多
    C++动态数组初始化怎么写?常用语句与代码示例
    C++动态数组初始化怎么写?常用语句与代码示例

    深入解析C++中动态数组的初始化机制,涵盖new操作符的不同用法、基本类型与类对象的初始化差异,以及为何在现代C++开发中应优先使用std::vector。

    C++类构造与析构函数详解
    C++类构造与析构函数详解

    C++类构造与析构函数详解 C++这门语言,可以说是从C语言这棵大树上衍生出的高级果实,如今的应用普及度有目共睹。作为一种静态类型的通用编程语言,它厉害的地方在于融合了多种编程哲学——无论是传统的面向过程,还是主流的面向对象,乃至数据抽象、泛型编程这些高级概念,它都能很好地支持。正因为这份卓越的扩展

    C++中std::upper
    C++中std::upper

    C++中std::upper_bound用法解析 在C++标准模板库(STL)的算法工具箱里,upper_bound() 绝对算得上是一把精准的“探针”。它的核心任务很明确:在一个已经排好序的区间 [first, last) 内,帮你快速定位到第一个**严格大于**指定值 value 的那个元素。这

    C++常对象与成员解析
    C++常对象与成员解析

    C++中“常”概念全景解析:从对象、成员到指针与引用 在C++的世界里,“常量性”是一个强大的保障机制。它不仅仅是一个const关键字那么简单,而是构建健壮、安全程序的重要基石。今天,我们就来系统梳理一下围绕“常”的一系列概念:常成员、常对象、常指针与常引用。理解它们,是写出高质量C++代码的关键一

    c++如何将结构体写入SQLite数据库_对象关系映射方案【进阶】
    c++如何将结构体写入SQLite数据库_对象关系映射方案【进阶】

    直接用SQLiteCAPI绑定结构体需要手动处理字段展平与顺序对齐,ORM库虽省代码但存在隐式行为风险。小项目建议原生绑定,中大型项目可搭配编译期校验使用轻量ORM。绑定std::string需传指针与长度,注意生命周期;浮点字段比较需设误差范围。

    什么是编程,学习编程的意义是?
    什么是编程,学习编程的意义是?

    编程是编写程序指令,让设备按意图运行,常用Python、C等语言或Scratch图形化编程。学习编程能跟上科技时代,锻炼自学与解决问题能力,提升逻辑思维,代表行动力,推动事物前进。各司其职,编程者尽本分。

    编程是门艺术_是编程艺术吗?
    编程是门艺术_是编程艺术吗?

    编程被争论是否为艺术。从定义看,编程是技能表达,但并非所有编程都是应用开发。写代码如音乐、文章,有独特风格。好代码需耐心与逻辑能力。编程是艺术,但应用开发不等同于编程艺术。

    【编程的感受】
    【编程的感受】

    很多人提起编程,总觉得这是一门“不起眼”的学问——不就是写写代码嘛,能有多深?但真走进去了才会发现,编程里头的门道,远比表面看上去要丰富得多。 学习编程的过程中,最容易卡住的往往是那些基础语法。就拿那个常见的 for 循环来说吧,刚开始时怎么都绕不过弯来:为什么这么写能循环?循环条件到底怎么控制?一

    对于懂得编程的人来说,编程对你来说有什么乐趣?编程大概是什么感觉?
    对于懂得编程的人来说,编程对你来说有什么乐趣?编程大概是什么感觉?

    解决编程问题后的痛快、完成作品的成就感、获取知识的满足感,以及用代码实现简化生活的惊喜与踏实,这些是编程独有的乐趣,只有真正写代码的人才能体会其中的酸甜苦辣、惊喜与满足,令人回味无穷。

    趣味编程:少儿编程思维的启蒙之旅
    趣味编程:少儿编程思维的启蒙之旅

    Scratch图形化编程以拖拽积木块方式启蒙少儿编程思维,无需记忆代码语法。通过素材库、即时反馈和社区协作,帮助孩子在创作中理解顺序执行、条件判断等核心概念,锻炼逻辑、创造力和问题解决能力。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。