ObjectARX中如何选择块参照中的对象

在利用ObjectARX进行CAD二次开发时,如何选择块参照中嵌套的实体,并进行进行下一步操作?这个问题的难点是:如何判断用户选中的实体到底是块参照里面的非嵌套对象实体?还是块参照中嵌套的块参照的实体?本文利用全局函数acedNEnsSelP解决了这个问题,并可实现:如果用户选择块参照中嵌套的实体,直接视为用户选择了这个嵌套的块参照,效果如图。
在这里插入图片描述

一、全局函数acedNEntSelP介绍

为了选中块参照中的实体,ObjectARX提供了一个接口:
int acedNEntSelP(
const ACHAR * str,
ads_name entres,
ads_point ptres,
int pickflag,
ads_matrix xformres,
struct resbuf ** refstkres
);

const ACHAR * str:在选择块参照中实体时的提示语,如果为NULL,AutoCAD 显示默认的提示语。
ads_name entres:选择实体的ads_name名称。
ads_point ptres:选择实体时点取的点。
int pickflag:指定acedNEntSelP是否用于和用户交互;如果为假,acedNEntSelP提示用户指定实体并忽略ptres;如果为真,使用ptres的初始值去选择实体。
ads_matrix xformres:该4×4变换矩阵可以将实体的任意ECS坐标转换为WCS坐标。如果选择的实体不是嵌套实体,该值设为单位矩阵。利用这个矩阵,可以将选中的实体从ECS坐标系转换到WCS坐标系。
struct resbuf ** refstkres :包含嵌套实体的各级块参照。
注意,最后一个参数最为重要,它实际记录了选择对象的各级嵌套块参照。

二、实现方法介绍

利用acedNEntSelP参数中最后的链表参数,查看选择对象的各级嵌套块参照,并对块参照进行坐标变换,将其坐标转为当前图形的WCS坐标。

BOOL SelectEntsFromBlock(CString csPrompt, PickSet &ssResult,AcGePoint3d& ptBase)
{
	ads_name ent;
	ads_point pt;
	ads_matrix mat;
	struct resbuf* pHead = NULL;
	int iRet = acedNEntSelP(csPrompt, ent, pt, FALSE, mat, &pHead);

	ads_name entOuterBlock;
	if (iRet == RTNORM)
	{
		if (!pHead)
		{
			acutPrintf(_T("这并不是一个块参照中的对象"));
			return FALSE;
		}

		ptBase.x = pt[0];
		ptBase.y = pt[1];
		ptBase.z = pt[2];

		//如果ent为块参照中的嵌套块参照对象,例如块参照A嵌套块参照B,块参照B嵌套块参照C,
		//用户点取了嵌套块C的某个实体,以下循环可以将ent修改为块参照B;并且获得最外层的块参照的ads_name
		while (pHead && pHead->restype == RTENAME)
		{
			if (pHead && !pHead->rbnext)	//如果点取的是块参照中的非嵌套对象
			{
				ads_name_set(pHead->resval.rlname, entOuterBlock);
				break;
			}
			else if (pHead->rbnext && !pHead->rbnext->rbnext)	//如果点取的是块参照的嵌套对象
			{
				ads_name_set(pHead->resval.rlname, ent);
				ads_name_set(pHead->rbnext->resval.rlname, entOuterBlock);
				break;
			}
			pHead = pHead->rbnext;
		}

		//求解块参照的变换矩阵
		AcGeMatrix3d matBlockRef;
		AcDbObjectId id;
		acdbGetObjectId(id, entOuterBlock);		//获取最外层块参照的ID
		AcDbBlockReference* pOuterBlockRef = NULL;
		if (Acad::eOk == acdbOpenObject(pOuterBlockRef, id, AcDb::kForRead))
		{
			if (pOuterBlockRef)
			{
				//获取转换矩阵,从块表记录中的MCS坐标转为当前图形的WCS坐标
				matBlockRef = pOuterBlockRef->blockTransform();
			}
			pOuterBlockRef->close();
		}
		
		acdbGetObjectId(id, ent);	//获取用户选中实体的ID
		AcDbEntity* pEnt = NULL;
		AcDbEntity* pEntClone = NULL;
		if (Acad::eOk == acdbOpenObject(pEnt, id, AcDb::kForRead))
		{
			if (pEnt)
			{
				pEntClone = (AcDbEntity*)pEnt->clone();
				//此步骤是关键,复制出来实体以后,将实体从块参照自己的WCS坐标系转换为当前数据库的WCS
				pEntClone->transformBy(matBlockRef);
				AddToCurrentSpace(pEntClone, true);	//加入到当前数据库
			}
			pEnt->close();
		}

		//这里省略了对选择对象进行拖动的代码
		//...........
		
		return TRUE;
	}
	else
		return FALSE;
}
  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
您好!对于使用 C# ObjectARX 进行参照属性值过滤筛选实体,您可以按照以下步骤进行操作: 1. 获取参照实体:使用 `ObjectId` 或 `Transaction` 对象获取参照的 `BlockReference` 实体。 ```csharp ObjectId blockRefId = ...; // 参照ObjectId Transaction tr = ...; // 当前事务 BlockReference blockRef = tr.GetObject(blockRefId, OpenMode.ForRead) as BlockReference; ``` 2. 获取定义:从参照实体获取定义。 ```csharp ObjectId blockDefId = blockRef.BlockTableRecord; BlockTableRecord blockDef = tr.GetObject(blockDefId, OpenMode.ForRead) as BlockTableRecord; ``` 3. 遍历定义的实体:遍历定义的实体,根据属性值进行筛选。 ```csharp foreach (ObjectId entityId in blockDef) { Entity entity = tr.GetObject(entityId, OpenMode.ForRead) as Entity; // 检查实体的属性值 if (entity is AttributeDefinition attDef) { // 如果是属性定义 string attTag = attDef.Tag; string attValue = blockRef.GetAttributeValue(attTag); // 根据属性值进行筛选 if (attValue == "筛选条件") { // 符合筛选条件的处理逻辑 } } else if (entity is AttributeReference attRef) { // 如果是属性引用 string attTag = attRef.Tag; string attValue = attRef.TextString; // 根据属性值进行筛选 if (attValue == "筛选条件") { // 符合筛选条件的处理逻辑 } } else { // 非属性实体的处理逻辑 } } ``` 请注意,这只是一个简单的示例,具体的实现可能需要根据您的需求进行调整。希望能对您有所帮助!如果您有任何其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Santiago

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值