ObjectArx块内元素显示排序

5 篇文章 0 订阅

1、AcDbSortentsTable

1.1、类简介

AcDbSortentsTable是绘制订单信息的持久容器。它位于关键的ACAD_SORTENTS下的关联AcDbBlockTableRecord的扩展字典中。 

AcDbSortentsTable包含一组对象ID /句柄对。对象ID是要绘制的实体的对象ID, 并且句柄是块表记录中的实体的句柄(通常但不总是与关联的对象ID不同), 其表示绘制顺序中的位置。实体按递增句柄值的顺序附加到块表记录中; 换句话说, 句柄值越高, 它就越晚出现在块表记录中。当在块表记录中绘制实体时, 迭代器以附加顺序遍历块表记录。在每个实体处, 获取句柄值并用于查询sortents表。如果匹配, 则绘制与sortents表中的句柄值关联的对象ID。如果sortents表中没有匹配项,  

当修改实体的绘制顺序时, 可以修改sortents表中的许多条目。例如, 块表记录具有五个具有以下句柄的实体(通常表示为表示十六进制数字的字符串):4A, 4B, 4C, 4D, 4E。这些句柄按升序显示。当应用程序在默认方向上迭代块表记录中的实体时, 句柄值总是从一个实体增加到next实体。 

要先在空间中绘制最后一个实体(或“后面”其他实体), 必须在sortents表中创建五个条目, 如下所示: 

实体ID 

绘制订单处理 

4E 

4A 

4A 

4B 

4B 

4C 

4C 

4D 

4D 

4E 

条目的顺序(表示为上表中的一行)无关紧要; 绘制订单处理在执行绘制时最终通过绘制顺序句柄对条目进行排序。换句话说, 在DXF文件中, 表条目可能按以下顺序出现, 但结果绘制顺序是相同的: 

实体ID 

绘制订单处理 

4C 

4D 

4B 

4C 

4E 

4A 

4D 

4E 

4A 

4B 

作为另一示例, 空间中的最后一个实体在空间中的倒数第二个实体“下”移动, 但其余实体以“自然”顺序绘制。在这种情况下, sortents表只需要两个条目, 如下所示: 

实体ID 

绘制订单处理 

4E 

4D 

4D 

4E 

使用隐式绘制顺序“last”将新实体添加到块表记录中不需要sortents表中的新条目。

1.2、成员方法

Acad::ErrorStatus moveToBottom( const AcDbObjectIdArray& ar);

将输入对象ID数组中指定的所有实体放置在绘制顺序的开头。被移动的实体保留其相对绘制顺序。 

返回eInvalidInput如果任何输入对象ID不在相关的块, 或eDuplicateKey如果任何对象ID输入数组中出现两次。 

2、代码实现

如果你要调整块内的显示顺序,就是获得AcDbBlockTableRecord的扩展辞典里面的ACAD_SORTENTS,执行完参数后记得CLOSE返回的对象。

打开块时要先以块参照AcDbBlockReference对象打开,然后用AcDbBlockReference::blockTableRecord()获取块表记录blockTableRecordId,用这个blockTableRecordId打开才是块表记录,直接用块blkid打开块,将返回eNullObjectId错误。详见Arx遍历块内实体_阿达和自己的博客-CSDN博客

2.1、获取块排序表对象

AcDbSortentsTable * getSortentsTable(AcDbBlockTableRecord * pRec)
{
    if (!pRec)
        return NULL;
    Acad::ErrorStatus es;
    AcDbObjectId ext_id = pRec->extensionDictionary();
    if (AcDbObjectId::kNull == ext_id)
    {
        pRec->upgradeOpen();
        es = pRec->createExtensionDictionary();
        if (es != eOk)
            return NULL;
        pRec->downgradeOpen();
        ext_id = pRec->extensionDictionary();
        if (AcDbObjectId::kNull == ext_id)
        {
            return NULL;
        }
        pRec->downgradeOpen();
    }
    AcDbDictionary *pExt;
    es = acdbOpenObject(pExt, ext_id, AcDb::kForRead);
    if (Acad::eOk != es)
        return NULL;
    AcDbObject *pObj;
    if (Acad::eOk != pExt->getAt(_T("ACAD_SORTENTS"), pObj, AcDb::kForWrite))
    {
        if (Acad::eOk != pExt->upgradeOpen())
        {
            pExt->close();
            return NULL;
        }
        AcDbSortentsTable *pSt = new AcDbSortentsTable;
        if (NULL == pSt)
        {
            pExt->close();
            return NULL;
        }
        AcDbObjectId new_id;
        if (Acad::eOk != pExt->setAt(_T("ACAD_SORTENTS"), pSt, new_id))
        {
            delete pSt;
            pExt->close();
            return NULL;
        }
        pSt->setBlockId(pRec->objectId());
        pObj = pSt;
    }
    pExt->close();
    if (!pObj->isKindOf(AcDbSortentsTable::desc()))
    {
        pObj->close();
        return NULL;
    }
    return (AcDbSortentsTable*)pObj;
}

2.2、遍历块实体,后置实体集合

void softBlockEntity(const AcDbObjectId& blkid)
{
    // 后置实体集合
    AcDbObjectIdArray behindids;
    AcDbBlockTableRecordIterator *iter;
    AcDbBlockReference *pBlkRef;
    AcDbBlockTableRecord *pRecord;
    Acad::ErrorStatus es = acdbOpenObject(pBlkRef, blkid, AcDb::kForRead);
    if (es != Acad::eOk)
        return;
    AcDbObjectId blockTableRecordId = pBlkRef->blockTableRecord();
    pBlkRef->close();
    es = acdbOpenObject(pRecord, blockTableRecordId, AcDb::kForWrite);
    if (es != Acad::eOk || pRecord == NULL)
        return;
    // 遍历块内实体
    pRecord->newIterator(iter);
    for (iter->start(); !iter->done(); iter->step())
    {
        AcDbObjectId id;
        es = iter->getEntityId(id);
        if (es != Acad::eOk || !id.isValid())
            continue;
        // 过滤出需要后置的实体集合           
        if (筛选条件)
            behindids.append(id);
    }
    AcDbSortentsTable *pSortentsTable = getSortentsTable(pRecord);
    // 排序表对象在使用完后记得close
    if (pSortentsTable != NULL)
    {
        es = pSortentsTable->moveToBottom(behindids);
        pSortentsTable->close();
    }
    delete iter;
    pRecord->close();
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值