Тема: Еще раз о переключении UCS

Я новичок в ObjectARX-программировании. В этой конференции я встретил обсуждение интересующего меня вопроса - "Переключение UCS" (30.05.02-04.06.02) от Sasquatch. Обсуждение было бурным и интересным, но осталось незаконченным. Поэтому я хочу повторить вопрос.

Мне необходимо создать UCS, сделать ее текущей, выполнить некоторые операции и восстановить текущей WCS. Ниже приведен мой программный код:

// создание пользовательской системы координат (ПСК - UCS)
Acad::ErrorStatus createUCS (const char *ucsName, AcDbObjectId &ucsId, AcGePoint3d Orign, AcGeVector3d ZAxis, AcGeVector3d XAxis) {
         Acad::ErrorStatus es;
         AcDbUCSTable *pUCSTable;
         AcDbUCSTableRecord *pUCSTRec;

         ucsId = AcDbObjectId::kNull;
         if ( (es =
         acdbHostApplicationServices()->workingDatabase()->getUCSTable(pUCSTable, AcDb::kForRead)) == Acad::eOk ) {
                 // получена таблица pUCSTable с правом доступа - "для чтения"
                 if ( (es = pUCSTable->getAt(ucsName, ucsId, Adesk::kFalse)) != Acad::eOk ) {
                         // UCS - не существует, необходимо ее создать
                         pUCSTRec = new AcDbUCSTableRecord;
                         pUCSTRec->setName(ucsName);
                         pUCSTRec->setOrigin(Orign);
                         pUCSTRec->setXAxis(XAxis);
                         pUCSTRec->setYAxis(-XAxis.crossProduct(ZAxis));
                         // добавить запись в таблицу
                         if ( (es = pUCSTable->upgradeOpen()) == Acad::eOk ) {
                                 es = pUCSTable->add(ucsId, pUCSTRec);
                         } else  delete pUCSTRec ;
                 } else {
                         // UCS - существует, требуется открыть ее и откорректировать
                         acdbOpenObject(pUCSTRec, ucsId, AcDb::kForWrite, Adesk::kFalse);
                         pUCSTRec->setName(ucsName);
                         pUCSTRec->setOrigin(Orign);
                         pUCSTRec->setXAxis(XAxis);
                         pUCSTRec->setYAxis(-XAxis.crossProduct(ZAxis));
                         pUCSTRec->close();
                 }
                 pUCSTable->close();
         }

// установка UCS - текущей
// далее идет неработающий код программы, есть три варианта

// вариант 1
         AcDbViewportTable* pViewportTable;
         if ((es = acdbHostApplicationServices()->workingDatabase()->getViewportTable(pViewportTable, AcDb::kForRead)) == Acad::eOk) {
                 AcDbViewportTableRecord *pViewportTRec;
                 if (pViewportTable->getAt("*ACTIVE", pViewportTRec, AcDb::kForWrite) == Acad::eOk) {
                         pViewportTRec->setUcs(ucsId);
                         pRecord->close();
                 }
                 pViewportTable->close();
         }

// вариант 2
         AcDbObjectId vportId = acedGetCurViewportObjectId();
         AcDbViewportTableRecord *pViewportTRec;
         acdbOpenObject(pViewportTRec, vportId, AcDb::kForWrite, Adesk::kFalse);
         pViewportTRec->setUcs(ucsId);
         pViewportTRec->close();

// вариант 3
         AcDbObjectId vportId;
         AcDbViewportTable *pViewportTable;
         AcDbViewportTableRecord *pViewportTRec;
         if ( (es = acdbHostApplicationServices()->workingDatabase()->getViewportTable(pViewportTable, AcDb::kForRead)) == Acad::eOk ) {
                 if ( pViewportTable->getAt("*ACTIVE", vportId, AcDb::kForWrite) == Acad::eOk ) {
                         acdbOpenObject(pViewportTRec, vportId, AcDb::kForWrite, Adesk::kFalse);
                         pViewportTRec->setUcs(ucsId);
                         pViewportTRec->close();
                 }
                 pViewportTable->close();
         }

         return(es);
}

Все три фрагмента кода успешно компилируются, но при выполнении либо ничего не происходит, либо возникает искючительная ситуация. На некоторых промежуточных этапах es содержит код 80 - eWasErased.

Итак первый вопрос. Как:
1) сделать UCS текущей;
2) сделать текущей WCS.

Второй вопрос. Как создать плоскость, если мне известны:
1) уравнение плоскости, вектор нормали;
2) три и более точек, принадлежащих плоскости.
Меня интересует не математическая сторона вопроса, а те примитивы которые нужно использовать. Т.е. плоскость - это плоская поверхность (surface)? Как ее построить? Может быть для этого необходимо построить
контур, а затем натянуть на него поверхность? А нельзя ли построить бесконечную плоскость?

Не могли бы вы ответить мне несколько более подробнее, чем это было при первом обсуждении. Особенно жду ответа от VVV.

Заранее благодарен.

Re: Еще раз о переключении UCS

Попробуйте для восстановления системы координат такой алгоритм:
?
AcDbUCSTable *pTable;
  AcDbUCSTableRecord *pUCS;
?
// получить  UCS
?
// получить параметры UCS
  AcGePoint3d origin = pUCS->origin();
  AcGeVector3d xDirection = pUCS->xAxis(),
   yDirection = pUCS->yAxis(),
   zDirection = xDirection.crossProduct(yDirection);
  pUCS->close();
 
  // Сформировать матрицу преобразования для  UCS
  AcGeMatrix3d matrix;
  matrix.setCoordSystem(origin, xDirection, yDirection, zDirection);
 
  // активизировать  UCS
  acedSetCurrentUCS(matrix);
?

В Help-e дано описание для функции acdbSetCurrentUCS, но  ни в одном  *.h она не описана. Скорее всего,  там опечатка.
Для перехода от UCS к WCS координатам можно воспользоваться функцией
AcdbUcsMatrix.

Что касается второго  вопроса, то я ничем не могу Вам помочь, т.к.  никогда не  работал с 3D. Безусловно, в ARX есть соответствующие классы, например, AcGePlanarEnt и все, что от него наследуется.

Re: Еще раз о переключении UCS

Спасибо VVV за ответ

Итак,
1) я программно создал UCS c именем "Plane UCS", получил matrix для перехода UCS;
2) далее командой acedSetCurrentUCS(matrix) сделал UCS текущей.

При этом,
1) в AutoCAD в списке UCS, появилась моя UCS c именем "Plane UCS";
2) текущей стала UCS с именем "Безымянный", которая совпадает с "Plane UCS";
3) если нарисовать плоский примитив (напр. прямоугольник), он строится в плоскости OXY UCS "Безымянный"-"Plane UCS".

Но, если я строю плоский примитив программно, он строится в WCS.
Может необходимо координаты примитива преобразовывать к UCS дополнительно?
И как сделать текущей именно "Plane UCS", а не "Безымянный"?

Жду ответа, заранее благодарен.

Re: Еще раз о переключении UCS

Работая с объектами в разных системах координат, Вам наверняка придется часто заниматься преобразованиями.
При этом следует иметь в виду, что, например, такая функция,  как acedGetPoint возвращает координаты в UCS, тогда как функции построения объектов предполагают, как правило, задание координат в WCS. Для преобразования UCS в WCS используется обычно acdbUcs2Wcs() функция.