# Python + ODA + ezdxf: CAD自动化处理解决方案 ## 🎯 项目目标 本部分旨在构建一个基于 Python 的自动化工作流程,用于对 CAD 文件(特别是 `.dwg` 和 `.dxf`)进行深度处理。它结合了外部转换工具的格式兼容性和 `ezdxf` 库强大的编程处理能力,以实现标准化的、可重复的、自动化的图纸操作。 ## ✅ 当前能力 截至目前,本解决方案已具备以下核心能力: 1. **DWG to DXF 自动转换**: 通过调用 ODA File Converter,将 `.dwg` 文件无损转换为 `.dxf` 格式,作为后续处理的起点。 2. **读取与查询 (Read/Query)**: * 加载并解析 DXF 文件的完整结构。 * 使用强大的查询语句,精确查找符合特定条件的图形实体(例如,`查询所有颜色为蓝色的直线` 或 `查询特定图层上的所有文字`)。 * 访问图形实体的所有属性(如坐标、长度、颜色、图层、文字内容等)。 3. **写入与修改 (Write/Modify)**: * 修改现有图形实体的属性(例如,批量更改颜色、移动位置)。 * 在图纸中添加新的图形实体,例如: * **添加文字**: 在指定坐标或相对某个元素的位置精确插入单行或多行文字。 * **添加几何图形**: 创建新的线条、圆、多段线等。 4. **格式转换 (Export)**: * 将处理后的 DXF 内容高质量地渲染并输出为 **PDF** 文件,适用于存档和打印。 * **模板化绘图**: 基于对现有图纸的几何分析,精确提取其完整的样式规范(包括所有线段、文字、尺寸、颜色、图层、对齐方式等),并将其固化为一个可复用的JSON模板。结合外部数据源,可以在任何DXF文件中**100%精确地复制**出符合原始设计意图的表格。 ## ⚠️ 前置要求 在运行脚本之前,你 **必须** 满足以下两个条件: 1. **安装 ODA File Converter**: * 这是一个免费的工具,用于在不同版本的 DWG 和 DXF 之间进行转换。 * 请从 [Open Design Alliance 官网](https://www.opendesign.com/guestfiles/oda-file-converter) 下载并安装。 * 安装后,请**务必**检查 `run_workflow.py` 等脚本中的 `ODA_CONVERTER_PATH` 变量,确保其指向你电脑上 `OdaFileConverter.exe` 的正确路径。 2. **设置 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)** 读取“数字快照”,分析其结构和样式(包括表头内部的所有复杂线段),并生成一个可复用的 `bom_template.json` 表格定义模板。 - `draw_table_from_template.py`: **(步骤3)** 最终执行脚本。它会加载`bom_template.json`模板,结合外部数据(脚本内预设),在目标DXF文件中精确绘制出完整的、几何上完全一致的表格。 - `bom_template.json`: 由步骤2生成的核心“蓝图”文件。它以机器可读的方式,精确定义了表格的所有几何与样式规范。**通过修改和使用此模板,可以实现对DXF文件的精准、自动化写入,是本方案最重要的部分**。 ## 🚀 如何运行 (模板化绘图工作流) ### 1. 准备工作 (仅需一次) 确保 `requirements.txt` 中的依赖已安装: ```shell ./venv/Scripts/pip install -r requirements.txt ``` ### 2. (可选) 生成或更新模板 如果您有一个新的、符合规范的DXF文件 (`source.dxf`),并希望基于它来创建或更新绘图模板,请按顺序执行以下脚本: ```shell # 步骤 1: 将DXF文件的几何信息提取为JSON # 注意:需要修改脚本内的源文件路径 ./venv/Scripts/python extract_entities_to_json.py # 步骤 2: 从JSON信息生成可复用的bom_template.json ./venv/Scripts/python generate_template_from_json.py ``` ### 3. 使用模板绘制表格 这是最终的执行步骤。此脚本会加载 `bom_template.json` 和内置的示例数据,在 `04_Test_Files/料表.dxf` 中绘制一个新表格,并输出到 `04_Test_Files/料表_with_template_table.dxf`。 ```shell # 步骤 3: 执行绘图 ./venv/Scripts/python draw_table_from_template.py ``` ### 4. 查看结果 脚本执行后,生成的目标文件 `料表_with_template_table.dxf` 会被保存在 `04_Test_Files/` 文件夹中。 --- ## 📘 核心概念:模板化绘图 我们的解决方案核心是将CAD设计规范转化为一个机器可读的JSON模板 (`bom_template.json`)。 - **几何与样式分离**: 模板定义了表格的“外观”(线的位置、文字的相对位置、大小、字体、图层、颜色、**对齐方式**),而数据(如“新零件-A”、“Q345R”)则由外部提供。 - **精确复制**: 通过提取现有图纸的完整几何属性(包括**每一根线段**和每一个文本的**对齐方式**),模板可以确保新生成的表格在每一个细节上都与原始设计意图保持一致,完美处理合并单元格等复杂样式。 - **自动化**: 一旦模板建立,就可以用程序结合任意数据源(Excel, 数据库等),批量、快速、无差错地生成符合规范的图纸。 - **模板复用与拆分**: `bom_template.json` 文件本身也可以被视为一个基础模板。在实际应用中,可以将其中定义的 `header_definition` (表头) 和 `column_definitions` (列样式) 拆分保存。这样,同一个表头可以方便地与多批次、不同来源的数据结合,生成不同的物料清单,进一步提高自动化效率。 ## 📘 核心操作指南 (ezdxf) 本节提供核心的代码片段,作为未来功能开发的快速参考。 ### 1. 读取和查询 DXF 文件 ```python 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 文件 ```python 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}") ```