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

13/09/2014

Ассоциативный Массив и его API

В AutoCAD 2012 появился так называемый ассоциативный массив. Одновременно с этим появилось и API для его создания, редактирования и получения информации о существующем ассоциативном массиве. Например, вот так можно получить характеристики массива:

Код - C++: [Выделить]
  1. // Предварительное описание вспомогательных функций
  2. std::wstring objIdToEnameStr(AcDbObjectId& id);
  3. std::wstring directionToStr(AcDbAssocArrayPolarParameters::Direction direction);
  4. std::wstring methodToStr(AcDbAssocArrayPathParameters::Method method);
  5.  
  6. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. // Использование: Печать характеристик массива в командную строку
  8. //
  9. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. Acad::ErrorStatus AssocArrayDemo::infoArray(AcDbObjectId& arrayId)
  11. {
  12.   Acad::ErrorStatus es;
  13.  
  14.   AcDbObjectPointer <AcDbEntity> pEntity(arrayId, AcDb::kForRead);
  15.  
  16.   if((es = pEntity.openStatus()) != Acad::eOk)
  17.     return es;
  18.  
  19.   // Мы можем использовать метод "isAssociativeArray" для проверки того действительно ли это ассоциативный массив
  20.   if(!AcDbAssocArrayActionBody::isAssociativeArray(pEntity))
  21.     return Acad::eInvalidInput;
  22.  
  23.  
  24.   acutPrintf(L"\n    ---- Информация об ассоциативном массиве ---- ");
  25.  
  26.   // Получаем AcDbAssocArrayActionBody из примитива массива
  27.   AcDbObjectId actionBodyId = AcDbAssocArrayActionBody::getControllingActionBody(pEntity, NULL);
  28.  
  29.   acutPrintf(L"\n - Управляющий AcDbAssocArrayActionBody: %s", objIdToEnameStr(actionBodyId).c_str());
  30.  
  31.   AcDbAssocArrayActionBody* pArrayActionBody = NULL;
  32.  
  33.   if( (es = acdbOpenAcDbObject((AcDbObject*&)pArrayActionBody, actionBodyId, AcDb::kForWrite)) != Acad::eOk)
  34.     return es;
  35.  
  36.  
  37.   acutPrintf(L"\n - Параметры:");
  38.  
  39.   // Получаем параметры массива и определяем тип массива
  40.   const AcDbAssocArrayParameters* pParameters = pArrayActionBody->parameters();
  41.  
  42.   AcDbAssocArrayCommonParameters* pComonParameters = AcDbAssocArrayCommonParameters::cast(pParameters);
  43.  
  44.   AcString expression;
  45.  
  46.   int levelCount = pComonParameters->levelCount(expression);
  47.   acutPrintf(L"\n  . Уровни = %d (Выражение: \"%s\")", levelCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
  48.  
  49.   double levelSpacing = pComonParameters->levelSpacing(expression);
  50.   acutPrintf(L"\n  . Интервал между уровнями = %f (Выражение: \"%s\")", levelSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
  51.  
  52.   int rowCount = pComonParameters->rowCount(expression);
  53.   acutPrintf(L"\n  . Строки = %d (Выражение: \"%s\")", rowCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
  54.  
  55.   double rowElevation = pComonParameters->rowElevation(expression);
  56.   acutPrintf(L"\n  . Приращение отметки строки = %f (Выражение: \"%s\")", rowElevation, (expression.length() != 0 ? expression.kwszPtr() : L""));
  57.  
  58.   double rowSpacing = pComonParameters->rowSpacing(expression);
  59.   acutPrintf(L"\n  . Интервал между строками = %f (Выражение: \"%s\")", rowSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
  60.  
  61.   // Параметры прямоугольного массива
  62.   if(pComonParameters->isKindOf(AcDbAssocArrayRectangularParameters::desc()))
  63.   {
  64.     acutPrintf(L"\n - Параметры прямоугольного массива:");
  65.  
  66.     AcDbAssocArrayRectangularParameters* pRectParameters = AcDbAssocArrayRectangularParameters::cast(pComonParameters);
  67.  
  68.     int columnCount = pRectParameters->columnCount(expression);
  69.     acutPrintf(L"\n  . Количество колонок = %d (Выражение: \"%s\")", columnCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
  70.  
  71.     double columnSpacing = pRectParameters->columnSpacing(expression);
  72.     acutPrintf(L"\n  . Расстояние между колонками = %f (Выражение: \"%s\")", columnSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
  73.  
  74.     double axesAngle = pRectParameters->axesAngle(expression);
  75.     acutPrintf(L"\n  . Угол оси = %f (Выражение: \"%s\")", axesAngle, (expression.length() != 0 ? expression.kwszPtr() : L""));
  76.  
  77.     AcGeVector3d axisDirection = pRectParameters->axisDirection();
  78.     acutPrintf(L"\n  . Направление оси = [%f, %f, %f]", axisDirection.x, axisDirection.y, axisDirection.z);
  79.   }
  80.  
  81.   // Параметры кругового массива
  82.   if(pComonParameters->isKindOf(AcDbAssocArrayPolarParameters::desc()))
  83.   {
  84.     acutPrintf(L"\n - Параметры кругового массива:");
  85.  
  86.     AcDbAssocArrayPolarParameters* pPolarParameters = AcDbAssocArrayPolarParameters::cast(pComonParameters);
  87.  
  88.     int itemCount = pPolarParameters->itemCount(expression);
  89.     acutPrintf(L"\n  . Количество элементов = %d (Выражение: \"%s\")", itemCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
  90.  
  91.     double angleBetweenItems = pPolarParameters->angleBetweenItems(expression);
  92.     acutPrintf(L"\n  . Угол между элементами = %f (Выражение: \"%s\")", angleBetweenItems, (expression.length() != 0 ? expression.kwszPtr() : L""));
  93.  
  94.     double fillAngle = pPolarParameters->fillAngle(expression);
  95.     acutPrintf(L"\n  . Угол заполнения = %f (Выражение: \"%s\")", fillAngle, (expression.length() != 0 ? expression.kwszPtr() : L""));
  96.     AcString evaluatorId;
  97.     double startAngle = pPolarParameters->startAngle(expression, evaluatorId);
  98.     acutPrintf(L"\n  . Начальный угол = %f (Выражение: \"%s\")", startAngle, (expression.length() != 0 ? expression.kwszPtr() : L""));
  99.  
  100.     AcDbAssocArrayPolarParameters::Direction direction = pPolarParameters->direction();
  101.     acutPrintf(L"\n  . Направление = %s", directionToStr(direction).c_str());
  102.  
  103.     bool rotateItems = pPolarParameters->rotateItems();
  104.     acutPrintf(L"\n  . Поворачивать элементы = %s", (rotateItems ? L"Да" : L"Нет"));
  105.  
  106.     double radius = pPolarParameters->radius(expression);
  107.     acutPrintf(L"\n  . Радиус = %f (Выражение: \"%s\")", radius, (expression.length() != 0 ? expression.kwszPtr() : L""));
  108.   }
  109.  
  110.   // Параметры по траектории
  111.   if(pComonParameters->isKindOf(AcDbAssocArrayPathParameters::desc()))
  112.   {
  113.     acutPrintf(L"\n - Параметры по траектории:");
  114.  
  115.     AcDbAssocArrayPathParameters* pPathParameters = AcDbAssocArrayPathParameters::cast(pComonParameters);
  116.  
  117.     int itemCount = pPathParameters->itemCount(expression);
  118.     acutPrintf(L"\n  . Количество элементов = %d (Выражение: \"%s\")", itemCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
  119.  
  120.     double itemSpacing = pPathParameters->itemSpacing(expression);
  121.     acutPrintf(L"\n  . Расстояние между элементами = %f (Выражение: \"%s\")", itemSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
  122.  
  123.     AcDbEdgeRef path = pPathParameters->path();
  124.     AcDbEntity* pathEnt = path.createEntity();
  125.     acutPrintf(L"\n  . Примитив траектории = %s ", pathEnt->isA()->name());
  126.     delete pathEnt;
  127.  
  128.     AcDbAssocArrayPathParameters::Method method = pPathParameters->method();
  129.     acutPrintf(L"\n  . Метод = %s", methodToStr(method).c_str());
  130.  
  131.     bool alignItems = pPathParameters->alignItems();
  132.     acutPrintf(L"\n  . Выравнивать элементы = %s", (alignItems ? L"Да" : L"Нет"));
  133.     AcString evaluatorId;
  134.     double startOffset = pPathParameters->startOffset(expression,evaluatorId);
  135.     acutPrintf(L"\n  . Начальное смещение = %f (Выражение: \"%s\")", startOffset, (expression.length() != 0 ? expression.kwszPtr() : L""));
  136.  
  137.     double endOffset = pPathParameters->endOffset(expression,evaluatorId);
  138.     acutPrintf(L"\n  . Конечное смещение = %f (Выражение: \"%s\")", endOffset, (expression.length() != 0 ? expression.kwszPtr() : L""));
  139.   }
  140.  
  141.  
  142.   // Получаем исходную запись таблицы блоков
  143.   AcDbObjectId btrId = pArrayActionBody->getArraySourceBTR();
  144.   acutPrintf(L"\n - Исходная BlockTableRecord: %s", objIdToEnameStr(btrId).c_str());
  145.  
  146.  
  147.   acutPrintf(L"\n - Исходные примитивы:");
  148.  
  149.   // Получаем исходные примитивы
  150.   AcDbObjectIdArray sourceEntityIds = pArrayActionBody->getSourceEntities();
  151.  
  152.   for(int i=0; i<sourceEntityIds.length(); ++i)
  153.   {
  154.     AcDbObjectPointer <AcDbEntity> pSourceEntity(sourceEntityIds[i], AcDb::kForRead);
  155.  
  156.     if( (es = pSourceEntity.openStatus()) != Acad::eOk)
  157.       continue;
  158.  
  159.     const ACHAR* name = pSourceEntity->isA()->name();
  160.  
  161.     acutPrintf(L"\n  . %s", name);
  162.   }
  163.  
  164.  
  165.   acutPrintf(L"\n - Исходная базовая точка:");
  166.  
  167.   // Точка, которая вычисляется в vertexRef может не совпадать с результирующим положением базовой точки,
  168.   // так как она вычисляется в пространстве (системе координат) исходной BTR
  169.   AcDbVertexRef vertexRef;
  170.   AcGePoint3d position;
  171.  
  172.   es = pArrayActionBody->getSourceBasePoint(vertexRef, position);
  173.  
  174.   acutPrintf(L"\n  . VertexRef: [%f, %f, %f]", vertexRef.point().x, vertexRef.point().y, vertexRef.point().z);
  175.   acutPrintf(L"\n  . Position: [%f, %f, %f]", position.x, position.y, position.z);
  176.  
  177.  
  178.   // Проходим по всем элементам массива и определяем не управляется ли какие-то из них другими
  179.   // ActionBody, что значит, что элемент переопределен.
  180.   acutPrintf(L"\n - Переопределенные элементы:");
  181.  
  182.   AcArray<AcDbItemLocator> indices;
  183.  
  184.   bool skipErased = true;
  185.  
  186.   pArrayActionBody->getItems(indices, skipErased);
  187.  
  188.   for(int i=0; i<indices.length(); ++i)
  189.   {
  190.     AcDbItemLocator itemLocator = indices[i];
  191.  
  192.     AcDbFullSubentPath path;
  193.  
  194.     const AcDbAssocArrayItem* arrayItem = pArrayActionBody->getItemAt(itemLocator, path);
  195.  
  196.     // Проверяем, что управляющий ActionBody элемента тот же, что и ActionBody всего массива
  197.     // Если нет, то переопределен.
  198.     if(!pArrayActionBody->controlsItem(*arrayItem))
  199.     {
  200.       int itemIndex = itemLocator[AcDbItemLocator::kItemIndex];
  201.  
  202.       acutPrintf(L"\n  . Индекс элемента: %d", itemIndex);
  203.  
  204.       // Получаем управляющий ActionBody
  205.       AcDbObjectId modifyActionBodyId = AcDbAssocArrayActionBody::getControllingActionBody(pEntity, &itemLocator);
  206.  
  207.       acutPrintf(L"\n  . AcDbAssocArrayModifyActionBody: %s", objIdToEnameStr(modifyActionBodyId).c_str());
  208.  
  209.       AcDbAssocArrayModifyActionBody* pArrayModifyActionBody = NULL;
  210.  
  211.       if( (es = acdbOpenAcDbObject((AcDbObject*&)pArrayModifyActionBody, modifyActionBodyId, AcDb::kForRead)) == Acad::eOk)
  212.       {
  213.         AcArray<AcDbItemLocator> overridenItems;
  214.         es = pArrayModifyActionBody->getOverridenItems(overridenItems);
  215.  
  216.         acutPrintf(L"\n  . Число переопределенных элементов: %i", overridenItems.length());
  217.  
  218.         pArrayModifyActionBody->close();
  219.       }
  220.     }
  221.   }
  222.  
  223.   pArrayActionBody->close();
  224.  
  225.   return es;
  226. }

Полный исходный код примеров на C++ (ObjectARX) и C# (AutoCAD .NET API) находится здесь.

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

Опубликовано 13.09.2014