CGAL CGAL::Polygon_mesh_processing::self_intersections解析
CGAL::Polygon_mesh_processing::self_intersections
是用于检测多边形网格(Polygon Mesh)中的自相交的函数。自相交是指网格中的某些面(例如三角形)与同一网格中的其他面交叉的情况。这种情况通常是不期望的,因为它会导致网格的不一致性和潜在的几何错误。
std::vector<std::pair<Mesh::face_index, Mesh::face_index>> self_intersections;CGAL::Polygon_mesh_processing::self_intersections(mesh,std::back_inserter(self_intersections));
关键代码:
// Checks for 'real' intersections, i.e. not simply a shared vertex or edge
template <class GT, class TM, class VPM>
bool do_faces_intersect(typename Triangle_mesh_and_triangle_soup_wrapper<TM>::face_descriptor fh,typename Triangle_mesh_and_triangle_soup_wrapper<TM>::face_descriptor fg,const TM& tmesh,const VPM vpmap,const typename GT::Construct_segment_3& construct_segment,const typename GT::Construct_triangle_3& construct_triangle,const typename GT::Do_intersect_3& do_intersect)
{typedef Triangle_mesh_and_triangle_soup_wrapper<TM> Wrapper;typedef typename Wrapper::vertex_descriptor vertex_descriptor;typedef typename GT::Segment_3 Segment;typedef typename GT::Triangle_3 Triangle;std::array<vertex_descriptor, 3> hv, gv;Wrapper::get_face_vertices(fh, hv, tmesh);Wrapper::get_face_vertices(fg, gv, tmesh);// check for shared edgestd::array<vertex_descriptor, 4> verts;if (Wrapper::faces_have_a_shared_edge(fh, fg, verts, tmesh)){if (verts[2]==verts[3]) return false; // only for a soup of triangles// there is an intersection if the four points are coplanar and the triangles overlapif(CGAL::coplanar(get(vpmap, verts[0]),get(vpmap, verts[1]),get(vpmap, verts[2]),get(vpmap, verts[3])) &&CGAL::coplanar_orientation(get(vpmap, verts[0]),get(vpmap, verts[1]),get(vpmap, verts[2]),get(vpmap, verts[3]))== CGAL::POSITIVE){return true;}else{// there is a shared edge but no intersectionreturn false;}}// check for shared vertex --> maybe intersection, maybe notint i(0), j(0);bool shared = false;for(; i<3 && (! shared); ++i){for(j=0; j<3 && (! shared); ++j){if(hv[i] == gv[j]){shared = true;break;}}if(shared)break;}if(shared){// found shared vertex:CGAL_assertion(hv[i] == gv[j]);// geometric check if the opposite segments intersect the trianglesconst Triangle t1 = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2]));const Triangle t2 = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2]));const Segment s1 = construct_segment(get(vpmap, hv[(i+1)%3]), get(vpmap, hv[(i+2)%3]));const Segment s2 = construct_segment(get(vpmap, gv[(j+1)%3]), get(vpmap, gv[(j+2)%3]));if(do_intersect(t1, s2))return true;else if(do_intersect(t2, s1))return true;return false;}// check for geometric intersectionconst Triangle th = construct_triangle(get(vpmap, hv[0]), get(vpmap, hv[1]), get(vpmap, hv[2]));const Triangle tg = construct_triangle(get(vpmap, gv[0]), get(vpmap, gv[1]), get(vpmap, gv[2]));if(do_intersect(th, tg))return true;return false;
}
解析:
1.初步筛选
将每个三角形的Bbox计算出来,再调用CGAL::box_self_intersection_d,使用分段树算法,快速筛选两两相交的Bbox对,此时得到的三角形对有可能相交,有可能只是相邻但不相交
//self_intersections_impltypedef internal::Strict_intersect_faces<Box, TM, VPM, GT, FacePairOutputIterator> Intersecting_faces_filter;Intersecting_faces_filter intersect_faces(tmesh, vpmap, gt, out);//省略......CGAL::box_self_intersection_d<CGAL::Sequential_tag>(box_ptr.begin(), box_ptr.end(), intersect_faces, cutoff);
2.精确判断
当检测到两个Bbox相交,box_self_intersection_d函数会调用函数对象(第三个参数Intersecting_faces_filter)的成员 void operator()(const Box* b, const Box* c)进一步判断
template <class Box, class TM, class VPM, class GT,class OutputIterator>
struct Strict_intersect_faces // "strict" as in "not sharing a subface"
{//省略.......void operator()(const Box* b, const Box* c) const{if(do_faces_intersect<GT>(b->info(), c->info(), m_tmesh, m_vpmap, m_construct_segment, m_construct_triangle, m_do_intersect))*m_iterator++ = std::make_pair(b->info(), c->info());}
};
do_faces_intersect的流程分三种情况,即有公共边,公共点的,没有公共边和公共顶点。
- ① t1和t2有公共边
1.若t1和t2不共面则不相交
2.若t1和t2共面,则判断v2是否在v0v1左边,若在左边则t1和 t2相交,否则不相交
- ② t1和t2有公共的顶点
1.判断边s1和三角形t2是否相交
2.判断边s2和三角形t1是否相交
- ③ t1和t2没有公共边和公共顶点
调用do_intersect碰撞检测,判断是否相交
步骤②步骤③中,判断边与三角形相交、三角形与三角形相交具体看CGAL\Intersections_3里面的实现
相关文章:

CGAL CGAL::Polygon_mesh_processing::self_intersections解析
CGAL::Polygon_mesh_processing::self_intersections 是用于检测多边形网格(Polygon Mesh)中的自相交的函数。自相交是指网格中的某些面(例如三角形)与同一网格中的其他面交叉的情况。这种情况通常是不期望的,因为它会…...
esp32触发相机
esp32触发相机,测试成功上升沿触发 串口发送命令 up 20000 1 20000 触发 #include <Arduino.h>const int outputPin 12; // 输出引脚 String inputCommand ""; // 串口输入缓冲区// 解析命令参数,例如 "up 10 5" 解析为…...
webrtc支持h265
Webrtc播放H265的技术探索(datachannelwasm) - 飞翔天空energy - 博客园 https://github.com/ZLMediaKit/ZLMediaKit/issues/3589 [技术咨询]addStreamProxy 添加拉流代理之后,webrtc协议无法播放,其它协议正常 Issue #1808 ZLMediaKit/ZLMediaKit G…...

macos 14.0 Monoma 修改顶部菜单栏颜色
macos 14.0 设置暗色后顶部菜单栏还维持浅色,与整体不协调。 修改方式如下:...

在 Mac(ARM 架构)上安装 JDK 8 环境
文章目录 步骤 1:检查系统版本步骤 2:下载支持 ARM 的 JDK 8步骤 3:安装 JDK步骤 4:配置环境变量步骤 5:验证安装步骤 6:注意事项步骤7:查看Java的安装路径 在 Mac(ARM 架构…...

Linux高阶——1123—
1、服务器版本介绍及实现 1、单进程单任务服务器(阻塞IO) 单进程模型,阻塞IO冲突,等待连接时无法读取数据,读取数据时无法连接 比较适合处理单任务,排队处理业务 伪代码 while(true) {addrlensizeof(c…...

VOLO实战:使用VOLO实现图像分类任务(二)
文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度,DP多卡,EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…...

【kafka02】消息队列与微服务之Kafka部署
Kafka 部署 Kafka 部署说明 kafka 版本选择 kafka 基于scala语言实现,所以使用kafka需要指定scala的相应的版本.kafka 为多个版本的Scala构建。这仅在使用 Scala 时才重要,并且希望为使用的相同 Scala 版本构建一个版本。否则,任何版本都可以 kafka下…...

MySQL系列之数据类型(Numeric)
导览 前言一、数值类型综述二、数值类型详解1. NUMERIC1.1 UNSIGNED或SIGNED1.2 数据类型划分 2. Integer类型取值和存储要求3. Fixed-Point类型取值和存储要求4. Floating-Point类型取值和存储要求 结语精彩回放 前言 MySQL系列最近三篇均关注了和我们日常工作或学习密切相关…...

BERT简单理解;双向编码器优势
目录 BERT简单理解 一、BERT模型简单理解 二、BERT模型使用举例 三、BERT模型的优势 双向编码器优势 BERT简单理解 (Bidirectional Encoder Representations from Transformers)模型是一种预训练的自然语言处理(NLP)模型,由Google于2018年推出。以下是对BERT模型的简…...

LLamafactory 批量推理与异步 API 调用效率对比实测
背景 在阅读 LLamafactory 的文档时候,发现它支持批量推理: 推理.https://llamafactory.readthedocs.io/zh-cn/latest/getting_started/inference.html 。 于是便想测试一下,它的批量推理速度有多快。本文实现了 下述两种的大模型推理,并对…...

spf算法、三类LSA、区间防环路机制/规则、虚连接
1.构建spf树: 路由器将自己作为最短路经树的树根根据Router-LSA和Network-LSA中的拓扑信息,依次将Cost值最小的路由器添加到SPF树中。路由器以Router ID或者DR标识。广播网络中DR和其所连接路由器的Cost值为0。SPF树中只有单向的最短路径,保证了OSPF区域内路由计管不…...

C语言学习 12(指针学习1)
一.内存和地址 1.内存 在讲内存和地址之前,我们想有个⽣活中的案例: 假设有⼀栋宿舍楼,把你放在楼⾥,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩,如果想找到你,就得挨…...
TypeError: issubclass() arg 1 must be a class
TypeError: issubclass() arg 1 must be a class 报错代码: import spacy 原因: 库版本错误, 解决方法: pip install typing-inspect0.8.0 typing_extensions4.5.0 感谢作者: langchain TypeError: issubclass() …...
Java面试题、八股文学习之JVM篇
1.对象一定分配在堆中吗?有没有了解逃逸分析技术? 对象不一定总是分配在堆中。在Java等一些高级编程语言中,对象的分配位置可以通过编译器或运行时系统的优化来决定。其中,逃逸分析(Escape Analysis)是用于…...

【eNSP】动态路由协议RIP和OSPF
动态路由RIP(Routing Information Protocol,路由信息协议)和OSPF(Open Shortest Path First,开放式最短路径优先)是两种常见的动态路由协议,它们各自具有不同的特点和使用场景。本篇会对这两种协…...

春秋云境 CVE 复现
CVE-2022-4230 靶标介绍 WP Statistics WordPress 插件13.2.9之前的版本不会转义参数,这可能允许经过身份验证的用户执行 SQL 注入攻击。默认情况下,具有管理选项功能 (admin) 的用户可以使用受影响的功能,但是该插件有一个设置允许低权限用…...

Linux入门攻坚——39、Nginx入门
Nginx:engine X Tengine:淘宝改进维护的版本 Registry: 使用了libevent库:高性能的网络库 epoll()函数 Nginx特性: 模块化设计、较好的扩展性;(但不支持动态加载模块功能&#…...

计算机网络的类型
目录 按覆盖范围分类 个人区域网(PAN) 局域网(LAN) 城域网(MAN) 4. 广域网(WAN) 按使用场景和性质分类 公网(全球网络) 外网 内网(私有网…...

解决 MySQL 5.7 安装中的常见问题及解决方案
目录 前言1. 安装MySQL 5.7时的常见错误分析1.1 错误原因及表现1.2 错误的根源 2. 解决方案2.1 修改YUM仓库配置2.2 重新尝试安装2.3 处理GPG密钥错误2.4 解决依赖包问题 3. 安装成功后的配置3.1 启动MySQL服务3.2 获取临时密码3.3 修改root密码 4. 结语 前言 在Linux服务器上…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...

SQL注入篇-sqlmap的配置和使用
在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap,但是由于很多朋友看不了解命令行格式,所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习,链接:https://wwhc.lanzoue.com/ifJY32ybh6vc…...