在参数化CAD建模场景中,检测模型中的圆角或倒角边缘是常见需求,比如需要批量修改圆角半径、统计倒角数量或者验证模型加工工艺性时,都需要先准确识别这类特殊边缘。CadQuery和build123d作为基于Python的CAD建模库,都提供了完整的拓扑和几何查询能力,我们可以通过分析边缘的几何特征来实现检测。
核心检测原理
圆角和倒角边缘的核心特征差异和识别依据如下:
- 圆角边缘本质是圆弧边,其几何类型为圆弧,曲率恒定且不为0,相邻两个面通常是垂直或成固定夹角的平面
- 倒角边缘是直线边,但相邻两个面的夹角不是直角,且两个相邻面与边缘的夹角相等
- 普通直线边要么是直角相邻面的交线,要么是模型的外轮廓直边,不符合上述两类特征
CadQuery 实现方案
CadQuery中可以通过Edge对象的几何属性判断边缘类型,首先获取边缘的几何类型,再结合相邻面的信息做进一步判断。
基础检测代码
import cadquery as cq
def detect_fillet_chamfer_cadquery(model):
fillet_edges = []
chamfer_edges = []
# 遍历模型所有边缘
for edge in model.edges().vals():
# 获取边缘的几何类型
geom_type = edge.geomType()
# 获取边缘相邻的两个面
adjacent_faces = edge.faces().vals()
# 圆角检测:几何类型为圆弧
if geom_type == "ARC":
fillet_edges.append(edge)
# 倒角检测:几何类型为直线,且有两个相邻面,计算面夹角
elif geom_type == "LINE" and len(adjacent_faces) == 2:
face1, face2 = adjacent_faces
# 获取两个面的法向量
normal1 = face1.normal()
normal2 = face2.normal()
# 计算法向量夹角,排除直角情况(夹角接近90度不是倒角)
dot_product = sum(n1 * n2 for n1, n2 in zip(normal1, normal2))
# 余弦值取绝对值,因为面可能朝向相反
cos_angle = abs(dot_product)
angle = math.acos(cos_angle) * 180 / math.pi
# 倒角夹角不是90度,且通常小于150度
if 30 < angle < 150 and abs(angle - 90) > 1:
chamfer_edges.append(edge)
return fillet_edges, chamfer_edges
# 测试示例:创建一个带圆角和倒角的立方体
model = (cq.Workplane("XY")
.box(10, 10, 10)
.edges("|Z")
.fillet(1)
.edges("<Z")
.chamfer(1)
)
import math
fillets, chamfers = detect_fillet_chamfer_cadquery(model)
print(f"检测到圆角边缘数量:{len(fillets)}")
print(f"检测到倒角边缘数量:{len(chamfers)}")
build123d 实现方案
build123d是CadQuery的继任者,API设计更现代化,边缘的几何属性获取方式略有不同,但核心逻辑一致。
基础检测代码
from build123d import *
import math
def detect_fillet_chamfer_build123d(model):
fillet_edges = []
chamfer_edges = []
# 遍历模型所有拓扑边缘
for edge in model.edges():
# 获取边缘的几何曲线
curve = edge.curve
# 圆角检测:曲线类型为圆弧
if isinstance(curve, Circle):
fillet_edges.append(edge)
# 倒角检测:曲线类型为直线,且有两个相邻面
elif isinstance(curve, Line) and len(edge.faces()) == 2:
face1, face2 = edge.faces()
# 获取面法向量
normal1 = face1.normal
normal2 = face2.normal
# 计算夹角
dot_product = sum(n1 * n2 for n1, n2 in zip(normal1, normal2))
cos_angle = abs(dot_product)
angle = math.acos(cos_angle) * 180 / math.pi
if 30 < angle < 150 and abs(angle - 90) > 1:
chamfer_edges.append(edge)
return fillet_edges, chamfer_edges
# 测试示例
with BuildPart() as part:
Box(10, 10, 10)
# 给顶部边缘倒角
chamfer(part.edges().filter_by(Axis.Z).sort_by(Axis.Z)[-1], 1)
# 给底部边缘圆角
fillet(part.edges().filter_by(Axis.Z).sort_by(Axis.Z)[0], 1)
fillets, chamfers = detect_fillet_chamfer_build123d(part.part)
print(f"检测到圆角边缘数量:{len(fillets)}")
print(f"检测到倒角边缘数量:{len(chamfers)}")
注意事项
实际使用中需要注意以下场景的适配:
- 如果模型存在非均匀圆角或者变半径圆角,圆弧检测依然有效,因为几何类型仍然是圆弧
- 复杂模型中可能存在三个及以上面共享的边缘,这类边缘需要额外判断,上述代码默认只处理两个相邻面的边缘
- 角度判断的阈值可以根据实际模型的精度需求调整,避免因为建模误差导致误判