Тема: Работа с shape

Интересуют вопросы:
1. Как загрузить shx файл (есть ли еще варианты кроме команды load)?
2. Как получить список всех shape в загруженном shx файле
3. Как коррекно создать AcDbShape и добавить его в чертеж?
Бросьте пжста кусочек кода.. :)

Re: Работа с shape

Все, разобрался сам.
Если кому интересно:
1. Ничего другого нет
2. Никакого способа пока не нашел :(
3. Это код работает корректно:

//Константы
const CString shxFileName = "???.shx";    //ставим по своему усмотрению
const CString formName    = "form";        //ставим по своему усмотрению
    
//Загрузить shape
setSysVar("FILEDIA", 0);
int res = acedCommand(RTSTR, "_load", RTSTR, shxFileName+" ", 0);
setSysVar("FILEDIA", 1);
if(res!=RTNORM) return;
//Найти созданный текстовый стиль
AcDbObjectId styleId;  bool bStyleFind = false;
AcDbTextStyleTable* pStyleTable;    
acdbHostApplicationServices()->workingDatabase()->getTextStyleTable(pStyleTable, AcDb::kForRead);
AcDbTextStyleTableIterator* pIterator;
pStyleTable->newIterator(pIterator);    
// iterate through the text style table
for( ; !pIterator->done(); pIterator->step())    
{
    AcDbTextStyleTableRecord *pStyle;
    pIterator->getRecord(pStyle, AcDb::kForRead);
        
    const char *name;
    pStyle->fileName(name);
    styleId = pStyle->objectId();
    pStyle->close();
        
    CString strName(name);
    if(strName.Find(shxFileName) != -1)  { bStyleFind = true; break; }
}
delete pIterator;
pStyleTable->close();
if(!bStyleFind) return;
//Создать shape, добавить в базу    
AcDbShape *pShape = new AcDbShape();
AcDbObjectId objId = postToDB(pShape);
//Задать параметры
acdbOpenAcDbEntity((AcDbEntity*&)pShape, objId, AcDb::kForWrite);
if(!pShape)  return;
        
Acad::ErrorStatus es = pShape->setShapeIndex(styleId);        
es = pShape->setName(formName);
pShape->close();

Фокусов несколько:
а. При загрузке файла с формами (shx) CAD автоматически создает безымянный текстовый стиль
б. Shape-у можно указать какую форму использовать (setName) только после того как он добавлен в базу

Re: Работа с shape

> Roman
1) Есть - посмотри внимательно здесь: https://www.caduser.ru/forum/topic27035.html
Там есть такой кусочек:

    //
    // Если подходящей записи в таблице стилей нет — создадим ее!
    //
    if (ttId.isNull()) {
      if (pTT->upgradeOpen() != Acad::eOk) {
        return;
      }
      AcDbTextStyleTableRecord *pTTR = new AcDbTextStyleTableRecord();
      pTTR->setFileName("ltypeshp.shx"); // Здесь можно задать свой shx-файл
      pTTR->setIsShapeFile(true);
      if ((es = pTT->add(ttId,pTTR)) != Acad::eOk) {
        acutPrintf("\npTT->add(ttId,pTTR)=%s",acadErrorStatusText(es));
        delete pTTR;
        return;
      }
      pTTR->close();
    }
    pTT->close();

2) Можно, если декодировать shx-файл

Re: Работа с shape

> Александр Ривилис
Програмно вызвать dumpshx.exe, и выполнять разбор полученного shp файла?
Меня интересует вариант похожий на использование AcDbBlockTableIterator, а такового пока не нашел :(

Re: Работа с shape

Roman пишет:

Програмно вызвать dumpshx.exe, и выполнять разбор полученного shp файла?

Это было бы слишком. :) Я имел в виду непосредственный анализ shx-файла из твоей программы:

static void ShapeNames(void)
{
  struct SHAPESTRUCT {
    unsigned short iShapeNumber;     // shape number
    unsigned short iDefBytes;        // number of data bytes in shape, 2000 max
    unsigned char *lpszShapeName;    // pointer to shapename
    unsigned char *lpszSpecBytes;    // pointer to shape specification bytes
  };
  char SHAPE10[] = "AutoCAD-86 shapes 1.0";
  char SHAPE11[] = "AutoCAD-86 shapes 1.1";
  resbuf *rbfile = NULL;
  if (RTNORM == acedGetFileNavDialog("Select shape file","","shx","ShapeNames",0,&rbfile))
  {
    FILE *fshx = fopen(rbfile->resval.rstring,"rb"); acutRelRb(rbfile);
    if (fshx) {
      char desc[32];
      fread (desc,sizeof(desc),1,fshx);
      if (!strstr(desc,SHAPE10) && !strstr(desc,SHAPE11)) {
        acutPrintf("\nIt is not shape file!");
        fclose(fshx);
        return;
      }
      fseek (fshx, (long)0x1c, SEEK_SET);
      unsigned short iNumShapes = 0;
      fread (&iNumShapes, sizeof (iNumShapes), 1, fshx);
      SHAPESTRUCT *lpShapeList, *lpShape;
      lpShapeList = (SHAPESTRUCT *)calloc(iNumShapes, sizeof (*lpShapeList));
      for (int i=0; i < iNumShapes; i++) {
        lpShape = lpShapeList + i;
        fread(&(lpShape->iShapeNumber), sizeof (lpShape->iShapeNumber), 1, fshx);
        fread(&(lpShape->iDefBytes), sizeof (lpShape->iDefBytes), 1, fshx);
      }
      if (lpShapeList->iShapeNumber != 0) { // Это файл формы
        for (int i = 0; i < iNumShapes; i++) {
          lpShape = lpShapeList + i;
          lpShape->lpszShapeName = (unsigned char *)(malloc (lpShape->iDefBytes));
          fread (lpShape->lpszShapeName, sizeof (*lpShape->lpszShapeName), lpShape->iDefBytes, fshx);
          acutPrintf("\nShape N%d = %s", i, lpShape->lpszShapeName);
          free(lpShape->lpszShapeName);
        }
      } else {
        acutPrintf("\nIt is not shape file!");
      }
      free(lpShapeList);
      fclose(fshx);
    }
  }
}

В этой этой программе не исключены ошибки, т.к. я ее переделывал из другой, но общая идея надеюсь понятна.

Re: Работа с shape

Оригинальное решение!
Большое спасибо.
Но вчера решил, этим путем не ити :(
Поскольку времени на эксперименты практически нет, воспользуюсь старыми проверенными блоками.
Помимо упрощения реализации, удастся получить еще несколько интересных пользователям фишек

Re: Работа с shape

> Roman
Ну тогда это решение может еще кому пригодится... :)