13/09/2014
Ассоциативный Массив и его API
В AutoCAD 2012 появился так называемый ассоциативный массив. Одновременно с этим появилось и API для его создания, редактирования и получения информации о существующем ассоциативном массиве. Например, вот так можно получить характеристики массива:
Код - C++: [Выделить]
- // Предварительное описание вспомогательных функций
- std::wstring objIdToEnameStr(AcDbObjectId& id);
- std::wstring directionToStr(AcDbAssocArrayPolarParameters::Direction direction);
- std::wstring methodToStr(AcDbAssocArrayPathParameters::Method method);
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Использование: Печать характеристик массива в командную строку
- //
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- Acad::ErrorStatus AssocArrayDemo::infoArray(AcDbObjectId& arrayId)
- {
- Acad::ErrorStatus es;
- AcDbObjectPointer <AcDbEntity> pEntity(arrayId, AcDb::kForRead);
- if((es = pEntity.openStatus()) != Acad::eOk)
- return es;
- // Мы можем использовать метод "isAssociativeArray" для проверки того действительно ли это ассоциативный массив
- if(!AcDbAssocArrayActionBody::isAssociativeArray(pEntity))
- return Acad::eInvalidInput;
- acutPrintf(L"\n ---- Информация об ассоциативном массиве ---- ");
- // Получаем AcDbAssocArrayActionBody из примитива массива
- AcDbObjectId actionBodyId = AcDbAssocArrayActionBody::getControllingActionBody(pEntity, NULL);
- acutPrintf(L"\n - Управляющий AcDbAssocArrayActionBody: %s", objIdToEnameStr(actionBodyId).c_str());
- AcDbAssocArrayActionBody* pArrayActionBody = NULL;
- if( (es = acdbOpenAcDbObject((AcDbObject*&)pArrayActionBody, actionBodyId, AcDb::kForWrite)) != Acad::eOk)
- return es;
- acutPrintf(L"\n - Параметры:");
- // Получаем параметры массива и определяем тип массива
- const AcDbAssocArrayParameters* pParameters = pArrayActionBody->parameters();
- AcDbAssocArrayCommonParameters* pComonParameters = AcDbAssocArrayCommonParameters::cast(pParameters);
- AcString expression;
- int levelCount = pComonParameters->levelCount(expression);
- acutPrintf(L"\n . Уровни = %d (Выражение: \"%s\")", levelCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double levelSpacing = pComonParameters->levelSpacing(expression);
- acutPrintf(L"\n . Интервал между уровнями = %f (Выражение: \"%s\")", levelSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
- int rowCount = pComonParameters->rowCount(expression);
- acutPrintf(L"\n . Строки = %d (Выражение: \"%s\")", rowCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double rowElevation = pComonParameters->rowElevation(expression);
- acutPrintf(L"\n . Приращение отметки строки = %f (Выражение: \"%s\")", rowElevation, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double rowSpacing = pComonParameters->rowSpacing(expression);
- acutPrintf(L"\n . Интервал между строками = %f (Выражение: \"%s\")", rowSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
- // Параметры прямоугольного массива
- if(pComonParameters->isKindOf(AcDbAssocArrayRectangularParameters::desc()))
- {
- acutPrintf(L"\n - Параметры прямоугольного массива:");
- AcDbAssocArrayRectangularParameters* pRectParameters = AcDbAssocArrayRectangularParameters::cast(pComonParameters);
- int columnCount = pRectParameters->columnCount(expression);
- acutPrintf(L"\n . Количество колонок = %d (Выражение: \"%s\")", columnCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double columnSpacing = pRectParameters->columnSpacing(expression);
- acutPrintf(L"\n . Расстояние между колонками = %f (Выражение: \"%s\")", columnSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double axesAngle = pRectParameters->axesAngle(expression);
- acutPrintf(L"\n . Угол оси = %f (Выражение: \"%s\")", axesAngle, (expression.length() != 0 ? expression.kwszPtr() : L""));
- AcGeVector3d axisDirection = pRectParameters->axisDirection();
- acutPrintf(L"\n . Направление оси = [%f, %f, %f]", axisDirection.x, axisDirection.y, axisDirection.z);
- }
- // Параметры кругового массива
- if(pComonParameters->isKindOf(AcDbAssocArrayPolarParameters::desc()))
- {
- acutPrintf(L"\n - Параметры кругового массива:");
- AcDbAssocArrayPolarParameters* pPolarParameters = AcDbAssocArrayPolarParameters::cast(pComonParameters);
- int itemCount = pPolarParameters->itemCount(expression);
- acutPrintf(L"\n . Количество элементов = %d (Выражение: \"%s\")", itemCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double angleBetweenItems = pPolarParameters->angleBetweenItems(expression);
- acutPrintf(L"\n . Угол между элементами = %f (Выражение: \"%s\")", angleBetweenItems, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double fillAngle = pPolarParameters->fillAngle(expression);
- acutPrintf(L"\n . Угол заполнения = %f (Выражение: \"%s\")", fillAngle, (expression.length() != 0 ? expression.kwszPtr() : L""));
- AcString evaluatorId;
- double startAngle = pPolarParameters->startAngle(expression, evaluatorId);
- acutPrintf(L"\n . Начальный угол = %f (Выражение: \"%s\")", startAngle, (expression.length() != 0 ? expression.kwszPtr() : L""));
- AcDbAssocArrayPolarParameters::Direction direction = pPolarParameters->direction();
- acutPrintf(L"\n . Направление = %s", directionToStr(direction).c_str());
- bool rotateItems = pPolarParameters->rotateItems();
- acutPrintf(L"\n . Поворачивать элементы = %s", (rotateItems ? L"Да" : L"Нет"));
- double radius = pPolarParameters->radius(expression);
- acutPrintf(L"\n . Радиус = %f (Выражение: \"%s\")", radius, (expression.length() != 0 ? expression.kwszPtr() : L""));
- }
- // Параметры по траектории
- if(pComonParameters->isKindOf(AcDbAssocArrayPathParameters::desc()))
- {
- acutPrintf(L"\n - Параметры по траектории:");
- AcDbAssocArrayPathParameters* pPathParameters = AcDbAssocArrayPathParameters::cast(pComonParameters);
- int itemCount = pPathParameters->itemCount(expression);
- acutPrintf(L"\n . Количество элементов = %d (Выражение: \"%s\")", itemCount, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double itemSpacing = pPathParameters->itemSpacing(expression);
- acutPrintf(L"\n . Расстояние между элементами = %f (Выражение: \"%s\")", itemSpacing, (expression.length() != 0 ? expression.kwszPtr() : L""));
- AcDbEdgeRef path = pPathParameters->path();
- AcDbEntity* pathEnt = path.createEntity();
- acutPrintf(L"\n . Примитив траектории = %s ", pathEnt->isA()->name());
- delete pathEnt;
- AcDbAssocArrayPathParameters::Method method = pPathParameters->method();
- acutPrintf(L"\n . Метод = %s", methodToStr(method).c_str());
- bool alignItems = pPathParameters->alignItems();
- acutPrintf(L"\n . Выравнивать элементы = %s", (alignItems ? L"Да" : L"Нет"));
- AcString evaluatorId;
- double startOffset = pPathParameters->startOffset(expression,evaluatorId);
- acutPrintf(L"\n . Начальное смещение = %f (Выражение: \"%s\")", startOffset, (expression.length() != 0 ? expression.kwszPtr() : L""));
- double endOffset = pPathParameters->endOffset(expression,evaluatorId);
- acutPrintf(L"\n . Конечное смещение = %f (Выражение: \"%s\")", endOffset, (expression.length() != 0 ? expression.kwszPtr() : L""));
- }
- // Получаем исходную запись таблицы блоков
- AcDbObjectId btrId = pArrayActionBody->getArraySourceBTR();
- acutPrintf(L"\n - Исходная BlockTableRecord: %s", objIdToEnameStr(btrId).c_str());
- acutPrintf(L"\n - Исходные примитивы:");
- // Получаем исходные примитивы
- AcDbObjectIdArray sourceEntityIds = pArrayActionBody->getSourceEntities();
- for(int i=0; i<sourceEntityIds.length(); ++i)
- {
- AcDbObjectPointer <AcDbEntity> pSourceEntity(sourceEntityIds[i], AcDb::kForRead);
- if( (es = pSourceEntity.openStatus()) != Acad::eOk)
- continue;
- const ACHAR* name = pSourceEntity->isA()->name();
- acutPrintf(L"\n . %s", name);
- }
- acutPrintf(L"\n - Исходная базовая точка:");
- // Точка, которая вычисляется в vertexRef может не совпадать с результирующим положением базовой точки,
- // так как она вычисляется в пространстве (системе координат) исходной BTR
- AcDbVertexRef vertexRef;
- AcGePoint3d position;
- es = pArrayActionBody->getSourceBasePoint(vertexRef, position);
- acutPrintf(L"\n . VertexRef: [%f, %f, %f]", vertexRef.point().x, vertexRef.point().y, vertexRef.point().z);
- acutPrintf(L"\n . Position: [%f, %f, %f]", position.x, position.y, position.z);
- // Проходим по всем элементам массива и определяем не управляется ли какие-то из них другими
- // ActionBody, что значит, что элемент переопределен.
- acutPrintf(L"\n - Переопределенные элементы:");
- AcArray<AcDbItemLocator> indices;
- bool skipErased = true;
- pArrayActionBody->getItems(indices, skipErased);
- for(int i=0; i<indices.length(); ++i)
- {
- AcDbItemLocator itemLocator = indices[i];
- AcDbFullSubentPath path;
- const AcDbAssocArrayItem* arrayItem = pArrayActionBody->getItemAt(itemLocator, path);
- // Проверяем, что управляющий ActionBody элемента тот же, что и ActionBody всего массива
- // Если нет, то переопределен.
- if(!pArrayActionBody->controlsItem(*arrayItem))
- {
- int itemIndex = itemLocator[AcDbItemLocator::kItemIndex];
- acutPrintf(L"\n . Индекс элемента: %d", itemIndex);
- // Получаем управляющий ActionBody
- AcDbObjectId modifyActionBodyId = AcDbAssocArrayActionBody::getControllingActionBody(pEntity, &itemLocator);
- acutPrintf(L"\n . AcDbAssocArrayModifyActionBody: %s", objIdToEnameStr(modifyActionBodyId).c_str());
- AcDbAssocArrayModifyActionBody* pArrayModifyActionBody = NULL;
- if( (es = acdbOpenAcDbObject((AcDbObject*&)pArrayModifyActionBody, modifyActionBodyId, AcDb::kForRead)) == Acad::eOk)
- {
- AcArray<AcDbItemLocator> overridenItems;
- es = pArrayModifyActionBody->getOverridenItems(overridenItems);
- acutPrintf(L"\n . Число переопределенных элементов: %i", overridenItems.length());
- pArrayModifyActionBody->close();
- }
- }
- }
- pArrayActionBody->close();
- return es;
- }
Полный исходный код примеров на C++ (ObjectARX) и C# (AutoCAD .NET API) находится здесь.
Обсуждение: http://adn-cis.org/forum/index.php?topic=957
Опубликовано 13.09.2014