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

26/09/2016

Создаем ассоциативный массив с помощью ObjectARX

В этой статье мы рассмотрим возможность создания объекта МАССИВ (Array) используя три класса параметров для создания ассоциативного массива унаследованных от класса AcDbAssocArrayCommonParameters:
  1. AcDbAssocArrayPathParameters
  2. AcDbAssocArrayPolarParameters
  3. AcDbAssocArrayRectangularParameters

который может использоваться для изменения параметров ассоциативного Прямоугольного Массива, Массива по Траектории и Кругового Массива независимо от типа массива.

AcDbAssocArrayActionBodyэто ассоциативное действие, которое выполняется для управления или позиционирования массива примитивов, основанное на параметрах массива.

Создание массива по траектории:

Этому массиву требуется направляющая кривая и исходный примитив в качестве профиля для прокладывания вдоль кривой. Все массивы представляют собой вставки (анонимных) блоков, которые ссылаются на массив записей таблицы блоков (массив BTR). Массив BTR содержит список примитивов, представляющих элементы массива. По-умолчанию, этот класс представляет массив как экземпляр AcDbBlocReference ссылающийся на исходную запись таблицы блоков (исходный BTR) с учетом смещения элементов массива. 

Код - C++: [Выделить]
  1. void createPathArray()
  2. {
  3.   try
  4.   {
  5.  
  6.     Acad::ErrorStatus es;
  7.     // Переменные аргументов
  8.     int nVarCount = 0;
  9.     int index = 0;
  10.  
  11.     Adesk::Boolean isAssociative;
  12.     AcGePoint3d basePoint;
  13.     double itemsapcing = 1.573;
  14.     double rowSpacing = 1.5;
  15.     double levelSpacing = 1;
  16.     int itemCount = 1;
  17.     int rowCount = 1;
  18.     int levelCount = 1;
  19.     double rowElevation = 1;
  20.     int method=0;
  21.  
  22.     AcDbObjectId      profileEntityId;
  23.     AcDbObjectId      CurveEntityId;
  24.     AcDbEntity *      profileEntity = NULL;
  25.     AcDbEntity *      curveEntity = NULL;
  26.     AcDbObjectIdArray profileEntityIdArray;
  27.     AcDbObjectId      arrayId;
  28.     AcDbObjectId      actionBodyId;
  29.  
  30.     index = 1;
  31.     isAssociative = Adesk::kTrue;
  32.     basePoint = basePoint.kOrigin;
  33.  
  34.     Adesk::Boolean isAssoc = isAssociative;
  35.     AcDbVertexRef *basePointVertex = new AcDbVertexRef(basePoint);
  36.  
  37.     // Создаем примитив профиля
  38.     profileEntity = createEntity(index);
  39.     // Добавляем новый примитив в базу
  40.     Adesk::Boolean rVal = post_to_database(profileEntity, profileEntityId);
  41.     // Создадим траекторию, по которой будет создан массив
  42.     index = 3;
  43.     curveEntity =  createEntity(index); 
  44.  
  45.     AcDbLine* path =  (AcDbLine*)curveEntity;
  46.     double param1,length;
  47.     path->getEndParam(param1);
  48.     path->getDistAtParam(param1,length);
  49.  
  50.  
  51.     itemCount = int(length / itemsapcing);
  52.     // добавляем примитив в базу
  53.     rVal = post_to_database(curveEntity, CurveEntityId);         
  54.  
  55.     if(rVal)
  56.     {
  57.       AcDbSmartObjectPointer<AcDbEntity> profileEntity1(profileEntityId,AcDb::kForRead);
  58.       if(!eOkVerify(profileEntity1.openStatus())) return;
  59.  
  60.       AcDbSmartObjectPointer<AcDbEntity> curveEntity1(CurveEntityId,AcDb::kForRead);
  61.       if(!eOkVerify(curveEntity1.openStatus())) return ;
  62.       // Добавим id примитива профиля в массив id профилей
  63.       profileEntityIdArray.append(profileEntityId);
  64.  
  65.  
  66.       // Создадим объект PathArrayParameters
  67.       AcDbAssocArrayPathParameters *pathParam =
  68.         new AcDbAssocArrayPathParameters(itemsapcing,rowSpacing,
  69.         levelSpacing,itemCount, rowCount,
  70.         levelCount, rowElevation);
  71.  
  72.       // Код устанавливает траекторию массива
  73.       AcDbEdgeRef edge(curveEntity1);
  74.       es=pathParam->setPath(edge);
  75.       // Выбираем метод Поделить или Измерить
  76.       if(method==1)
  77.         es= pathParam->setMethod(AcDbAssocArrayPathParameters::kDivide);
  78.       else
  79.         es= pathParam->setMethod(AcDbAssocArrayPathParameters::kMeasure);
  80.  
  81.       // Создаем массив из исходных примитивов
  82.       es = AcDbAssocArrayActionBody::createInstance(profileEntityIdArray,
  83.         *basePointVertex,pathParam,arrayId,actionBodyId);
  84.  
  85.       // Созданное действие будет автоматически выполнено в конце команды
  86.       //
  87.       // Если мы хотим узнать будет ли успешным вычисление, мы можем явно
  88.       // выполнить вычисление и проверить его статус
  89.       //
  90.       bool beval= AcDbAssocManager::evaluateTopLevelNetwork(arrayId.database());
  91.  
  92.       if(pathParam != NULL)
  93.         delete pathParam;
  94.     }
  95.  
  96.   } // try
  97.   catch (...)
  98.   {
  99.      acutPrintf( _T("Перехвачено прерывание: Acad::eUnrecoverableErrors"));
  100.   }
  101.  
  102. }
 

Создание Прямоугольного Массива:

Код - C++: [Выделить]
  1. void createRectArray()
  2. {
  3.   try
  4.   {
  5.     // Переменные аргументов
  6.     int index = 1;
  7.     double columnSpacing = 10;
  8.     double rowSpacing = 10;
  9.     double levelSpacing = 10;
  10.     int columnCount = 10;
  11.     int rowCount =  10;
  12.     int levelCount = 1;
  13.     double rowElevation = 1;
  14.     double axesAngle = 90;
  15.     double rotation = 0;
  16.     AcGePoint3d basePoint;
  17.  
  18.     AcDbObjectId      profileEntityId;
  19.     AcDbEntity *      profileEntity = NULL;
  20.     AcDbObjectIdArray profileEntityIdArray;
  21.     AcDbObjectId      arrayId;
  22.     AcDbObjectId      actionBodyId;
  23.  
  24.     basePoint = basePoint.kOrigin;
  25.     AcDbVertexRef basePointVertex(basePoint);
  26.  
  27.  
  28.     // Создаем примитив профиля на основе индекса профиля
  29.     profileEntity = createEntity(index);
  30.  
  31.  
  32.     // Добавляем новый примитив в базу
  33.     Adesk::Boolean rVal = post_to_database(profileEntity, profileEntityId);
  34.  
  35.     if(rVal)
  36.     {
  37.       // Добавляем id примитива профиля к массиву id профилей
  38.       profileEntityIdArray.append(profileEntityId);
  39.  
  40.       // Создаем объект RectangularParameters
  41.       AcDbAssocArrayRectangularParameters *rectParam =
  42.         new AcDbAssocArrayRectangularParameters(columnSpacing,
  43.         rowSpacing,levelSpacing,columnCount,rowCount,
  44.         levelCount,rowElevation,axesAngle);
  45.  
  46.       // Создаем массив из исходных примитивов
  47.       if(!eOkVerify(AcDbAssocArrayActionBody::createInstance(
  48.         profileEntityIdArray,basePointVertex,rectParam,arrayId,actionBodyId))) return;
  49.  
  50.       // Созданное действие будет автоматически выполнено в конце команды
  51.       //
  52.       // Если мы хотим узнать будет ли успешным вычисление, мы можем явно
  53.       // выполнить вычисление и проверить его статус
  54.       //
  55.       bool beval = AcDbAssocManager::evaluateTopLevelNetwork(arrayId.database());
  56.     }
  57.  
  58.  
  59.  
  60.   } // try
  61.   catch (...)
  62.   {
  63.     acutPrintf( _T("Перехвачено прерывание: Acad::eUnrecoverableErrors"));
  64.   } // catch
  65. }

Создание Кругового Массива :

Код - C++: [Выделить]
  1. void createPolarArray()
  2. {
  3.   Acad::ErrorStatus es;
  4.   try
  5.   {
  6.     // Переменные аргументы
  7.     int NoOfSrcEntities = 2;
  8.     int index = 1;
  9.     double columnSpacing = 0;
  10.     double rowSpacing = 10;
  11.     double levelSpacing = 5;
  12.     int itemCount = 6;
  13.     int rowCount = 2;
  14.     int levelCount = 2;
  15.     double rowElevation = 3;
  16.     double Angle = 90;
  17.  
  18.     AcGePoint3d basePoint;
  19.     basePoint = basePoint.kOrigin;
  20.  
  21.  
  22.     AcDbObjectId      profileEntity1Id;
  23.     AcDbObjectId      profileEntity2Id;
  24.  
  25.     AcDbEntity *      profileEntity1 = NULL;
  26.     AcDbEntity *      profileEntity2 = NULL;
  27.  
  28.     AcDbObjectIdArray profileEntityIdArray;
  29.     AcDbObjectId      arrayId;
  30.     AcDbObjectId      actionBodyId;
  31.  
  32.  
  33.     AcDbVertexRef *basePointVertex = new AcDbVertexRef(basePoint);
  34.  
  35.     // Создаем примитив профиля на основе индекса
  36.     profileEntity1 = createEntity(index);          
  37.  
  38.     // Добавляем примитив в базу
  39.     Adesk::Boolean rval = post_to_database(profileEntity1, profileEntity1Id);
  40.     if(rval)
  41.     {
  42.       // Добавляем id примитива профиля в массив id примитивов профилей
  43.       profileEntityIdArray.append(profileEntity1Id);
  44.  
  45.       // Создаем AssocArrayParameters
  46.       AcDbAssocArrayPolarParameters *polarParam =
  47.         new AcDbAssocArrayPolarParameters (Angle,rowSpacing,levelSpacing,
  48.         itemCount,rowCount,levelCount,rowElevation);
  49.  
  50.       // Создаем массив из исходных примитивов
  51.       es = AcDbAssocArrayActionBody::createInstance(
  52.         profileEntityIdArray,*basePointVertex,polarParam,arrayId,actionBodyId
  53.       );
  54.  
  55.       // Созданное действие будет автоматически выполнено в конце команды
  56.       //
  57.       // Если мы хотим узнать будет ли успешным вычисление, мы можем явно
  58.       // выполнить вычисление и проверить его статус
  59.       //
  60.       bool beval = AcDbAssocManager::evaluateTopLevelNetwork(arrayId.database());
  61.  
  62.     }
  63.   }
  64.   catch(...)
  65.   {
  66.     acutPrintf( _T("Отловлено прерывание: Acad::eUnrecoverableErrors"));
  67.   }
  68. }
 

Утилиты и команда:

Код - C++: [Выделить]
  1. #include "eoktest.h"
  2. #include "dbobjptr2.h"
  3. #include "AcDbAssocArrayPathParameters.h"
  4. #include "AcDbAssocArrayActionBody.h"
  5. #include "AcDbAssocManager.h"
  6. #include "AcDbAssocArrayRectangularParameters.h"
  7. #include "AcDbAssocArrayPolarParameters.h"
  8.  
  9. /* Вспомогательный метод для создания примитива */
  10. AcDbEntity* createEntity(int index)
  11. {
  12.   AcDbEntity* entity = NULL;
  13.   AcGePoint3d startPt(0,0,0);
  14.   AcGePoint3d endPt(20,20,0);
  15.   switch(index)
  16.   {
  17.     /* Профиль 1 */
  18.   case 1:
  19.     {
  20.       AcDbCircle* c = new AcDbCircle(AcGePoint3d(0.0,0.0,0.0),AcGeVector3d(0.0,0.0,1.0),0.5);
  21.       entity = (AcDbEntity*)c;
  22.       break;
  23.     }
  24.     /* Профиль 2 */
  25.   case 2:
  26.     {
  27.       AcDbPolyline *pRect = new AcDbPolyline();
  28.       AcGePoint2d vertex1(startPt.x,startPt.y);
  29.       AcGePoint2d vertex2(endPt.x,startPt.y);
  30.       AcGePoint2d vertex3(endPt.x,endPt.y);
  31.       AcGePoint2d vertex4(startPt.x,endPt.y);
  32.       pRect->addVertexAt(0,vertex1);
  33.       pRect->addVertexAt(1,vertex2);
  34.       pRect->addVertexAt(2,vertex3);
  35.       pRect->addVertexAt(3,vertex4);
  36.       pRect->setClosed(Adesk::kTrue);
  37.       entity = (AcDbEntity*)pRect;
  38.       break;
  39.     }
  40.     /* Путь для МАССИВА по траектории */
  41.   case 3:
  42.     {
  43.       AcDbLine *line = new AcDbLine(startPt,endPt);
  44.       entity = (AcDbEntity*)line;
  45.       break;
  46.     }
  47.   default:
  48.     break;
  49.   }
  50.   return entity;
  51. }
  52.  
  53. /* Вспомогательный метод для добавления примитива в базу */
  54. bool post_to_database(AcDbEntity* ent, AcDbObjectId& objId)
  55. {
  56.   AcDbBlockTablePointer pBlockTable(acdbCurDwg(), AcDb::kForRead);
  57.   if (!eOkVerify(pBlockTable.openStatus())) return false;
  58.   AcDbObjectId idModelSpace;
  59.   if (!eOkVerify(pBlockTable->getAt(ACDB_MODEL_SPACE, idModelSpace)))
  60.     return false;
  61.   AcDbBlockTableRecordPointer pSpaceRecord(idModelSpace, AcDb::kForWrite);
  62.   if (!eOkVerify(pSpaceRecord.openStatus())) return false;
  63.   if (!eOkVerify(pSpaceRecord->appendAcDbEntity(objId, ent))) {
  64.     return false;
  65.   }
  66.   return eOkVerify(ent->close());
  67. }
  68.  void createArray()
  69. {
  70.  
  71.   CString prompt = _T("Укажите тип массива: "); 
  72.   acedInitGet(0, _T("Траектория Прямоугольный Круговой"));
  73.   ACHAR kword[255]; ACHAR pr[255];
  74.   wsprintf(pr, ACRX_T("%s[Траектория/Прямоугольный/Круговой]: "), prompt);
  75.   if(acedGetKword(pr, kword) == RTNORM)
  76.   {
  77.     if(!_tcscmp(kword,L"Траектория"))
  78.     {
  79.       acutPrintf(_T("Траектория\n"));
  80.       createPathArray();
  81.     }
  82.     else if(!_tcscmp(kword,L"Прямоугольный"))
  83.     {
  84.       acutPrintf(_T("Прямоугольный\n"));
  85.       createRectArray();
  86.     }
  87.     else if(!_tcscmp(kword,L"Круговой"))
  88.     {
  89.       acutPrintf(_T("Круговой\n"));
  90.       createPolarArray();
  91.     }
  92.     else
  93.     {
  94.       acutPrintf(_T("Ошибочный ввод"));
  95.     }
  96.   }     
  97. }
  98.  
  99. //******************************************************************************
  100. extern "C" AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void *pkt)
  101. //******************************************************************************
  102. {
  103.   switch(msg)
  104.   {
  105.   case AcRx::kInitAppMsg:
  106.     acrxDynamicLinker->unlockApplication(pkt);
  107.     acrxDynamicLinker->registerAppMDIAware(pkt);   
  108.     acedRegCmds->addCommand(_T("TestCmd"),_T("ARY"),_T("ARY"), ACRX_CMD_TRANSPARENT, createArray);
  109.     break;
  110.   case AcRx::kUnloadAppMsg:
  111.     acedRegCmds->removeGroup(_T("TestCmd"));
  112.  
  113.     break;
  114.  
  115.   default:
  116.     break;
  117.   }
  118.   return AcRx::kRetOK;
  119. }
  120. #if !defined(_WIN64) && !defined (_AC64)
  121. #pragma comment(linker, "/export:_acrxGetApiVersion,PRIVATE")
  122. #pragma comment(linker, "/export:_acrxEntryPoint,PRIVATE")
  123. #else
  124. #pragma comment(linker, "/export:acrxGetApiVersion,PRIVATE")
  125. #pragma comment(linker, "/export:acrxEntryPoint,PRIVATE")
  126. #endif
 

 

Видео создания ассоциативных массивов:

Источник: http://adndevblog.typepad.com/autocad/2016/05/creating-assoc-array-objects-with-objectarx.html

Автор перевода: Александр Ривилис

Обсуждение: http://adn-cis.org/forum/index.php?topic=7355

Опубликовано 26.09.2016
Отредактировано 26.09.2016 в 23:05:24