Получить углы Эйлера у детали в сборке

Автор bbb, 06.07.17, 15:38:09

« назад - далее »

0 Пользователи и 2 гостей просматривают эту тему.

bbb

Есть деталь в сборке, пытаюсь получить углы Эйлера (поворота ее системы координат), их можно в Компасе посмотреть если выполнить команду "Разместить компонент"

Нашел в SDK что они есть в ILocalCSEulerParam. Пробую так:

IPart7 p7=......тут есть нужная деталь

IAuxiliaryGeomContainer pgCon=(IAuxiliaryGeomContainer )p7;
ILocalCoordinateSystem lsk=pgCon.LocalCoordinateSystems.Current as ILocalCoordinateSystem;  //// тут lsk=null
ILocalCSEulerParam lParam=lsk.LocalCsarameters as ILocalCSEulerParam;


Проблема в том что у детали нет локальных систем координат (pgCon.LocalCoordinateSystems.Count возвращает 0) , есть только основная.
Как в этом случае мне получить углы Эйлера, если локальных систем координат нет?

Возможно как то еще можно получить углы Эйлера у детали вставленной в сборку, без лск?

UPD: Пробовал брать деталь на редактирование, тоже самое - (pgCon.LocalCoordinateSystems.Count возвращает 0

bbb

Добавил детали лск, код заработал, но так я получаю значения углов именно лск, а не углов детали в сборке.

Складывается ощущение, что углы детали в сборке через API не достать... Возможно их как то можно вычислить, но получить их значения из сборки, по моему нельзя.

ТрындецЪ

Цитата: bbb от 07.07.17, 08:21:04
Складывается ощущение, что углы детали в сборке через API не достать... Возможно их как то можно вычислить, но получить их значения из сборки, по моему нельзя.
Может быть, метод GetMatrix (Получить суммарную матрицу преобразования координат) поможет?

bbb

Цитата: ТрындецЪ от 07.07.17, 09:28:52
Может быть, метод GetMatrix (Получить суммарную матрицу преобразования координат) поможет?
Получить матрицу можно, но придется рассчитывать эти углы, хотелось бы просто получить значения углов, если это возможно.

bbb

#4
Может не совсем понятно о каких углах идет речь. На картинке выделил красным значения которые я хочу получить программно. Возможно ли это?

UPD: Вот для этих углов, которые на картинке, матрица положения, полученная функцией GetMatrix3D, как из этой матрицы можно получить эти углы?
UPD2: последний элемент не влез (там единичка), но это не важно, т.к. 4 последних элемента этой матрицы это координаты опорной точки

Akew

Может быть, получив матрицу размещения компоненты, ею нужно инициализировать систему координат (вероятно, придется временно создать новую), и уже из нее - получить искомые углы Эйлера? Т.е.,
1) Получаем матрицу (IPlacement3D::GetMatrix());
2) Создаем новую ЛСК (ILocalCoordinateSystems::Add());
3) Инициализируем ее матрицей (ILocalCoordinateSystem::InitByMatrix3D());
4) Для этой ЛСК получаем интерфейс углов Эйлера (ILocalCSEulerParam);
5) Получаем углы Эйлера (ILocalCSEulerParam::(NutationAngle, PrecessionAngle и RotationAngle) ).
Нет КОМПАСа под рукой сейчас - не могу проверить свое предположение

Akew

Мое предположение подтвердилось.
Прилагаю готовый код функции:
//-------------------------------------------------------------------------------
// Получить Эйлеровы углы вставки компоненты IPart7 componentAsIPart7. Углы записать в angleOfNutation, angleOfPrecession, angleOfRotation.
// Вернуть true, если успешно; false - в случае неудачи.
// ---
bool GetEulerAngelsOfComponentInsertion( ksDocument3DPtr &document3D, IPart7Ptr componentAsIPart7, double &angleOfNutation, double &angleOfPrecession, double &angleOfRotation ) {
CString tmpstr;
CString titleDialog = _T("Функция GetEulerAngelsOfComponentInsertion");

if ( !document3D ) {
MessageBox(NULL, _T( "Err 01: не задан document3D. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

// 1. Получить новую ЛСК
IKompasDocument3DPtr kompasDocument3D( IUnknownPtr(ksTransferInterface( document3D, ksAPI7Dual, 0), false) );
if ( !kompasDocument3D ) {
MessageBox(NULL, _T( "Err 02: не получен kompasDocument3D. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

IPart7Ptr topPart7( kompasDocument3D->TopPart );
if (!topPart7) {
MessageBox(NULL, _T( "Err 03: не получен topPart7. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

IAuxiliaryGeomContainerPtr auxiliaryGeomContainer( topPart7 );
if( !auxiliaryGeomContainer ) {
MessageBox(NULL, _T( "Err 04: не получен auxiliaryGeomContainer. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

ILocalCoordinateSystemsPtr localCoordinateSystems( auxiliaryGeomContainer->GetLocalCoordinateSystems() );
if( !localCoordinateSystems ) {
MessageBox(NULL, _T( "Err 05: не получен localCoordinateSystems. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

ILocalCoordinateSystemPtr lscForEulerAngels( localCoordinateSystems->Add() );
if( !lscForEulerAngels ) {
MessageBox(NULL, _T( "Err 06: не удалось создать lscForEulerAngels. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

// 2. Задать тип ЛСК (как система углов Эйлера)
lscForEulerAngels->PutOrientationType( ksEulerCorners );

// 3. Инициализировать ЛСК параметрами вставки рассматриваемой компоненты ( componentAsIPart7 )
// 3.1. Получить массив (из 16 элементов) параметров вставки компоненты
IPlacement3DPtr placement3DOfComponent( componentAsIPart7->GetPlacement() );
if ( !placement3DOfComponent ) {
MessageBox(NULL, _T( "Err 07: не получен placement3DOfComponent. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return false;
}

_variant_t matrix3DofPlacement3DOfComponent( placement3DOfComponent->GetMatrix3D() );
if ( matrix3DofPlacement3DOfComponent.vt != ( VT_ARRAY | VT_R8 ) ) {
MessageBox(NULL, _T( "Err 08: не удалось получить матрицу параметров размещения компоненты. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return false;
}

if( matrix3DofPlacement3DOfComponent.parray->cDims != 1 ) {
MessageBox(NULL, _T( "Err 09: неверная размерность матрицы. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return false;
}

if( matrix3DofPlacement3DOfComponent.parray->rgsabound[0].cElements != 16 ) {
MessageBox(NULL, _T( "Err 10: число элементов матрицы не 16. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return false;
}

// 3.2. Инициализировать этим массивом новую ЛСК
if( !(lscForEulerAngels->InitByMatrix3D( matrix3DofPlacement3DOfComponent ) ) ) {
MessageBox(NULL, _T( "Err 11: не удалось выполнить InitByMatrix3D. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

// 4. Получить Эйлеровы углы из новой ЛСК
// 4.1. Указать тип ЛСК - система углов Эйлера
ILocalCSEulerParamPtr eulerParametersOfLSC( lscForEulerAngels->LocalCSParameters );
if( !eulerParametersOfLSC ) {
MessageBox(NULL, _T( "Err 12: не удалось получить eulerParametersOfLSC. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return false;
}

// 4.2. Получить углы Эйлера
angleOfNutation = eulerParametersOfLSC->NutationAngle;
angleOfPrecession = eulerParametersOfLSC->PrecessionAngle;
angleOfRotation = eulerParametersOfLSC->RotationAngle;

return true;
}

и код организации ее вызова:
//-------------------------------------------------------------------------------
// Получить углы Эйлера параметров вставки компоненты (вызывающая функция)
// ---
void GetEulersAnglesOfComponentInsertion() {
CString tmpstr;
CString titleDialog = _T("Функция GetEulersAnglesOfComponentInsertion");

// 0. Получить основные интерфейсы модели
ksDocument3DPtr document3D = globalKompasObject->ActiveDocument3D();
if ( !document3D ) {
MessageBox(NULL, _T("document3D не получен. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return;
}

IKompasDocument3DPtr kompasDocument3D( IUnknownPtr(ksTransferInterface( document3D, ksAPI7Dual, 0), false) );
if ( !kompasDocument3D ) {
MessageBox(NULL, _T( "kompasDocument3D не получен. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return;
}

IPart7Ptr topPart7( kompasDocument3D->TopPart );
if (!topPart7) {
MessageBox(NULL, _T( "topPart7 не получен. Выход"), titleDialog, MB_OK|MB_ICONERROR );
return;
}

// 1. Получить массив вставленных компонент
_variant_t parts7OfModel( topPart7->PartsEx[ ( long )ksAllParts ] );
if ( ! ( parts7OfModel.vt == ( VT_ARRAY | VT_DISPATCH ) ) ) {
MessageBox(NULL, _T( "Массив компонент не получен. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return;
}

// 2. Проверить массив
long countOfInsertedComponents = parts7OfModel.parray->rgsabound[0].cElements - parts7OfModel.parray->rgsabound[0].lLbound;
if( countOfInsertedComponents == 0 ) {
MessageBox(NULL, _T( "В модели нет ни одного компонента. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return;
}

if ( parts7OfModel.parray->cDims != 1 ) {
MessageBox(NULL, _T( "Неверная размерность массив компонент. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return;
}

// 3. Получить из массива компонент, для которого требуется узнать Эйлеровы углы
long numComponentForSubmit = 1; // ЗДЕСЬ УКАЗАТЬ НОМЕР КОМПОНЕНТЫ, для которой требуется определить Эйлеровы углы вставки
if( numComponentForSubmit >= countOfInsertedComponents ) {
tmpstr.Format( _T("Номер заданной компоненты (%ld) превышает кол-во компонент модели (%ld)"), numComponentForSubmit+1, countOfInsertedComponents );
MessageBox(NULL, tmpstr, titleDialog, MB_OK|MB_ICONWARNING );
return;
}

LPDISPATCH HUGEP *pvar;
HRESULT hr = ::SafeArrayAccessData( parts7OfModel.parray, ( void HUGEP* FAR*)&pvar);
if ( ! ( !FAILED( hr ) && pvar ) ) {
MessageBox(NULL, _T( "Не получена ссылка на данные массива компонент. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return;
}

IPart7Ptr part7OfSubmittedComponent( pvar[ numComponentForSubmit ] ); // Требуемый компонент
hr = ::SafeArrayUnaccessData( parts7OfModel.parray );

if ( !part7OfSubmittedComponent ) {
MessageBox(NULL, _T( "Не получен part7SubmittedComponent. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return;
}

// 4. Получить Эйлеровы углы (в функции)
double angle_Nutation;
double angle_Precession;
double angle_Rotation;
if( !GetEulerAngelsOfComponentInsertion(document3D, part7OfSubmittedComponent, angle_Nutation, angle_Precession, angle_Rotation ) ) {
MessageBox(NULL, _T( "Не удалось получить Эйлеровы углы вставки компоненты. Выход"), titleDialog, MB_OK|MB_ICONWARNING );
return;
}

tmpstr.Format( _T("Эйлеровы углы вставки компоненты № %ld \"%s\" (в градусах):\nугол нутации: %f,\nугол прецессии: %f,\nугол вращения: %f."),
numComponentForSubmit+1,
(LPWSTR)part7OfSubmittedComponent->Name,
angle_Nutation,
angle_Precession,
angle_Rotation
);
MessageBox(NULL, tmpstr, titleDialog, MB_OK|MB_ICONINFORMATION );

MessageBox(NULL, _T("Работа закончена"), titleDialog, MB_OK|MB_ICONINFORMATION );

return;
}

При организации вызова по представленной программе укажите номер компоненты (numComponentForSubmit), для которой требуется найти Эйлеровы углы.

+ Благодарностей: 1