第07章-高级建模技巧

第07章:高级建模技巧

7.1 参数化设计

7.1.1 参数化设计概述

参数化设计是CadQuery的核心优势之一。通过将尺寸和几何关系定义为参数,可以轻松生成不同规格的模型。

参数化设计的优点:

  • 快速生成变体模型
  • 易于修改和维护
  • 支持批量生产
  • 便于设计优化

7.1.2 基本参数化

import cadquery as cq

# 定义参数
length = 80.0
width = 60.0
height = 20.0
hole_diameter = 15.0
fillet_radius = 3.0
wall_thickness = 3.0

# 使用参数创建模型
result = (
    cq.Workplane("XY")
    .box(length, width, height)
    .faces(">Z")
    .shell(-wall_thickness)
    .faces(">Z")
    .workplane()
    .hole(hole_diameter)
    .edges("|Z")
    .fillet(fillet_radius)
)

cq.exporters.export(result, "parametric_box.step")

7.1.3 参数化函数

import cadquery as cq

def make_enclosure(length, width, height, wall=2.0, corner_radius=3.0):
    """
    创建参数化外壳
    
    Args:
        length: 长度
        width: 宽度
        height: 高度
        wall: 壁厚
        corner_radius: 圆角半径
    """
    result = (
        cq.Workplane("XY")
        .box(length, width, height)
        .edges("|Z")
        .fillet(corner_radius)
        .faces(">Z")
        .shell(-wall)
    )
    return result

# 生成不同尺寸的外壳
small = make_enclosure(50, 30, 20)
medium = make_enclosure(80, 50, 30, wall=3.0)
large = make_enclosure(120, 80, 40, wall=4.0, corner_radius=5.0)

cq.exporters.export(small, "enclosure_small.step")
cq.exporters.export(medium, "enclosure_medium.step")
cq.exporters.export(large, "enclosure_large.step")

7.1.4 参数关联

import cadquery as cq

# 参数定义
bolt_diameter = 8
bolt_spacing = 30
num_bolts_x = 4
num_bolts_y = 3

# 派生参数(自动计算)
plate_length = bolt_spacing * (num_bolts_x - 1) + bolt_diameter * 4
plate_width = bolt_spacing * (num_bolts_y - 1) + bolt_diameter * 4
plate_thickness = bolt_diameter * 0.5
edge_distance = bolt_diameter * 2

# 创建带关联参数的安装板
result = (
    cq.Workplane("XY")
    .box(plate_length, plate_width, plate_thickness)
    .faces(">Z")
    .workplane()
    .rarray(bolt_spacing, bolt_spacing, num_bolts_x, num_bolts_y)
    .cboreHole(bolt_diameter, bolt_diameter * 1.8, plate_thickness * 0.3)
    .edges()
    .fillet(plate_thickness * 0.2)
)

cq.exporters.export(result, "mounting_plate.step")

7.1.5 配置驱动设计

import cadquery as cq

# 配置字典
configs = {
    "M6": {
        "thread_diameter": 6,
        "head_diameter": 10,
        "head_height": 4,
        "length": 20
    },
    "M8": {
        "thread_diameter": 8,
        "head_diameter": 13,
        "head_height": 5,
        "length": 25
    },
    "M10": {
        "thread_diameter": 10,
        "head_diameter": 16,
        "head_height": 6.4,
        "length": 30
    }
}

def make_hex_bolt(config):
    """根据配置创建六角螺栓"""
    td = config["thread_diameter"]
    hd = config["head_diameter"]
    hh = config["head_height"]
    length = config["length"]
    
    return (
        cq.Workplane("XY")
        .polygon(6, hd)
        .extrude(hh)
        .faces("<Z")
        .workplane()
        .circle(td / 2)
        .extrude(-length)
        .edges(">Z")
        .chamfer(hh * 0.1)
    )

# 生成不同规格的螺栓
for name, config in configs.items():
    bolt = make_hex_bolt(config)
    cq.exporters.export(bolt, f"bolt_{name}.step")

7.2 复杂曲面建模

7.2.1 样条曲面

import cadquery as cq
import math

# 创建样条曲线并放样
points1 = [(0, 0), (20, 10), (40, 5), (60, 15), (80, 0)]
points2 = [(0, 0), (20, -10), (40, -5), (60, -15), (80, 0)]

result = (
    cq.Workplane("XZ")
    .spline(points1)
    .close()
    .workplane(offset=30)
    .spline(points2)
    .close()
    .loft()
)

cq.exporters.export(result, "spline_surface.step")

7.2.2 旋转曲面

import cadquery as cq
import math

def vase_profile(height, base_radius, neck_radius, belly_radius):
    """创建花瓶轮廓"""
    points = []
    segments = 50
    
    for i in range(segments + 1):
        t = i / segments
        h = t * height
        
        # 使用正弦函数创建曲线轮廓
        if t < 0.3:
            r = base_radius + (belly_radius - base_radius) * math.sin(t / 0.3 * math.pi / 2)
        elif t < 0.7:
            r = belly_radius * (1 + 0.1 * math.sin((t - 0.3) / 0.4 * 2 * math.pi))
        else:
            r = belly_radius + (neck_radius - belly_radius) * math.sin((t - 0.7) / 0.3 * math.pi / 2)
        
        points.append((r, h))
    
    return points

# 创建花瓶
profile = vase_profile(100, 15, 10, 30)
vase = (
    cq.Workplane("XZ")
    .moveTo(0, 0)
    .spline(profile)
    .lineTo(0, 100)
    .close()
    .revolve(360, (0, 0, 0), (0, 1, 0))
    .shell(-2)  # 创建空心
)

cq.exporters.export(vase, "vase.step")

7.2.3 扫略曲面

import cadquery as cq
import math

# 创建螺旋路径
def helix_path(radius, pitch, turns):
    points = []
    segments = int(turns * 36)
    
    for i in range(segments + 1):
        angle = 2 * math.pi * i / 36
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)
        z = pitch * i / 36
        points.append((x, y, z))
    
    return points

# 使用内置的螺旋线
helix = cq.Wire.makeHelix(pitch=10, height=80, radius=25)

# 创建截面
# 异形截面
profile = (
    cq.Workplane("XY")
    .ellipse(5, 3)
)

# 沿螺旋线扫略
result = profile.sweep(helix, isFrenet=True)

cq.exporters.export(result, "helix_sweep.step")

7.2.4 放样曲面进阶

import cadquery as cq
from cadquery import Sketch

# 多截面放样
s1 = Sketch().rect(40, 40).vertices().fillet(5)
s2 = Sketch().circle(15)
s3 = Sketch().polygon(8, 20).vertices().fillet(2)
s4 = Sketch().rect(30, 30).vertices().fillet(8)

result = (
    cq.Workplane("XY")
    .placeSketch(s1)
    .workplane(offset=20)
    .placeSketch(s2)
    .workplane(offset=20)
    .placeSketch(s3)
    .workplane(offset=20)
    .placeSketch(s4)
    .loft()
)

cq.exporters.export(result, "multi_loft.step")

7.3 图案和阵列

7.3.1 矩形阵列

import cadquery as cq

# 使用rarray创建矩形阵列
result = (
    cq.Workplane("XY")
    .box(100, 80, 10)
    .faces(">Z")
    .workplane()
    .rarray(15, 15, 5, 4)  # x间距, y间距, x数量, y数量
    .hole(5)
)

cq.exporters.export(result, "rect_array.step")

7.3.2 极坐标阵列

import cadquery as cq

# 圆周阵列
result = (
    cq.Workplane("XY")
    .circle(50)
    .extrude(10)
    .faces(">Z")
    .workplane()
    .polarArray(35, 0, 360, 8)  # 半径, 起始角, 结束角, 数量
    .hole(8)
    .faces(">Z")
    .workplane()
    .hole(20)  # 中心孔
)

cq.exporters.export(result, "polar_array.step")

7.3.3 自定义点阵列

import cadquery as cq
import math

# 自定义点位置
custom_points = [
    (0, 0),
    (30, 0),
    (15, 26),  # 三角形布局
    (-30, 15),
    (30, 30),
]

result = (
    cq.Workplane("XY")
    .box(100, 80, 10)
    .faces(">Z")
    .workplane()
    .pushPoints(custom_points)
    .hole(8)
)

cq.exporters.export(result, "custom_array.step")

7.3.4 沿路径阵列

import cadquery as cq
import math

# 沿曲线分布
def points_along_curve(num_points):
    points = []
    for i in range(num_points):
        t = i / (num_points - 1)
        x = 80 * t - 40
        y = 20 * math.sin(t * 2 * math.pi)
        points.append((x, y))
    return points

# 创建基板
base = cq.Workplane("XY").box(100, 60, 5)

# 沿曲线放置凸台
curve_points = points_along_curve(10)
result = (
    base
    .faces(">Z")
    .workplane()
    .pushPoints(curve_points)
    .circle(3)
    .extrude(8)
)

cq.exporters.export(result, "curve_array.step")

7.4 镜像与对称

7.4.1 平面镜像

import cadquery as cq

# 创建半边模型
half = (
    cq.Workplane("XY")
    .moveTo(0, 0)
    .lineTo(30, 0)
    .lineTo(30, 20)
    .lineTo(20, 20)
    .lineTo(20, 10)
    .lineTo(0, 10)
    .close()
    .extrude(10)
)

# 镜像得到完整模型
result = half.mirror("XZ")

# 或者使用union合并原始和镜像
full = half.union(half.mirror("XZ"))

cq.exporters.export(full, "mirrored.step")

7.4.2 多轴对称

import cadquery as cq

# 创建四分之一模型
quarter = (
    cq.Workplane("XY")
    .moveTo(0, 0)
    .lineTo(20, 0)
    .threePointArc((28, 8), (20, 20))
    .lineTo(0, 20)
    .close()
    .extrude(10)
)

# X和Y方向都镜像
half = quarter.union(quarter.mirror("YZ"))
full = half.union(half.mirror("XZ"))

cq.exporters.export(full, "quad_symmetric.step")

7.4.3 旋转对称

import cadquery as cq
import math

# 创建一个扇区
sector = (
    cq.Workplane("XY")
    .moveTo(0, 0)
    .lineTo(30, 0)
    .threePointArc((30 * math.cos(math.pi/3), 30 * math.sin(math.pi/3)), 
                   (30 * math.cos(math.pi/6), 30 * math.sin(math.pi/6)))
    .lineTo(0, 0)
    .close()
    .extrude(5)
)

# 旋转复制
result = sector
for i in range(1, 6):
    angle = i * 60
    rotated = sector.rotate((0, 0, 0), (0, 0, 1), angle)
    result = result.union(rotated)

cq.exporters.export(result, "rotational_symmetric.step")

7.5 布尔运算进阶

7.5.1 复杂布尔组合

import cadquery as cq

# 创建基础形状
box = cq.Workplane("XY").box(50, 50, 30)
cylinder = cq.Workplane("XY").cylinder(40, 15)
sphere = cq.Workplane("XY").sphere(20)

# 复杂布尔运算
# box和cylinder的并集,减去sphere
result = box.union(cylinder).cut(sphere)

cq.exporters.export(result, "complex_boolean.step")

7.5.2 交集应用

import cadquery as cq

# 使用交集创建特殊形状
# 两个圆柱的交集(双曲抛物面)
cyl1 = cq.Workplane("XY").cylinder(60, 25)
cyl2 = cq.Workplane("XZ").cylinder(60, 25)

result = cyl1.intersect(cyl2)

cq.exporters.export(result, "cylinder_intersect.step")

7.5.3 条件布尔运算

import cadquery as cq

def make_part_with_holes(add_holes=True, num_holes=4):
    """根据条件添加特征"""
    result = (
        cq.Workplane("XY")
        .box(80, 60, 10)
        .edges("|Z")
        .fillet(5)
    )
    
    if add_holes and num_holes > 0:
        result = (
            result
            .faces(">Z")
            .workplane()
            .rarray(60 / (num_holes - 1), 40, num_holes, 2)
            .hole(5)
        )
    
    return result

# 生成不同版本
part_no_holes = make_part_with_holes(add_holes=False)
part_4_holes = make_part_with_holes(num_holes=4)
part_6_holes = make_part_with_holes(num_holes=6)

7.6 特征识别与操作

7.6.1 面积筛选

import cadquery as cq

# 创建模型
model = (
    cq.Workplane("XY")
    .box(50, 30, 20)
    .faces(">Z")
    .workplane()
    .circle(10)
    .extrude(10)
)

# 获取所有面并按面积排序
faces = model.faces().vals()
face_areas = [(f, f.Area()) for f in faces]
face_areas.sort(key=lambda x: x[1], reverse=True)

print("面积从大到小:")
for f, area in face_areas[:5]:
    print(f"  {area:.2f} mm²")

7.6.2 边长筛选

import cadquery as cq

# 创建模型
model = cq.Workplane("XY").box(50, 30, 20)

# 获取所有边
edges = model.edges().vals()

# 按长度筛选
long_edges = [e for e in edges if e.Length() > 25]
print(f"长度>25mm的边数: {len(long_edges)}")

7.6.3 几何中心定位

import cadquery as cq

# 创建模型
model = (
    cq.Workplane("XY")
    .box(50, 30, 20)
    .faces(">Z")
    .workplane()
    .rect(30, 15)
    .cutBlind(-10)
)

# 获取边界框信息
bb = model.val().BoundingBox()
center = ((bb.xmin + bb.xmax) / 2, 
          (bb.ymin + bb.ymax) / 2, 
          (bb.zmin + bb.zmax) / 2)

print(f"模型中心: {center}")
print(f"尺寸: {bb.xmax - bb.xmin} x {bb.ymax - bb.ymin} x {bb.zmax - bb.zmin}")

7.7 性能优化

7.7.1 减少布尔运算

import cadquery as cq

# 低效:多次布尔运算
# def inefficient():
#     result = cq.Workplane("XY").box(100, 100, 10)
#     for i in range(10):
#         for j in range(10):
#             hole = cq.Workplane("XY").center(i*10, j*10).circle(3).extrude(15)
#             result = result.cut(hole)
#     return result

# 高效:使用阵列一次性操作
def efficient():
    result = (
        cq.Workplane("XY")
        .box(100, 100, 10)
        .faces(">Z")
        .workplane()
        .rarray(10, 10, 10, 10)
        .hole(6)
    )
    return result

model = efficient()
cq.exporters.export(model, "optimized_holes.step")

7.7.2 简化几何

import cadquery as cq

# 使用合理的精度
# 对于大型模型,可以降低某些特征的精度

def make_model(fillet_segments=20):
    """控制圆角分段数"""
    result = (
        cq.Workplane("XY")
        .box(50, 50, 20)
        .edges()
        .fillet(3)
    )
    return result

model = make_model()

7.7.3 延迟求值

import cadquery as cq

# 构建操作链而不立即求值
operations = [
    lambda wp: wp.box(50, 50, 20),
    lambda wp: wp.faces(">Z").workplane().hole(10),
    lambda wp: wp.edges("|Z").fillet(2),
]

# 按需执行
def build_model(ops):
    result = cq.Workplane("XY")
    for op in ops:
        result = op(result)
    return result

model = build_model(operations)

7.8 调试技巧

7.8.1 中间结果可视化

import cadquery as cq

# 在CQ-editor中分步显示
# step1 = cq.Workplane("XY").box(50, 50, 20)
# show_object(step1, name="step1_box", options={"color": "blue"})

# step2 = step1.faces(">Z").workplane().hole(10)
# show_object(step2, name="step2_hole", options={"color": "green"})

# step3 = step2.edges("|Z").fillet(3)
# show_object(step3, name="step3_fillet", options={"color": "red"})

7.8.2 几何信息打印

import cadquery as cq

def debug_model(model, name="model"):
    """打印模型的详细信息"""
    print(f"\n=== {name} 信息 ===")
    
    # 边界框
    bb = model.val().BoundingBox()
    print(f"边界框: ({bb.xmin:.2f}, {bb.ymin:.2f}, {bb.zmin:.2f}) - "
          f"({bb.xmax:.2f}, {bb.ymax:.2f}, {bb.zmax:.2f})")
    
    # 体积
    vol = model.val().Volume()
    print(f"体积: {vol:.2f} mm³")
    
    # 面数和边数
    num_faces = len(model.faces().vals())
    num_edges = len(model.edges().vals())
    print(f"面数: {num_faces}")
    print(f"边数: {num_edges}")

# 使用
model = cq.Workplane("XY").box(30, 20, 10)
debug_model(model, "测试盒子")

7.8.3 选择器验证

import cadquery as cq

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

# 验证选择器
def test_selector(model, selector_str, element_type="faces"):
    """测试选择器是否正确选择元素"""
    try:
        if element_type == "faces":
            selected = model.faces(selector_str)
        elif element_type == "edges":
            selected = model.edges(selector_str)
        elif element_type == "vertices":
            selected = model.vertices(selector_str)
        
        count = len(selected.vals())
        print(f"选择器 '{selector_str}' ({element_type}): 选中 {count} 个元素")
        return True
    except Exception as e:
        print(f"选择器 '{selector_str}' 错误: {e}")
        return False

# 测试各种选择器
test_selector(model, ">Z")
test_selector(model, "<Z")
test_selector(model, "|Z", "edges")
test_selector(model, "#Z", "edges")

7.9 本章小结

本章介绍了CadQuery的高级建模技巧:

  1. 参数化设计

    • 参数定义和关联
    • 参数化函数
    • 配置驱动设计
  2. 复杂曲面

    • 样条曲面
    • 旋转曲面
    • 扫略和放样
  3. 图案和阵列

    • 矩形阵列
    • 极坐标阵列
    • 自定义阵列
  4. 镜像与对称

    • 平面镜像
    • 多轴对称
    • 旋转对称
  5. 布尔运算进阶

    • 复杂组合
    • 条件布尔
  6. 性能优化

    • 减少布尔运算
    • 简化几何
  7. 调试技巧

    • 中间结果可视化
    • 几何信息打印

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

  • 创建参数化的复杂模型
  • 使用高级曲面建模技术
  • 高效地创建图案和阵列
  • 优化模型性能
  • 有效调试CadQuery脚本

下一章我们将进入二次开发部分,学习如何扩展CadQuery功能。


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