arx读取dwg文件并选择块插入当前数据库的问题
请问关于arx读取文件的问题用AcDbDatabase pDb建一个临时数据库
用它来读取dwg文件,
pDb->readDwgFile(fileName);
然后得到所需块的id AcDbBlockTable *pBlockTable;
pDb->getBlockTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(blockName,blockId);//blockName已知
pBlockTable->close();
这样得到blockId后如何将这个块插入到当前数据库并显示?
谢谢!
想的太简单了
从一个文件中的块定义Id不能直接拿到另一个文件中作为块参照Id用的,给你一个函数参考
它将外部DWG文件中的块定义复制到当前文件中作为块定义,之后用这个块在当前文件中的块定义Id并插入
//将外部DWG中的块定义导入到当前图形中
//如果当前有同名块定义,则无论是否被参照都将被覆盖,同时参照实体更新
Acad::ErrorStatus ImportBlockDefineFromDwg(CString strSourceDwgFile,CString strBlockName,CString strNewBlockName)
{
AcDbDatabase* pSourceDb;
Acad::ErrorStatus es;
//打开外部文件
pSourceDb=new AcDbDatabase(Adesk::kFalse);
es=pSourceDb->readDwgFile(strSourceDwgFile);
if (es!=Acad::eOk) {
//ads_printf("Error readDwgFile %d",es);
delete pSourceDb;
return es;
}
//获取源文件中的块表
AcDbBlockTable *pBlockTable;
#ifdef ACADR14
es=pSourceDb->getBlockTable(pBlockTable,AcDb::kForRead);
#else
es=pSourceDb->getSymbolTable(pBlockTable,AcDb::kForRead);
#endif
if (es!=Acad::eOk) {
//ads_printf("Error getSymBolTable %d",es);
delete pSourceDb;
return es;
}
//寻找块strBlockName
AcDbBlockTableRecord * pBlockTableRecord;
es = pBlockTable->getAt(strBlockName,pBlockTableRecord,AcDb::kForRead);
if (es!=Acad::eOk) {
//源DWG中未找到块定义
delete pSourceDb;
pBlockTable->close();
return es;
}
//插入到目标DWG中
AcDbObjectId eId;
AcGePoint3d ptBase;
AcDbObjectIdArray ayBlock,aySolids;
AcDbDatabase *pBlockDatabase;
AcDbEntity *pEnt;
ptBase.set(0,0,0);
//遍历源DWG中组成块定义的实体,并添加到实体表ayBlock中
AcDbBlockTableRecordIterator *pBlkIter;
pBlockTableRecord->newIterator(pBlkIter);
for (pBlkIter->start();!pBlkIter->done();pBlkIter->step()) {
pBlkIter->getEntityId(eId);
if (acdbOpenObject(pEnt,eId,AcDb::kForRead)==Acad::eOk) {
if (pEnt->isKindOf(AcDbSolid::desc()) ||
pEnt->isKindOf(AcDb2dPolyline::desc()) ||
pEnt->isKindOf(AcDbPolyline::desc()) ||
pEnt->isKindOf(AcDbFace::desc()) ||
pEnt->isKindOf(CommonPolyline::desc()) ||
pEnt->isKindOf(CommonSolid::desc())
)
{
aySolids.append(eId);
}
else {
ayBlock.append(eId);
}
pEnt->close();
}
}
delete pBlkIter;
//将aySolids中底实体按大至小排序,先显示大图形
int i;
int iLen=aySolids.length();
if (iLen>0) {
BOOL bExchange=TRUE;
double dArea;
AcDbExtents extEnt1,extEnt2;
AcGePoint3d ptExt;
AcDbObjectId eId1,eId2;
AcDbEntity *pEnt1,*pEnt2;
while (bExchange==TRUE) {
bExchange=FALSE;
for (i=0;i;
eId2=aySolids;
if (acdbOpenObject(pEnt1,eId1,AcDb::kForRead)==Acad::eOk) {
if (acdbOpenObject(pEnt2,eId2,AcDb::kForRead)==Acad::eOk) {
if (pEnt1->getGeomExtents(extEnt1)==Acad::eOk) {
if (pEnt2->getGeomExtents(extEnt2)==Acad::eOk) {
ptExt=extEnt1.minPoint();
ptExt=extEnt1.maxPoint();
dArea=fabs((ptExt-ptExt)*(ptExt-ptExt));
ptExt=extEnt2.minPoint();
ptExt=extEnt2.maxPoint();
dArea=fabs((ptExt-ptExt)*(ptExt-ptExt));
if (dAreaclose();
}
pEnt1->close();
}
if (bExchange==TRUE) {break;}
}
}
for (i=0;iclose();
pBlockTable->close();
//写新块数据到pBlockDatabase;
es=pSourceDb->wblock(pBlockDatabase,ayBlock,ptBase);
//ads_printf("\nwblock=%d",es);
AcDbObjectId eNewBlockId;
//将数据pBlockDatabase读入到目标DWG中,新块定义eNewBlockId;
es = CurrectWorkingDWG->insert(eNewBlockId, strNewBlockName, pBlockDatabase, Adesk::kTrue);
//ads_printf("\nInsert=%d",es);
delete pBlockDatabase;
delete pSourceDb;
return es;
} 我以前的做法是用一个临时数据库读取dwg文件,然后insert到当前数据库
但是这样的做就会把所有的块都先插入到当前数据库后,再选择自己想要的
如果我原来的那个dwg定义了10个block,而我只要插入一个的话,那就很不合理了,因为这10个都已经放到当前数据库了,并且还有一个newId,很浪费
不知道这个怎么解决???
AcDbDatabase *pDb = new AcDbDatabase(Adesk::kFalse);
if (Acad::eOk != pDb->readDwgFile(path))
{
acedAlert( "Error reading DWG!" );
return;
}
AcDbObjectId newId;
acdbHostApplicationServices()->workingDatabase()->insert(newId,"newBlock",pDb);
delete pDb;
AcDbBlockTable *pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable,AcDb::kForRead);
AcDbObjectId blockId;
pBlockTable->getAt(blockName,blockId);
AcDbBlockReference *pBlkRef=new AcDbBlockReference();
pBlkRef->setBlockTableRecord(blockId);
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRecord,AcDb::kForWrite);
pBlockTable->close();
pBlockTableRecord->appendAcDbEntity(pBlkRef);
pBlockTableRecord->close();
pBlkRef->close();
后来我又找到doc里面有个sample,是讲clone的,它的做法也是用一个临时的Database读取,然后遍历到另一个database里,然后Insert到当前数据库
但是我把其中一个小地方改了一下就不行了,郁闷
它的源码是这样:
AcDbObjectId id;
AcDbObjectIdArray list;
AcDbDatabase extDatabase( Adesk::kFalse );
if (Acad::eOk != extDatabase.readDwgFile(path))
{
acedAlert( "Error reading DWG!" );
return;
}
AcDbBlockTable* pBT;
if (Acad::eOk != extDatabase.getSymbolTable( pBT, AcDb::kForRead ))
{
acedAlert( "Error getting BlockTable of DWG" );
return;
}
AcDbBlockTableRecord* pBTR;
Acad::ErrorStatus es = pBT->getAt( ACDB_MODEL_SPACE, pBTR, AcDb::kForRead );
pBT->close();
if (Acad::eOk != es) {
acedAlert( "Error getting model space of DWG" );
return;
}
AcDbBlockTableRecordIterator* pIT;
if (Acad::eOk != pBTR->newIterator( pIT )) {
acedAlert( "Error iterating model space of DWG" );
pBTR->close();
return;
}
for ( ; !pIT->done(); pIT->step()) {
if (Acad::eOk == pIT->getEntityId( id )) {
acutPrintf(" %lx",id);
list.append( id );
AcDbEntity *pEnt;
if ( Acad::eOk == pIT->getEntity(pEnt, AcDb::kForRead)) {
AcDbObjectId obj;
if ((obj = pEnt->extensionDictionary())
!= AcDbObjectId::kNull)
{
AcDbDictionary *pDict = NULL;
acdbOpenObject(pDict, obj, AcDb::kForWrite);
if (pDict) {
pDict->setTreatElementsAsHard(Adesk::kTrue);
pDict->close();
}
}
pEnt->close();
}
}
}
delete pIT;
pBTR->close();
if (list.isEmpty()) {
acedAlert( "No entities found in model space of DWG" );
return;
}
AcDbDatabase *pTempDb;
if (Acad::eOk != extDatabase.wblock( pTempDb, list, AcGePoint3d::kOrigin ))
{
acedAlert( "wblock failed!" );
return;
}
if (Acad::eOk != acdbHostApplicationServices()->workingDatabase()
->insert( AcGeMatrix3d::kIdentity, pTempDb ))
acedAlert( "insert failed!" );
delete pTempDb;
它是遍历每个实体,而我只想要我自己想要的
所以我改成了这样
AcDbObjectId id;
AcDbObjectIdArray list;
AcDbDatabase extDatabase( Adesk::kFalse );
if (Acad::eOk != extDatabase.readDwgFile(path))
{
acedAlert( "Error reading DWG!" );
return;
}
AcDbBlockTable* pBT;
if (Acad::eOk != extDatabase.getSymbolTable( pBT, AcDb::kForRead ))
{
acedAlert( "Error getting BlockTable of DWG" );
return;
}
pBT->getAt(blockName,id); //修改的地方
acutPrintf(" %lx",id); //修改的地方
list.append( id ); //修改的地方
if (list.isEmpty()) {
acedAlert( "No entities found in model space of DWG" );
return;
}
AcDbDatabase *pTempDb;
if (Acad::eOk != extDatabase.wblock( pTempDb, list, AcGePoint3d::kOrigin ))
{
acedAlert( "wblock failed!" );
return;
}
if (Acad::eOk != acdbHostApplicationServices()->workingDatabase()
->insert( AcGeMatrix3d::kIdentity, pTempDb ))
acedAlert( "insert failed!" );
delete pTempDb;
这样就不行了
提示就是wblock failed!
这又是什么原因呢?照理说应该行的啊?
页:
[1]