說明
這個操作用來提供查找同名塊,
見代碼一共有兩種方案,一種是遍歷全圖,一種是通過cad內部儲存機制(大概是一個表結構)
遍歷全圖必然比cad預先提供的獲取慢.
其中獲取嵌套塊的id,大家可以自己推導一下規律...
代碼
c#
#if !HC2020
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.Runtime;
using GrxCAD.EditorInput;
using Acap = GrxCAD.ApplicationServices.Application;
#endif
using System;
namespace JoinBox
{
public class GetBlockReferenceIds
{
[CommandMethod("CmdTest_GetBlockReferenceIds")]
public void CmdTest_GetBlockReferenceIds()
{
var dm = Acap.DocumentManager;
var doc = dm.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
ed.WriteMessage("\n根據塊名獲取所有插入塊圖元名列表:");
ed.WriteMessage("\n選擇圖元(兒子)");
//定義選擇集選項
var pso = new PromptSelectionOptions
{
RejectObjectsOnLockedLayers = true, //選擇鎖定圖層對象
AllowDuplicates = true, //允許重復選擇
};
var ssPsr = ed.GetSelection(pso);
if (ssPsr.Status != PromptStatus.OK)
return;
db.Action(tr => {
foreach (var id in ssPsr.Value.GetObjectIds())
{
if (!id.IsOk())
continue;
var ent = id.ToEntity(tr);
if (ent == null)
continue;
if (ent is BlockReference brf)
{
var btRec = tr.GetObject(brf.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
/*
* btRec.GetBlockReferenceIds(true不獲取嵌套的最外層,用於舊圖元修復一直為true就好)
* 必須是 BlockReference ,是模型空間就什么都獲取不了
* 這個方法是用來尋找 BlockReference 塊參照 在數據庫中全部數量!
*
* 利用嵌套塊,選擇兒子,得到:
*
* false參數++++++++++++++++++++++++++
* 塊名:子;;;Handle是:1E3 (我)
*
* 塊名:子;;;Handle是:1EA (我,一層嵌套)
* 塊名:父;;;Handle是:1EB
*
* 塊名:父;;;Handle是:1F2
* 塊名:爺;;;Handle是:1F3
*
* 塊名:爺;;;Handle是:1FC
* 塊名:曾爺;;;Handle是:1FD
*
* true參數++++++++++++++++++++++++++
* 塊名:子;;;Handle是:1E3 (我)
* 塊名:子;;;Handle是:1EA (我,一層嵌套)
*/
//方案一:例如cad自帶的樹形圖進行查詢,比遍歷塊
var brfIds1 = btRec.GetBlockReferenceIds(false, true);
ed.WriteMessage("\nfalse參數++++++++++++++++++++++++++");
foreach (ObjectId item in brfIds1)
{
if (item.ToEntity(tr) is BlockReference brf2)
ed.WriteMessage($"\n塊名:{brf2.Name};;;Handle是:{brf2.Handle}");
}
var brfIds2 = btRec.GetBlockReferenceIds(true, true);
ed.WriteMessage("\ntrue參數++++++++++++++++++++++++++");
foreach (ObjectId item in brfIds2)
{
if (item.ToEntity(tr) is BlockReference brf2)
ed.WriteMessage($"\n塊名:{brf2.Name};;;Handle是:{brf2.Handle}");
}
}
}
});
return;
//方案二:遍歷全圖
db.Action(tr => {
var id = SymbolUtilityServices.GetBlockModelSpaceId(db);
var modelSpace = tr.GetObject(id, OpenMode.ForRead) as BlockTableRecord;
var insert = RXObject.GetClass(typeof(BlockReference)).DxfName;
//遍歷模型空間,獲取同名動態塊數量
var blocks = modelSpace/*也可以直接用 整個塊表 啊...*/
.Cast<ObjectId>()
//.Where(id => id.ObjectClass.DxfName == insert)
.Where(id =>
id.GetDxfName(tr) == insert)//如果是塊參照
.Select(id =>
(BlockReference)tr.GetObject(id, OpenMode.ForRead))//打開定義
.GroupBy(br =>
((BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)).Name);//獲取真實的塊名
foreach (var group in blocks)
ed.WriteMessage($"\n{group.Key}: {group.Count()}");
});
}
}
}
lisp
;;根據塊名獲取所有插入塊圖元名列表
(defun GetBlockReferenceIds (blkName / blkHeader dxf330 elist lst @sk_dxf)
(defun @sk_dxf (ent code)
(cdr (assoc code (entget ent)))
)
(if (setq blkHeader (tblobjname "block" blkname))
(progn
(setq dxf330 (@sk_dxf blkHeader 330))
(setq elist (entget dxf330))
(while (setq a (car elist))
(if (= (car a) 331)
(setq lst (cons (cdr a) lst))
)
(setq elist (cdr elist))
)
(reverse lst)
)
)
)
相關問題
0x01 getNext得到的entity怎么能獲取它所在的塊參照呢?
提示,ent.blockId和ent.blockName是塊表記錄
答案:不可能.
塊內圖元直接get的話,因為是塊表記錄着圖元,不是儲存在模型同級的.
也就是每次都拷貝一份出來,然后顯示在模型(概念)
圖元和圖元之間沒有從屬關系,所以只有塊表記錄儲存圖元信息,因此不存在這樣的操作...
要修改getNext的圖元也會作用在塊表記錄上(全體參照).
如果圖元和圖元之間有從屬關系,那么就會導致我修改這個圖元所屬,
便不需要打開另一個圖元記錄,造成權限溢出.
也會導致,不是塊參照的圖元擁有了另一個圖元,造成歧義.
0x02 那么要怎么getNext到塊內塊上面呢?
而不是到entity.
getNext參數上面有這個選項.
(完)