使其能够自动识别 STEP 文件中的每个独立部件(即导入后的每个对象),为每个部件单独计算其边界框尺寸和体积,并生成序号(同一文件内从 1 开始递增)。输出 CSV 文件在原有列(文件名、长、宽、高、三维尺寸、体积)前增加一列“序号”,其他格式处理(如尺寸整数化、保留两位小数)保持不变。

修改后的完整脚本 BatchStepBBox

# -*- coding: utf-8 -*-
import os
import csv
import FreeCAD
import Part
from PySide2 import QtWidgets

def select_folder():
    """弹出文件夹选择对话框,返回所选文件夹路径"""
    folder = QtWidgets.QFileDialog.getExistingDirectory(
        None,
        "选择包含 STEP 文件的文件夹",
        "",
        QtWidgets.QFileDialog.ShowDirsOnly
    )
    return folder

def format_dimension(value):
    """
    格式化尺寸值:如果是整数则返回整数形式,否则保留两位小数
    """
    # 判断是否为整数(容差1e-6)
    if abs(value - round(value)) < 1e-6:
        return str(int(round(value)))
    else:
        return f"{value:.2f}"

def process_step_files(folder_path, output_csv):
    """
    批量处理文件夹内的STEP文件,识别每个独立部件,提取尺寸并导出为CSV
    """
    extensions = ('.step', '.stp')
    results = []

    for filename in os.listdir(folder_path):
        if filename.lower().endswith(extensions):
            file_path = os.path.join(folder_path, filename)
            print(f"正在处理: {filename}")

            try:
                doc = FreeCAD.newDocument("TempDoc")
                Part.insert(file_path, doc.Name)

                # 收集所有具有形状的对象
                shapes = [obj for obj in doc.Objects if hasattr(obj, 'Shape') and obj.Shape]

                if not shapes:
                    print(f"警告: {filename} 没有有效形状")
                    FreeCAD.closeDocument(doc.Name)
                    continue

                # 为每个对象单独处理
                for idx, obj in enumerate(shapes, start=1):
                    bbox = obj.Shape.BoundBox
                    # 获取三边长度并排序(长、宽、高)
                    lengths = [bbox.XLength, bbox.YLength, bbox.ZLength]
                    lengths.sort(reverse=True)
                    length, width, height = lengths
                    volume = length * width * height

                    # 格式化
                    length_str = format_dimension(length)
                    width_str = format_dimension(width)
                    height_str = format_dimension(height)
                    dimension_str = f"{length_str}*{width_str}*{height_str}"
                    volume_str = format_dimension(volume)

                    results.append([
                        filename,
                        idx,                     # 新增序号
                        length_str,
                        width_str,
                        height_str,
                        dimension_str,
                        volume_str
                    ])

                FreeCAD.closeDocument(doc.Name)

            except Exception as e:
                print(f"处理 {filename} 时出错: {e}")

    # 写入CSV文件(表头增加“序号”列)
    with open(output_csv, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(['文件名', '序号', '长', '宽', '高', '三维尺寸', '体积(mm³)'])
        writer.writerows(results)

    print(f"处理完成,结果保存至: {output_csv}")

if __name__ == "__main__":
    folder = select_folder()
    if not folder:
        print("未选择文件夹,程序退出。")
        exit()

    output = os.path.join(folder, "dimensions.csv")
    process_step_files(folder, output)

主要修改点说明

  1. 移除全局边界框合并:原代码通过 combined_box.union 将所有形状合并为一个整体边界框,现改为逐个形状处理。
  2. 单独处理每个对象:遍历 doc.Objects 中所有带有 Shape 属性的对象,为每个对象独立计算边界框尺寸和体积。
  3. 添加序号:使用 enumerate(shapes, start=1) 为每个文件内的部件生成连续序号,并作为新列写入 CSV。
  4. 更新 CSV 表头:在输出列中加入“序号”列,位于文件名之后。

效果示例

假设一个 STEP 文件中包含 3 个独立部件,CSV 将输出如下内容:

文件名 序号 三维尺寸 体积(mm³)
part1.step 1 100 50 20 1005020 100000
part1.step 2 80 60 30 806030 144000
part1.step 3 40 40 40 404040 64000

注意事项

  • 本方法将导入 STEP 后 FreeCAD 文档中的每个独立对象视为一个“件”。若 STEP 中某些零件由多个对象组成(如装配体),仍会分别列出,如需合并请另行说明。
  • 原脚本中的 format_dimension 函数未作改动,尺寸格式化规则保持不变。
  • 若某个文件无有效形状,会给出警告并跳过。

可以将上述函数替换原脚本中的对应部分,其余代码(如 select_folderif __name__ == "__main__" 等)保持不变即可直接使用。