夜雨聆风学习资料网

ARTICLE · 1086004

实战|用 AI 写 CAD 插件:单线变层板侧板(附源码+提示词)

实战|用 AI 写 CAD 插件:单线变层板侧板(附源码+提示词)
这是《零基础 CAD 插件从 0 到 1》第 9 篇

做全屋定制的设计师都知道,我们一般画内部结构都是先分好门板,再去定内部结构,当把门板的图复制过来后画内部结构就得去做左右偏移,操作起来还是很繁琐的。特别有时候偏移错了门缝就对不到。拆单就会发现问题。

今天咱们用 AI 写一个提升画板效率的 CAD 插件:选中单线一键生成板厚。不用反复偏移。直接节省操作步骤,并支持设置厚度,设置板厚方向,是居中还是左偏移还是右偏移。

先看效果:选一根线,秒变标准板件

先上动图看实际操作:

实例演示

不用反复输偏移命令,删除多余的线。

这个插件解决了什么问题?

针对画板件的重复劳动痛点,做了几个核心优化:

  1. 一键单线转板件
    选中定位单线,一键生成对应厚度的双线板件,不用再手动输入偏移距离、来回修剪。
  2. 板厚灵活可调
    默认常用的 18mm 板材厚度,也可以根据需求自己改数值,适配 9mm、25mm 等不同板材。
  3. 批量转换高效
    支持同时选多根单线,一次性全部转成板件,几十根线也能几秒搞定,不用一根根改。

交互设计:贴合画图习惯,三步搞定

完全按照设计师日常画线的操作逻辑设计,不用学新操作:

  1. 启动命令
    :输入 KJBoard 回车,启动转换功能
  2. 选择单线
    :框选要转成板件的定位单线
  3. 生成板件
    :无需多余操作,命令会自动判定,是竖线还是横线
没有多余设置,和平时用 CAD 命令的操作一模一样,拿到手就能用。

核心干货:给 AI 的精准提示词

还是那句话

用 AI 写插件出来的功能不对,本质是需求没说细。AI 就像助理,你说清楚规则,它才能做准。下面是实测多轮、输出稳定能用的提示词模板,直接复制就能用:

角色设定
:你是资深 AutoCAD .NET 二次开发工程师,精通 C# 与 CAD的API,面向全屋定制设计与报价场景开发插件。

功能需求

:开发一个「单线转层板侧板」插件,具体要求:

命令名:KJBoard
交互逻辑:
输入命令-->提示用户选择直线-->然后插件会自动判断是水平的线还是垂直的线,判断完之后就直接生成 层板或者是侧板,并删除原来选择的线。提示完成。生成了几个层板几个侧板。
生成逻辑:
以选中的单线为中心,向两侧对称偏移生成双线,默认板厚 18mm,可通过参数调整厚度,并创建实时预览。预览颜色为淡黄色
环境:
.NET Framework 4.8,AutoCAD 2021,引用 AcMgd、AcDbMgd

输出要求:

给出完整可复制编译的代码
关键逻辑加中文注释
说明编译和加载方法

写提示词的核心原则

  1. 先定身份
    先让 AI 进入专业 CAD 开发的角色,避免用错 API、写出行外代码。
  2. 再划边界
    明确命令名、CAD 版本、运行环境,从根源减少兼容问题和报错。
  3. 讲清规则
    怎么选、怎么生成、图层怎么分,每一步规则都说死,不给 AI 自由发挥的空间。
  4. 固定格式
    要完整代码、要注释、要部署说明,都明确提出来,输出直接能用。

照着这个结构写,AI 输出代码的可用率至少提升 80%。

其实AI给的东西好不好,就看你提示词写得好不好细不细。

核心源码分享

using System;using System.Collections.Generic;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.Colors;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.Runtime;namespace KJBoardPlugin{    /// <summary>    /// 单线转层板/侧板插件    /// 命令:KJBoard    /// 流程:选择直线[S设置板厚] → 回车 → 淡黄预览 → 点击确认 → 恢复颜色 + 删原线    /// </summary>    public class KJBoardCommand    {        private const double DefaultThickness = 18.0;        // 预览色:淡黄色        private static readonly Color PreviewColor = Color.FromRgb(255, 255, 150);        [CommandMethod("KJBoard")]        public void KJBoard()        {            Document doc = Application.DocumentManager.MdiActiveDocument;            Editor ed = doc.Editor;            Database db = doc.Database;            double thickness = DefaultThickness;            // 选择过滤器:只允许 LINE            SelectionFilter sf = new SelectionFilter(new TypedValue[] {                new TypedValue((int)DxfCode.Start, "LINE")            });            // ============ 1. 循环提示:选择直线 或 [S]设置板厚 ============            PromptSelectionResult psr = null;            while (true)            {                PromptSelectionOptions pso = new PromptSelectionOptions();                pso.MessageForAdding =                    $"\n请选择直线 (当前板厚 {thickness:F1}mm)";                // 添加 [设置板厚(S)] 关键字,AutoCAD 自动拼到提示末尾                pso.Keywords.Add("S", "S", "设置板厚");                psr = ed.GetSelection(pso, sf);                // ESC 取消                if (psr.Status == PromptStatus.Cancel)                {                    ed.WriteMessage("\n已取消。");                    return;                }                // 用户按了 S(只有一个关键字,判定状态即可)                if (psr.Status == PromptStatus.Keyword)                {                    PromptDoubleOptions pdo = new PromptDoubleOptions(                        $"\n请输入板厚(mm) <{thickness:F1}> ");                    pdo.DefaultValue = thickness;                    pdo.UseDefaultValue = true;                    pdo.AllowNegative = false;                    pdo.AllowZero = false;                    PromptDoubleResult pdr = ed.GetDouble(pdo);                    if (pdr.Status == PromptStatus.OK)                        thickness = pdr.Value;                    continue;   // 回到选择提示                }                // 正常选到对象                if (psr.Status == PromptStatus.OK)                {                    if (psr.Value.Count == 0)                    {                        ed.WriteMessage("\n未选择直线,请重新选择。");                        continue;                    }                    break;                }            }            double halfThickness = thickness / 2.0;            // ============ 2. 计算偏移双线 ============            List<Line> previewLines = new List<Line>();            List<ObjectId> sourceIds = new List<ObjectId>();            List<int> sourceColors = new List<int>();            int layerCount = 0;            int sideCount = 0;            using (Transaction tr = db.TransactionManager.StartTransaction())            {                foreach (SelectedObject so in psr.Value)                {                    if (so == null) continue;                    Line srcLine = tr.GetObject(so.ObjectId, OpenMode.ForRead) as Line;                    if (srcLine == null) continue;                    sourceIds.Add(so.ObjectId);                    sourceColors.Add(srcLine.ColorIndex);                    Point3d sp = srcLine.StartPoint;                    Point3d ep = srcLine.EndPoint;                    // 方向判断:水平→层板;垂直→侧板                    double dx = Math.Abs(ep.X - sp.X);                    double dy = Math.Abs(ep.Y - sp.Y);                    if (dx >= dy) layerCount++;                    else sideCount++;                    // 法向量                    Vector3d dir = (ep - sp).GetNormal();                    Vector3d normal = new Vector3d(-dir.Y, dir.X, 0);                    // 对称偏移半个板厚                    Line l1 = new Line(sp + normal * halfThickness, ep + normal * halfThickness);                    Line l2 = new Line(sp - normal * halfThickness, ep - normal * halfThickness);                    l1.Color = PreviewColor;                    l2.Color = PreviewColor;                    previewLines.Add(l1);                    previewLines.Add(l2);                }            }            if (previewLines.Count == 0) { ed.WriteMessage("\n未生成任何板件。"); return; }            // ============ 3. 临时插入数据库作为预览 ============            List<ObjectId> previewIds = new List<ObjectId>();            using (Transaction tr = db.TransactionManager.StartTransaction())            {                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;                BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace],                                                    OpenMode.ForWrite) as BlockTableRecord;                foreach (Line ln in previewLines)                {                    btr.AppendEntity(ln);                    tr.AddNewlyCreatedDBObject(ln, true);                    previewIds.Add(ln.ObjectId);                }                tr.Commit();            }            ed.UpdateScreen();            // ============ 4. 等待用户点击确认(已移除 UserInputControls 那行) ============            PromptPointOptions ppo = new PromptPointOptions(                "\n点击鼠标左键确认生成板件,或按 ESC 取消 ");            PromptPointResult ppr = ed.GetPoint(ppo);            if (ppr.Status != PromptStatus.OK)            {                // 取消:删除预览线                using (Transaction tr = db.TransactionManager.StartTransaction())                {                    foreach (ObjectId id in previewIds)                    {                        Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;                        if (ent != null) ent.Erase();                    }                    tr.Commit();                }                ed.UpdateScreen();                ed.WriteMessage("\n已取消,未生成板件。");                return;            }            // ============ 5. 确认:恢复颜色 + 删除原线 ============            using (Transaction tr = db.TransactionManager.StartTransaction())            {                // 5.1 恢复颜色                for (int i = 0; i < previewIds.Count; i++)                {                    Entity ent = tr.GetObject(previewIds[i], OpenMode.ForWrite) as Entity;                    if (ent != null)                    {                        int srcIdx = i / 2;                        ent.ColorIndex = (srcIdx < sourceColors.Count)                            ? sourceColors[srcIdx]                            : 256;                    }                }                // 5.2 删除原线                foreach (ObjectId id in sourceIds)                {                    Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;                    if (ent != null) ent.Erase();                }                tr.Commit();            }            ed.UpdateScreen();            // ============ 6. 统计输出 ============            ed.WriteMessage(                $"\n绘制完成!共生成 {layerCount} 个层板,{sideCount} 个侧板 " +                $"(板厚 {thickness:F1}mm)。");        }    }}

用 AI 开发插件的完整流程

这类效率型小插件,用 AI 分步开发,上手最快:

  1. 需求拆解
    把 “单线转板件” 拆成「选择直线→偏移生成→设置参数→实时预览」几个模块,逐个让 AI 实现,不要一次性丢完整需求。
  2. 分步验证
    先写选择和偏移逻辑,测准生成的板厚和方向;再加可调参数,实时预览。每一步跑通再往下,出问题好定位。
  3. 实测优化
    拿真实柜体图测试:比如斜线、短线、不同角度的线,看生成的板件是否正常;把遇到的问题丢给 AI,让它优化偏移逻辑。
  4. 细节调整
    比如默认板厚、预览颜色、线型,都可以根据自己的出图标准改,让 AI 直接调参数就行。

成品领取 / 下期预告

成品插件直接领

不想自己折腾的朋友,关注公众号 「下班让AI教我做插件」,后台回复 「层板侧板」,直接领取编译好的 DLL 插件文件,NETLOAD 加载即用或者使用插件加载工具。 完整工程源码 拿到手就能使用。

下期预告

下一篇咱们继续深化设计提效工具:设置标注

我是做插件的设计师,专注用 AI 提高 CAD 设计效率。 关注我,下班一起做插件,把重复工作交给程序。

相关学习资料