newer 发表于 2021-2-2 10:00:01

AcDbBlockReference::explode 失败

AcDbBlockReference::explode fails

问题:

Why does AcDbBlockReference::explode produce incorrect results if there are
AcDbText or AcDbAttribute definition entities in the block that is exploded?

解答:

This isa known problem that is desribed in DevNote #TS36113.
AcDbBlockReference::explode internally calls AcDbText::getTransformedCopy that
produces incorrect results. The code below uses the code in DevNote #TS36113 to
explode an AcDbBlockReference correctly.


Acad::ErrorStatus safeExplode(const AcDbBlockReference* pRef,AcDbVoidPtrArray&entitySet)
{
AcDbBlockTableRecord* pBTR;
Acad::ErrorStatus es;
if ((es = acdbOpenAcDbObject((AcDbObject*&)pBTR, pRef->blockTableRecord(), AcDb::kForRead)) == Acad::eOk)
{   
AcDbBlockTableRecordIterator* pIterator;
if (pBTR->newIterator(pIterator) == Acad::eOk)
{
   AcGeMatrix3d xform = pRef->blockTransform();   
   AcGePoint3d pt3dBlkOrigin = pBTR->origin();
   if (pt3dBlkOrigin != AcGePoint3d::kOrigin)
   {   
    AcGeVector3d xformOrigin = xform.translation();
    AcGeVector3d vectorOrigin(pt3dBlkOrigin.x,pt3dBlkOrigin.y,0.0);
    vectorOrigin.transformBy(xform);
    xformOrigin -= vectorOrigin;   
    xform.setTranslation(xformOrigin);   
   }   
   pIterator->start();   
   while (!pIterator->done())
   {   
    AcDbEntity* pEntity;
    if (pIterator->getEntity(pEntity, AcDb::kForRead) == Acad::eOk)
    {
      // If pEntity does not implement getTransformedCopy()
      // or explode() methods, we should simply ignore
      // that entity and continue to step into next entity
      // instead of exit prematurely. Most operations such
      // as BHATCH depends on complete iteration through
      // the entire block entities.      
      AcDbEntity* pNewEntity;
      AcDbText* pText =NULL;   
      if (pText=AcDbText::cast(pEntity))
       es = AdskUtil::safeGetTransformedCopy(pText,xform, pNewEntity);      
      else
      es = pEntity->getTransformedCopy(xform, pNewEntity);
      if (es==Acad::eOk)
      {
      entitySet.append(pNewEntity);
      }
      else if (Acad::eExplodeBeforeTransform == es)
      {
      AcDbVoidPtrArray explSet;
      if (Acad::eOk == pEntity->explode(explSet))
      {
       for (int i = 0; i < explSet.length(); i++)
       {         
      AcDbEntity* pObj = (AcDbEntity*)explSet;
      if (Acad::eOk == pObj->getTransformedCopy( xform, pNewEntity))
      {   
         entitySet.append(pNewEntity);   
      }      
      delete pObj;   
       }
      }
   }
   else if (Acad::eCopyFailed == es)
   {            
      AcDbVoidPtrArray explSet;   
      if (Acad::eOk == pEntity->explode(explSet))
      {            
       for (int i = 0; i < explSet.length(); i++)   
       {         
      AcDbEntity* pObj = (AcDbEntity*)explSet;
      if (Acad::eOk == pObj->transformBy(xform))
      {         
         entitySet.append(pObj);
      }         
       }   
      }   
   }   
   pEntity->close();
    }
    pIterator->step();
   }   
   delete pIterator;
}
pBTR->close();
}
return es;
}


革天明 发表于 2022-11-5 22:28:28

请问safeGetTransformedCopy这个函数是自定义的吗?源码可否发一下

XDSoft 发表于 2023-11-14 03:08:58

革天明 发表于 2022-11-5 22:28
请问safeGetTransformedCopy这个函数是自定义的吗?源码可否发一下

对AcDbText的安全的transformedCopy方法


Acad::ErrorStatus XdDbUtils::safeGetTransformedCopy(const AcDbText* pText,
                                                                                                        const AcGeMatrix3d xform, AcDbEntity*& pNewEntity)
{
        static AcDbText text;   
        Acad::ErrorStatus es;   
        text.copyFrom(pText);   
        AcGePoint3d posorig(text.position());   
        AcGePoint3d alignorig(text.alignmentPoint());
        AcGePoint3d pos,align;
        AcGeVector3d norm(text.normal());
        acdbWcs2Ecs(asDblArray(posorig),asDblArray(pos),asDblArray(norm),
                Adesk::kFalse);   
        double elev = pos.z;
        if (fabs(elev)>1E-10)   
        {   
                pos.z = 0;   
                align.z =0;      
                acdbEcs2Wcs(asDblArray(pos),asDblArray(pos),asDblArray(norm),
                        Adesk::kFalse);      
                acdbEcs2Wcs(asDblArray(align),asDblArray(align),asDblArray(norm),
                        Adesk::kFalse);   
                text.setPosition(pos);   
                text.setAlignmentPoint(align);   
        }   
        if ((es = text.getTransformedCopy(xform,pNewEntity))==Acad::eOk)   
        {   
                AcDbText* pNewText = NULL;   
                if ((pNewText = AcDbText::cast(pNewEntity)) && fabs(elev)>1E-10)   
                {      
                        posorig.transformBy(xform);      
                        alignorig.transformBy(xform);      
                        pNewText->setPosition(posorig);      
                        pNewText->setAlignmentPoint(alignorig);   
                }   
        }   
        return es;
}

革天明 发表于 2023-11-27 09:00:00

XDSoft 发表于 2023-11-14 03:08
对AcDbText的安全的transformedCopy方法

谢谢回复,我学习一下
页: [1]
查看完整版本: AcDbBlockReference::explode 失败