Тема: Вставка блоков

Здравствуйте!
Может ли кто-то подсказать?
Такой вопрос: есть пространство чертежа, в котором несколько блоков (2D) с разными именами. И есть группа файлов с такими же именами. В каждом из этих файлов находится блок (3D) (в одном файле - один блок).
Нужно программно занести в пространство чертежа блоки (3D), соответствующие блокам (2D). Как это можно осуществить?
Спасибо за внимание!

Re: Вставка блоков

AutoCAD 2008, ObjectARX 2008

Re: Вставка блоков

> tati
Мало информации. Во внешних файлах содержится блок или в пространстве модели внешних блоков примитивы, которые должны попасть в основной чертеж как блок.

Re: Вставка блоков

Во внешних файлах содержатся блоки.

Re: Вставка блоков

Надеюсь имена 2D и 3D блоков отличаются?

Re: Вставка блоков

> Александр Ривилис
Да, отличаются последней цифрой. Например, file_1.1.dwg (блок 2D) и file_1.2.dwg (блок 3D)

Re: Вставка блоков

P.S.: Имя файла такое же, как и имя содержащегося в нем блока.

Re: Вставка блоков

Вот тебе заготовочка:

static void CPBLOCK(void)
{
  resbuf *result = NULL;
  result = acutNewRb(RTSTR);
  result->resval.rstring = NULL;
  Acad::ErrorStatus es = Acad::eOk;
  ACHAR *filepath = NULL;
  if  (acedGetFileD(_T("Select file:"), NULL, _T("dwg"), 0, result) == RTNORM) {
    filepath = acad__strdup(result->resval.rstring); acutRelRb(result);
  } else {
    acutRelRb(result);
    return;
  }
  AcDbDatabase *db = new AcDbDatabase();
  if ((es = db->readDwgFile(filepath,_SH_DENYNO)) != Acad::eOk) {
    acutPrintf(_T("\nError open database <%s> with error %s!"),filepath, acadErrorStatusText(es));
    delete db;
    return;
  }
  ACHAR path_buffer[_MAX_PATH], drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
  _tsplitpath(filepath,drive,dir,fname,ext);
  AcDbIdMapping idMap;
  idMap.setDestDb(acdbCurDwg());
  AcDbObjectId idBTR;
  AcDbBlockTablePointer pBT(db,AcDb::kForRead);
  if (pBT.openStatus() == Acad::eOk && pBT->getAt(fname,idBTR) == Acad::eOk) {
    AcDbObjectIdArray ids; ids.append(idBTR);
    if ((es = db->wblockCloneObjects(ids,acdbCurDwg()->blockTableId(),idMap,AcDb::kDrcReplace)) != Acad::eOk) {
      acutPrintf(_T("\nError copy block definition <%s> with error %s!"),fname, acadErrorStatusText(es));
    }
    pBT.close(); // Обязательно перед delete db; !!!
  }
  delete db;
}

Re: Вставка блоков

> Александр Ривилис
Большое спасибо за помощь! Буду пробовать.

Re: Вставка блоков

> tati
Только не забудь:

free(filepath);

Иначе будет "утечка" памяти.

Re: Вставка блоков

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

Re: Вставка блоков

Здравствуйте, Александр. Почему-то программа не работает.
Пробую пока делать в ObjectARX 2006.
Ввожу команду, выбираю в окошке нужный файл с блоком, и AutoCAD выдает ошибку:
"Необрабатываемое исключение С0000005 (Access Violation Reading 0xffffffff) по адресу 7EF9731Bh".
И еще, удобнее было бы работать не с файлом, в котором содержится блок, а конкретно с файлом-блоком.
Не подскажете, что для этого нужно изменить в коде?

Re: Вставка блоков

> tati
Что такое файл-блок? Это то что я имел в виду в начале т.е. в пространстве модели содержаться примитивы из которых должен быть создан блок?

Re: Вставка блоков

> Александр Ривилис
Создается динамический блок как отдельный файл: рисуется объект, вызывается команда ПБЛОК и этот объект сохраняется как блок.

Re: Вставка блоков

> tati
Ну тогда попробуй такой код:

static void CPBLOCK(void)
{
  resbuf *result = NULL;
  result = acutNewRb(RTSTR);
  result->resval.rstring = NULL;
  Acad::ErrorStatus es = Acad::eOk;
  ACHAR filepath[_MAX_PATH];
  if  (acedGetFileD("Select file:", NULL, "dwg", 0, result) == RTNORM) {
    strcpy(filepath,result->resval.rstring); acutRelRb(result);
  } else {
    acutRelRb(result);
    return;
  }
  AcDbDatabase *db = new AcDbDatabase();
  if ((es = db->readDwgFile(filepath,_SH_DENYNO)) != Acad::eOk) {
    acutPrintf("\nError open database <%s> with error %s!",filepath, acadErrorStatusText(es));
    delete db;
    return;
  }
  ACHAR path_buffer[_MAX_PATH],drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
  _splitpath(filepath,drive,dir,fname,ext);
  AcDbIdMapping idMap; idMap.setDestDb(acdbCurDwg());
  AcDbObjectId idBTR_new;
  AcDbObjectIdArray ids;
  if (acdbSNValid(fname,FALSE) == RTNORM) {
    AcDbBlockTableRecordPointer pBTR(ACDB_MODEL_SPACE,db,AcDb::kForRead);
    if (pBTR.openStatus() == Acad::eOk) {
      AcDbBlockTableRecordIterator *pIter = NULL;  pBTR->newIterator(pIter);
      if (pIter) {
        for (pIter->start();!pIter->done(); pIter->step()) {
          AcDbObjectId id;
          if (pIter->getEntityId(id) == Acad::eOk) {
            ids.append(id);
          }
        }
        delete pIter;
      }
    }
    AcDbBlockTableRecord *pBTR_new = new AcDbBlockTableRecord();
    pBTR_new->setName(fname);
    pBTR_new->setOrigin(db->insbase());
    AcDbBlockTablePointer pBT(acdbCurDwg(),AcDb::kForWrite);
    if (pBT.openStatus() == Acad::eOk) {
      if (!pBT->has(fname)) {
        pBT->add(idBTR_new,pBTR_new);
        pBTR_new->close();
      }
    } else {
      delete pBTR_new;
    }
  } else {
    acedAlert("Invalid file name - can not be set as block name!!!");
  }
  if (idBTR_new.isValid() && ids.length() > 0) {
    if ((es = db->wblockCloneObjects(ids,idBTR_new,idMap,AcDb::kDrcReplace)) != Acad::eOk) {
      acutPrintf("\nError copy block definition <%s> with error %s!",fname,acadErrorStatusText(es));
    }
  } else {
    acedAlert("Can not copy block definition!!!");
  }
  delete db;
}

Re: Вставка блоков

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

Re: Вставка блоков

А еще проще так:

#include "axlock.h"
static void CPBLOCK(void)
{
  AcAxDocLock doc(acdbCurDwg());
  if (doc.lockStatus() != Acad::eOk) {
    acedAlert("Error locking working database!!!");
  } else {
    resbuf *result = NULL;
    result = acutNewRb(RTSTR);
    result->resval.rstring = NULL;
    Acad::ErrorStatus es = Acad::eOk;
    ACHAR filepath[_MAX_PATH];
    if  (acedGetFileD("Select file:", NULL, "dwg", 0, result) == RTNORM) {
      strcpy(filepath,result->resval.rstring); acutRelRb(result);
    } else {
      acutRelRb(result);
      return;
    }
    AcDbDatabase *db = new AcDbDatabase();
    if ((es = db->readDwgFile(filepath,_SH_DENYNO)) != Acad::eOk) {
      acutPrintf("\nError open database <%s> with error %s!",filepath, acadErrorStatusText(es));
      delete db;
      return;
    }
    ACHAR path_buffer[_MAX_PATH],drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
    _splitpath(filepath,drive,dir,fname,ext);
    AcDbObjectId id_new;
    if (acdbSNValid(fname,FALSE) != RTNORM) {
      acutPrintf("\nFile name can not be used as block name!!!");
    } else if ((es = acdbCurDwg()->insert(id_new,ACDB_MODEL_SPACE,fname,db)) != Acad::eOk) {
      acutPrintf("\nError copy block definition <%s> with error %s!",fname,acadErrorStatusText(es));
    }
    delete db;
  }
}

Re: Вставка блоков

> Александр Ривилис
А так почему-то не получается.
Пишет: Блок new block2 ссылается сам на себя.
Error copy block definition <new block2> with error eSelfReference!

Re: Вставка блоков

> tati
Значит неправильно сформирован dwg-файл. Судя по всему в нем есть и примитивы в MODEL_SPACE и описание блока с именем равным имени dwg-файла.