2026/5/21 14:07:04
网站建设
项目流程
外贸网站建设 soho,下载微信公众号平台官网,运营 网站,建设小说网站1. Entity对象基础操作入门
在CAD二次开发中#xff0c;Entity对象是所有图形实体的基类#xff0c;理解它的基本操作是开发的基础。我们先从最简单的实体创建和属性修改开始。
创建直线实体的完整示例代码如下#xff1a;
using Autodesk.AutoCAD.ApplicationServices;
…1. Entity对象基础操作入门在CAD二次开发中Entity对象是所有图形实体的基类理解它的基本操作是开发的基础。我们先从最简单的实体创建和属性修改开始。创建直线实体的完整示例代码如下using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; public void CreateLine() { Document doc Application.DocumentManager.MdiActiveDocument; Database db doc.Database; using (Transaction tr db.TransactionManager.StartTransaction()) { // 获取模型空间块表记录 BlockTable bt (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord btr (BlockTableRecord)tr.GetObject( bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); // 创建直线对象 Line line new Line( new Point3d(0, 0, 0), new Point3d(100, 100, 0)); // 设置线型属性 line.ColorIndex 1; // 红色 line.LineWeight LineWeight.LineWeight030; // 添加到模型空间 btr.AppendEntity(line); tr.AddNewlyCreatedDBObject(line, true); tr.Commit(); } }这段代码展示了Entity对象的基本生命周期创建→设置属性→添加到数据库→提交事务。实际开发中我经常遇到新手忘记提交事务导致操作不生效的情况这点需要特别注意。2. 几何变换实战技巧几何变换是CAD开发中最常用的功能之一Entity对象提供了多种变换方法2.1 平移变换public void MoveEntity(ObjectId entId, Vector3d offset) { using (Transaction tr entId.Database.TransactionManager.StartTransaction()) { Entity ent (Entity)tr.GetObject(entId, OpenMode.ForWrite); ent.TransformBy(Matrix3d.Displacement(offset)); tr.Commit(); } }2.2 旋转变换public void RotateEntity(ObjectId entId, Point3d basePoint, double angle) { using (Transaction tr entId.Database.TransactionManager.StartTransaction()) { Entity ent (Entity)tr.GetObject(entId, OpenMode.ForWrite); ent.TransformBy(Matrix3d.Rotation( angle, Vector3d.ZAxis, basePoint)); tr.Commit(); } }2.3 缩放变换public void ScaleEntity(ObjectId entId, Point3d basePoint, double scaleFactor) { using (Transaction tr entId.Database.TransactionManager.StartTransaction()) { Entity ent (Entity)tr.GetObject(entId, OpenMode.ForWrite); ent.TransformBy(Matrix3d.Scaling(scaleFactor, basePoint)); tr.Commit(); } }在实际项目中我经常需要组合这些变换。比如先旋转再平移这时候要注意变换矩阵的乘法顺序会影响最终结果。正确的做法是Matrix3d mat Matrix3d.Rotation(angle, Vector3d.ZAxis, center) * Matrix3d.Displacement(offset); ent.TransformBy(mat);3. 批量处理实战批量处理能显著提高操作效率以下是几种常见场景的实现3.1 批量修改图层public void ChangeLayer(ObjectIdCollection ids, string layerName) { if (ids.Count 0) return; Database db ids[0].Database; using (Transaction tr db.TransactionManager.StartTransaction()) { // 验证图层是否存在 LayerTable lt (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (!lt.Has(layerName)) { tr.Abort(); throw new Exception($图层{layerName}不存在); } // 批量修改 foreach (ObjectId id in ids) { Entity ent (Entity)tr.GetObject(id, OpenMode.ForWrite); ent.Layer layerName; } tr.Commit(); } }3.2 批量删除实体public void DeleteEntities(ObjectIdCollection ids) { if (ids.Count 0) return; Database db ids[0].Database; using (Transaction tr db.TransactionManager.StartTransaction()) { foreach (ObjectId id in ids) { Entity ent (Entity)tr.GetObject(id, OpenMode.ForWrite); ent.Erase(); } tr.Commit(); } }在批量处理时我建议先对ObjectIdCollection进行非空检查避免无效操作。同时要注意事务的范围不要把整个循环放在事务外这样会导致性能下降。4. 高级交互操作4.1 使用Jig实现动态绘制EntityJig可以实现实时的交互式绘图效果下面是绘制多边形的实现public class PolyJig : EntityJig { private Polyline pline; private Point3d currentPoint; private int vertexCount 0; public PolyJig() : base(new Polyline()) { pline (Polyline)Entity; pline.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); vertexCount; } protected override SamplerStatus Sampler(JigPrompts prompts) { JigPromptPointOptions opts new JigPromptPointOptions(\n指定下一点: ); opts.UserInputControls UserInputControls.Accept3dCoordinates | UserInputControls.NoZeroResponseAccepted | UserInputControls.NoNegativeResponseAccepted; PromptPointResult res prompts.AcquirePoint(opts); if (res.Status PromptStatus.Cancel) return SamplerStatus.Cancel; if (res.Value currentPoint) return SamplerStatus.NoChange; currentPoint res.Value; return SamplerStatus.OK; } protected override bool Update() { pline.AddVertexAt(vertexCount, new Point2d(currentPoint.X, currentPoint.Y), 0, 0, 0); vertexCount; return true; } public Entity GetEntity() { return pline; } }使用时只需要创建Jig实例并启动拖拽操作Editor ed Application.DocumentManager.MdiActiveDocument.Editor; PolyJig jig new PolyJig(); PromptResult res ed.Drag(jig); if (res.Status PromptStatus.OK) { // 添加到数据库 Database db HostApplicationServices.WorkingDatabase; using (Transaction tr db.TransactionManager.StartTransaction()) { BlockTable bt (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord btr (BlockTableRecord)tr.GetObject( bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); btr.AppendEntity(jig.GetEntity()); tr.AddNewlyCreatedDBObject(jig.GetEntity(), true); tr.Commit(); } }4.2 实体捕捉与修改实现夹点编辑功能public void EditWithGrips(ObjectId entId) { Database db entId.Database; Editor ed Application.DocumentManager.MdiActiveDocument.Editor; using (Transaction tr db.TransactionManager.StartTransaction()) { Entity ent (Entity)tr.GetObject(entId, OpenMode.ForWrite); // 获取实体夹点 Point3dCollection grips new Point3dCollection(); IntegerCollection snapModes new IntegerCollection(); IntegerCollection geomIds new IntegerCollection(); ent.GetGripPoints(grips, snapModes, geomIds); // 让用户选择夹点 PromptIntegerResult res ed.GetInteger(\n选择要移动的夹点(1-grips.Count):); if (res.Status ! PromptStatus.OK) return; int index res.Value - 1; if (index 0 || index grips.Count) { ed.WriteMessage(\n无效的夹点索引); return; } // 获取移动向量 PromptPointOptions opts new PromptPointOptions(\n指定新位置:) .UseBasePoint(grips[index]); opts.UserInputControls UserInputControls.NoZeroResponseAccepted | UserInputControls.NoNegativeResponseAccepted; PromptPointResult ptRes ed.GetPoint(opts); if (ptRes.Status ! PromptStatus.OK) return; // 移动夹点 Vector3d offset ptRes.Value - grips[index]; IntegerCollection indices new IntegerCollection(); indices.Add(index); ent.MoveGripPointsAt(indices, offset); tr.Commit(); } }5. 性能优化技巧在处理大量实体时性能优化尤为重要5.1 使用OpenMode.ForRead只读访问时使用ForRead模式using (Transaction tr db.TransactionManager.StartTransaction()) { Entity ent (Entity)tr.GetObject(entId, OpenMode.ForRead); Extents3d extents ent.GeometricExtents; // 只读操作 // 不需要tr.Commit() }5.2 批量操作时重用事务public void ProcessEntities(ObjectIdCollection ids) { if (ids.Count 0) return; Database db ids[0].Database; using (Transaction tr db.TransactionManager.StartTransaction()) { foreach (ObjectId id in ids) { Entity ent (Entity)tr.GetObject(id, OpenMode.ForWrite); // 处理逻辑... } tr.Commit(); } }5.3 使用索引加速查询public ObjectIdCollection FindEntitiesInArea(Extents3d area) { Document doc Application.DocumentManager.MdiActiveDocument; Editor ed doc.Editor; // 创建选择过滤器 TypedValue[] values new TypedValue[] { new TypedValue((int)DxfCode.Start, LINE,ARC,CIRCLE) // 只选择这些类型 }; SelectionFilter filter new SelectionFilter(values); // 使用窗口选择 PromptSelectionResult res ed.SelectCrossingWindow( area.MinPoint, area.MaxPoint, filter); if (res.Status PromptStatus.OK) return new ObjectIdCollection(res.Value.GetObjectIds()); else return new ObjectIdCollection(); }6. 常见问题解决方案6.1 实体无法修改常见原因是事务未提交或打开模式不正确using (Transaction tr db.TransactionManager.StartTransaction()) { // 错误使用ForRead模式尝试修改 // Entity ent (Entity)tr.GetObject(entId, OpenMode.ForRead); // 正确使用ForWrite模式 Entity ent (Entity)tr.GetObject(entId, OpenMode.ForWrite); ent.ColorIndex 1; tr.Commit(); // 必须提交 }6.2 实体克隆问题克隆实体时要注意处理扩展数据public Entity CloneEntity(ObjectId entId, Database targetDb) { using (Transaction tr entId.Database.TransactionManager.StartTransaction()) { Entity source (Entity)tr.GetObject(entId, OpenMode.ForRead); // 简单克隆不包含扩展数据 Entity clone (Entity)source.Clone(); // 如果需要完整克隆包含扩展数据 IdMapping mapping new IdMapping(); DBObjectCollection clones new DBObjectCollection(); source.DeepClone(source.Database, clones, mapping); if (clones.Count 0) { clone (Entity)clones[0]; } return clone; } }6.3 处理复杂实体对于多段线等复杂实体需要特殊处理顶点public void ProcessPolyline(ObjectId plineId) { using (Transaction tr plineId.Database.TransactionManager.StartTransaction()) { Polyline pline (Polyline)tr.GetObject(plineId, OpenMode.ForWrite); // 遍历所有顶点 for (int i 0; i pline.NumberOfVertices; i) { Point2d pt pline.GetPoint2dAt(i); // 处理顶点... } // 添加新顶点 pline.AddVertexAt(pline.NumberOfVertices, new Point2d(100, 100), 0, 0, 0); tr.Commit(); } }7. 实战案例批量偏移曲线结合前面介绍的技术我们实现一个实用的批量偏移功能public void OffsetCurves(ObjectIdCollection curveIds, double offsetDist) { if (curveIds.Count 0) return; Database db curveIds[0].Database; using (Transaction tr db.TransactionManager.StartTransaction()) { BlockTable bt (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord btr (BlockTableRecord)tr.GetObject( bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); foreach (ObjectId id in curveIds) { Entity ent (Entity)tr.GetObject(id, OpenMode.ForRead); if (ent is Curve curve) { try { // 创建偏移曲线 DBObjectCollection offsetCurves curve.GetOffsetCurves(offsetDist); // 添加到模型空间 foreach (DBObject obj in offsetCurves) { Entity offsetEnt (Entity)obj; btr.AppendEntity(offsetEnt); tr.AddNewlyCreatedDBObject(offsetEnt, true); } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( $\n无法偏移实体 {id}: {ex.Message}); } } } tr.Commit(); } }这个例子展示了如何处理多种曲线类型直线、圆弧、多段线等进行批量操作添加错误处理维护事务完整性8. 扩展应用自定义实体操作除了内置实体类型我们还可以操作自定义实体public void ProcessCustomEntity(ObjectId entId) { using (Transaction tr entId.Database.TransactionManager.StartTransaction()) { Entity ent (Entity)tr.GetObject(entId, OpenMode.ForRead); // 检查是否为自定义实体 if (ent is ProxyEntity proxy) { // 获取代理实体的原始类名 string originalClass proxy.OriginalClassName; // 处理代理实体... } else if (ent.XData ! null) { // 处理带有扩展数据的实体 foreach (TypedValue tv in ent.XData) { // 解析扩展数据... } } tr.Commit(); } }9. 最佳实践总结经过多个项目的实践我总结了以下Entity对象操作的最佳实践事务管理每个独立操作使用单独事务批量操作合并到一个事务中及时释放事务资源错误处理捕获特定异常如eInvalidInput提供有意义的错误信息确保事务在异常时正确回滚性能优化最小化事务范围合理使用OpenMode避免频繁的数据库查询代码组织封装常用操作为独立方法使用扩展方法增强可读性保持代码与CAD版本兼容下面是一个封装好的实用工具方法示例public static class EntityExtensions { public static void SafeTransform(this Entity ent, Matrix3d mat) { try { ent.TransformBy(mat); } catch (Autodesk.AutoCAD.Runtime.Exception ex) { if (ex.ErrorStatus ErrorStatus.InvalidGeometry) { // 处理无效几何体情况 } throw; } } public static bool IsVisible(this Entity ent) { return ent.Visible !ent.IsErased ent.LayerId.IsValid ent.ColorIndex ! 0; // 0表示BYBLOCK } }使用时只需要ent.SafeTransform(transformationMatrix); if (ent.IsVisible()) { /*...*/ }