采用 OpenCASCADE 提取布尔运算后平面图形的外轮廓
在 CAD 建模和几何处理中,经常需要从复杂形状中提取外轮廓。本文将深入探讨如何使用 OpenCASCADE 库在 C++ 中高效提取布尔运算后平面图形的外轮廓,并提供完整可运行的代码示例。
理论基础
平面图形的数学表示
在计算几何中,一个平面图形可以表示为:
S={(x,y)∈R2∣f(x,y)≥0}S = \{ (x,y) \in \mathbb{R}^2 | f(x,y) \geq 0 \}S={(x,y)∈R2∣f(x,y)≥0}
其中 f(x,y)f(x,y)f(x,y) 是定义图形边界的隐式函数。对于通过布尔运算获得的图形,其边界由多个分段曲线组成:
∂S=⋃i=1nCi(t),t∈[ai,bi]\partial S = \bigcup_{i=1}^{n} C_i(t), \quad t \in [a_i, b_i]∂S=i=1⋃nCi(t),t∈[ai,bi]
其中 Ci(t)C_i(t)Ci(t) 是参数化的曲线段。
OpenCASCADE 拓扑结构
OpenCASCADE 使用 BREP(边界表示)模型表示几何形状,其拓扑结构包括:
- 顶点 (Vertex):0维几何元素
- 边 (Edge):1维几何元素,由曲线定义
- 线框 (Wire):边的有序连接
- 面 (Face):由线框界定的2维曲面
- 壳 (Shell):面的集合
- 实体 (Solid):封闭壳
对于平面图形,我们关注的是其外线框 (Outer Wire),即定义图形最外边界的线框。
完整代码实现
示例 1:基本外轮廓提取
#include <BRepTools.hxx>#include <TopExp_Explorer.hxx>#include <TopoDS.hxx>#include <TopoDS_Face.hxx>#include <TopoDS_Wire.hxx>#include <gp_Circ.hxx>#include <gp_Pln.hxx>#include <gp_Ax2.hxx>#include <gp_Dir.hxx>#include <gp_Pnt.hxx>#include <BRepBuilderAPI_MakeEdge.hxx>#include <BRepBuilderAPI_MakeWire.hxx>#include <BRepBuilderAPI_MakeFace.hxx>#include <BRepAlgoAPI_Cut.hxx>#include <iostream>// 创建圆形平面TopoDS_Shape CreateCircleFace(double radius) {gp_Pln plane(gp::XOY());gp_Circ circle(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), radius);TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(circle);TopoDS_Wire wire = BRepBuilderAPI_MakeWire(edge);return BRepBuilderAPI_MakeFace(wire);}// 创建矩形平面TopoDS_Shape CreateRectangleFace(double width, double height) {gp_Pnt p1(-width/2, -height/2, 0);gp_Pnt p2(width/2, -height/2, 0);gp_Pnt p3(width/2, height/2, 0);gp_Pnt p4(-width/2, height/2, 0);TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(p1, p2);TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(p2, p3);TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(p3, p4);TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(p4, p1);TopoDS_Wire wire = BRepBuilderAPI_MakeWire(e1, e2, e3, e4);return BRepBuilderAPI_MakeFace(wire);}// 获取形状的外轮廓TopoDS_Wire GetOuterWire(const TopoDS_Shape& shape) {if (shape.IsNull()) {throw std::runtime_error("输入形状为空");}TopExp_Explorer faceExplorer(shape, TopAbs_FACE);if (!faceExplorer.More()) {throw std::runtime_error("形状中未找到面");}const TopoDS_Face& face = TopoDS::Face(faceExplorer.Current());TopoDS_Wire outerWire = BRepTools::OuterWire(face);if (outerWire.IsNull()) {throw std::runtime_error("提取外轮廓失败");}return outerWire;}int main() {try {// 创建几何图形TopoDS_Shape circle = CreateCircleFace(50.0);TopoDS_Shape rectangle = CreateRectangleFace(40.0, 40.0);// 执行布尔运算BRepAlgoAPI_Cut cutter(circle, rectangle);cutter.Build();if (!cutter.IsDone()) {throw std::runtime_error("布尔运算失败");}// 获取结果形状TopoDS_Shape resultShape = cutter.Shape();// 提取外轮廓TopoDS_Wire outerWire = GetOuterWire(resultShape);// 输出结果std::cout << "成功提取外轮廓" << std::endl;std::cout << "轮廓包含 " << outerWire.NbChildren() << " 条边" << std::endl;} catch (const std::exception& e) {std::cerr << "错误: " << e.what() << std::endl;return 1;}return 0;}
示例 2:高级外轮廓处理

#include <BRepTools.hxx>#include <TopExp_Explorer.hxx>#include <TopoDS.hxx>#include <TopoDS_Face.hxx>#include <TopoDS_Wire.hxx>#include <TopTools_ListOfShape.hxx>#include <gp_Circ.hxx>#include <gp_Pln.hxx>#include <gp_Ax2.hxx>#include <gp_Dir.hxx>#include <gp_Pnt.hxx>#include <BRepBuilderAPI_MakeEdge.hxx>#include <BRepBuilderAPI_MakeWire.hxx>#include <BRepBuilderAPI_MakeFace.hxx>#include <BRepAlgoAPI_Cut.hxx>#include <BRepAlgoAPI_Fuse.hxx>#include <BRepCheck_Analyzer.hxx>#include <iostream>#include <vector>// 创建圆形平面TopoDS_Shape CreateCircleFace(double radius) {gp_Pln plane(gp::XOY());gp_Circ circle(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), radius);TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(circle);TopoDS_Wire wire = BRepBuilderAPI_MakeWire(edge);return BRepBuilderAPI_MakeFace(wire);}// 创建多边形平面TopoDS_Shape CreatePolygonFace(const std::vector<gp_Pnt>& points) {if (points.size() < 3) {throw std::runtime_error("多边形至少需要3个点");}BRepBuilderAPI_MakeWire wireMaker;for (size_t i = 0; i < points.size(); i++) {size_t next = (i + 1) % points.size();TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(points[i], points[next]);wireMaker.Add(edge);}if (!wireMaker.IsDone()) {throw std::runtime_error("创建线框失败");}return BRepBuilderAPI_MakeFace(wireMaker.Wire());}// 获取所有外轮廓TopTools_ListOfShape GetAllOuterWires(const TopoDS_Shape& shape) {TopTools_ListOfShape resultWires;// 验证形状有效性BRepCheck_Analyzer analyzer(shape);if (!analyzer.IsValid()) {throw std::runtime_error("形状拓扑结构无效");}// 遍历所有面for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) {TopoDS_Face face = TopoDS::Face(exp.Current());// 获取面的外轮廓TopoDS_Wire outerWire = BRepTools::OuterWire(face);if (!outerWire.IsNull()) {resultWires.Append(outerWire);}// 可选:获取内轮廓(孔洞)/*TopExp_Explorer wireExp(face, TopAbs_WIRE);for (; wireExp.More(); wireExp.Next()) {TopoDS_Wire wire = TopoDS::Wire(wireExp.Current());if (!wire.IsSame(outerWire)) {// 处理内轮廓}}*/}return resultWires;}int main() {try {// 创建复杂几何图形std::vector<gp_Pnt> hexPoints = {gp_Pnt(0, 0, 0),gp_Pnt(30, 0, 0),gp_Pnt(45, 25, 0),gp_Pnt(30, 50, 0),gp_Pnt(0, 50, 0),gp_Pnt(-15, 25, 0)};TopoDS_Shape hexagon = CreatePolygonFace(hexPoints);TopoDS_Shape circle = CreateCircleFace(25.0);// 执行布尔并集运算BRepAlgoAPI_Fuse fuser(hexagon, circle);fuser.Build();if (!fuser.IsDone()) {throw std::runtime_error("布尔并集运算失败");}// 获取结果形状TopoDS_Shape fusedShape = fuser.Shape();// 提取所有外轮廓TopTools_ListOfShape outerWires = GetAllOuterWires(fusedShape);// 输出结果std::cout << "找到 " << outerWires.Extent() << " 个外轮廓" << std::endl;// 遍历所有外轮廓int wireCount = 1;for (TopTools_ListIteratorOfListOfShape it(outerWires); it.More(); it.Next()) {TopoDS_Wire wire = TopoDS::Wire(it.Value());std::cout << "轮廓 " << wireCount++ << " 包含 "<< wire.NbChildren() << " 条边" << std::endl;}} catch (const std::exception& e) {std::cerr << "错误: " << e.what() << std::endl;return 1;}return 0;}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/965725.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
很多争论不是认知问题,而是数学问题
🧠 很多争论不是认知问题,而是数学问题一、我们日常遇到的大部分争论,其实都是“数学逻辑问题”
很多人以为自己在讨论观点,其实他们在无意识地做数学,只是形式极其粗糙:没定义:集合不明确
没量化:变量无值
没…
题解:AtCoder ARC209D A_A_i
闲话帅炸了。
这是主播被 \(n=1\) 的 case 卡爆了,望周知。
题意
给定长度为 \(n\) 的序列 \(a\),值域为 \([1,n]\),有一些位置未确定。你需要给这些未确定的位置的确定取值,使得序列 \(b_i=a_{a_i}\) 的字典序最小…
代码制作数学动画 python manim jjmpeg - 何苦
代码制作数学动画 python manim jjmpeg安装 manimpip install manim安装ffmpeg
下载未完待续。。。
重组融合蛋白技术概述
重组融合蛋白的基本概念
重组融合蛋白是通过基因工程技术将两个或多个不同基因的编码序列连接,在宿主细胞中表达产生的单一多肽链。这种技术使得研究人员能够将不同蛋白质的功能域进行组合,创造出具有新特性的蛋白质…
OpenEuler安装宝塔
准备环境
sudo dnf update -y
sudo dnf install -y wget curl vim
#确认系统架构和版本,宝塔官方支持的系统主要是 CentOS/RHEL 7/8、Ubuntu 16-22,openEuler属于RHEL兼容系统,所以通常可以用CentOS安装脚本
uname -…
20230827 - Balancer 攻击事件:价格操纵 + 精度丢失的经典组合拳
攻击背景介绍
2023.08.27(没错是 2023 不是 2025),Balancer V2 的稳定币池遭到了黑客攻击,导致多条链上价值约 368k 美元的资产被盗。黑客利用 rounding down(精度丢失)问题操纵 bb-a-USDC 的价格,从稳定币池中…
破解cocos creator 2.3.2, 让它支持M芯片
cocos creator 貌似低于2.4.3的版本,都无法在mac m芯片上运行, 之所以不能运行,还是因为electron版本太低导致
对它进行逆向,破解app.asar, 然后升级electron相关的东西,并且升级vue ui组建
开源地址:https://gi…
Kotlin Coroutines
https://kotlinlang.org/docs/coroutines-overview.html
协程是作为三方库进行提供的,类似 javax
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><kotlin.co…
深入解析:软考中级-系统集成项目管理工程师**的超详细知识点笔记。
深入解析:软考中级-系统集成项目管理工程师**的超详细知识点笔记。2025-11-14 21:14
tlnshuju
阅读(0)
评论(0) 收藏
举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !…
GeoScene Pro试用申请
GeoScene Pro试用申请 按在线的文档配置
GeoScene Pro申请试用 - 易智瑞教育网
1)要求你输入许可的,如下图,这时候需要更换【许可类型】为“指定用户许可”(4.0版本软件这里写的是“授权用户许可”) 更换许可…
题解:P13573 [CCPC 2024 重庆站] Pico Park
P13573:区间 DP、组合数学VP 的时候没题可跟了,就开了这题切掉了,结果 VP 结束发现正赛就一个队伍过了???
若 \(x\) 用缩小枪击中了 \(y\),则从 \(x\) 向 \(y\) 连一条有向边。注意到,任何一个时刻得到的图是若…
【AI智能体】Coze 提取对标账号短视频生成视频文案实战详解 - 指南
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …
Java Benchmark使用
如何测量Java代码的性能
在 Java 中,可以使用多种方法来测量一段代码的执行性能。使用 System.currentTimeMillis()是最常见的方法
long startTime = System.currentTimeMillis();// 需要测量的代码块
for (int i = 0…
实用指南:12-机器学习与大模型开发数学教程-第1章1-4 导数与几何意义
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …
基于Vue社区共享游泳馆预约高效的系统n897q36e (工具+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …
docker登录容器镜像仓库
容器镜像仓库就是我们平时自己构建的镜像有一个存储的位置,方便自己平时进行拉取,测试用的我使用的是ucloud这容器仓库ucloud.cn登录容器仓库的操作docker logindocker login uhub.service.ucloud.cn# username 为登…