用AI自动标准化CAD 图层标准化

在建筑和工程办公室中,最重复且容易出错的任务之一是标准化 AutoCAD 图纸。

用AI自动标准化CAD 图层标准化
AI编程/Vibe Coding 遇到问题需要帮助的,联系微信 ezpoda,免费咨询。

在建筑和工程办公室中,最重复且容易出错的任务之一是标准化 AutoCAD 图纸。每个顾问和分包商都使用自己的命名图层的约定。结构顾问可能使用 SLAB_GF,而另一个可能使用 FLOOR_1。在团队能够生成数量、协调模型或提取有意义的数据之前,所有图层必须组织成一组一致的类别。

手动执行此操作既耗时又有错误风险。更好的方法是结合自动化和人工智能。

1、方法

我构建的工作流使用 Python 和 AI 模型来自动化图层标准化的第一遍,同时仍然让工程师控制审查和调整映射。主要步骤是:

  1. 使用 ezdxf 库从 DXF 文件中提取所有图层。
  2. 询问 AI 模型(本地使用 Ollama 服务)提出标准化的工程类别。这些类别不限于固定列表 —— 它们会根据图纸进行调整。
  3. 询问 AI 将每个图层分类为类别之一。
  4. 向用户显示 GUI,显示所有图层、建议的映射和用于覆盖的下拉菜单。下拉菜单始终包含一组预期的基准类别(COLUMNS、WALLS、SLABS、BEAMS、STAIRS、FOOTINGS、OTHER),因此即使用户错过了 AI,用户也可以重新分配图层。
  5. 保存一个新的 DXF 文件,其中图层已标准化并使用颜色编码:
  • OTHER 始终为灰色。
  • 常见类别被分配有意义的颜色(例如,COLUMNS = 红色,WALLS = 绿色)。
  • 任何新的 AI 建议的类别都会自动获得独特的颜色。

2、Python 脚本

以下是完整脚本(normalize_ai_ollama_gui_open.py)。它连接到 Ollama 的本地 API,生成建议,显示 GUI 供审查,并保存标准化的 DXF。

import ezdxf
import requests
import tkinter as tk
from tkinter import ttk
import sys

OLLAMA_URL = "http://localhost:11434/api/generate"
OLLAMA_MODEL = "llama3.2"
DEFAULT_CATEGORIES = ["COLUMNS", "WALLS", "BEAMS", "SLABS", "STAIRS", "FOOTINGS", "OTHER"]
CATEGORY_COLORS = {
    "OTHER": 8,      # gray
    "COLUMNS": 1,    # red
    "WALLS": 3,      # green
    "BEAMS": 5,      # blue
    "SLABS": 6,      # magenta
    "STAIRS": 2,     # yellow
    "FOOTINGS": 4,   # cyan
}
def ask_ollama(prompt: str, timeout=120) -> str:
    payload = {"model": OLLAMA_MODEL, "prompt": prompt, "stream": False}
    try:
        r = requests.post(OLLAMA_URL, json=payload, timeout=timeout)
        r.raise_for_status()
        return r.json().get("response", "").strip()
    except:
        return ""
def suggest_categories(layers):
    prompt = (
        "You are a civil/structural engineer working with AutoCAD drawings.\n"
        f"Here are the layer names: {', '.join(layers)}.\n\n"
        "Suggest a concise list of normalized categories that best describe these layers. "
        "Return only a comma-separated list of categories."
    )
    raw = ask_ollama(prompt)
    ai_cats = [c.strip().upper() for c in raw.split(",") if c.strip()]
    return sorted(set(ai_cats) | set(DEFAULT_CATEGORIES))
def classify_layer(layer_name, categories):
    prompt = (
        f"Classify the CAD layer '{layer_name}' into one of these categories: {', '.join(categories)}. "
        "Answer with only the category."
    )
    raw = ask_ollama(prompt).upper()
    for c in categories:
        if c in raw:
            return c
    return "OTHER"
def build_gui(layer_names, suggestions, categories):
    root = tk.Tk()
    root.title("DXF Layer Normalizer")
    mapping = {}
    canvas = tk.Canvas(root)
    frame = tk.Frame(canvas)
    scrollbar = tk.Scrollbar(root, orient="vertical", command=canvas.yview)
    canvas.configure(yscrollcommand=scrollbar.set)
    scrollbar.pack(side="right", fill="y")
    canvas.pack(side="left", fill="both", expand=True)
    canvas.create_window((0,0), window=frame, anchor="nw")
    def on_frame_configure(event):
        canvas.configure(scrollregion=canvas.bbox("all"))
    frame.bind("<Configure>", on_frame_configure)
    for i, layer in enumerate(layer_names):
        tk.Label(frame, text=layer).grid(row=i, column=0, sticky="w", padx=5, pady=2)
        cb = ttk.Combobox(frame, values=categories, state="readonly", width=20)
        cb.set(suggestions[layer])
        cb.grid(row=i, column=1, padx=5, pady=2)
        mapping[layer] = cb
    result = {}
    def save_and_exit():
        nonlocal result
        result = {layer: cb.get() for layer, cb in mapping.items()}
        root.destroy()
    tk.Button(frame, text="Confirm", command=save_and_exit).grid(
        row=len(layer_names)+1, column=0, columnspan=2, pady=10)
    root.mainloop()
    return result
def assign_colors(categories):
    used_colors = set(CATEGORY_COLORS.values())
    next_color = 1
    color_map = {}
    for cat in categories:
        if cat in CATEGORY_COLORS:
            color_map[cat] = CATEGORY_COLORS[cat]
        else:
            while next_color in used_colors and next_color <= 255:
                next_color += 1
            if next_color > 255:
                next_color = 7
            color_map[cat] = next_color
            used_colors.add(next_color)
    return color_map
def normalize_drawing(input_file, output_file):
    doc = ezdxf.readfile(input_file)
    msp = doc.modelspace()
    layers = sorted({e.dxf.layer for e in msp})
    print(f"Found {len(layers)} layers")
    categories = suggest_categories(layers)
    print(f"Categories available: {categories}")
    suggestions = {layer: classify_layer(layer, categories) for layer in layers}
    print("AI suggestions:")
    for orig, cat in suggestions.items():
        print(f"  {orig} -> {cat}")
    final_mapping = build_gui(layers, suggestions, categories)
    print("Final mapping confirmed:", final_mapping)
    color_map = assign_colors(categories)
    print("Assigned colors:", color_map)
    for cat in categories:
        if cat not in doc.layers:
            layer = doc.layers.new(name=cat)
        else:
            layer = doc.layers.get(cat)
        layer.color = color_map[cat]
    for e in msp:
        orig = e.dxf.layer
        new = final_mapping.get(orig, "OTHER")
        e.dxf.layer = new
        e.dxf.color = 256
    doc.saveas(output_file)
    print(f"Normalized drawing saved as {output_file}")
if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("Usage: python normalize_ai_ollama_gui_open.py input.dxf output.dxf")
        sys.exit(1)
    normalize_drawing(sys.argv[1], sys.argv[2])

3、实践中的工作流

  • 使用输入 DXF 运行脚本并指定输出 DXF。
  • AI 提出类别(例如,SLABS、WALLS、BEAMS、ELECTRICAL、HVAC)。
  • 每个图层被分配给这些类别之一。
  • GUI 显示所有图层及其建议的映射。下拉菜单包括 AI 建议的类别和默认预期类别,因此用户可以轻松地重新分配。
  • 确认后,生成一个新的 DXF,其中包含标准化的图层和一致的颜色。

4、结束语

此工作流程简化了准备图纸中的一个痛苦但必要的步骤。工程师可以节省时间、避免错误,并且可以更快地转移到下游任务,如数量提取、协调和文档。AI 加速分类,同时 GUI 确保人类专业知识仍然在循环中。


原文链接: Automating CAD Layer Normalization with AI and Python

汇智网翻译整理,转载请标明出处