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

ADN Club => ObjectARX => Тема начата: Gurikin от 13-12-2015, 00:38:47

Название: Изменение поворота текста
Отправлено: Gurikin от 13-12-2015, 00:38:47
Добрый день, решил попробовать себя в разработке простейших функций для autocad. Занимаюсь этим около недели, прошу строго не судить. Возникла такая проблема: есть несколько тысяч объектов однострочного текста в чертеже. Все объекты нужно повернуть на 180 градусов (как при использовании поля свойств "поворот"), чтобы каждый текст поворачивался относительно точки вставки. Также хотелось бы добавить какой-нибудь префикс/суффикс к каждому текстовому объекту. Я пытаюсь использовать класс AcDbText и методы setrotation и settextstring, но ничего не получается. Текст не поворачивается, а значение содержимого не меняется. Использую такой код.
Код - C++ [Выбрать]
  1. static void MyGroupMyPickFirst () {
  2.                 ads_name result ;
  3.                 resbuf *prb = acutBuildList(RTDXF0, L"TEXT", RTNONE);
  4.                 int iRet = acedSSGet (ACRX_T("_I"), NULL, NULL, prb, result) ;
  5.                 if ( iRet == RTNORM )
  6.                 {
  7.                         AcTransaction* pTrans = acdbTransactionManager->startTransaction();
  8.                         if (NULL == pTrans)
  9.                         {
  10.                                 return;
  11.                         }
  12.  
  13.                         acutRelRb(prb);
  14.                        
  15.                         AcDbObjectIdArray ids;
  16.                         AcDbText *txtEnt = new AcDbText();
  17.                         AcDbObjectId id = 0;
  18.                         AcDbText* pExistingText = NULL;
  19.                         double rad, myrad, radexsist;
  20.                         int res;
  21.                         ACHAR* mytext;
  22.                         ACHAR pref[10];
  23.                        
  24.                         if (ObjectIdArrayFromSelSet(result, ids) != Acad::eOk)
  25.                                 acutPrintf(L"\n Нет выбранных объектов.");
  26.  
  27.                         int i = ids.length() - 1;
  28.                         //Запрос угла поворота текста
  29.                         res = acedGetAngle(NULL, L"\n Введите угол поворота текста: ", &rad);
  30.                         if (res == RTNONE) rad = 0.0;
  31.                         else if (res != RTNORM) return;
  32.                        
  33.                         //Запрос префикса
  34.                         res = acedGetString(0, L"\n Введите префикс для текста: ", pref);
  35.                         if (res == RTNONE) rad = 0.0;
  36.                         else if (res != RTNORM) return;
  37.  
  38.                         while (i >= 0)
  39.                         {
  40.                                 id = ids[i];
  41.                                 Acad::ErrorStatus es = acdbTransactionManager->getObject((AcDbObject*&)pExistingText, id, AcDb::kForWrite);
  42.                                 if (!eOkVerify(es))
  43.                                 {
  44.                                         acdbTransactionManager->abortTransaction();
  45.                                         acedPrompt(_T("\nЭто не текст"));
  46.                                         return;
  47.                                 }
  48.                                
  49.                                 //mytext = strcat (pref, pExistingText->textString());
  50.                                 es = pExistingText->setTextString(mytext);
  51.                                 if (es != Acad::eOk)
  52.                                 {
  53.                                         acutPrintf(L"\n-- Ошибка при изменении строки текста - %s", Acad::ErrorStatus());
  54.                                         return;
  55.                                 }
  56.  
  57.                                 myrad = pExistingText->rotation()+rad;
  58.                                 radexsist = pExistingText->rotation();
  59.                                 acutPrintf(L"\n-- Новый угол поворота текста - %.6q0", myrad);
  60.  
  61.                                 es = pExistingText->setRotation(myrad);
  62.                                 if (es != Acad::eOk)
  63.                                 {
  64.                                         acutPrintf(L"\n-- Ошибка при повороте текста - %s", Acad::ErrorStatus());
  65.                                         return;
  66.                                 }
  67.  
  68.                                 acutPrintf(L"\n-- Предыдущий угол поворота текста - %.6q0", radexsist);
  69.                                 i--;
  70.                         }
  71.                         acdbTransactionManager->abortTransaction();
  72.                 }
  73.                 else
  74.                 {
  75.                         // There are no selected entities
  76.                         // Put your command code here
  77.                 }
  78.         }
  79.  
  80.         static Acad::ErrorStatus ObjectIdArrayFromSelSet(ads_name sset, AcDbObjectIdArray &ids) {
  81.                 Acad::ErrorStatus es = Acad::eOk;
  82.                 long nset = -1;
  83.                 if (acedSSLength(sset, &nset) != RTNORM) return Acad::eAmbiguousInput;
  84.                 ids.setLogicalLength(nset);
  85.                 ads_name en;
  86.                 AcDbObjectId id;
  87.                 for (long i = 0; i < nset; i++) {
  88.                         if (acedSSName(sset, i, en) == RTNORM) {
  89.                                 if ((es = acdbGetObjectId(id, en)) != Acad::eOk) return es;
  90.                                 ids[i] = id;
  91.                         }
  92.                 }
  93.                 return Acad::eOk;
  94.         }
  95.  
Строку "mytext = pref + pExistingText->textString();" закомментировал, потому что пока не разобрался как объединить эти значения вместе. Если подскажете как это сделать, буду очень благодарен.
Может я не в том направлении решил двигаться? Может мне нужно работать с текстовыми объектами как AcDbEntity и поворачивать как при использовании автокадовской операции "поворот"? Подскажите, пожалуйста.

Название: Re: Изменение поворота текста
Отправлено: Александр Ривилис от 13-12-2015, 01:08:35
Приветствую на форуме!
Я пытаюсь использовать класс AcDbText и методы setrotation и settextstring, но ничего не получается. Текст не поворачивается, а значение содержимого не меняется.
Ну это как бы очевидно. Разберись с тем как ты используешь транзакции. В одном месте ты её создаёшь и потом вызываешь acdbTransactionManager->abortTransaction(); вместо того, чтобы вызвать acdbTransactionManager->endTransaction();
Да и вообще мне не ясно зачем ты связался с транзакциями. Всё-тоже самое можно было сделать значительно проще и без них.
Далее непонятно что ты имеешь в виду под поворотом на 180 градусов. Это поворот относительно текущего поворота каждого из текстов? Тогда логичнее использовать метод transformBy(), создав матрицу поворота относительно базовой точки на угол 180 градусов.
Название: Re: Изменение поворота текста
Отправлено: Александр Ривилис от 13-12-2015, 02:37:15
Сравни этот код со своим:
Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.cpp
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #define _USE_MATH_DEFINES
  6. #include <math.h>
  7.  
  8. #include "resource.h"
  9.  
  10. static Acad::ErrorStatus ObjectIdArrayFromSelSet(ads_name sset, AcDbObjectIdArray &ids) {
  11.   Acad::ErrorStatus es = Acad::eOk;
  12.   long nset = -1;
  13.   if (acedSSLength(sset, &nset) != RTNORM) return Acad::eAmbiguousInput;
  14.   ids.setLogicalLength(nset);
  15.   ads_name en;
  16.   AcDbObjectId id;
  17.   for (long i = 0; i < nset; i++) {
  18.     if (acedSSName(sset, i, en) == RTNORM) {
  19.       if ((es = acdbGetObjectId(id, en)) != Acad::eOk) return es;
  20.       ids[i] = id;
  21.     }
  22.   }
  23.   return Acad::eOk;
  24. }
  25.  
  26. //-----------------------------------------------------------------------------
  27. //----- ObjectARX EntryPoint
  28. class CTextRotateApp : public AcRxArxApp {
  29. public:
  30.   CTextRotateApp () : AcRxArxApp () {}
  31.   virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
  32.     AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
  33.     return (retCode) ;
  34.   }
  35.   virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
  36.     AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
  37.     return (retCode) ;
  38.   }
  39.  
  40.   virtual void RegisterServerComponents () {    }
  41.  
  42.   static void RivilisTransformText () {
  43.     ads_name result ;
  44.     resbuf *filter = acutBuildList(RTDXF0, L"TEXT", RTNONE);
  45.     int rc = acedSSGet (NULL, NULL, NULL, filter, result) ;
  46.     acutRelRb(filter);
  47.     if (rc == RTCAN) return;
  48.     if (rc != RTNORM) {
  49.       acutPrintf(_T("\nПримитивы TEXT не найдены."));
  50.       return;
  51.     }
  52.     AcDbObjectIdArray ids;
  53.     ObjectIdArrayFromSelSet(result, ids);
  54.     double ang = 0;
  55.     acedGetAngle(NULL,_T("\nУкажите угол, на который поворочивается каждый текст: "), &ang);
  56.     if (rc == RTCAN) return;
  57.     ACHAR prefix[256] = _T(""),
  58.       suffix[256] = _T("");
  59.     if (acedGetString(TRUE,_T("\nУкажите префикс: "), prefix) == RTCAN) return;
  60.     if (acedGetString(TRUE,_T("\nУкажите суффикс: "), suffix) == RTCAN) return;
  61.  
  62.     for (int i = 0; i < ids.length(); i++)
  63.     {
  64.       AcDbObjectPointer<AcDbText> pText(ids[i], AcDb::kForWrite);
  65.       if (pText.openStatus() == Acad::eOk) {
  66.         pText->setTextString(AcString(prefix) + pText->textString() + AcString(suffix));
  67.         pText->setRotation(pText->rotation() + ang); // Поворачиваем на заданный угол.
  68.         // pText->setRotation(ang); // Устанавливаем угол поворота
  69.       }
  70.     }
  71.   }
  72.  
  73. } ;
  74.  
  75. //-----------------------------------------------------------------------------
  76. IMPLEMENT_ARX_ENTRYPOINT(CTextRotateApp)
  77.  
  78. ACED_ARXCOMMAND_ENTRY_AUTO(CTextRotateApp, Rivilis, TransformText, TFT, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET, NULL)
Название: Re: Изменение поворота текста
Отправлено: Gurikin от 13-12-2015, 02:52:05
Спасибо огромное за помощь. С транзакцией код поправил - стало работать. Ваш пример просмотрел, без транзакций код более прозрачен и прост в понимании. К сожалению не знал про класс AcDbObjectPointer. Ещё раз благодарю за помощь.
Название: Re: Изменение поворота текста
Отправлено: Александр Ривилис от 13-12-2015, 02:54:11
Ещё раз благодарю за помощь
Пожалуйста. Обращайся :)
P.S.: Прочитай у меня в подписи о кнопке Решение.