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