第04章-选择器系统详解

第04章:选择器系统详解

4.1 选择器概述

4.1.1 什么是选择器

选择器(Selector)是CadQuery中用于精确选择几何元素的强大工具。在CAD建模中,我们经常需要对特定的面、边或顶点进行操作,选择器提供了一种直观且灵活的方式来定位这些元素。

import cadquery as cq

# 选择器示例:选择盒子的顶面
result = (
    cq.Workplane("XY")
    .box(20, 20, 10)
    .faces(">Z")        # 选择Z方向最高的面
    .workplane()
    .hole(5)
)

4.1.2 可选择的几何元素类型

CadQuery支持选择以下类型的几何元素:

方法 选择的元素类型 说明
.faces() 面(Face) 实体的表面
.edges() 边(Edge) 面与面的交线
.vertices() 顶点(Vertex) 边的端点
.wires() 线框(Wire) 闭合的边集合
.solids() 实体(Solid) 完整的3D实体
.shells() 壳(Shell) 封闭的面集合
.compounds() 复合体(Compound) 多个形状的组合

4.1.3 选择器的工作原理

选择器本质上是一个过滤器,它遍历当前对象的所有子元素,并返回符合条件的元素:

# 不带参数 - 选择所有该类型的元素
box.faces()      # 选择所有6个面
box.edges()      # 选择所有12条边

# 带选择器字符串 - 过滤元素
box.faces(">Z")  # 只选择Z方向最高的面
box.edges("|X")  # 只选择平行于X轴的边

4.2 方向选择器

4.2.1 最大/最小方向选择器

使用 >< 选择在某个方向上最大或最小的元素:

# 选择各方向的面
box = cq.Workplane("XY").box(20, 30, 10)

top_face = box.faces(">Z")      # 顶面(Z最大)
bottom_face = box.faces("<Z")   # 底面(Z最小)
front_face = box.faces(">Y")    # 前面(Y最大)
back_face = box.faces("<Y")     # 后面(Y最小)
right_face = box.faces(">X")    # 右面(X最大)
left_face = box.faces("<X")     # 左面(X最小)

多元素选择:

# 当多个元素在同一方向上处于相同位置时,都会被选中
# 例如选择圆柱的顶面边缘
cylinder = cq.Workplane("XY").circle(10).extrude(20)
top_edges = cylinder.edges(">Z")  # 选择顶面的圆形边

4.2.2 平行/垂直选择器

使用 | 选择平行于某轴的元素,使用 # 选择垂直于某轴的元素:

box = cq.Workplane("XY").box(20, 30, 10)

# 平行选择器
vertical_edges = box.edges("|Z")     # 4条竖直边
horizontal_x = box.edges("|X")       # 4条平行于X轴的边
horizontal_y = box.edges("|Y")       # 4条平行于Y轴的边

# 垂直选择器
faces_perp_z = box.faces("#Z")       # 顶面和底面(垂直于Z轴)
faces_perp_x = box.faces("#X")       # 左面和右面(垂直于X轴)

4.2.3 自定义方向向量

可以使用任意方向向量进行选择:

import cadquery as cq
from cadquery import Vector

# 使用Vector指定方向
box = cq.Workplane("XY").box(20, 20, 10)

# 选择法向量指向(1, 1, 0)方向的面(如果存在)
# 对于标准盒子,这不会选中任何面
# 但对于倾斜的面会有效

4.3 位置选择器

4.3.1 中心点选择器

使用中心点选择器选择接近某一位置的元素:

box = cq.Workplane("XY").box(20, 30, 10)

# 按中心点位置选择
# 这在有多个相似元素时特别有用

4.3.2 索引选择器

当有多个相似元素时,可以使用索引选择特定元素:

# 选择特定索引的元素
box = cq.Workplane("XY").box(20, 30, 10)

# 获取所有竖直边,然后选择第一条
first_vertical_edge = box.edges("|Z").val()

4.4 几何选择器

4.4.1 圆形/圆弧选择器

使用 % 选择圆形或包含圆弧的元素:

# 选择圆形边
cylinder = cq.Workplane("XY").circle(10).extrude(20)

# %Circle 选择圆形边
circular_edges = cylinder.edges("%Circle")

# 选择圆形面
circular_faces = cylinder.faces("%Plane")  # 顶面和底面(平面)

4.4.2 形状类型选择器

# 按形状类型选择
result = cq.Workplane("XY").box(20, 20, 10)

# 选择平面(Plane类型的面)
planar_faces = result.faces("%Plane")

# 对于有圆角的物体
filleted_box = cq.Workplane("XY").box(20, 20, 10).edges().fillet(2)

# 选择圆柱面(圆角产生的)
curved_faces = filleted_box.faces("%Cylinder")

4.5 组合选择器

4.5.1 逻辑AND组合

使用 and 关键字组合多个条件:

box = cq.Workplane("XY").box(20, 30, 10)

# 选择平行于Z轴且X最大的边
edges = box.edges("|Z and >X")  # 右侧的2条竖直边

# 选择顶部且平行于X轴的边
edges = box.edges(">Z and |X")  # 顶面的2条平行于X轴的边

4.5.2 逻辑OR组合

使用 or 关键字表示满足任一条件:

box = cq.Workplane("XY").box(20, 30, 10)

# 选择顶面或底面
faces = box.faces(">Z or <Z")

# 选择所有水平边
edges = box.edges("|X or |Y")

4.5.3 逻辑NOT组合

使用 not 关键字排除某些元素:

box = cq.Workplane("XY").box(20, 30, 10)

# 选择不是顶面的所有面
faces = box.faces("not >Z")  # 5个面

# 选择不是竖直的所有边
edges = box.edges("not |Z")  # 8条水平边

4.5.4 复杂组合

box = cq.Workplane("XY").box(20, 30, 10)

# 复杂组合示例
# 选择顶部或底部的、平行于X轴的边
edges = box.edges("(>Z or <Z) and |X")

# 选择不在顶面的竖直边
edges = box.edges("|Z and not >Z")

4.6 自定义选择器

4.6.1 使用过滤函数

可以使用自定义函数进行过滤:

import cadquery as cq

box = cq.Workplane("XY").box(20, 30, 10)

# 获取所有边并手动过滤
all_edges = box.edges().vals()

# 自定义过滤:选择长度大于15的边
long_edges = [e for e in all_edges if e.Length() > 15]

4.6.2 创建自定义选择器类

from cadquery import Selector, Edge
from cadquery.occ_impl.shapes import Shape

class LengthSelector(Selector):
    """选择指定长度范围的边"""
    
    def __init__(self, min_length, max_length=float('inf')):
        self.min_length = min_length
        self.max_length = max_length
    
    def filter(self, objectList):
        result = []
        for obj in objectList:
            if isinstance(obj, Edge):
                length = obj.Length()
                if self.min_length <= length <= self.max_length:
                    result.append(obj)
        return result

# 使用自定义选择器
box = cq.Workplane("XY").box(20, 30, 10)
long_edges = box.edges(LengthSelector(20, 35))

4.6.3 基于属性的选择器

class RadiusSelector(Selector):
    """选择指定半径的圆形边"""
    
    def __init__(self, radius, tolerance=0.001):
        self.radius = radius
        self.tolerance = tolerance
    
    def filter(self, objectList):
        result = []
        for obj in objectList:
            if hasattr(obj, 'radius'):
                r = obj.radius()
                if abs(r - self.radius) < self.tolerance:
                    result.append(obj)
        return result

4.7 标签系统

4.7.1 为元素添加标签

标签系统允许在建模过程中标记特定元素,以便后续选择:

import cadquery as cq

result = (
    cq.Workplane("XY")
    .box(30, 20, 10)
    .faces(">Z")
    .tag("top_face")          # 为顶面添加标签
    .workplane()
    .circle(5)
    .extrude(15)
    .edges(">Z")
    .tag("top_circle")        # 为圆形边添加标签
)

4.7.2 使用标签选择元素

# 通过标签选择之前标记的元素
top_face = result.faces(tag="top_face")

# 在标签选中的面上继续操作
result = result.faces(tag="top_face").workplane().hole(8)

4.7.3 标签的最佳实践

# 完整的标签使用示例
result = (
    cq.Workplane("XY")
    # 创建基础板
    .box(100, 60, 10)
    .faces(">Z").tag("base_top")
    .end()
    
    # 创建凸台
    .faces(tag="base_top")
    .workplane()
    .circle(20)
    .extrude(15)
    .faces(">Z").tag("boss_top")
    .end()
    
    # 在凸台顶部钻孔
    .faces(tag="boss_top")
    .workplane()
    .hole(10)
    
    # 在基础板上创建安装孔
    .faces(tag="base_top")
    .workplane()
    .rect(80, 40, forConstruction=True)
    .vertices()
    .hole(8)
)

4.8 实际应用示例

4.8.1 选择性圆角

import cadquery as cq

# 创建L型支架,只对某些边倒圆角
result = (
    cq.Workplane("XY")
    .box(50, 30, 5)
    .faces(">Z")
    .workplane()
    .center(-20, 0)
    .rect(10, 30)
    .extrude(40)
    
    # 只对竖直边进行大圆角
    .edges("|Z")
    .fillet(3)
    
    # 对顶部边进行小圆角
    .edges(">Z")
    .fillet(1)
)

4.8.2 多面孔加工

# 在多个面上创建相同的特征
result = (
    cq.Workplane("XY")
    .box(40, 40, 40)
    
    # 在每个面中心创建凹槽
    .faces(">X")
    .workplane()
    .rect(20, 20)
    .cutBlind(-5)
    
    .faces("<X")
    .workplane()
    .rect(20, 20)
    .cutBlind(-5)
    
    .faces(">Y")
    .workplane()
    .rect(20, 20)
    .cutBlind(-5)
)

4.8.3 复杂零件的边处理

# 创建复杂零件并选择性处理边
result = (
    cq.Workplane("XY")
    .box(60, 40, 20)
    
    # 顶面凸台
    .faces(">Z")
    .workplane()
    .circle(15)
    .extrude(10)
    
    # 对基础板的竖直边大圆角
    .faces("<Z")
    .edges("|Z")
    .fillet(5)
    
    # 对凸台的顶部边小圆角
    .faces(">Z")
    .edges()
    .fillet(2)
    
    # 对基础板的底部边倒角
    .faces("<Z")
    .edges()
    .chamfer(1)
)

4.8.4 装配孔定位

# 使用选择器精确定位装配孔
result = (
    cq.Workplane("XY")
    .box(80, 60, 10)
    
    # 在四个角落钻孔
    .faces(">Z")
    .workplane()
    .rect(60, 40, forConstruction=True)
    .vertices()
    .cboreHole(6, 12, 4)
    
    # 在中心钻大孔
    .faces(">Z")
    .workplane()
    .hole(20)
    
    # 只对四个角落的孔边缘倒角
    .faces(">Z")
    .edges("%Circle and >X and >Y")  # 右上角的圆形边
    # 注意:实际使用中可能需要更复杂的选择逻辑
)

4.9 选择器性能优化

4.9.1 选择器链优化

# 低效:多次遍历
result = box.faces(">Z").edges().edges("|X")

# 高效:直接组合条件
result = box.edges(">Z and |X")

4.9.2 缓存选择结果

# 如果需要多次使用同一选择结果
top_face = box.faces(">Z")

# 复用选择结果
feature1 = top_face.workplane().circle(5).extrude(10)
feature2 = top_face.workplane().rect(3, 3).cutBlind(-3)

4.9.3 使用标签减少重复选择

# 使用标签避免重复选择
result = (
    cq.Workplane("XY")
    .box(50, 50, 10)
    .faces(">Z").tag("top")
    .end()
    
    # 后续多次引用
    .faces(tag="top").workplane().circle(10).extrude(5)
    .faces(tag="top").workplane().rarray(15, 15, 2, 2).hole(3)
)

4.10 常见问题与解决方案

4.10.1 选择器没有选中任何元素

# 问题:选择器字符串拼写错误或条件不匹配
box = cq.Workplane("XY").box(20, 20, 10)

# 错误:大小写敏感
# box.edges("|z")  # 应该是 "|Z"

# 解决:使用正确的语法
edges = box.edges("|Z")

# 调试:检查有多少元素被选中
print(f"选中的边数: {len(box.edges('|Z').vals())}")

4.10.2 选择了过多的元素

# 问题:条件太宽泛
box = cq.Workplane("XY").box(20, 20, 10)

# 选择了所有12条边
all_edges = box.edges()

# 解决:添加更多条件
top_edges = box.edges(">Z")  # 只选择顶部的4条边
specific_edges = box.edges(">Z and |X")  # 只选择顶部平行于X的2条边

4.10.3 组合选择器语法错误

# 错误的语法
# box.edges(">Z && |X")  # 不支持 &&

# 正确的语法
box.edges(">Z and |X")  # 使用 and

# 括号用于复杂条件
box.edges("(>Z or <Z) and |X")

4.11 本章小结

本章详细介绍了CadQuery的选择器系统:

  1. 基本选择器

    • 方向选择器:><|#
    • 几何选择器:%Circle%Plane
  2. 组合选择器

    • 逻辑运算:andornot
    • 括号分组
  3. 自定义选择器

    • 过滤函数
    • 自定义选择器类
  4. 标签系统

    • 添加和使用标签
    • 标签最佳实践
  5. 实际应用

    • 选择性圆角/倒角
    • 精确定位特征

通过本章的学习,您应该能够:

  • 使用各种选择器精确选择几何元素
  • 组合多个选择条件
  • 创建自定义选择器
  • 使用标签系统管理复杂模型

下一章我们将学习装配体(Assembly)功能,这是创建复杂多零件模型的关键。


posted @ 2026-01-10 13:15  我才是银古  阅读(20)  评论(0)    收藏  举报