1. 程式人生 > 其它 >cad.net 根據塊名獲取所有插入塊的id

cad.net 根據塊名獲取所有插入塊的id

說明

這個操作用來提供查詢同名塊,
見程式碼一共有兩種方案,一種是遍歷全圖,一種是通過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)
    )
  )
)

(完)