Тема: Перенос примитива на произвольную плоскость

Приветствую всех!
Чего-то запутался в матрицах преобразования. Задача сводится к переносу без искожения геометрии планарного примитива
расположенного в плоскости WCS в произвольную плоскость.
Сначала переношу объект из плоскости EntPlane на плоскость WCS:

AcDbEntity *pEnt;
AcGePlane EntPlane; // Плоскость в которой расположен примитив. Точки начала координат плоскости WCS и EntPlane совпадают.
AcGeMatrix3d TMatrix;
...
TMatrix.setToWorldToPlane(EntPlane);
pEnt->transformBy(TMatrix);
...

Объект корректно переносится в плоскость WCS. Далее пытаюсь вернуть примитив обратно в плоскость EntPlane

...
TMatrix.setToPlaneToWorld(EntPlane);
pEnt->transformBy(TMatrix);
...

но ничего не выходит - примитив по-прежнему лежит в плоскости WCS. Что я делаю не так?

Re: Перенос примитива на произвольную плоскость

> Завын-Дувайло
Посмотри пример здесь в конце темы: https://www.caduser.ru/forum/topic29005.html

Re: Перенос примитива на произвольную плоскость

P.S.: А вообще-то ты что-то перемудрил. Так работает:

static void test1(void)
{
  ads_name en; ads_point p;
  ACHAR res[512];
  if (acedEntSel("\nSelect entity: ",en,p) == RTNORM) {
    AcDbObjectId eid; acdbGetObjectId(eid,en);
    AcGePlane plan;
    {
      AcDbObjectPointer<AcDbPolyline> pEnt(eid, AcDb::kForRead);
      if (pEnt.openStatus() == Acad::eOk) {
        plan.set(AcGePoint3d::kOrigin,pEnt->normal());
      }
    }
    {
      AcDbObjectPointer<AcDbPolyline> pEnt(eid, AcDb::kForWrite);
      if (pEnt.openStatus() == Acad::eOk) {
        AcGeMatrix3d mat; mat.setToPlaneToWorld(plan);
        pEnt->transformBy(mat);
      }
    }
    acedGetString(FALSE,"\n*** press Enter key ***",res);
    {
      AcDbObjectPointer<AcDbPolyline> pEnt(eid, AcDb::kForWrite);
      if (pEnt.openStatus() == Acad::eOk) {
        AcGeMatrix3d mat; mat.setToWorldToPlane(plan);
        pEnt->transformBy(mat);
      }
    }
  }
}

Re: Перенос примитива на произвольную плоскость

А вообще-то ты что-то перемудрил...

Да, действительно...))) Я же сказал что запутался. Спасибо, Александр!

Re: Перенос примитива на произвольную плоскость

> Александр Ривилис
Попробовал реализовать Ваш пример, а точнее первую часть Вашего кода до строчки

acedGetString(FALSE,"\n*** press Enter key ***",res);

Правда эксперимент проводил на объекте ДУГА т.е. имеем следующее:

  ads_name en; ads_point p;
  char res[512];
  if (acedEntSel("\nSelect entity: ",en,p) == RTNORM) {
    AcDbObjectId eid; acdbGetObjectId(eid,en);
    AcGePlane plan;
    {
      AcDbObjectPointer<AcDbArc> pEnt(eid, AcDb::kForRead);
      if (pEnt.openStatus() == Acad::eOk) {
        plan.set(AcGePoint3d::kOrigin,pEnt->normal());
      }
    }
    {
      AcDbObjectPointer<AcDbArc> pEnt(eid, AcDb::kForWrite);
      if (pEnt.openStatus() == Acad::eOk) {
        AcGeMatrix3d mat; mat.setToPlaneToWorld(plan);
        pEnt->transformBy(mat);
      }
    }
  }

Далее открыв Акад, я развернул плоскость вокруг оси X на 45 градусов. Рисую дугу. Запускаю программу. Выбираю дугу. Визуально наблюдаю перемещение объекта. Анализируя полученный результат внезапно замечаю, что преобразованная дуга имеет вектор нормали (0,-1,0), что само по себе странно, ибо предполагалось, что вектор будет иметь вид (0,0,1) ну или (0,0,-1). Таким образом полученный объект расположен совсем не в плоскости WCS!
Интересно, что проделывая тот же самый эксперимент в плоскости развернутой вокруг той же оси X на 90 градусов имеем уже корректный вектор нормали (0,0,-1).
Остается лишь гадать как поведет себя метод setToPlaneToWorld при работе с другими менее тривиальными примерами...