ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FreeCAD教程(三)

FreeCAD教程(三) 第3章 B-Rep 深入拓扑、几何与病态问题本章摘要本章深入剖析 B-Rep 实体建模的底层机制。首先梳理 OCCT/FreeCAD 的八级拓扑层级Vertex→Edge→Wire→Face→Shell→Solid→CompSolid→Compound及对应 Python 访问器随后讲解几何层中曲线与曲面的类型划分。核心部分揭示拓扑挂载几何的三大机制——pcurve边在面参数域中的二维投影、Orientation内外方向判定与Tolerance局部容差体系并解释看起来重合的两点为何不重合。接着用欧拉公式 V−EF2−2G 自检拓扑一致性区分流形与非流形。最后总结五类典型病态缝隙、自交、退化面、微小边、法向不一致及 Check Geometry / Refine shape 修复工具并深入剖析拓扑命名问题TNP的本质、FreeCAD 1.0 的 ElementMap 缓解方案与八条建模纪律。 学习目标背出 B-Rep 的八级拓扑层级并对应到 OCCT 的TopoDS_*类与 FreeCAD Python 的访问器。说出常用曲线与曲面类型并能在 FreeCAD 中查出某条边/某个面到底是什么几何类型。理解 pcurve、Orientation、Tolerance 三个机制解释看起来重合的两点为什么可能不重合。会用欧拉公式 V−EF2−2G 自检模型理解流形与非流形的区别。能用 Part 的Check Geometry与Refine shape诊断并修复典型病态形状。说清拓扑命名问题TNP的本质、FreeCAD 1.0 的 ElementMap 方案以及规避 TNP 的建模纪律。3.1 拓扑八级与 FreeCAD 访问器概念讲解OCCT也就是 FreeCAD的拓扑体系是严格的八级嵌套从零维到三维逐级构建级别名称OCCT 类维度含义FreeCAD Python 访问器1Vertex 顶点TopoDS_Vertex0D空间中一个点shape.Vertexes2Edge 边TopoDS_Edge1D由两个顶点界定的一段曲线shape.Edges3Wire 线框TopoDS_Wire1D首尾相接的边序列可开可闭shape.Wires4Face 面TopoDS_Face2D由一个外 Wire 若干内 Wire 作为孔界定的一片曲面shape.Faces5Shell 壳TopoDS_Shell2D通过共享边连接起来的面集合可开可闭shape.Shells6Solid 实体TopoDS_Solid3D由一个封闭 Shell 包围的空间内部 Shell 表示空腔shape.Solids7CompSolid 复合实体TopoDS_CompSolid3D通过共享面连接的实体集合相邻但不重叠像砖墙shape.CompSolids8Compound 复合体TopoDS_Compound混合任意形状的松散集合成员之间无需有任何关系shape.Compounds几个关键理解点Wire 与 Edge 的区别Edge 是单段曲线Wire 是一串边。你在 Sketcher 里画的一个封闭矩形轮廓是 1 个 Wire、4 条 Edge、4 个 Vertex。PartDesign 的 Pad 需要的是封闭 Wire这就是为什么草图不封闭就 Pad 不出来。Face 可以有洞一个带圆孔的方板正面是 1 个 Face但有 2 个 Wire——外面的矩形 Wire 和里面的圆 Wire。Shell 与 Solid 的区别Shell 只是一层皮可以是敞开的比如只有 5 个面的盒子只有封闭且定向正确的 Shell 才能升级为 Solid。这是曲面建模转实体的关键门槛见第 5.5 节。Compound 是万能容器Part → 复合 → 生成复合体把任意对象打包但打包不等于合并——Compound 里的两个立方体即使重叠也仍然是两个独立实体体积会重复计算。初学者常把 Compound 误当成 Fusion一定要分清。CompSolid 少见但重要常用于 FEM 的多材料分析几块实体共享界面网格在界面上连续。配图说明功能示意图一张自下而上的金字塔/阶梯图八层从下到上依次为 Vertex → Edge → Wire → Face → Shell → Solid → CompSolid → Compound。每一层右侧画出对应的小图例一个点、一段弧、一个封闭矩形回路、一个带圆孔的平板面、一个缺顶盖的开口盒Shell、一个完整立方体Solid、两块共享一个面的砖CompSolid、三个互不相干的散件被虚线框住Compound。每层左侧标注对应的TopoDS_*类名与 Python 访问器名。操作步骤数一个形状的拓扑元素Part → 基本体 → 立方体全默认10×10×10。打开Python 控制台视图 → 面板 → Python 控制台。输入s App.ActiveDocument.Box.Shape。依次输入并观察输出len(s.Vertexes)→8len(s.Edges)→12len(s.Wires)→6len(s.Faces)→6len(s.Shells)→1len(s.Solids)→1s.ShapeType→Solid现在对它倒圆角选中 BoxPart → 圆角全选 12 条边半径2 mm确定。对结果重复第 4 步面数变成266 个原面 12 个圆角面 8 个球角面边数变成48顶点24。观察倒圆角改变了拓扑结构而改 Length 不会。这个区别是第 3.6 节 TNP 的根源。3.2 几何层级曲线与曲面类概念讲解拓扑元素挂载的真正形状来自几何层。OCCT 的几何类型分两大族族曲线类型Edge 挂载类型OCCT/Python 名参数常见来源直线Line起点、方向草图线段、多边形边圆Circle圆心、法向、半径草图圆/圆弧、圆柱端面边椭圆Ellipse中心、长短轴斜切圆柱产生的边双曲线Hyperbola中心、实虚轴圆锥被平面斜切抛物线Parabola焦点、准线圆锥被平行母线的平面切Bezier 曲线BezierCurve控制点少数导入数据B 样条曲线BSplineCurve控制点、节点矢量、权重草图 B 样条、放样边、绝大多数导入的自由曲线偏移曲线OffsetCurve基曲线 偏移量Draft 偏移、抽壳中间结果类型Python 名参数常见来源平面Plane基点、法向立方体各面、拉伸的侧面圆柱面Cylinder轴线、半径孔、轴、Pad 出来的圆形侧面圆锥面Cone轴线、半角锪孔、拔模面球面Sphere中心、半径球体、球角圆角环面Toroid中心、大半径、小半径边圆角最常见旋转面SurfaceOfRevolution母线 轴复杂母线旋转拉伸面SurfaceOfExtrusion母线 方向曲线拉伸B 样条曲面NURBSBSplineSurface控制点网格、双向节点矢量、权重放样、扫掠、填充、导入的自由曲面为什么要认识这些三个实用理由诊断问题布尔失败时看看参与的面是不是 B 样条——解析面平面/柱/锥/球/环之间的求交有专门的快速稳健算法B 样条求交则要走通用数值迭代慢且易失败。判断可加工性CAM 中平面和圆柱面容易加工NURBS 曲面需要三轴以上联动。理解圆角等半径边圆角的结果面是环面Toroid这解释了为什么两个不同半径的圆角在角点相遇时会失败——那里需要一张 B 样条过渡面OCCT 有时算不出来。操作步骤查询几何类型创建一个 Radius10、Height30 的圆柱体。在 3D 视图中点选它的侧面观察状态栏显示形如Cylinder.Face1 (12.3 mm, 0 mm, 15 mm)。Python 控制台输入s App.ActiveDocument.Cylinder.Shape[f.Surface.__class__.__name__ for f in s.Faces]→ 得到类似[Cylinder, Plane, Plane][e.Curve.__class__.__name__ for e in s.Edges]→ 得到[Circle, Line, Circle]现在对圆柱顶边倒 R3 圆角重复上面的查询——你会看到列表里多出一个Toroid环面。3.3 拓扑如何挂载几何pcurve、Orientation、Tolerance概念讲解这一节是理解 B-Rep 病态问题的钥匙也是初学者最容易忽略的部分。① pcurve参数曲线一条 Edge 在三维空间中有它的三维曲线Curve。但当这条边位于某个 Face 上时它在那个面的参数域 (u,v) 里还有一条二维曲线叫pcurve。为什么需要 pcurve因为 Face 的裁剪是在参数域里做的一个圆柱面本身是无限延展的u∈[0,2π]v∈(−∞,∞)要裁出一段有限的侧面必须在 (u,v) 平面上画出边界框——那个边界框就是由 pcurve 组成的。关键坑点一条被两个面共享的边会有两条 pcurve在面 A 的参数域一条在面 B 的参数域一条加上一条三维曲线一共三份数据描述同一条边。这三份数据必须彼此一致在容差范围内。当它们不一致时就产生了病态几何——这是 Check Geometry 报告 “Invalid pcurve” 类错误的来源也是导入 STEP 文件后常见问题的根源。**② Orientation方向*拓扑元素有方向标记FORWARD正向、REVERSED反向、INTERNAL、EXTERNAL。对 Edge决定沿曲线走的方向。- 对 Face决定法向朝内还是朝外。这是判断实体哪边是里的唯一依据。*关键机制同一个几何面可以被两个 Solid 以相反的 Orientation 引用这样它们就能共享这张面而各自把它当作自己的外表面。这是 CompSolid 和布尔运算的基础法向不一致的后果如果一个 Shell 里有几个面的法向反了这个 Shell 就无法正确判断内外Part.Solid()会失败或者做出一个“体积为负”的怪物。Python 里shape.Volume返回负数就是这个信号。信号。③ Tolerance容差体系**OCCT 采用局部容差模型每个 Vertex、Edge、Face 各自携带自己的容差值。*- 默认容差是1e-7 mmPrecision::Confusion()即 0.0000001 mm。容差的语义是“真实几何在以此为半径的管道/球内的某处”。一个 Vertex 的容差是 0.01意思是“这个点的真实位置在半径 0.01 的球内”。容差有层级约束Face 的容差 ≤ 它的 Edge 的容差 ≤ Edge 的 Vertex 的容差。也就是说越低维的元素容差越大“点最不确定”。“看起来重合的两点为什么可能不重合”现在可以回答了答了假设有两条边应该在一点相接。三维曲线 A 在该处的端点算出来是 (10.000000, 0, 0)曲线 B 的端点算出来是 (10.000003, 0, 0)。二者相差 3e-6 mm肉眼、甚至放大一万倍都看不出来。但默认容差是 1e-73e-6 1e-7所以 OCCT 认为它们是两个不同的点。结果是- 这两条边不共享顶点Wire 不封闭Pad 会报“轮廓不封闭”缝合会失败Shell 有缝。有缝。解决办法有两条提高容差治标Part → 设置容差Part_ToleranceSet把相关元素的容差放大到比如 1e-5。或者缝合时给一个较大的 sewing tolerance。修正几何治本找出为什么会差 3e-6——通常是因为上游数据是从其他 CAD 导入的、单位换算过、或者做过缩放。容差不是越大越好容差过大会让内核把本不该合并的元素合并产生退化面、自交反而制造新问题。经验区间1e-7默认到 1e-4 mm之间超过 0.001 mm 就要警惕。配图说明功能示意图分两栏。左栏画pcurve 机制上方一张空间中的圆柱面片一条粗黑边在上面下方一个矩形参数域 (u,v)同一条边在参数域里画成一条曲线用虚线箭头连接上下标注同一条边1 条 3D 曲线 N 条 pcurve。右栏画容差机制两条曲线的端点几乎重合各自画一个半径不同的虚线圆表示容差球一种情况两球相交判为同一点绿勾另一种情况两球分离判为两点红叉旁边标注具体数值 1e-7 与 3e-6。3.4 欧拉公式与流形性概念讲解欧拉-庞加莱公式是检验 B-Rep 拓扑一致性的经典工具。简化形式针对单个闭合曲面**V − E F 2 − 2G其中 V顶点数E边数F面数G亏格genus即“穿透的洞数”甜甜圈 G1八字形 G2。2。验证一下立方体V8, E12, F6 → 8 − 12 6 2 2 − 2×0 ✓G0四面体V4, E6, F4 → 4 − 6 4 2 ✓圆环体Torus在 OCCT 中通常是 V1, E2, F1 → 1 − 2 1 0 2 − 2×1 ✓G1完整形式还要考虑面上的内环孔和分离的壳V − E F − L 2(S − G)其中 L 是内环数S 是壳数。这个公式有什么用它是内核内部做**欧拉操作Euler operators**的正确性保证——每个建模操作分裂一条边、加一个面都必须保持等式成立。作为用户你可以用它做粗略自检手工数一数元素个数如果等式不成立模型的拓扑一定有问题。流形与非流形二维流形2-manifold的直观定义曲面上任意一点取一个足够小的邻域这个邻域看起来都像一小片平坦的圆盘。翻译成 B-Rep 的规则每一条边恰好被两个面共享对封闭实体而言。非流形non-manifold的典型情形一条边被 3 个或更多面共享比如三块板在一条线上交汇T 形接头那条棱就是非流形边。两个实体只在一个顶点接触像两个立方体角对角碰在一起。那个顶点的邻域不是圆盘而是两个3.零厚度结构一个面从实体内部伸出来“内隔板”。板。面自交一张面穿过自非流形一定是错的吗不一定。有些应用FEM 的壳单元建模、BIM 的空间拓扑故意使用非流形。但对于CAD 实体建模、3D 打印、CAM 加工非流形几乎总是错误——因为物理上造不出零厚度的板也不知道“角对角接触”的两个块到底连不连。连不连。isValid() 到底检查什么在 Python 里shape.isValid()返回 True/False它调用的是 OCCT 的BRepCheck_Analyzer。检查内容包括每个 Vertex 是否在它所属 Edge 的容差范围内每条 Edge 的 3D 曲线与各条 pcurve 是否一致每条 Edge 是否有有效的 pcurve每个 Wire 是否闭合、边的顺序与方向是否连贯、Wire 是否自交每个 Face 的外环是否包含所有内环、内环之间是否相交、Face 的方向是否有效每个 Shell 的面方向是否一致、是否闭合每个 Solid 的外壳方向是否朝外、内壳空腔方向是否朝注意isValid()不检查什么它不检查两个独立实体之间是否互相穿透自交检查需要 BOP Check也不检查是否存在过小的边/面。所以isValid() True不等于“模型没问题”。问题。3.5 典型病态与修复工具概念讲解五类最常见的 B-Rep 病态病态现象成因后果缝隙gap两个面之间有肉眼看不见的裂缝容差不匹配、导入数据精度损失、单位换算Shell 不闭合 → 无法转 Solid → Pad/布尔失败自交self-intersection面穿过自己或穿过邻面偏移量过大、抽壳厚度大于最小圆角半径、扫掠路径曲率半径小于截面布尔失败、体积计算错误、切片崩溃退化面degenerate face面积趋近于 0 的面或退化成一条线的面圆角在尖角处收缩、锥体顶点、放样端点重合网格划分失败、CAM 刀路异常微小边sliver / tiny edge长度接近容差量级的边如 1e-5 mm布尔运算的求交副产物、几乎相切的面后续布尔连锁失败、网格单元质量差法向不一致部分面法向朝内手工缝合曲面、导入数据Volume 为负、渲染黑面、打印切片内外颠倒两大修复工具工具 APart → 检查几何体Check GeometryPart_CheckGeometry这是 FreeCAD 的诊断中枢。它在任务面板中给出一棵树状报告Shape Content分支统计各类拓扑元素数量VERTEX / EDGE / WIRE / FACE / SHELL / SOLID 各多少个。错误分支按拓扑元素列出具体错误如Face1: Invalid Point On Surface、Shell: Not Closed、Wire: Not Closed、Edge: Invalid Curve On Surface。可勾选的高级检查Run BOP check布尔运算专用检查能查出自交isValid()查不出的那类。代价是慢大模型可能等很久。Log errors / Single-threaded调试用。怎么读报告三步法先看有没有 “Shell: Not Closed” 或 “Solid” 相关错误 —— 这类是结构性致命错误。再看 Face / Edge 级错误 —— 通常是 pcurve 或容差问题。最后看 BOP check 结果 —— 自交必须修否则后续必炸。工具 BPart → 精炼形状Refine shapePart_RefineShape作用是移除冗余的边和面——具体说把共面且相邻的两个面合并成一个删掉它们之间那条本可以不存在的分界边。典型场景两个立方体做并集接缝处会留下十字分割线Refine 之后接缝消失得到干净的大平面。Refine 的代价它会重新编号所有面和边。如果你在 Refine 之前的模型上做过基于面选择的操作比如在 Face7 上开孔Refine 之后 Face7 可能变成另一张面——这就是 TNP。所以 Refine 要么在建模一开始就统一开启首选项里的自动 Refine要么就在建模全部完成后最后做一次。中途开关 Refine 是灾难。配图说明界面截图FreeCAD 的 Check Geometry 任务面板截图。左侧为组合视图中的任务面板展开的树中显示 “Shape Content”列出 VERTEX: 8, EDGE: 12, FACE: 6 等统计以及一个红色错误分支如Shell: BRepCheck_NotClosed。面板底部要能看到 “Run BOP check” 复选框。右侧 3D 视图中被检查的形状高亮显示出问题的面用红色标出。用箭头标注三处①统计区 ②错误列表 ③BOP check 开关。实际案例制造一个带缝隙的形状并诊断它我们用曲面拼盒子但故意少一面来制造一个不闭合 Shell然后读报告。新建文档切到Part工作台。Part → 基本体 → 立方体Length30、Width20、Height15。打开Python 控制台输入以下三行这里只用最少的代码演示实际操作也可用 GUIs App.ActiveDocument.Box.Shapesh Part.Shell(s.Faces[0:5])—— 只取 6 个面中的 5 个故意漏掉顶面Part.show(sh, BrokenShell)模型树中出现BrokenShell。选中它菜单Part → 检查几何体。报告怎么读“Shape Content” 里显示SHELL: 1、FACE: 5、SOLID: 0——SOLID 为 0 是第一个红灯说明它不是实体。错误分支中出现Shell: BRepCheck_NotClosed壳未闭合。面级别通常没有错误 —— 说明五个面各自都是好的问题在少了一片。验证Python 里输入sh.isClosed()→ 返回False。输入Part.Solid(sh)→ 抛出异常。修复把第 3 步改成sh Part.Shell(s.Faces)六个面全要再Part.Solid(sh)就能成功isValid()返回True。第二个案例微小边导致的容差问题Part → 基本体 → 立方体Length20、Width20、Height20。再建一个立方体Length20、Width20、Height20Placement Position 设为 (19.99999, 0, 0) —— 让它们几乎完全错开但重叠 0.00001 mm。全选 →Part → 布尔运算 → 并集。对结果执行Part → 检查几何体勾选Run BOP check。你很可能看到微小面/微小边相关的告警或者布尔运算本身就报错。修复思路要么让重叠足够大比如 Position 改成 (15, 0, 0)要么让它们完全分开再用 Compound。几乎重合是最坏的情况——比完全重合和明显分开都糟糕。参数说明参数位置默认值取值范围影响Run BOP checkCheck Geometry 面板关闭开/关开启后能查自交耗时可能增加数倍容差 TolerancePart → 设置容差 /shape.Tolerance1e-7 mm1e-7 ~ 1e-3放大可强行缝合小缝隙过大会引入新病态Sewing tolerance形状构建器 → 从面构建壳体0.1 mm0缝合面时判定两条边是同一条的阈值Refine自动精炼首选项 → Part 设计 → 常规关闭开/关建议项目一开始就决定开或关中途不要改3.6 拓扑命名问题TNP概念讲解TNPTopological Naming Problem拓扑命名问题是参数化 B-Rep CAD 的世纪难题FreeCAD 用户尤其熟悉它的痛。问题的本质在 B-Rep 中拓扑元素是用序号标识的Face1、Face2、Edge7……这个序号由 OCCT 在构建形状时按内部遍历顺序生成不是稳定的语义标识。当你在 PartDesign 里做了这样一串操作Pad 出一个长方体产生 Face1~Face6选中Face6顶面在上面画草图Pocket 一个孔回到第 1 步把 Pad 的长度从 10 改成 重算时OCCT 重新构建 Pad 的形状面的遍历顺序可能变化——原来的 Face6 现在可能变成了 Face3。而你的草图仍然写着“附着在 Face6 上”于是孔跑到了侧面或者直接报错 “Links go out of the allowed scope”、“Face not found”。un为什么序号会变因为 OCCT 的形状构建是“重新做一遍”而不是“增量修改”。任何改变几何的操作——尤其是布尔运算、圆角、Refine、改变特征顺序——都可能改变元素的枚举次序。改一个纯尺寸有时不会变但只要拓扑发生变化比如一个面被分裂成两个就必然会变。必然会变。FreeCAD ≤ 0.21 的困境在 1.0 之前FreeCAD 几乎没有 TNP 缓解机制。典型症状改一个早期参数后面十几个特征全部变- 圆角/倒角“跑到”错误的边上误的边上草图的外部几何引用External Geometry- 用户被迫遵守极端保守的建模纪律甚至“不敢改参数”。改参数。社区的临时对策包括尽量在基准面而非模型面上画草图、避免使用外部几何、把圆角全部放到最后、用附件Attachment而非直接选面。FreeCAD 1.0 的 ElementMap 方案FreeCAD 1.0 合并了长期开发的拓扑命名缓解分支源自 RealThunder 的 Link/TNP 分支1.1 继续完善。核心机制src/App/ElementMap.h/ElementMap.cpp定义了元素映射表把每个拓扑元素与一个稳定的字符串名字关联起来。src/App/MappedElement.h定义MappedName映射名稳定与IndexedName索引名如Face6不稳定的配对结构。src/App/ComplexGeoData.h几何数据基类承载元素映射能力使得Part::TopoShape能够携带并传递元素它是怎么做到“稳定”的思路是用生成历史给元素编码名字而不是用枚举序号。一个面的名字不再是“第 6 个面”而是形如“由草图 Sketch 的第 3 条线段经 Pad 操作沿正方向生成的侧面”这样一条可追溯的编码路径。哪怕重算后它的序号从 6 变成 3它的映射名不变于是下游引用依然指向正确的面。正确的面。重要提醒这是缓解不是根治。TNP 在理论上无法被完全消除——因为有些编辑操作会让一个面真的消失或一分为二此时原来那个面在语义上已经不存在了任何命名系统都救不回来。1.0/1.1 的 ElementMap 大幅降低了故障率但你仍然会遇到断链。使用者的建模纪律重要请当作检查清单优先在基准几何上画草图用原点的 XY/XZ/YZ 平面、或自建的 Datum Plane / Datum Line而不是模型的某个面。基准平面不参与形状重算永远稳定。需要贴在模型面上时用附件Attachment 明确的附着模式而不是随手点面。修饰特征圆角、倒角、抽壳尽量放在特征树最后。它们大量改变拓扑放在中间会污染后面所有引用。减少草图外部几何引用External Geometry。如果必须引用考虑改用表达式引用参数值。Refine 策略要一开始就定死项目开始时决定全程开自动 Refine或全程关中途不要切换。一个草图只画一个轮廓、一个特征只做一件事。巨型全约束草图看起来高效一旦出问题会牵连所有下游。分阶段保存与验证每加 3~5 个特征就存一次并按 CtrlR 强制全量重算一次确认不报错再继续。早发现早修。善用 Body 与 Part 容器隔离把复杂零件拆成多个 Body减少单棵树的深度。配图说明步骤流程图上半部分画TNP 发生过程三格连环画①一个长方体顶面标Face6上面有一个孔箭头注明草图附着在 Face6②改长度参数的示意10 → 20③重算后同一个长方体变长但顶面标签变成了Face3孔跑到了侧面并标红引用失效。下半部分画ElementMap 解决思路同样三格但面的标签从Face6换成一个稳定字符串如Pad;:M;Sketch;Line3;F重算后标签不变孔仍在顶面标绿引用有效。侧边标注源码路径src/App/ElementMap.h、src/App/MappedElement.h。操作步骤复现并规避 TNP切到PartDesign创建 Body。在XY 平面新建草图画一个 40×30 的矩形用约束固定关闭草图。Pad长度10 mm。在 Pad 的顶面上新建草图点选顶面 → 创建草图画一个 φ8 的圆圆心约束在 (10, 8)关闭。Pocket类型选贯穿所有Through all。得到一个带孔的板。现在双击 Pad把长度改成25回车。观察是否报错。规避做法对照实验删掉第 4 步的草图改为PartDesign → 创建基准 → 基准平面选 XY 平面Attachment Offset 的 Z 填10等于 Pad 长度甚至更好——把这个 Offset 写成表达式Pad.Length。然后在这个基准平面上画孔草图。现在再改 Pad 长度到 25基准平面因为绑定了表达式会自动跟随孔的位置始终正确且从未引用过任何模型面。第 7 步就是用基准几何代替模型面这条纪律的具体落地。❓ 常见问题解答Q1Check Geometry 说我的模型 “No errors”但布尔运算还是失败为A默认的 Check Geometry 只跑BRepCheck_Analyzer它不检查自交**。请勾选Run BOP check再检查一次很可能会发现自交。另外还要检查是否存在共面/相切的接触区域——那不算“错误”但会让布尔算法走进病态分支。进病态分支。Q2什么是 “Shell is not closed”我明明看到模型是封闭的。A肉眼看到的封闭和拓扑上的封闭是两回事。常见原因① 相邻两个面的边不共享各有各的边中间差了 1e-5 mm② 真的缺了一片面比如从曲面缝合时漏了③ 面法向不一致。用 Python 的shape.Shells[0].isClosed()确认然后用形状构建器 → 从面构建壳体并加大 sewing tolerance 重新缝合。Q3为什么我改了一个尺寸后面所有特征都变红了A典型的 TNP。检查你的下游特征是否引用了模型面草图附着面、圆角选中的边、外部几何。修复步骤① 双击报错特征重新选择正确的面/边② 长远方案是按 3.6 节的八条纪律重构模型把关键草图挪到基准平面上。FreeCAD 1.0 的 ElementMap 已大幅降低发生率但深层依赖仍可能断链。Q4Refine shape 是不是应该总是开着A开着的好处是模型干净、面数少、后续布尔更容易坏处是每次 Refine 都会重编号加剧 TNP 风险。推荐策略在项目开始时于首选项中一次性设定全程不改。如果做的是简单零件建议开如果是有大量面引用的复杂零件建议关最后统一 Refine 一次再导出。Q5容差调大一点是不是能解决所有缝隙A不能而且危险。容差调大只是让内核“睁一只眼闭一只眼”底层的几何不一致依然存在会在后续操作网格划分、CAM 刀路、切片中爆发。而且容差过大会把本该分开的元素合并制造退化面。正确顺序是先查清缝隙的成因**导入精度单位换算缩放能修几何就修几何容差只作为最后手段且不要超过 1e-4 mm 量级。mm 量级。 本章小结拓扑八级Vertex → Edge → Wire → Face → Shell → Solid → CompSolid → Compound对应 OCCT 的TopoDS_*在 FreeCAD Python 中用.Vertexes/.Edges/.Wires/.Faces/.Shells/.Solids/.CompSolids/.Compounds访问。几何层曲线有直线/圆/椭圆/双曲线/抛物线/Bezier/B-Spline/Offset曲面有平面/柱/锥/球/环/旋转/拉伸/NURBS。等半径边圆角产生的是环面Toroid。挂pcurve**边在面参数域中的二维投影一条边可有多份不一致即病态、Orientation决定内外法向反了就无法成实体、Tolerance每个元素各带容差默认 1e-7 mm这就是“看起来重合的点其实不重合”的原因。合的原因。欧拉公式 V−EF2−2G可做拓扑自检流形要求每条边恰被两个面共享isValid()检查容差一致性、pcurve 有效性、Wire 闭合性、Shell 方向与闭合性但不检查自交。五类病态缝隙、自交、退化面、微小边诊断用Part → Check Geometry记得勾Run BOP check查自交清理用Part → Refine shape。精炼形TNP的本质是“拓扑元素用不稳定的序号标识”。的序号标识。FreeCAD 1.0 引入ElementMapsrc/App/ElementMap.h、src/App/MappedElement.h、src/App/ComplexGeoData.h用可追溯的生成历史编码代替序号大幅缓解但不能根治。用户仍须遵守建模纪律基准优先、修饰特征靠后、少用外部几何、Refine 策略一次定死、分阶段验证。✏️ 练习题用 Part 创建一个 Radius20、Height40 的圆柱在 Python 控制台中统计它的 V、E、F 数量并用欧拉公式验证 G0。然后创建一个圆环体TorusR130、R28同样统计并验证 G1。写出两次的等式。参照 3.5 节的第一个案例用Part.Shell(s.Faces[0:5])制造一个不闭合的壳运行 Check Geometry把报告中的 “Shape Content” 统计和错误信息完整抄录下来并指出哪一行是这不是实体的直接证据。然后修复它并再次检查。按 3.6 节第 1~6 步复现一次 TNP 场景在 Pad 顶面画草图开孔然后改 Pad 长度记录是否报错、孔的位置是否正确。再按第 7~8 步用基准平面 表达式Pad.Length重做一次对比两者在改参数时的稳健性差异。
返回列表