ARTICLE · 1048985
实战|用 AI 写 CAD 插件:一键画层板(附源码+提示词)
上一篇我们把门板铰链孔跑通了,后台有读者留言:“层板能不能也搞一个?每次等分算半天。”
能。这一篇就写:一键画层板。
先看效果
以前画层板,我是这么干的:
量区域内的高度
然后还要看区域高度计算几块层板
算出层板间隔
画出第一块层板
然后复制
画完然后标注尺寸
如果是鞋柜一个柜子好几个区域都要算,非常的麻烦。
当我写好插件后是这样的:
输入命令 DrawShelf → 点柜体内框 → 输入层板数量 → 自动等分画线。
图层自动创建,颜色自动设置,一秒钟搞定。

我们需要CAD帮干什么样的活
怎么给AI写提示词:
1,告诉AI你使用的环境比如说编程语言和cad的版本
2,告诉AI你需要实现的功能
3,告诉AI你是0编程经验的新手让它直接给出完整可编译的源码Q
看我的的提示词:
今天我需要写一个一键画层板的CAD插件,要求是用C# .net4.8 功能需求: 1,交互流程为,用户输入命令DrawShelf --->用户点选矩形内部或者是选择4条线组成的矩形--->然后默认居中画出层板--->画完后命令提示画了几个层板。 2,要求层板数量可以增加输入W为+S为- 3,层板需要做出实时预览 4,矩形框要有高亮显示,高亮显示需要在绘制完成之后取消 5,因为用户水平不一所以你需要处理区域,有可能是矩形,也有可能不是封闭图形,也有可能是几条线段,所以你需要设置封闭阈值等等因素 6,层板厚度默认为18,用户可以自己设置厚度 请你帮我写出完整代码,我直接可复制编译的代码。 |
这段提示词可以直接复制去问 AI。重点就是:命令名、交互流程、需要的功能,全部写清楚。
AI 给我的代码(核心部分)
AI 生成之后,我做了修改和适配。完整代码如下:
using System;using System.Collections.Generic;using System.Linq;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.Runtime;[assembly: CommandClass(typeof(DrawShelfPlugin.DrawShelfCmd))]namespace DrawShelfPlugin{public class DrawShelfCmd{// 配置参数private const double DefaultThickness = 18.0;private const double CloseTolerance = 1e-3; // 封闭阈值private const double PickTol = 1e-2;private Document _doc;private Editor _ed;private Database _db;private Polyline _highlightPoly; // 高亮框private int _shelfCount = 1; // 当前层数private double _shelfThick = DefaultThickness;private Point3d _insPoint;private bool _isValidRect = false;private Rect3d _boundRect;///<summary>/// 主命令 DrawShelf///</summary>[CommandMethod("DrawShelf", CommandFlags.Modal)]publicvoidDrawShelf(){_doc = Application.DocumentManager.MdiActiveDocument;_ed = _doc.Editor;_db = _doc.Database;_shelfCount = 1;_shelfThick = DefaultThickness;_highlightPoly = null;_isValidRect = false;try{// 第一步:拾取点(矩形内部点)或者选择线段PromptPointResult ppr = _ed.GetPoint("\n请点选矩形内部点,或框选4条线段组成的矩形:");if (ppr.Status != PromptStatus.OK){CleanHighlight();return;}_insPoint = ppr.Value;// 尝试拾取包围这个点的封闭多段线/矩形,或者拾取选择集PromptSelectionResult psr = _ed.SelectCrossingWindow(new Point3d(_insPoint.X - 100, _insPoint.Y - 100, 0),new Point3d(_insPoint.X + 100, _insPoint.Y + 100, 0));List<Line> lines = new List<Line>();Polyline pl = null;if (psr.Status == PromptStatus.OK){SelectionSet ss = psr.Value;foreach (ObjectId oid in ss.GetObjectIds()){using (DBObject obj = oid.Open(OpenMode.ForRead)){if (obj is Line line)lines.Add(line);else if (obj is Polyline p)pl = p;}}}// 解析图形,得到外框矩形if (pl != null && pl.Closed){// 找到封闭多段线_boundRect = GetRectFromPolyline(pl);_isValidRect = CheckValidRect(_boundRect);}else if (lines.Count >= 4){// 4条线段,尝试重构矩形,带闭合阈值容错_boundRect = BuildRectFromLines(lines);_isValidRect = CheckValidRect(_boundRect);}else{_ed.WriteMessage("\n未能识别有效矩形,请重新拾取!");CleanHighlight();return;}if (!_isValidRect){_ed.WriteMessage("\n识别图形不是有效矩形,请检查图形!");CleanHighlight();return;}// 创建高亮框CreateHighlightPoly(_boundRect);// 第二步:交互实时预览,W增加层数 S减少层数 T修改厚度bool finish = false;while (!finish){PromptKeywordOptions pko = new PromptKeywordOptions($"\n【预览】层数:{_shelfCount},厚度:{_shelfThick:F2} | W+层数 S-层数 T设置厚度 回车确认绘制");pko.Keywords.Add("W");pko.Keywords.Add("S");pko.Keywords.Add("T");pko.AllowNone = true;PromptResult pr = _ed.GetKeywords(pko);switch (pr.Status){case PromptStatus.OK:switch (pr.StringResult){case "W":_shelfCount++;UpdatePreview();break;case "S":if (_shelfCount > 1){_shelfCount--;UpdatePreview();}else{_ed.WriteMessage("\n层数不能小于1");}break;case "T":PromptDoubleOptions pdo = new PromptDoubleOptions("\n输入层板厚度");pdo.DefaultValue = _shelfThick;PromptDoubleResult pdr = _ed.GetDouble(pdo);if (pdr.Status == PromptStatus.OK && pdr.Value > 0){_shelfThick = pdr.Value;UpdatePreview();}break;}break;case PromptStatus.None:// 回车确认绘制finish = true;break;default:finish = true;break;}}// 正式绘制层板int drawed = DrawShelfGeometry(_boundRect, _shelfCount, _shelfThick);_ed.WriteMessage($"\n绘制完成!一共生成 {drawed} 块层板");}catch (Exception ex){_ed.WriteMessage($"\n插件异常:{ex.Message}");}finally{CleanHighlight();}}#region 矩形解析///<summary>/// 从封闭多段线获取外接矩形///</summary>private Rect3d GetRectFromPolyline(Polyline pl){Extents3d ext = pl.GeometricExtents;return new Rect3d(ext.MinPoint, ext.MaxPoint);}///<summary>/// 从4条线段重构矩形(带闭合阈值容错)///</summary>private Rect3d BuildRectFromLines(List<Line> lines){Point3dCollection pts = new Point3dCollection();foreach (var ln in lines){pts.Add(ln.StartPoint);pts.Add(ln.EndPoint);}double minX = pts.Cast<Point3d>().Min(p => p.X);double maxX = pts.Cast<Point3d>().Max(p => p.X);double minY = pts.Cast<Point3d>().Min(p => p.Y);double maxY = pts.Cast<Point3d>().Max(p => p.Y);// 阈值修正,微小缺口自动闭合if (Math.Abs(maxX - minX) < CloseTolerance || Math.Abs(maxY - minY) < CloseTolerance)return new Rect3d();return new Rect3d(new Point3d(minX, minY, 0), new Point3d(maxX, maxY, 0));}privateboolCheckValidRect(Rect3d rect){if (rect.Min.IsEqualTo(rect.Max, new Tolerance(CloseTolerance, CloseTolerance)))return false;double w = rect.Width;double h = rect.Height;if (w < CloseTolerance || h < CloseTolerance)return false;return true;}#endregion#region 高亮预览///<summary>/// 创建外框高亮多段线///</summary>privatevoidCreateHighlightPoly(Rect3d rect){CleanHighlight();_highlightPoly = new Polyline();_highlightPoly.AddVertexAt(0, new Point2d(rect.Min.X, rect.Min.Y), 0, 0, 0);_highlightPoly.AddVertexAt(1, new Point2d(rect.Max.X, rect.Min.Y), 0, 0, 0);_highlightPoly.AddVertexAt(2, new Point2d(rect.Max.X, rect.Max.Y), 0, 0, 0);_highlightPoly.AddVertexAt(3, new Point2d(rect.Min.X, rect.Max.Y), 0, 0, 0);_highlightPoly.Closed = true;_highlightPoly.ColorIndex = 1; // 红色高亮_highlightPoly.LineWeight = LineWeight.LineWeight050;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;ObjectId id = btr.AppendEntity(_highlightPoly);tr.AddNewlyCreatedDBObject(_highlightPoly, true);tr.Commit();}}///<summary>/// 更新预览(重绘高亮,实时看层数变化)///</summary>privatevoidUpdatePreview(){CleanHighlight();CreateHighlightPoly(_boundRect);Application.UpdateScreen();}///<summary>/// 清除高亮///</summary>privatevoidCleanHighlight(){if (_highlightPoly != null && !_highlightPoly.IsDisposed){try{using (Transaction tr = _db.TransactionManager.StartTransaction()){_highlightPoly.UpgradeOpen();_highlightPoly.Erase();tr.Commit();}}catch{}_highlightPoly = null;}}#endregion#region 绘制层板核心///<summary>/// 在矩形内部居中绘制层板///</summary>privateintDrawShelfGeometry(Rect3d rect, int count, double thick){double boxH = rect.Height;double boxW = rect.Width;// 总占用高度 = 层数*厚度double totalShelfH = count * thick;// 上下留白均分double gapTotal = boxH - totalShelfH;if (gapTotal < 0){_ed.WriteMessage("\n警告:层板总高度大于外框高度!");gapTotal = 0;}double gapEach = gapTotal / (count + 1);double startY = rect.Min.Y + gapEach + thick / 2;int drawNum = 0;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;for (int i = 0; i < count; i++){double yPos = startY + i * (thick + gapEach);// 绘制层板矩形Polyline shelfPl = new Polyline();shelfPl.AddVertexAt(0, new Point2d(rect.Min.X, yPos - thick / 2), 0, 0, 0);shelfPl.AddVertexAt(1, new Point2d(rect.Max.X, yPos - thick / 2), 0, 0, 0);shelfPl.AddVertexAt(2, new Point2d(rect.Max.X, yPos + thick / 2), 0, 0, 0);shelfPl.AddVertexAt(3, new Point2d(rect.Min.X, yPos + thick / 2), 0, 0, 0);shelfPl.Closed = true;shelfPl.ColorIndex = 3; // 绿色层板ObjectId oid = btr.AppendEntity(shelfPl);tr.AddNewlyCreatedDBObject(shelfPl, true);drawNum++;}tr.Commit();}return drawNum;}#endregion///<summary>/// 矩形辅助结构体///</summary>public struct Rect3d{public Point3d Min;public Point3d Max;publicRect3d(Point3d min, Point3d max){Min = min;Max = max;}public double Width => Max.X - Min.X;public double Height => Max.Y - Min.Y;}}}
当前代码仅供参考
编译加载
Visual Studio 新建“类库(.NET Framework)”项目。
目标框架选 .NET Framework 4.8。
引用
acdbmgd.dll、acmgd.dll。粘贴代码,编译生成 DLL。
打开 AutoCAD,输入
NETLOAD。选择刚生成的 DLL。
输入命令:DrawShelf
我踩的坑
坑 1:高亮框不消失
AI 第一版给的代码,画完层板之后,红色高亮框还留在图上。
怎么解决:用了 try...finally,不管成功还是异常,最后一定执行 CleanHighlight(),把高亮框删掉。
坑 2:层板数量减到 0
按 S 一直减,减到 0 之后,插件会画出 0 块层板,但预览还在。
怎么解决:加了判断,_shelfCount > 1 才能减,减到 1 就提示“层数不能小于1”。
坑 3:层板总厚度超过柜体高度
如果层数太多、厚度太大,层板会超出柜体。
怎么解决:算 gapTotal 的时候判断,如果小于 0,提示警告,并把留白设为 0。这样层板会紧贴着画,不会跑到柜子外面。
坑 4:用直线画的矩形不识别
新手画图经常用 4 条直线拼矩形,不是闭合多段线。
怎么解决:加了 BuildRectFromLines,把 4 条线的端点全部收集起来,取最大最小值重构矩形。还加了 CloseTolerance 闭合阈值,即使线没完全接上,也能容错。
获取源码和提示词
这篇的完整代码和 AI 提示词,我整理好了。
回复“层板”,直接领取。
上一篇的铰链孔源码,回复“铰链孔”领取。
如果你也是全屋定制设计师、拆单师,想利用下班时间学一门真正能变现的技能,关注我,我按打工人的节奏更新,全程带新手落地。
下一篇预告
下一篇继续实战:
实战|用 AI 写 CAD 插件:一键标注柜体尺寸(附源码+提示词)
我们会让插件自动识别柜体外框,并标注总宽、总高、层板间距。
《零基础 CAD 插件从 0 到 1》系列:
关注我,不错过后续更新。如果这篇对你有帮助,点个赞,转发给身边的拆单同行。