Тема: Проблема с конвертацией AcDb2dPolyline

Конвертирую на чертеже все объекты AcDb2dPolyline в полилинии типа AcDbPolyline при помощи convertFrom(...). Все замечательно. Но нашелся один объект который упорно не хочет конвертится. Метод возвращает Acad::eNotApplicable. Причем сам объект прост "как студенческий батон" - polyType() возвращает k2dSimplePoly. Замечено следующее: стоит немного изменить объект (например при помощи команды TRIM) объект конвертится без вопросов.
Что с объектом не так? И куда копать чтобы заставить его успешно пройти конвертацию? Может кто сталкивался с такой проблемой?

Re: Проблема с конвертацией AcDb2dPolyline

> Debalance
Нет случайно расширенных данных (XDATA) у вершин этой полилинии?

Re: Проблема с конвертацией AcDb2dPolyline

> Александр Ривилис
Не знаю, Александр. Объект был получен конвертацией из Inventer'а, кто его знает что он туда запихнул...
Признаюсь не доводилось общаться с объектами XDATA. Правильно ли я понимаю, что проверить наличие расширенных данных у вершины можно по средством метода AcDbObject::xData()? Получается что условие присутствия неких данных - есть ненулевой указатель?

Re: Проблема с конвертацией AcDb2dPolyline

> Debalance
Именно так. Мне интересно было бы вглянуть на такой объект.

Re: Проблема с конвертацией AcDb2dPolyline

P.S.: Может быть не стоит полагаться на возможности convertFrom, а использовать подобный код для конвертации AcDb2dPolyline в AcDbPolyline:

static void P2DtoLWPoly(void)
{
  ads_name en; ads_point p;
  Acad::ErrorStatus es;
  AcDbCurve *pEnt = NULL;
  while (acedEntSel("\nУкажите 2D-полилинию: ",en,p) == RTNORM) {
    acedBeginUndoGroup(curDoc());
    AcDbObjectId objId; acdbGetObjectId(objId,en);
    AcDbObjectPointer<AcDb2dPolyline> pPoly2D(objId,AcDb::kForWrite);
    if ((es = pPoly2D.openStatus()) == Acad::eOk) {
      AcDbPolyline *pLWPoly = new AcDbPolyline();
      pLWPoly->setDatabaseDefaults(acdbCurDwg());
      pLWPoly->setPropertiesFrom(pPoly2D.object());
      pLWPoly->setNormal(pPoly2D->normal());
      pLWPoly->setElevation(pPoly2D->elevation());
      pLWPoly->setPlinegen(pPoly2D->isLinetypeGenerationOn());
      pLWPoly->setThickness(pPoly2D->thickness());
      pLWPoly->setClosed(pPoly2D->isClosed());
      AcDbObjectIterator *pIter = pPoly2D->vertexIterator();
      if (pIter) {
        for (int iVert = 0; !pIter->done(); (pIter->step(), iVert++)) {
          AcDbObjectId objId = pIter->objectId();
          AcDbObjectPointer<AcDb2dVertex> pVert(objId,AcDb::kForRead);
          if ((es = pVert.openStatus()) == Acad::eOk) {
            es = pLWPoly->addVertexAt(iVert,asPnt2d(asDblArray(pVert->position())),
              pVert->bulge(),
              pVert->startWidth(),
              pVert->endWidth()
            );
            if (es != Acad::eOk) {
              acutPrintf("\npLWPoly->addVertexAt() = %s", acadErrorStatusText(es));
            }
          } else {
            acutPrintf("\npVert.openStatus() = %s", acadErrorStatusText(es));
          }
        }
      }
      if (pLWPoly->numVerts() < 2) {
        acutPrintf("\nКоличество вершин полилинии < 2!");
        delete pLWPoly;
      } else {
        // Добавляем новую полилинию в чертеж
        postToDatabase(pPoly2D->blockId(),pLWPoly);
        pLWPoly->recordGraphicsModified();
        pLWPoly->close(); // Не забываем закрыть новую полилинию
        pPoly2D->erase(); // Удаляем старую 2D-полилинию
        acutPrintf("... Готово!");
      }
    } else {
      acutPrintf("\nЭто не 2D-полилиния или ее нельзя открыть для записи!");
    }
    acedEndUndoGroup(curDoc(),false);
  }
}

Тут во всяком случае не будет ограничений, которые накладывает AutoCAD на возможность конвертации.

Re: Проблема с конвертацией AcDb2dPolyline

> Александр Ривилис
Спасибо, Александр, за такое чуткое отношение к моей маленькой проблеме. Приведенный Вами код обязательно протестирую. Что касается моего капризного объекта, то направлю на Ваш мэйл в ближайшие дни (к сожалению чертеж остался на работе).

Re: Проблема с конвертацией AcDb2dPolyline

> Debalance
Договорились. Только если он там не один (т.е. не одна 2D-полилиния), то пометь его как-нибудь на чертеже, чтобы легче было искать.

Re: Проблема с конвертацией AcDb2dPolyline

Чертеж получил. Как я и предпологал, вершины полилинии имели расширенные данные. Поэтому AutoCAD и отказывался конвертировать такую полилинию.

Re: Проблема с конвертацией AcDb2dPolyline

> Александр Ривилис
Отказываюсь от метода AcDbPolyline::convertFrom(...) Ваш вариант функции работает превосходно: с небольшими изменениями он нашел достойное место в недрах моего проекта :))) Спасибо ещё раз.
P.S.
А можно ли воспользоваться методом AcDbObject::setXData(NULL) для очистки расширенных данных?

Re: Проблема с конвертацией AcDb2dPolyline

> Debalance
А можно ли воспользоваться методом AcDbObject::setXData(NULL) для очистки расширенных данных?
Увы нет. Все несколько сложнее:

static void RemoveXdata(void)
{
  ads_name en;
  ads_point pt;
  Acad::ErrorStatus es;
  if (acedEntSel("\nВыберите примитив для удаления расширенных данных: ", en, pt) != RTNORM)
    return;
  AcDbObjectId objId; acdbGetObjectId(objId, en);
  AcDbObjectPointer<AcDbEntity> pEnt(objId,AcDb::kForWrite);
  if ((es = pEnt.openStatus()) != Acad::eOk) {
    acutPrintf("\nОшибка открытия примитива: %s", acadErrorStatusText(es));
    return;
  }
  // Удаляем все расширенные данные
  resbuf *xdata = NULL;
  while ((xdata = pEnt->xData(NULL)) != NULL) {
    if (xdata) {
      resbuf *xdata_next = xdata->rbnext;
      xdata->rbnext = NULL;
      pEnt->setXData(xdata);
      xdata->rbnext = xdata_next;
      acutRelRb(xdata);
    }
  }
}

Re: Проблема с конвертацией AcDb2dPolyline

> Александр Ривилис
А зачем нужен if (xdata) если while и так, казалось бы, проверяет это условие?

Re: Проблема с конвертацией AcDb2dPolyline

> Debalance
Согласен - if лишний. Я просто переделывал из другого кода и забыл убрать.