找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 211|回复: 1

[每日一码] 计算AcDbBlockReference准确的包围盒

[复制链接]

0

主题

0

回帖

26

积分

管理员

积分
26
发表于 2024-2-23 22:24:05 | 显示全部楼层 |阅读模式
  1. void test()
  2. {
  3. ads采用name ename;
  4. ads采用point pt;
  5. if (acedEntSel("Select a block reference:",ename,pt)!=RTNORM)
  6.   return;
  7. AcDbObjectId id;
  8. if (acdbGetObjectId(id,ename)!=Acad::eOk)
  9.   return;
  10. AcDbExtents extents;
  11. AcDbBlockReference* pRef;
  12. if (acdbOpenObject(pRef,id,AcDb::kForRead)==Acad::eOk)
  13. {
  14.   if (Acad::eOk==getBlockRefGeomExtents(pRef,extents))
  15.   {
  16.    //just display the 2d box
  17.    AcGePoint2d minpt(extents.minPoint()[X],extents.minPoint()[Y]);
  18.    AcGePoint2d maxpt(extents.maxPoint()[X],extents.maxPoint()[Y]);
  19.    AcGePoint2dArray points;
  20.    points.append(minpt);
  21.    AcGePoint2d pt(maxpt[X],minpt[Y]);
  22.    points.append(pt);
  23.    points.append(maxpt);
  24.    pt.set(minpt[X],maxpt[Y]);
  25.    points.append(pt);
  26.    AcDbPolyline* pPline;
  27.    if ((pPline=makeSimplePline(points))!=NULL){
  28.     pPline->setClosed(Adesk::kTrue);
  29.     AcDbObjectId id;
  30.     postToDb(pPline,id);
  31.    }
  32.   } else
  33.    acutPrintf("\nCannot calculate accurate extents");
  34.   pRef->close();
  35. }
  36. }
  37. //creates a polyline with 0 width, without bulges
  38. AcDbPolyline* makeSimplePline(const AcGePoint2dArray& points)
  39. {
  40.    AcDbPolyline* pPline = new AcDbPolyline(points.length());
  41.    if (pPline==NULL)
  42.     return pPline;
  43.    for (int i=0;i<points.length();i++)
  44.     if (pPline->addVertexAt(i,points<i>)!=Acad::eOk)
  45. {
  46.         delete pPline;
  47.         pPline = NULL;
  48.         break;
  49.     }
  50.    return pPline;
  51. }//explodes a 2dpolyline by first converting it to a new polyline
  52. Acad::ErrorStatus explodeAcDb2dPolyline(const AcDb2dPolyline*
  53. p2d,AcDbVoidPtrArray& ents){
  54.    if (p2d==NULL)
  55.     return Acad::eInvalidInput;
  56.    AcDbPolyline* pPline;
  57.    if ((pPline=new AcDbPolyline)==NULL)
  58.     return Acad::eOutOfMemory;
  59.    Acad::ErrorStatus es;
  60.    if ((es=pPline->convertFrom((AcDbEntity*&)p2d,Adesk::kFalse))==Acad::eOk)
  61.    {
  62.     es=pPline->explode(ents);
  63.    }
  64.    return es;
  65. }
  66. Acad::ErrorStatus getBlockRefGeomExtents(AcDbBlockReference* pRef, AcDbExtents&
  67. extents, const AcGeMatrix3d& mat)
  68. {   
  69.    Acad::ErrorStatus es;
  70.    AcGeMatrix3d xform;
  71.    AcDbEntity* pCopy;
  72.    AcDbEntity* pE;
  73.    xform=mat*pRef->blockTransform();
  74.    AcDbObjectId idBlock = pRef->blockTableRecord();
  75.    AcDbBlockTableRecord* pBlock;
  76.    if ((es=acdbOpenObject(pBlock,idBlock,AcDb::kForRead))==Acad::eOk){
  77.     AcDbBlockTableRecordIterator* pIter;
  78.     if ((es=pBlock->newIterator(pIter))==Acad::eOk){
  79.        for (pIter->start();!pIter->done();pIter->step()){
  80.         AcDbExtents ext;
  81.         if ((es=pIter->getEntity(pE,AcDb::kForRead))==Acad::eOk)
  82.   {
  83.             AcDbBlockReference* pRefNested;
  84.             if ((pRefNested=AcDbBlockReference::cast(pE))!=NULL)
  85.    {
  86.     if ((es=getBlockRefGeomExtents(pRefNested,ext,xform))!=Acad::eOk)
  87.     {
  88.      pE->close();
  89.      break;
  90.     }
  91.             }
  92.    else
  93.    {
  94.     AcRxClass* pDesc = pE->isA();
  95.     if (pDesc==AcDbPolyline::desc() ||
  96.      pDesc==AcDb2dPolyline::desc() ||
  97.      pDesc==AcDbMText::desc())
  98.     {
  99.      //need explode
  100.      AcDbVoidPtrArray array;
  101.      if (pDesc==AcDbPolyline::desc())
  102.      es=pE->explode(array);
  103.      if (pDesc==AcDbMText::desc())
  104.      es=pE->explode(array);     if (pDesc==AcDb2dPolyline::desc())
  105.      es=explodeAcDb2dPolyline(AcDb2dPolyline::cast(pE),array);     if (es==Acad::eOk)
  106.      {
  107.       for(int i=0;i<array.length();i++)
  108.       {
  109.        AcDbExtents ext2;
  110.        AcDbEntity* pPart = ((AcDbEntity*)(array<i>));
  111.        if((es=pPart->getTransformedCopy(xform,pCopy))==Acad::eOk)
  112.        {
  113.         es=pCopy->getGeomExtents(ext2);
  114.         delete pCopy;
  115.        }
  116.        if (es!=Acad::eOk)
  117.        {
  118.         delete pPart;
  119.         if (es==Acad::eNullExtents)
  120.          continue;
  121.         else
  122.          break;
  123.        }
  124.        delete pPart;
  125.        ext.addExt(ext2);
  126.       }
  127.      }
  128.     }
  129.     else
  130.     {
  131.      if((es=pE->getTransformedCopy(xform,pCopy))==Acad::eOk)
  132.      {
  133.       es=pCopy->getGeomExtents(ext);
  134.       delete pCopy;
  135.      }
  136.     }
  137.             }
  138.             if (es!=Acad::eOk)
  139.    {
  140.     pE->close();
  141.     if (es==Acad::eNullExtents)
  142.      continue;
  143.     else
  144.      break;
  145.    }
  146.             extents.addExt(ext);
  147.             pE->close();
  148.         }
  149.         }
  150.         delete pIter;
  151.     }
  152.    }
  153.    pBlock->close();
  154.    //add non constant attributes
  155.    AcDbObjectIterator* pIter;
  156.    if ((pIter=pRef->attributeIterator())==NULL)
  157.     return Acad::eOutOfMemory;
  158.    for (pIter->start();!pIter->done();pIter->step())
  159.    {
  160.     AcDbExtents ext;
  161.     if((es=acdbOpenObject(pE,pIter->objectId(),AcDb::kForRead))==Acad::eOk)
  162. {
  163.         pE->getGeomExtents(ext);
  164.         if (es!=Acad::eOk)
  165.   {
  166.    pE->close();
  167.    if (es==Acad::eNullExtents)
  168.     continue;
  169.    else
  170.     break;
  171.         }
  172.         extents.addExt(ext);
  173.         pE->close();
  174.     }
  175.    }
  176.    delete pIter;
  177.    return es;
  178. }//Posts an entity to the database
  179. //
  180. Acad::ErrorStatus postToDb(AcDbEntity* ent, AcDbObjectId& objId)
  181. {
  182.    Acad::ErrorStatus       es;
  183.    AcDbBlockTable*       pBlockTable;
  184.    AcDbBlockTableRecord*  pSpaceRecord;
  185.     if (NULL == ent)
  186.         return Acad::eNullObjectPointer;
  187.     if (NULL == acdbHostApplicationServices()->workingDatabase())
  188.         return Acad::eNoDatabase;
  189.    if ((es = acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead))!= Acad::eOk)
  190.         return es;
  191.    if ((es = pBlockTable->getAt(ACDB采用MODEL采用SPACE,pSpaceRecord,AcDb::kForWrite))!= Acad::eOk)
  192.     {
  193.         pBlockTable->close();
  194.         return es;
  195.     }
  196.    pBlockTable->close();
  197.    if ((es = pSpaceRecord->appendAcDbEntity(objId, ent)) != Acad::eOk)
  198.     {
  199.         pSpaceRecord->close();
  200.     return es;
  201.    }
  202.    pSpaceRecord->close();
  203.    return ent->close();
  204. }
复制代码

0

主题

0

回帖

26

积分

管理员

积分
26
 楼主| 发表于 2024-2-23 22:26:15 | 显示全部楼层
  1. AcDbExtents CEntity::GetRefBoundingBox (AcDbBlockReference *pRef, const AcGeMatrix3d & mat)
  2. {
  3.         AcDbExtents ext;
  4.         AcDbExtents RetExt;
  5.         AcDbObjectId recId = pRef->blockTableRecord();
  6.         AcDbBlockTableRecordPointer block(recId,AcDb::kForRead);
  7.         Acad::ErrorStatus es = block.openStatus();
  8.         if (es == eOk)
  9.         {
  10.                 AcDbBlockTableRecordIterator *pItr = NULL;
  11.                 block->newIterator(pItr);
  12.                 AcDbObjectId id;
  13.                 AcDbEntity *pEnt = NULL;
  14.                 for (pItr->start();!pItr->done();pItr->step())
  15.                 {
  16.                         es = pItr->getEntity(pEnt,AcDb::kForWrite);
  17.                         if (es == eOk)
  18.                         {
  19.                                 pEnt->transformBy(mat);
  20.                                 if (pEnt->isKindOf(AcDbBlockReference::desc()))
  21.                                 {
  22.                                         AcGeMatrix3d blkmat=((AcDbBlockReference*)pEnt)->blockTransform();
  23.                                         ext = GetRefBoundingBox((AcDbBlockReference *)pEnt,blkmat);
  24.                                 }
  25.                                 else
  26.                                 {
  27.                                         pEnt->getGeomExtents(ext);
  28.                                 }
  29.                                 pEnt->transformBy(mat.inverse());
  30.                                 RetExt.addExt(ext);
  31.                                 pEnt->close();
  32.                         }
  33.                 }
  34.                 delete pItr;
  35.                 pItr = NULL;
  36.         }
  37.         return RetExt;
  38. }
  39. 譬如:
  40. AcDbObjectPointer<AcDbBlockReference> blkref(id,AcDb::kForRead);     //id块参照的id
  41. AcDbExtents  ext = CEntity::GetRefBoundingBox(blkref.object(),blkref->blockTransform());
  42. 这个代码得到的box跟geomExtentsBestFit是一致的。
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|膜结构网

GMT+8, 2024-12-28 14:36 , Processed in 0.157876 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表