天天看點

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;
        }
}
           

繼續閱讀