OpenSCAD polyhedron差集运算失败:网格未闭合报错求助
OpenSCAD Polyhedron差集运算报错:
ERROR: The given mesh is not closed! Unable to convert to CGAL_Nef_Polyhedron 问题现象
- F5预览完全正常,但F6渲染差集时失败,报错提示网格未闭合
- 单独渲染polyhedron模型(不做差集)时,F5和F6都正常,甚至能导出STL
- 已尝试用F12检查面的手性,调整点顺序使所有面手性一致,但问题依旧
- 使用
hull()包裹形状后差集可正常工作,但hull()无法处理复杂凹形,不符合需求
复现代码
//提示:F12可按面的手性着色,绿色为顺时针,紫色为逆时针,所有面的点遍历方向需一致 y_separation = 10.0; module poly_prism_segmented() { //分段数量 cn_segments = 2; cx_length = 30.0; cy_width = y_separation; cz_thickness = 3.0; // 索引规则 // 底部外侧 [0N, 1N-1] // 底部内侧 [1N, 2N-1] // 顶部内侧 [2N, 3N-1] // 顶部外侧 [3N, 4N-1] //将棱柱拆分为四条线 ap_bottom_outer = [ for (cnt_n = [0:cn_segments-1]) let (k=cnt_n/(cn_segments-1),x_temp = cx_length*k) [x_temp,+cy_width/2,0] ]; ap_bottom_inner = [ for (cnt_n = [0:cn_segments-1]) let (k=cnt_n/(cn_segments-1),x_temp = cx_length*k) [x_temp,-cy_width/2,0] ]; ap_top_inner = [ for (cnt_n = [0:cn_segments-1]) let (k=cnt_n/(cn_segments-1),x_temp = cx_length*k) [x_temp,-cy_width/2,cz_thickness] ]; ap_top_outer = [ //遍历每个分段 for (cnt_n = [0:cn_segments-1]) let (k=cnt_n/(cn_segments-1),x_temp = cx_length*k) [x_temp,+cy_width/2,cz_thickness] ]; //拼接所有点,顺序很重要 ap_points = concat ( ap_bottom_outer, ap_bottom_inner, ap_top_inner, ap_top_outer ); //首尾端面:第一个面取各线的第一个点,最后一个面取各线的最后一个点 ap_lid_endpoints = [ [0, cn_segments, cn_segments*2, cn_segments*3], [cn_segments-1, cn_segments*2-1, cn_segments*3-1, cn_segments*4-1] ]; // 面的点顺序规则 // 顶部 | 顶部内侧 顶部外侧 下一个顶部外侧 下一个顶部内侧 // 内侧 | 底部内侧 顶部内侧 下一个顶部内侧 下一个底部内侧 // 底部 | 底部内侧 底部外侧 下一个底部外侧 下一个底部内侧 // 外侧 | 底部外侧 顶部外侧 下一个顶部外侧 下一个底部外侧 //顶部面 // 顶部内侧 [2N, 3N-1] // 顶部外侧 [3N, 4N-1] ap_box_top = [ //遍历每个分段 for (cnt_n = [0:cn_segments-2]) //创建四边形面,包含四个点的索引 [ //顶部内侧 [2N, 3N-2] cn_segments*2 +cnt_n, //顶部外侧 [3N, 4N-2] cn_segments*3 + cnt_n, //下一个顶部外侧 [3N+1, 4N-1] cn_segments*3 + cnt_n + 1, //下一个顶部内侧 [2N+1, 3N-1] cn_segments*2 + cnt_n + 1 ], ]; //底部面 // 底部外侧 [0N, 1N-1] // 底部内侧 [1N, 2N-1] ap_box_bot = [ //遍历每个分段 for (cnt_n = [0:cn_segments-2]) //创建四边形面,包含四个点的索引 [ //底部外侧 [0N, 1N-2] cn_segments*0 +cnt_n, //底部内侧 [1N, 2N-2] cn_segments*1 + cnt_n, //下一个底部内侧 [1N+1, 2N-1] cn_segments*1 + cnt_n + 1, //下一个底部外侧 [0N+1, 1N-1] cn_segments*0 + cnt_n + 1 ], ]; //内侧面 // 底部内侧 [1N, 2N-1] // 顶部内侧 [2N, 3N-1] //如果按顶部、底部、底部、顶部的顺序,会导致旋转方向错误,进而出现开放网格 ap_box_in = [ //遍历每个分段 for (cnt_n = [0:cn_segments-2]) //创建四边形面,包含四个点的索引 [ //底部内侧 [1N, 2N-2] cn_segments*1 + cnt_n, //顶部内侧 [2N, 3N-2] cn_segments*2 +cnt_n, //下一个顶部内侧 [2N+1, 3N-1] cn_segments*2 + cnt_n + 1, //下一个底部内侧 [1N+1, 2N-1] cn_segments*1 + cnt_n + 1 ], ]; //外侧面 // 底部外侧 [0N, 1N-1] // 顶部外侧 [3N, 4N-1] ap_box_out = [ //遍历每个分段 for (cnt_n = [0:cn_segments-2]) //创建四边形面,包含四个点的索引 [ //顶部外侧 [3N, 4N-2] cn_segments*3 + cnt_n, //底部外侧 [0N, 1N-2] cn_segments*0 +cnt_n, //下一个底部外侧 [0N+1, 1N-1] cn_segments*0 + cnt_n + 1, //下一个顶部外侧 [3N+1, 4N-1] cn_segments*3 + cnt_n + 1 ], ]; //拼接所有面,传入polyhedron ap_faces = concat ( ap_lid_endpoints, ap_box_top, ap_box_bot, ap_box_in, ap_box_out ); polyhedron ( points = ap_points, faces = ap_faces ); } translate([0,-y_separation,0]) poly_prism_segmented(); translate([0,y_separation,0]) difference() { sphere(r=10,$fa=1,$fs=1); poly_prism_segmented(); }
问题分析与解决方案
核心原因
OpenSCAD的CGAL后端要求布尔运算的网格必须完全闭合且流形。F5预览用OpenGL渲染,容错性高;但F6的CGAL运算会严格检查网格拓扑,微小错误都会导致失败。你的代码存在两处关键问题:
- 首尾端面的手性错误:端面点顺序朝向模型内部,破坏了网格闭合性
- 外侧面的点顺序错误:遍历方向与其他面手性不一致,导致面朝向异常
修正代码
修正首尾端面
ap_lid_endpoints = [ // 起始端面:调整为逆时针顺序(从模型左侧看),统一手性 [0, cn_segments*3, cn_segments*2, cn_segments], // 结束端面:调整为逆时针顺序(从模型右侧看),统一手性 [cn_segments-1, cn_segments, cn_segments*2, cn_segments*3-1] ];
修正外侧面
ap_box_out = [ for (cnt_n = [0:cn_segments-2]) [ // 调整点顺序,保持与其他面一致的手性 cn_segments*0 +cnt_n, cn_segments*3 + cnt_n, cn_segments*3 + cnt_n + 1, cn_segments*0 + cnt_n + 1 ], ];
验证步骤
- 修正后按F12预览,所有面应显示为同一种颜色,说明手性统一
- 执行F6渲染差集,CGAL可成功转换网格,布尔运算正常
内容的提问来源于stack exchange,提问作者05032 Mendicant Bias
相关产品推荐
相关产品推荐

