[每日一码] 计算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();
} 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]