This commit introduces several new scripts to the DXF project to improve diagnostics and data extraction capabilities: - find_block_coordinates.py: A new utility to accurately find the coordinates of rectangular blocks, which is essential for automated positioning and plotting. - diagnose_block_geometry.py: A script to analyze and report the geometric properties of blocks, aiding in debugging and validation. - list_layouts.py: A simple tool to list all available layouts within a DXF file. Associated documentation has been added to .specstory to cover these new features. |
||
|---|---|---|
| .. | ||
| .claude | ||
| .github/workflows | ||
| fonts | ||
| src/cad_automation | ||
| test_complete | ||
| test_complete2 | ||
| test_complete_render | ||
| test_correct | ||
| test_final | ||
| test_output | ||
| test_precise | ||
| test_results | ||
| tests | ||
| 模板 | ||
| .gitignore | ||
| add_text_to_specific_line.py | ||
| analyze_dxf_tables.py | ||
| column2.json | ||
| columns_template.json | ||
| config.example.json | ||
| diagnose_block_geometry.py | ||
| diagnose_blocks.py | ||
| draw_table_from_template.py | ||
| Drawing1_entities.json | ||
| empty_template.dxf | ||
| export_dxf.py | ||
| extract_entities_to_json.py | ||
| find_block_coordinates.py | ||
| generate_pattern_report.py | ||
| generate_template_from_json.py | ||
| head2.json | ||
| header_template.json | ||
| insert_tables_from_data.py | ||
| list_layouts.py | ||
| Makefile | ||
| my_snapshot.json | ||
| plot_by_block_name_simple.py | ||
| plot_by_block_name.py | ||
| pyproject.toml | ||
| README_IMPROVED.md | ||
| README.md | ||
| requirements.txt | ||
| run_workflow.py | ||
| test_bom_data.json | ||
| test_dxf_rw.py | ||
| test_workflow.py | ||
| 图签测试.bak | ||
| 图签测试.dxf | ||
Python + ODA + ezdxf: CAD自动化处理解决方案
🎯 项目目标
本部分旨在构建一个基于 Python 的自动化工作流程,用于对 CAD 文件(特别是 .dwg 和 .dxf)进行深度处理。它结合了外部转换工具的格式兼容性和 ezdxf 库强大的编程处理能力,以实现标准化的、可重复的、自动化的图纸操作。
✅ 当前能力
截至目前,本解决方案已具备以下核心能力:
- DWG to DXF 自动转换: 通过调用 ODA File Converter,将
.dwg文件无损转换为.dxf格式,作为后续处理的起点。 - 读取与查询 (Read/Query):
- 加载并解析 DXF 文件的完整结构。
- 使用强大的查询语句,精确查找符合特定条件的图形实体(例如,
查询所有颜色为蓝色的直线或查询特定图层上的所有文字)。 - 访问图形实体的所有属性(如坐标、长度、颜色、图层、文字内容等)。
- 写入与修改 (Write/Modify):
- 修改现有图形实体的属性(例如,批量更改颜色、移动位置)。
- 在图纸中添加新的图形实体,例如:
- 添加文字: 在指定坐标或相对某个元素的位置精确插入单行或多行文字。
- 添加几何图形: 创建新的线条、圆、多段线等。
- 格式转换 (Export):
- 将处理后的 DXF 内容高质量地渲染并输出为 PDF 文件,适用于存档和打印。
- 模板化绘图: 基于对现有图纸的几何分析,精确提取其完整的样式规范(包括所有线段、文字、尺寸、颜色、图层、对齐方式等),并将其固化为一个可复用的JSON模板。结合外部数据源,可以在任何DXF文件中100%精确地复制出符合原始设计意图的表格。
⚠️ 前置要求
在运行脚本之前,你 必须 满足以下两个条件:
-
安装 ODA File Converter:
- 这是一个免费的工具,用于在不同版本的 DWG 和 DXF 之间进行转换。
- 请从 Open Design Alliance 官网 下载并安装。
- 安装后,请务必检查
run_workflow.py等脚本中的ODA_CONVERTER_PATH变量,确保其指向你电脑上OdaFileConverter.exe的正确路径。
-
设置 Python 虚拟环境:
- 本项目已配置为使用虚拟环境,以避免与其他项目的依赖冲突。
- 运行
venv/Scripts/pip install -r requirements.txt来安装所有必要的依赖。
📂 文件说明
venv/: Python 虚拟环境目录。requirements.txt: 项目依赖库列表。run_workflow.py: 核心工作流脚本,演示 DWG -> DXF 转换和批量颜色修改。add_text_to_specific_line.py: 高级示例。演示如何查询特定条件(颜色、长度)的线段,并在其上方精确添加文字。convert_dxf_to_pdf.py: 高级示例。演示如何将 DXF 文件内容渲染为 PDF。图签测试.dxf: 用于测试的源 DXF 文件。extract_entities_to_json.py: (步骤1) 从一个作为“模板”的DXF文件中,提取所有线、文字及其完整属性(坐标、图层、颜色、对齐方式),并保存为一个JSON文件(“数字快照”)。generate_template_from_json.py: (步骤2) 读取“数字快照”,分析其结构和样式,并生成两个独立的、模块化的模板文件:header_template.json(定义表头几何) 和columns_template.json(定义数据列样式)。draw_table_from_template.py: (步骤3) 最终的“绘图引擎”。它会加载模块化的模板,并结合外部数据源 (一个JSON文件),在目标DXF中精确绘制表格。header_template.json/columns_template.json: 由步骤2生成的核心模板文件,实现了表头样式和数据列样式的分离。test_workflow.py: (测试) 一个自动化的测试脚本,用于执行完整的“绘图 -> 提取 -> 验证”流程,确保整个工作流的正确性和稳定性。test_bom_data.json: 为测试脚本提供标准化的输入数据。
🚀 如何运行 (模板化绘图工作流)
如何用于您自己的图纸 (分步指南)
本指南将向您展示如何使用您自己的DXF文件(包含一个您想复制的表格样式),来为您自己的数据创建模板,并最终将其绘制到任何目标DXF文件中。
准备工作:制作一个符合规范的“模板源DXF文件”
为了让脚本能正确工作,您需要准备一个DXF文件,它必须包含一个结构清晰的表格,并且这个表格应满足以下条件:
- 包含完整的表头:位于表格的最底部。
- 至少包含一行示例数据:位于表头的正上方。
您可以参考项目中的 04_Test_Files/Drawing1.dxf 作为标准示例。
第1步:从您的DXF中创建表格模板
假设您有一个名为 My_Table_Style.dxf 的文件,其中包含一个几何、样式都非常标准的表格。我们的目标就是将这个表格的“外观”提取出来,做成可复用的模板。
1.1. 将DXF的几何信息提取为JSON快照
运行 extract_entities_to_json.py 脚本,告诉它读取您的DXF文件,并将结果保存为一个“数字快照”JSON文件。
# 用法: python extract_entities_to_json.py <您的源DXF> <输出的JSON快照>
./venv/Scripts/python 03_Python_OpenSource_DXF/extract_entities_to_json.py "C:/path/to/My_Table_Style.dxf" 03_Python_OpenSource_DXF/my_snapshot.json
1.2. 从JSON快照生成模块化模板
现在,运行 generate_template_from_json.py 脚本,它会读取上一步生成的快照文件,并自动分析、拆分,生成两个核心模板。
# 用法: python generate_template_from_json.py <输入的JSON快照> <输出的表头模板> <输出的列模板>
./venv/Scripts/python 03_Python_OpenSource_DXF/generate_template_from_json.py 03_Python_OpenSource_DXF/my_snapshot.json 03_Python_OpenSource_DXF/my_header_template.json 03_Python_OpenSource_DXF/my_columns_template.json
完成这一步后,您就已经成功地将您图纸中的表格样式“数字化”并保存为了 my_header_template.json 和 my_columns_template.json。
第2步:准备您的数据
接下来,您需要按照指定的格式创建一个JSON文件来存放您想填入表格的数据。您可以参考项目中的 test_bom_data.json 文件。
核心格式是一个列表,其中每个对象代表一行。对象的键(Key)必须与您的 columns_template.json 中定义的 name 相匹配。
my_data.json 示例:
[
{
"件 号": {"main": "A-001"},
"名 称": {"chinese_name": "轴承", "english_name": "Bearing"},
"数量": {"main": "10"},
"材 料": {"main": "GCr15"},
"单": {"main": "5.5"},
"总": {"main": "55.0"},
"备 注": {"main": "进口"}
},
{
"件 号": {"main": "A-002"},
"名 称": {"chinese_name": "螺栓", "english_name": "Bolt"},
"数量": {"main": "100"},
"材 料": {"main": "35#"},
"单": {"main": "0.2"},
"总": {"main": "20.0"},
"备 注": {"main": "M8x20"}
}
]
请将您的数据保存为一个文件,例如 my_data.json。
第3步:将数据绘制到目标DXF文件
万事俱备!现在运行 draw_table_from_template.py 脚本,将您的模板、您的数据和您的目标文件作为参数传入。
最重要的,您现在可以通过 --x 和 --y 参数来指定插入坐标,并通过 --anchor 参数来定义这些坐标所对应的锚点。
锚点选项:
bottom-left(默认):(x, y)是表格的左下角。bottom-right:(x, y)是表格的右下角。top-left:(x, y)是表格的左上角。top-right:(x, y)是表格的右上角。
# 用法: python draw_table_from_template.py <目标DXF> <您的表头模板> <您的列模板> <您的数据JSON> <输出DXF> --x <X坐标> --y <Y坐标> --anchor <锚点>
./venv/Scripts/python 03_Python_OpenSource_DXF/draw_table_from_template.py "C:/path/to/target_drawing.dxf" "C:/path/to/my_header_template.json" "C:/path/to/my_columns_template.json" "C:/path/to/my_data.json" "C:/path/to/output_with_table.dxf" --x 420 --y 297 --anchor top-right
执行完毕后,output_with_table.dxf 文件的右上角将被精确定位在 (420, 297) 坐标点,并出现一个根据您的样式和数据绘制好的、崭新的表格。
(附) 运行自动化测试
为了确保所有脚本功能正常,可以随时运行测试套件。
# 运行端到端测试
./venv/Scripts/python 03_Python_OpenSource_DXF/test_workflow.py
📘 核心概念:模板化绘图
我们的解决方案核心是将CAD设计规范转化为一个机器可读的JSON模板。当前版本的核心工作原理基于一个简单而明确的几何假设:
- 基于几何的区域识别: 脚本通过分析DXF文件中的所有水平线来识别表格的行结构。
- “表头在底部”的核心假设: 脚本假定表格最底部的区域是表头,而表头之上的区域是数据区。为了让模板能被正确提取,您作为模板的源DXF文件应遵循此结构。
- 精确复制: 脚本会提取出表头区域内所有的文字、线条及其完整的几何属性(坐标、尺寸、对齐方式、颜色、图层等),确保生成的表头与原始设计100%一致。
- 数据模板化: 脚本会分析紧邻表头上方的第一行数据,并将其样式(文字的相对位置、字体、高度等)作为后续所有数据行的统一模板。
📘 核心操作指南 (ezdxf)
本节提供核心的代码片段,作为未来功能开发的快速参考。
1. 读取和查询 DXF 文件
import ezdxf
# 加载 DXF 文件
try:
doc = ezdxf.readfile("图签测试.dxf")
msp = doc.modelspace() # 获取模型空间
# --- 查询操作 ---
# 1. 查询所有颜色为蓝色(5)的直线
query = 'LINE[color==5]'
blue_lines = msp.query(query)
print(f"找到了 {len(blue_lines)} 条蓝色的线。")
# 2. 遍历查询结果并访问属性
for line in blue_lines:
start_point = line.dxf.start
end_point = line.dxf.end
length = start_point.distance(end_point)
print(f" - 线段长度: {length:.2f}, "
f"起点: ({start_point.x:.2f}, {start_point.y:.2f})")
except IOError:
print("无法读取文件。")
except Exception as e:
print(f"发生错误: {e}")
2. 修改和写入 DXF 文件
import ezdxf
from ezdxf.math import Vec3
# 加载 DXF 文件
try:
doc = ezdxf.readfile("图签测试.dxf")
msp = doc.modelspace()
# --- 修改操作 ---
# 1. 将所有图元颜色改为红色(1)
for entity in msp:
if entity.dxf.hasattr('color'):
entity.dxf.color = 1 # 1 代表红色
# --- 写入/添加操作 ---
# 2. 添加一个新的文字样式 (如果不存在)
if "MyTextStyle" not in doc.styles:
# 使用宋体 (simsun.ttc)。确保操作系统中存在此字体
doc.styles.new("MyTextStyle", dxfattribs={"font": "simsun.ttc"})
# 3. 在指定位置添加多行文字 (MTEXT)
msp.add_mtext(
"这是新添加的文字",
dxfattribs={
'char_height': 10.0, # 文字高度
'style': 'MyTextStyle', # 应用我们创建的样式
'color': 2, # 颜色为黄色
}
).set_placement(
insert=Vec3(100, 100, 0), # 插入点坐标
align=ezdxf.enums.TextEntityAlignment.MIDDLE_CENTER
)
# 4. 使用对齐方式添加单行文字 (TEXT)
msp.add_text(
"中心对齐",
height=2.5,
dxfattribs={
'style': 'Standard',
'color': 3,
}
).set_placement(
Vec3(200, 100, 0),
align=ezdxf.enums.TextEntityAlignment.MIDDLE_CENTER
)
# 保存修改后的文件
output_path = "修改后的文件.dxf"
doc.saveas(output_path)
print(f"文件已成功保存到: {output_path}")
except IOError:
print("无法读取文件。")
except Exception as e:
print(f"发生错误: {e}")