天天看点

AutoCAD.NET学习笔记之绘制、插入图形和块访问内部数据库的方法访问块表的方法块表、模型空间绘制、插入图形插入块

AutoCAD打印模型的图元的基本组成是“块”,其存储于内部数据库中的块表之中。

目录

访问内部数据库的方法

访问块表的方法

块表、模型空间

绘制、插入图形

插入块

访问内部数据库的方法

var db = HostApplicationServices.WorkingDatabase
           

 或者通过document访问:

var doc = Application.DocumentManager.MdiActiveDocument;

var db = doc.Database;
           

区别是前者不需要AutoCAD的运行环境。

访问块表的方法

AutoCAD内部数据库中的信息的查询(get)操作都可以通过Transaction.GetObject方法获得ObjectId,块表也不例外。

通常这样写以自动释放资源:

using(var tran = db.TransactionManager.StartTransaction())
{
    var blockTable = tran.GetObject(db.BlockTableId,OpenMode.Read) as BlockTable;
    // 其他操作
    tran.Commit(); // 最后要提交数据库操作
}
           

块表、模型空间

块表blockTable的每一条记录BlockTableRecord就是一个块,所有的BlockTableRecord记录中有一条特殊的记录叫做ModelSpace(模型空间),就是我们常规的绘图用的空间。

var modelSpace = tran.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
           

绘制、插入图形

得到模型空间的块表记录后,向其中AppendEntity,即可在模型空间中添加图形,所添加的entity(实体)可以是二维(线、圆等等)、三维图形(三维实体)、块等等。

resultObjectId = modelSpace.AppendEntity(entity);// 返回添加的实体id
tran.AddNewlyCreatedDBObject(entity, true);// 向数据库中添加实体,true是增加,false是删除
           

插入块

不少地方在讲插入块时是通过外部文件的方式链接进来(Xref),这里推荐使用数据库自带的Insert方法来模拟AutoCAD本身的insert命令。

前文讲明所有的块包括整个模型空间都是块表的一条记录(Record),这些“块”的记录和模型空间中实例化的块模型,显然不是一个东西。前者叫BlockTableRecord,后者叫BlockReference,换言之,前者叫“块定义”,后者叫“块参照”。

类似的还有“块属性定义(AttributeDefinition)”和“属性(AttributeReference)”。

如下代码简单的演示了如何模拟AutoCAD的insert命令从其他文件插入块,并选择插入点。

public class CommandClass
        {
            [CommandMethod(nameof(MyCommand))]
            public void MyCommand()
            {
                var doc = Application.DocumentManager.MdiActiveDocument;
                // 让用户决定插入点
                var pointPickResult = doc.Editor.GetPoint(new PromptPointOptions("请输入插入点"));
                if (pointPickResult.Status == PromptStatus.Cancel) return;
                var insertPoint = pointPickResult.Value;

                AddBlock2ModelSpace("xx/xx.dwg",insertPoint);
            }

        private static ObjectId AddBlock2ModelSpace(string blockFilePath, Point3d insertPoint)
        {
            var db = HostApplicationServices.WorkingDatabase;
            var resultObjectId = ObjectId.Null;
            using (var transaction = db.TransactionManager.StartTransaction())
            {
                var blockTable = transaction.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                if (blockTable != null)
                {
                    BlockReference br = default;
                    var blockFileName = Path.GetFileNameWithoutExtension(blockFilePath);
                     // 模拟CAD的insert块操作,无的从blockFilePath导入,有的直接读取块名
                    if (blockTable.Has(blockFileName))
                    {
                        // blockTable[blockFileName]读取块记录,并将其转化为块参照
                        br = new BlockReference(insertPoint, blockTable[blockFileName]);
                    }
                    else
                    {
                        // 没有记录的,从其他dwg文件导入
                        var sourceDb = new Database(false, false);
                        // 这里假定dwg文件是一个纯粹的放置块的dwg,否则需要过滤掉一些不需要的东西
                        sourceDb.ReadDwgFile(blockFilePath, FileShare.Read, true, "");
                        var btrId = db.Insert(blockFileName, sourceDb, true);
                        if (!btrId.IsNull) br = new BlockReference(insertPoint, btrId);
                    }

                    if (br == null) return resultObjectId;

                    // 导入模型空间
                    var modelSpace =
                        transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                    if (modelSpace != null)
                    {
                        resultObjectId = modelSpace.AppendEntity(br);
                        transaction.AddNewlyCreatedDBObject(br, true);
                    }

                    // 添加块属性
                    var blockTableRecord =
                        transaction.GetObject(blockTable[blockFileName], OpenMode.ForRead) as BlockTableRecord;
                    if (blockTableRecord != null)
                        // 遍历块记录,寻找块属性定义AttributeDefinition
                        foreach (var objectId in blockTableRecord)
                            if (transaction.GetObject(objectId, OpenMode.ForRead) is AttributeDefinition ad)
                                // 块属性定义如果被定义为常数是不可以修改的
                                if (!ad.Constant)
                                    // 块定义↔块参照,类比,块属性定义↔块属性参照
                                    using (var ar = new AttributeReference())
                                    {
                                        ar.SetAttributeFromBlock(ad, br.BlockTransform);
                                        ar.Position = ad.Position.TransformBy(br.BlockTransform);
                                        ar.TextString = ad.TextString; // 这里改属性值
                                        br.AttributeCollection.AppendAttribute(ar);
                                        transaction.AddNewlyCreatedDBObject(ar, true);
                                    }
                }

                transaction.Commit();
            }

            return resultObjectId;
        }
}
           

继续阅读