cad.net 根据块名获取所有插入块的id+GetNext块
说明
这个操作用来提供查找同名块,
见代码一共有两种方案,一种是遍历全图,一种是通过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参数上面有这个选项.
(完)