FreeCAD 批量获取Step文件各零件包围盒尺寸
使其能够自动识别 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)
主要修改点说明
- 移除全局边界框合并:原代码通过
combined_box.union将所有形状合并为一个整体边界框,现改为逐个形状处理。 - 单独处理每个对象:遍历
doc.Objects中所有带有Shape属性的对象,为每个对象独立计算边界框尺寸和体积。 - 添加序号:使用
enumerate(shapes, start=1)为每个文件内的部件生成连续序号,并作为新列写入 CSV。 - 更新 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_folder、if __name__ == "__main__" 等)保持不变即可直接使用。
评论功能已关闭