Сообщество программистов Autodesk в СНГ

ADN Club => ObjectARX => Тема начата: Михаил Голубев от 12-09-2021, 18:08:11

Название: subViewportDraw() и плот
Отправлено: Михаил Голубев от 12-09-2021, 18:08:11
Добрый день
Сделал объект, производный от AcDbText, с целью добиться автоматическтого разворота текста на 180 градусов, если он читается вверх ногами на листе.

Добился результата используяю subViewportDraw(). В нем я сравниваю угол viewport и угол текста. Если текст попадает в опроделенный диапазон, то AcDbText::subViewportDraw(mode) не вызывается, но вырисовывается новый текст с помощью mode->geometry().text(), который переворачивается на 180 градусов при отрисовке. Таки образом текст, к примеру, названий улиц, всегда "лицом" к читателю.

В программе работает как надо, пока... но при распечатке все разворачивается на 90 градусов, а код это не улавливает. Подскажите, как уловить угов viewport при распечатке, или еще как решить эту проблему.

В программе так:

(https://i.postimg.cc/dh6yLHQR/Good.png) (https://postimg.cc/dh6yLHQR)

При печате так:

(https://i.postimg.cc/p9ZtFSpZ/Bad.png) (https://postimg.cc/p9ZtFSpZ)

На всякий случай код subViewportDraw():

Код - C++ [Выбрать]
  1. void DRIText::subViewportDraw(AcGiViewportDraw * mode)
  2. {
  3.         assertReadEnabled();
  4.         AcGePoint3d orgn;
  5.         AcGeVector3d xa, ya, za;
  6.         AcGeMatrix3d transform;
  7.         mode->viewport().getEyeToWorldTransform(transform);
  8.         transform.getCoordSystem(orgn, xa, ya, za);
  9.        
  10.         double lLimit, uLimit;
  11.         double rot = rotation();
  12.         double vpRot = atan2(xa.y, xa.x);
  13.         //Counterclockwise rotation
  14.         if (vpRot < 0) vpRot *= -1;
  15.         else vpRot = 2.0 * PI - vpRot;
  16.  
  17.         lLimit = (PI * 0.5) - vpRot;
  18.         uLimit = (1.5 * PI) - vpRot;
  19.         if (lLimit < 0) lLimit += 2.0 * PI;
  20.         if (uLimit <= 0) uLimit += 2.0 * PI;
  21.  
  22.         bool toRotate = false;
  23.  
  24.         //General case, quadrant I and IV
  25.         if ((vpRot < (PI * 0.5)) || (vpRot >= (1.5 * PI)))
  26.         {
  27.                 if (rot > lLimit && rot < uLimit) toRotate = true;
  28.         }
  29.         //General case, quadrant II and III
  30.         else if ((vpRot >= (PI * 0.5)) && (vpRot < (1.5 * PI)))
  31.         {
  32.                 if (rot < uLimit || rot > lLimit) toRotate = true;
  33.         }
  34.  
  35.         if (toRotate)
  36.         {
  37.                 AcGeVector3d dir{ AcGeVector3d(cos(rot),sin(rot),0.0) }; dir.normalize();
  38.                 AcGeVector3d dirPerp{ AcGeVector3d(cos(rot + PI * 0.5),sin(rot + PI * 0.5),0.0) }; dirPerp.normalize();
  39.                 AcString text = textString();
  40.                 AcGiTextStyle style;
  41.                 fromAcDbTextStyle(style, this->textStyle());
  42.                 style.loadStyleRec();
  43.                 AcGePoint2d extents = style.extents(textString(), Adesk::kFalse, text.length(), Adesk::kTrue);
  44.                 mode->geometry().text(position() + dir * extents.x + dirPerp * extents.y,
  45.                         AcGeVector3d::kZAxis, dir * -1, height(), 1.0, 0.0, text);
  46.         }
  47.         else AcDbText::subViewportDraw(mode);
  48. }
  49.  
Название: Re: subViewportDraw() и плот
Отправлено: Александр Ривилис от 12-09-2021, 18:25:22
Используй AcGiContext::isPlotGeneration для проверки это для печати или для просмотра.
Название: Re: subViewportDraw() и плот
Отправлено: Михаил Голубев от 12-09-2021, 18:31:18
Спасибо. Я сейчас не за компьютером, этот контекст как достать из subViewportDraw()?
Название: Re: subViewportDraw() и плот
Отправлено: Александр Ривилис от 12-09-2021, 18:34:54
mode
В твоём коде:
Код - C++ [Выбрать]
  1. if (mode->context().isPlotGeneration())
  2. {
  3.   // Идёт печать
  4. }
  5. else
  6. {
  7.   // Вывод на экран
  8. }
Название: Re: subViewportDraw() и плот
Отправлено: Александр Ривилис от 12-09-2021, 18:37:05
Кстати, возможны нюансы при задании угла поворота при печати. С ходу не скажу как это повлияет и как это анализировать в классе Custom Entity, так как эту информацию можно получить из AcDbPlotSettings::plotRotation.
И еще. Убедись, что при печати срабатывает метод  subViewportDraw(). Вполне возможно, что раз ты унаследовался от AcDbText, срабатывает метод subWorldDraw()   
Название: Re: subViewportDraw() и плот
Отправлено: Михаил Голубев от 12-09-2021, 18:45:33
Не, не, должен срабатывать, так как несколько viewPort на листе, а так же текст вообще не крутился бы, а он крутится, но только под неправильным улом -- это можно пофиксить!
Название: Re: subViewportDraw() и плот
Отправлено: Александр Ривилис от 12-09-2021, 20:00:43
Михаил Голубев,
Посмотри эту статью: https://adn-cis.org/risovanie-gorizontalnogo-teksta-v-sobstvennom-primitive.html
Там есть много полезного.
Название: Re: subViewportDraw() и плот
Отправлено: Михаил Голубев от 13-09-2021, 01:21:12
Да, спасибо, прям в точку. Только я использую getEyeToWorldTransform, а не getCameraUpVector, так как я не знал про этот вектор и нашел только трансформ, в котором оказалась нужная информация. Надеюсь, что это не вызовет никаких проблем. И, кстати, решил проблему с использованием isPlotGeneration() метода, спасибо.