Тема: Как подгрузить блоки из другого файла?

Как можно в текущий открытый файл подгрузить блоки из другого файла?

Re: Как подгрузить блоки из другого файла?

Это функция переносит блок с данным именем из pBlockDatabase в pWorkDatabase. pBlockDatabase открывается таким вот образом:

AcDbDatabase* pBlockDatabase=new AcDbDatabase(false,true);
pBlockDatabase->readDwgFile(strFileName);
BOOL ImportBlock(AcDbDatabase* pBlockDatabase,AcDbDatabase* pWorkDatabase,LPCSTR pszBlockName,AcDbObjectId& idImported)
{
    BOOL bRes=TRUE;
    Acad::ErrorStatus es=Acad::eOk;
    
    try
    {
        AcDbBlockTable* pBlockTable;
        es=pBlockDatabase->getSymbolTable(pBlockTable,AcDb::kForRead);
        if(es!=Acad::eOk)throw es;        
        
        AcDbObjectId idInsRecord;        
        es=pBlockTable->getAt(pszBlockName,idInsRecord);
        pBlockTable->close();
        if(es!=Acad::eOk)throw es;
        
        AcDbDatabase* pTempDB;
        es=pBlockDatabase->wblock(pTempDB,idInsRecord);
        if(es!=Acad::eOk)throw es;        
        
        es=pWorkDatabase->insert(idImported,pszBlockName,pTempDB);
        delete pTempDB;
        if(es!=Acad::eOk)throw es;        
    }catch(Acad::ErrorStatus)
    {
        bRes=FALSE;
    }
    return bRes;    
}

Со вставкой блока, думаю, сложностей не возникнет. Если надо перенести все блоки, можно изменить функцию так, чтобы использовать итератор.

Re: Как подгрузить блоки из другого файла?

Огромное спасибо.

Re: Как подгрузить блоки из другого файла?

Спасибо за подробный ответ.

Re: Как подгрузить блоки из другого файла?

Аналогично примеру (см. выше) делаю следующее:

CString sBlockName = "MyBlock"
CString sFileName = "c:\mydwg.dwg"
Acad::ErrorStatus err;
try
{
AcDbDatabase *pDB = new AcDbDatabase(Adesk::kFalse);
err = pDB->readDwgFile(sFileName,_SH_DENYRW);
if (err!=Acad::eOk) throw err;
AcDbBlockTable* pBlockTable;
err = pDB->getSymbolTable(pBlockTable,AcDb::kForRead);
if (err!=Acad::eOk) throw err;
AcDbObjectId idInsRecord;
err = pBlockTable->getAt(sBlockName,idInsRecord);
if (err!=Acad::eOk) throw err;
AcDbDatabase* pTempDB;
err = pDB->wblock(pTempDB,idInsRecord);
if (err!=Acad::eOk) throw err;
pBlockTable->close();
pBlockTable->close();
err = acdbHostApplicationServices()->workingDatabase()->insert(idInsRecord,sBlockName,pTempDB);
if (err!=Acad::eOk) throw err;
delete pTempDB;
delete pDB;
}
catch(Acad::ErrorStatus)
{
acutPrintf("Error loading %s from %s!\n",sBlockName,sFileName);
fCurBlockOk = false;
}
            
}

Но после

err = pDB->wblock(pTempDB,idInsRecord);

В pTempDB попадает почему-то не только нужный мне блок, но и др. блоки, присутствующие в mydwg.dwg
Может кто-то сможет пояснить причину?

Re: Как подгрузить блоки из другого файла?

Может быть, это из-за того, что wblock() использует механизм wblockClone, который, например, может скопировать в новую базу что-то лишнее из-за наличия "Hard" ссылок между объектами?

Re: Как подгрузить блоки из другого файла?

Каким образом тогда нужно корректно решать задачу:
Есть название файла и имя блока.
Нужно добавить определение этого блока в таблицу блоков текущего чертежа.
?
(чтобы исключить возможность добавления "лишних" блоков)

Re: Как подгрузить блоки из другого файла?

err = pBlockTable->getAt(sBlockName,idInsRecord);

err == eKeyNotFound
Подскажите пож. в чем грабли?

Re: Как подгрузить блоки из другого файла?

> Lanter
Дык нету blockTableRecord-а с указанным именем.

Re: Как подгрузить блоки из другого файла?

> Exhumer
- спасибо, бывает :)
Может кому понадобится код (по названию темы) - можно сразу вставлять в проект:

AcDbObjectId id;
AcDbObjectIdArray list;
AcDbDatabase extDatabase( Adesk::kFalse );
char * dwgName = NULL;
struct resbuf *rb;    
rb = acutNewRb(RTSTR);
acedGetFileD("Pick a drawing", NULL, "dwg", 0, rb);
dwgName = (char*)acad_malloc(strlen(rb->resval.rstring) + 1);
strcpy(dwgName, rb->resval.rstring);
acutRelRb(rb);
if (Acad::eOk != extDatabase.readDwgFile(dwgName ))
{
    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 )) {
        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;

Re: Как подгрузить блоки из другого файла?

Нужно вставить содержимое файла как блок в текущий файл (аналог INSERT+BROWSE...). Имя файла известно. Файл находится на путях поддержки, однако точный путь к нему неизвестен.
Как открыть этот файл?
Метод AcDbDatabase::readDwgFile(name) не проводит поиск по путям поддержки, о чем написано в справочнике ObjectArx 2005. Во всех примерах форума точный путь к файлу известен, у меня - нет. Как заставить автокад искать внешнюю AcDbDatabase по имени файла без указания папки по всем путям поддержки (support path)?

Re: Как подгрузить блоки из другого файла?

> Зигмус

extern "C" int acedFindFile(const ACHAR * fname, ACHAR * result);

Re: Как подгрузить блоки из другого файла?

> Александр Ривилис
Спасибо!

Re: Как подгрузить блоки из другого файла?

В продолжение вопроса - что-то вставка блока осуществляется очень медленно.
Т.е. на вставку 100 разных блоков уходит 5-20 секунд в зависимости от размера блоков.
Самая "тягомотная" операция - это
es=pWorkDatabase->insert(idImported,pszBlockName,pTempDB);
Почему то даже быстрее открывается чертеж, из которого надо скопировать, и делается pDB->wblock(pTempDB,idInsRecord);
Я вот даже не знаю что делать. Мне надо вставлять из разных файлов блоки. Много и разных. И даже приличный ПК висит по 15-30 секунд... хотя вставить 200 блоков - казалось бы это - "пшик"...