C# CAD二次开发中Solid类的深度解析从入门到实战带你全面理解CAD中这个容易被混淆的实体类避开3D建模的陷阱大家好我是专注于CAD二次开发的技术博主。今天我们来深入聊聊Autodesk.AutoCAD.DatabaseServices命名空间下的Solid类。这个话题看似基础但很多初学者甚至有一定经验的开发者都会在这里栽跟头——因为它和你想象中的三维实体完全是两码事。一、Solid类到底是什么在开始写代码之前我们先要澄清一个最核心的概念Solid类代表的是AutoCAD中的2D填充实体SOLID实体而不是三维实体3D Solid。这个类位于继承链的什么位置呢看看它的家谱就清楚了DBObject数据库对象基类 └── Entity图形实体基类 └── Solid2D填充实体 ← 我们今天的主角在AutoCAD的图形学中Solid实体实际上是一个二维的、填充了颜色的多边形区域。你可以在命令行输入SOLID命令试试它会提示你指定第一点、第二点、第三点、第四点然后生成一个填充的四边形或三角形区域。与之相对应的是Solid3d类它才是我们通常所说的三维实体长方体、圆柱体、球体等。这两个类千万不要搞混否则你的代码方向就全错了。二、Solid对象的创建明确了Solid是什么之后创建它就很简单了。和所有Entity派生类一样创建过程遵循创建-添加-提交的三步走模式。[CommandMethod(CreateMySolid)]publicstaticvoidCreateMySolid(){DocumentdocApplication.DocumentManager.MdiActiveDocument;Databasedbdoc.Database;using(Transactiontrdb.TransactionManager.StartTransaction()){// 1. 获取模型空间的块表记录BlockTablebttr.GetObject(db.BlockTableId,OpenMode.ForRead)asBlockTable;BlockTableRecordbtrtr.GetObject(bt[BlockTableRecord.ModelSpace],OpenMode.ForWrite)asBlockTableRecord;// 2. 创建Solid对象// 构造函数参数四个角点按顺序左下、右下、左上、右上// 如果第三点和第四点重合则形成三角形SolidsolidnewSolid(newPoint3d(0,0,0),// 第一点左下newPoint3d(10,0,0),// 第二点右下newPoint3d(0,10,0),// 第三点左上newPoint3d(10,10,0)// 第四点右上);// 3. 设置实体样式solid.ColorColor.FromRgb(255,0,0);// 红色填充solid.Layer0;// 4. 添加到数据库btr.AppendEntity(solid);tr.AddNewlyCreatedDBObject(solid,true);tr.Commit();}}注意Solid的构造函数接收四个点如果想让点顺序更直观可以这样记逆时针方向依次指定顶点最后一个点可以和第三个点重合来形成三角形。三、添加图形数据库这个环节其实在上面的代码中已经演示了。核心要点是所有可见图形Entity派生类都必须添加到模型空间或图纸空间的BlockTableRecord中才能显示在CAD界面上 。这里有一个很多人容易犯的错误——直接new了一个实体后忘记添加到数据库结果怎么都看不到图形。记住这三行是关键btr.AppendEntity(solid);// 追加到块表记录tr.AddNewlyCreatedDBObject(solid,true);// 通知事务管理这个新对象tr.Commit();// 提交事务持久化到数据库四、修改与获取Solid对象4.1 修改Solid对象修改Solid对象时需要通过事务获取该对象的写权限然后直接修改其属性即可。[CommandMethod(ModifySolid)]publicstaticvoidModifySolid(){DocumentdocApplication.DocumentManager.MdiActiveDocument;Databasedbdoc.Database;Editoreddoc.Editor;// 让用户选择一个Solid对象PromptEntityResultpered.GetEntity(\n请选择一个2D Solid对象: );if(per.Status!PromptStatus.OK)return;using(Transactiontrdb.TransactionManager.StartTransaction()){Solidsolidtr.GetObject(per.ObjectId,OpenMode.ForWrite)asSolid;if(solidnull){ed.WriteMessage(\n选中的不是Solid对象);return;}// 修改颜色solid.ColorColor.FromRgb(0,0,255);// 改为蓝色// 修改位置平移solid.TransformBy(Matrix3d.Displacement(newVector3d(5,5,0)));tr.Commit();}}4.2 获取Solid对象获取对象有两种常见场景场景一通过ObjectId获取using(Transactiontrdb.TransactionManager.StartTransaction()){Solidsolidtr.GetObject(someObjectId,OpenMode.ForRead)asSolid;if(solid!null){// 读取Solid的属性Point3d[]pointsnewPoint3d[4];points[0]solid.GetPointAt(0);// 获取第i个顶点// 注意Solid类没有直接的Points属性需要通过GetPointAt方法}}场景二遍历模型空间筛选所有Solid[CommandMethod(ListAllSolids)]publicstaticvoidListAllSolids(){DocumentdocApplication.DocumentManager.MdiActiveDocument;Databasedbdoc.Database;Editoreddoc.Editor;using(Transactiontrdb.TransactionManager.StartTransaction()){BlockTableRecordbtrtr.GetObject(db.CurrentSpaceId,OpenMode.ForRead)asBlockTableRecord;intcount0;foreach(ObjectIdidinbtr){Entityenttr.GetObject(id,OpenMode.ForRead)asEntity;if(entisSolid){count;ed.WriteMessage($\n找到SolidObjectId:{id});}}ed.WriteMessage($\n共找到{count}个Solid对象);}}五、获取具体实体区分Solid与Solid3d在实际开发中我们经常需要区分2D填充实体和3D实体。这里给出一个安全的获取方式publicstaticvoidProcessEntity(ObjectIdid){using(Transactiontrdb.TransactionManager.StartTransaction()){Entityenttr.GetObject(id,OpenMode.ForRead)asEntity;// 判断是2D Solid还是3D Solid3dif(entisSolid){Solidsolid2DentasSolid;ed.WriteMessage(\n这是一个2D填充实体);}elseif(entisSolid3d){Solid3dsolid3DentasSolid3d;ed.WriteMessage(\n这是一个3D实体);// 如果还想进一步获取3D实体的具体类型Box、Sphere等// 需要通过COM接口获取Acad3DSolidcomSolid(Acad3DSolid)solid3D.AcadObject;stringsolidTypecomSolid.SolidType;ed.WriteMessage($\n3D实体类型{solidType});// 输出Box、Sphere等}else{ed.WriteMessage($\n这是一个{ent.GetType().Name});}}}特别注意Solid3d的具体类型是Box还是Sphere等在托管API中并没有直接暴露需要通过COM接口的SolidType属性获取 。这算是一个小技巧在需要精准识别实体类型时非常有用。六、实际开发中的典型应用场景场景批量生成填充色块用于图例假设我们需要在图纸中生成一个色块图例每个色块是一个2D Solid。[CommandMethod(CreateColorLegend)]publicstaticvoidCreateColorLegend(){DocumentdocApplication.DocumentManager.MdiActiveDocument;Databasedbdoc.Database;// 定义颜色列表Color[]colorsnewColor[]{Color.FromRgb(255,0,0),// 红Color.FromRgb(0,255,0),// 绿Color.FromRgb(0,0,255),// 蓝Color.FromRgb(255,255,0),// 黄Color.FromRgb(255,0,255)// 紫};using(Transactiontrdb.TransactionManager.StartTransaction()){BlockTableRecordbtrtr.GetObject(db.CurrentSpaceId,OpenMode.ForWrite)asBlockTableRecord;doublesize10.0;doublegap2.0;for(inti0;icolors.Length;i){doublexi*(sizegap);SolidsolidnewSolid(newPoint3d(x,0,0),newPoint3d(xsize,0,0),newPoint3d(x,size,0),newPoint3d(xsize,size,0));solid.Colorcolors[i];solid.Layer图例;btr.AppendEntity(solid);tr.AddNewlyCreatedDBObject(solid,true);}tr.Commit();}}七、Solid类常用属性总结属性/方法类型说明ColorColor实体的颜色继承自EntityLayerstring实体所在图层继承自EntityLinetypestring线型名称继承自EntityLineWeightLineWeight线宽设置继承自EntityVisiblebool可见性控制继承自EntityTransformBy(Matrix3d)void对实体进行几何变换平移/旋转/缩放GetPointAt(int)Point3d获取第i个顶点0~3SetPointAt(int, Point3d)void设置第i个顶点的位置AcadObjectobject获取COM接口对象用于访问COM扩展属性八、一个完整的实战命令最后放一个可以直接编译运行的完整命令集成了创建、查询、修改于一体usingAutodesk.AutoCAD.Runtime;usingAutodesk.AutoCAD.ApplicationServices;usingAutodesk.AutoCAD.DatabaseServices;usingAutodesk.AutoCAD.Geometry;usingAutodesk.AutoCAD.EditorInput;usingAutodesk.AutoCAD.Interop.Common;[assembly:CommandClass(typeof(SolidDemo.Commands))]namespaceSolidDemo{publicclassCommands{[CommandMethod(SolidDemo)]publicstaticvoidSolidDemo(){DocumentdocApplication.DocumentManager.MdiActiveDocument;Databasedbdoc.Database;Editoreddoc.Editor;ed.WriteMessage(\n Solid类实战演示 );ed.WriteMessage(\n1. 正在创建一个2D填充正方形...);using(Transactiontrdb.TransactionManager.StartTransaction()){BlockTableRecordbtrtr.GetObject(db.CurrentSpaceId,OpenMode.ForWrite)asBlockTableRecord;// 创建正方形填充SolidsolidnewSolid(newPoint3d(0,0,0),newPoint3d(20,0,0),newPoint3d(0,20,0),newPoint3d(20,20,0));solid.ColorColor.FromRgb(0,200,100);solid.Layer0;btr.AppendEntity(solid);tr.AddNewlyCreatedDBObject(solid,true);ed.WriteMessage(\n2. 已创建ObjectId: solid.ObjectId);ed.WriteMessage(\n3. 正在查询该实体的顶点信息...);for(inti0;i4;i){Point3dptsolid.GetPointAt(i);ed.WriteMessage($\n 顶点{i}: X{pt.X:F2}, Y{pt.Y:F2});}ed.WriteMessage(\n4. 演示完成);tr.Commit();}}}}写在最后总结一下今天的内容Solid ≠ Solid3d一个是2D填充一个是3D实体这是最容易混淆的地方所有实体操作都离不开事务Transaction这是CAD二次开发的核心模式获取3D实体具体类型时可能需要借助COM接口的SolidType属性希望这篇文章能帮你理清Solid类的使用脉络。如果你在开发中遇到其他问题欢迎在评论区留言交流博主提醒本文基于AutoCAD .NET API编写不同版本的API可能存在细微差异建议参考对应版本的官方文档。如果觉得有帮助请点赞收藏支持一下