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