admin 发表于 2024-2-23 22:24:05

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

void test()
{
ads采用name ename;
ads采用point pt;
if (acedEntSel("Select a block reference:",ename,pt)!=RTNORM)
return;
AcDbObjectId id;
if (acdbGetObjectId(id,ename)!=Acad::eOk)
return;
AcDbExtents extents;
AcDbBlockReference* pRef;
if (acdbOpenObject(pRef,id,AcDb::kForRead)==Acad::eOk)
{
if (Acad::eOk==getBlockRefGeomExtents(pRef,extents))
{
   //just display the 2d box
   AcGePoint2d minpt(extents.minPoint(),extents.minPoint());
   AcGePoint2d maxpt(extents.maxPoint(),extents.maxPoint());
   AcGePoint2dArray points;
   points.append(minpt);
   AcGePoint2d pt(maxpt,minpt);
   points.append(pt);
   points.append(maxpt);
   pt.set(minpt,maxpt);
   points.append(pt);
   AcDbPolyline* pPline;
   if ((pPline=makeSimplePline(points))!=NULL){
    pPline->setClosed(Adesk::kTrue);
    AcDbObjectId id;
    postToDb(pPline,id);
   }
} else
   acutPrintf("\nCannot calculate accurate extents");
pRef->close();
}
}
//creates a polyline with 0 width, without bulges
AcDbPolyline* makeSimplePline(const AcGePoint2dArray& points)
{
   AcDbPolyline* pPline = new AcDbPolyline(points.length());
   if (pPline==NULL)
    return pPline;
   for (int i=0;i<points.length();i++)
    if (pPline->addVertexAt(i,points<i>)!=Acad::eOk)
{
      delete pPline;
      pPline = NULL;
      break;
    }
   return pPline;
}//explodes a 2dpolyline by first converting it to a new polyline
Acad::ErrorStatus explodeAcDb2dPolyline(const AcDb2dPolyline*
p2d,AcDbVoidPtrArray& ents){
   if (p2d==NULL)
    return Acad::eInvalidInput;
   AcDbPolyline* pPline;
   if ((pPline=new AcDbPolyline)==NULL)
    return Acad::eOutOfMemory;
   Acad::ErrorStatus es;
   if ((es=pPline->convertFrom((AcDbEntity*&)p2d,Adesk::kFalse))==Acad::eOk)
   {
    es=pPline->explode(ents);
   }
   return es;
}






Acad::ErrorStatus getBlockRefGeomExtents(AcDbBlockReference* pRef, AcDbExtents&
extents, const AcGeMatrix3d& mat)
{   
   Acad::ErrorStatus es;
   AcGeMatrix3d xform;
   AcDbEntity* pCopy;
   AcDbEntity* pE;
   xform=mat*pRef->blockTransform();
   AcDbObjectId idBlock = pRef->blockTableRecord();
   AcDbBlockTableRecord* pBlock;
   if ((es=acdbOpenObject(pBlock,idBlock,AcDb::kForRead))==Acad::eOk){
    AcDbBlockTableRecordIterator* pIter;
    if ((es=pBlock->newIterator(pIter))==Acad::eOk){
       for (pIter->start();!pIter->done();pIter->step()){
      AcDbExtents ext;
      if ((es=pIter->getEntity(pE,AcDb::kForRead))==Acad::eOk)
{
            AcDbBlockReference* pRefNested;
            if ((pRefNested=AcDbBlockReference::cast(pE))!=NULL)
   {
    if ((es=getBlockRefGeomExtents(pRefNested,ext,xform))!=Acad::eOk)
    {
   pE->close();
   break;
    }
            }
   else
   {
    AcRxClass* pDesc = pE->isA();
    if (pDesc==AcDbPolyline::desc() ||
   pDesc==AcDb2dPolyline::desc() ||
   pDesc==AcDbMText::desc())
    {
   //need explode
   AcDbVoidPtrArray array;
   if (pDesc==AcDbPolyline::desc())
   es=pE->explode(array);
   if (pDesc==AcDbMText::desc())
   es=pE->explode(array);   if (pDesc==AcDb2dPolyline::desc())
   es=explodeAcDb2dPolyline(AcDb2dPolyline::cast(pE),array);   if (es==Acad::eOk)
   {
      for(int i=0;i<array.length();i++)
      {
       AcDbExtents ext2;
       AcDbEntity* pPart = ((AcDbEntity*)(array<i>));
       if((es=pPart->getTransformedCopy(xform,pCopy))==Acad::eOk)
       {
      es=pCopy->getGeomExtents(ext2);
      delete pCopy;
       }
       if (es!=Acad::eOk)
       {
      delete pPart;
      if (es==Acad::eNullExtents)
         continue;
      else
         break;
       }
       delete pPart;
       ext.addExt(ext2);
      }
   }
    }
    else
    {
   if((es=pE->getTransformedCopy(xform,pCopy))==Acad::eOk)
   {
      es=pCopy->getGeomExtents(ext);
      delete pCopy;
   }
    }
            }
            if (es!=Acad::eOk)
   {
    pE->close();
    if (es==Acad::eNullExtents)
   continue;
    else
   break;
   }
            extents.addExt(ext);
            pE->close();
      }
      }
      delete pIter;
    }
   }
   pBlock->close();
   //add non constant attributes
   AcDbObjectIterator* pIter;
   if ((pIter=pRef->attributeIterator())==NULL)
    return Acad::eOutOfMemory;
   for (pIter->start();!pIter->done();pIter->step())
   {
    AcDbExtents ext;
    if((es=acdbOpenObject(pE,pIter->objectId(),AcDb::kForRead))==Acad::eOk)
{
      pE->getGeomExtents(ext);
      if (es!=Acad::eOk)
{
   pE->close();
   if (es==Acad::eNullExtents)
    continue;
   else
    break;
      }
      extents.addExt(ext);
      pE->close();
    }
   }
   delete pIter;
   return es;
}//Posts an entity to the database
//
Acad::ErrorStatus postToDb(AcDbEntity* ent, AcDbObjectId& objId)
{
   Acad::ErrorStatus       es;
   AcDbBlockTable*       pBlockTable;
   AcDbBlockTableRecord*pSpaceRecord;

    if (NULL == ent)
      return Acad::eNullObjectPointer;
    if (NULL == acdbHostApplicationServices()->workingDatabase())
      return Acad::eNoDatabase;

   if ((es = acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead))!= Acad::eOk)
      return es;

   if ((es = pBlockTable->getAt(ACDB采用MODEL采用SPACE,pSpaceRecord,AcDb::kForWrite))!= Acad::eOk)
    {
      pBlockTable->close();
      return es;
    }
   pBlockTable->close();

   if ((es = pSpaceRecord->appendAcDbEntity(objId, ent)) != Acad::eOk)
    {
      pSpaceRecord->close();
    return es;
   }
   pSpaceRecord->close();
   return ent->close();
}

admin 发表于 2024-2-23 22:26:15

AcDbExtents CEntity::GetRefBoundingBox (AcDbBlockReference *pRef, const AcGeMatrix3d & mat)
{
      AcDbExtents ext;
      AcDbExtents RetExt;
      AcDbObjectId recId = pRef->blockTableRecord();
      AcDbBlockTableRecordPointer block(recId,AcDb::kForRead);
      Acad::ErrorStatus es = block.openStatus();
      if (es == eOk)
      {
                AcDbBlockTableRecordIterator *pItr = NULL;
                block->newIterator(pItr);
                AcDbObjectId id;
                AcDbEntity *pEnt = NULL;
                for (pItr->start();!pItr->done();pItr->step())
                {
                        es = pItr->getEntity(pEnt,AcDb::kForWrite);
                        if (es == eOk)
                        {
                              pEnt->transformBy(mat);
                              if (pEnt->isKindOf(AcDbBlockReference::desc()))
                              {
                                        AcGeMatrix3d blkmat=((AcDbBlockReference*)pEnt)->blockTransform();
                                        ext = GetRefBoundingBox((AcDbBlockReference *)pEnt,blkmat);
                              }
                              else
                              {
                                        pEnt->getGeomExtents(ext);
                              }
                              pEnt->transformBy(mat.inverse());
                              RetExt.addExt(ext);
                              pEnt->close();
                        }
                }
                delete pItr;
                pItr = NULL;
      }
      return RetExt;
}



譬如:
AcDbObjectPointer<AcDbBlockReference> blkref(id,AcDb::kForRead);   //id块参照的id
AcDbExtentsext = CEntity::GetRefBoundingBox(blkref.object(),blkref->blockTransform());

这个代码得到的box跟geomExtentsBestFit是一致的。
页: [1]
查看完整版本: [每日一码] 计算AcDbBlockReference准确的包围盒