• Добро пожаловать на Форум пользователей ПО АСКОН. Пожалуйста, авторизуйтесь.
 

Уважаемые пользователи,

Хотим проинформировать вас о режиме работы регистрации на нашем сайте.

Зарегистрироваться возможно в рабочие дни, с 8:00 до 20:00 (мск).

Если у вас возникнут вопросы или потребуется дополнительная информация, не стесняйтесь обращаться к нашей службе поддержки. Вы можете связаться с нами по указанным контактным данным на нашем сайте.

Благодарим вас за понимание и сотрудничество. Мы ценим ваше терпение и стремимся предоставить вам лучший опыт использования нашего сервиса.

С уважением,
Команда Ascon

Проблема с использованием метода IMassInertiaParam7::Calculate()

Автор Akew, 05.05.15, 19:41:40

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

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

Akew


Доброго времени суток!

Есть необходимость получать параметры МЦХ посредством метода IMassInertiaParam7::Calculate().
Интерфейс IMassInertiaParam7 получаю без проблем, доступны его свойства и методы.
Однако, при вызове ::Calculate() возвращается false, что говорит о неудачном завершении расчета.
Пробовал на разных трехмерных моделях - результат тот же.

Пробовал также игнорировать то, что расчет завершился неудачей, - параметры МЦХ (в свойствах IMassInertiaParam7) получаются вроде бы нормальные (сравнивал с теми, что получаются при расчете посредством меню КОМПАСа "Сервис | МЦХ модели"). Только при расчете векторов направлений главных центральных осей инерции по осям X, Y, Z (методы IMassInertiaParam7::GetAxisX, ::GetAxisY и ::GetAxisZ) наблюдается следующая картина:
- все методы возвращаяют true (успешный расчет);
- ::GetAxisX вычисляет ось не X, а Y;
- ::GetAxisY вычисляет ось не Y, а Z;
- ::GetAxisZ вычисляет вектор явно неверно: получается тройка чисел 137 порядка (10 в 137 степени), а должно быть не больше (не меньше) плюс (минус) единица.

Проверку проводил на КОМПАСах 14 SP1, SP2 и 15 SP1, - результат одинаково неверный, - как описано.

Это моя ошибка или что-то более серьезное, например, ошибка в методе ::Calculate()?
Какие существуют альтернативные работоспособные способы получения параметров МЦХ?
Требуются получать: массу, центр массы, осевые моменты инерции и векторы направлений главных центральных осей инерции по всем трем осям.

Спасибо всем, кто откликнется.

Прилагаю фрагмент кода, который использую при вызове метода ::Calculate():

void TestMCKH() {
CString title_dialog; title_dialog.Format( _T( "Функция %s" ), _T( "TestMCKH" ) ); // Заголовок окна сообщений функции

ksDocument3DPtr pDocument3d = MyKompasObject->ActiveDocument3D(); // Ранее было объявлено:
// KompasObjectPtr MyKompasObject( NULL ); ...
// MyKompasObject = IDispatchPtr( pCreateKompasObject(), false );
if (!pDocument3d) {
MessageBox(NULL, _bstr_t( _T("*** Интерфейс pDocument3d не получен. Выход.") ), title_dialog, MB_OK); return;
}

IKompasDocument3DPtr doc3D( IUnknownPtr( ksTransferInterface( pDocument3d, ksAPI7Dual, 0), false ) );
if ( !doc3D ) {
MessageBox(NULL, _bstr_t( _T("*** Интерфейс doc3D не получен. Выход.") ), title_dialog, MB_OK); return;
}

IPart7Ptr part7 = doc3D->TopPart;
if (!part7) {
MessageBox(NULL, _bstr_t( _T("*** Интерфейс part7 не получен. Выход.") ), title_dialog, MB_OK); return;
}

IMassInertiaParam7Ptr MassParam7 = part7;
if (!MassParam7) {
MessageBox(NULL, _bstr_t( _T("*** Интерфейс MassParam7 не получен. Выход.") ), title_dialog, MB_OK); return;
}

// Подготовка к вычислениям
MassParam7->PutLengthUnits(ksLUnMM); // Миллиметры
MassParam7->PutMassUnits(ksMUnGR); // Граммы

MassParam7->MassSettingMode = ksCalculateParam; // Вычисление параметров
MassParam7->PutSourceData( VARIANT_TRUE ); // Данные из источника
MassParam7->PutDensityMode( VARIANT_FALSE ); // Плотность - из справочника

bool res_Calculate = MassParam7->Calculate(); // ВЫЧИСЛИТЬ ПАРАМЕТРЫ МЦХ И ПОЛУЧИТЬ РЕЗУЛЬТАТ РАСЧЕТА (успешный или не успешный)
if (!res_Calculate) {   // ПОСТОЯННО ВОЗВРАЩАЕТСЯ FALSE
MessageBox(NULL, _bstr_t( _T("*** MassParam7->Calculate() не отработала. Выход.") ), title_dialog, MB_OK); return;
}

MessageBox(NULL, _bstr_t( _T("MassParam7->Calculate() отработала нормально.") ), title_dialog, MB_OK);

return;
}







Sprinter500

Через API7 не пробовал, но через API5 нормально работает следующий код:

....
const
pTop_Part = -1;

var
//переменная – интерфейс системы КОМПАС
kompas: KompasObject;
Document2D: ksDocument2D;
Document3D: ksDocument3D;
DocumentParam: ksDocumentParam;
Part: ksPart;
VariableCollection: ksVariableCollection;
Variable: ksVariable;
MIPar: ksMassInertiaParam;

.....

function GetValMCH(EdIzm: integer; TypVal:string): real;//Получение значения МЦХ
begin
Part:= ksPart(Document3D.GetPart(pTop_Part));
MIPar := ksMassInertiaParam(Part.CalcMassInertiaProperties(EdIzm));
if TypVal = 'XC' then result:=MIPar.xc;
if TypVal =  'YC' then result:=MIPar.yc;
if TypVal =  'ZC' then result:=MIPar.zc;
if TypVal =  'R' then result:=MIPar.r;
if TypVal =  'M' then result:=MIPar.m;
if TypVal =  'V' then result:=MIPar.v;
if TypVal =  'S' then result:=MIPar.F;
end;

Slaviation

ЦитироватьЭто моя ошибка или что-то более серьезное, например, ошибка в методе ::Calculate()?

В коде есть строчка:
IMassInertiaParam7Ptr MassParam7 = part7;

В SDK же получение IMassInertiaParam7 документировано так:
Интерфейс контейнера является дополнительным к интерфейсу IPart7 и IEmbodiment. Данный интерфейс можно получить от IPart7 и от IEmbodiment посредством вызова ме­тода IUnknown::QueryInterface (const GUID far& iid, void** pif);

Поэтому нужно как-то так:
const IMassInertiaParam7Ptr MassParam7(NULL);
if(FAILED(part7->QueryInterface(IID_IMassInertiaParam7, (void**)&MassParam7)) || !MassParam7)
{
   MessageBox(NULL, _bstr_t( _T("*** Интерфейс MassParam7 не получен. Выход.") ), title_dialog, MB_OK);
   return;
}


Akew

Цитата: Sprinter500 от 05.05.15, 20:19:19
Через API7 не пробовал, но через API5 нормально работает следующий код:

....

Согласен, что этот способ получения МЦХ получше, но, к сожалению, тоже не без странностей: при вычислении оси Z метод GetAxisZ( &x, &y, &z ) также сообщает о неудаче. Но, тем не менее, эта ось вычисляется правильно.

Кто-нибудь знает, что означает "получение (вычисление) вектора завершилось неудачей"? Можно ли в этом случае доверять полученному результату?

Akew

Цитата: Slaviation от 06.05.15, 06:29:44
В коде есть строчка:
IMassInertiaParam7Ptr MassParam7 = part7;

В SDK же получение IMassInertiaParam7 документировано так:
Интерфейс контейнера является дополнительным к интерфейсу IPart7 и IEmbodiment. Данный интерфейс можно получить от IPart7 и от IEmbodiment посредством вызова ме­тода IUnknown::QueryInterface (const GUID far& iid, void** pif);

Поэтому нужно как-то так:
const IMassInertiaParam7Ptr MassParam7(NULL);
if(FAILED(part7->QueryInterface(IID_IMassInertiaParam7, (void**)&MassParam7)) || !MassParam7)
{
   MessageBox(NULL, _bstr_t( _T("*** Интерфейс MassParam7 не получен. Выход.") ), title_dialog, MB_OK);
   return;
}

Очень интересное замечание, - завтра попробую Ваш способ.

Вместе с тем, в связи с тем, что другие свойства и методы интерфейса IMassInertiaParam7 работали нормально, на мой взгляд, должно означать, что он был получен корректно.

По идеи, если вектор X и Y получены правильно, то для Z достаточно получить знак, т.к. вектора взаимно перпендикулярны.

Akew

Цитата: Sabahs от 06.05.15, 20:14:59
По идеи, если вектор X и Y получены правильно, то для Z достаточно получить знак, т.к. вектора взаимно перпендикулярны.

Да, верно: по условию перпендикулярности вектора Z векторам X и Y, и по равенству единице суммы квадратов компонент этого вектора можно его восстановить (система из трех уравнений с тремя неизвестными решается элементарно). Однако я исхожу из того, что функцией (методом) ::Calculate() было сообщено о неуспешном завершении расчета, что, по логике, должно означать, что полученные результаты не являются достоверными. А мне нужен достоверный результат. Если бы где-нибудь было оговорено, что недоработка метода ::Calculate() состоит только в этом, то вопроса бы не стояло.

Akew

Цитата: Akew от 06.05.15, 19:31:01
Очень интересное замечание, - завтра попробую Ваш способ.

Вместе с тем, в связи с тем, что другие свойства и методы интерфейса IMassInertiaParam7 работали нормально, на мой взгляд, должно означать, что он был получен корректно.

Как и ожидал, - чуда не произошло: Ваш способ показал точно такой же результат, что и мой.
Вопрос остается открытым.

Slaviation

ЦитироватьВопрос остается открытым
.
После вызова Calculate попробуйте сделать парту приятно вызовом для него Update().

Slaviation

08.05.15, 07:43:02 #9 Последнее редактирование: 08.05.15, 11:24:26 от Slaviation
ЦитироватьВопрос остается открытым

Попробовал потестировать (во вложении). Если строка 20 (установка материала) теста закомментирована, то Calculate всегда возвращает False. Если  раскомментирована, то True; Это согласуется с описанием Calculate в SDK: Метод следует вызывать после изменения одного из параметров объекта, чтобы привести остальные параметры в соответствие с измененным.


Еще один момент. В коде есть строчка: MassParam7->PutSourceData( VARIANT_TRUE );   // Данные из источника
В SDK, в описании IMassInertiaParam7::SourceData есть примечание: Свойство доступно только для компонента, вставленного в сборку.
В коде же MassParam7 взят от part7, а part7 определен как doc3D->TopPart - т.е это никак не компонент вставленный в сборку.

Совет по вызову Update() в предыдущем моем посте снимаю.

Akew

Цитата: Slaviation от 08.05.15, 07:43:02
... Это согласуется с описанием Calculate в SDK: Метод следует вызывать после изменения одного из параметров объекта, чтобы привести остальные параметры в соответствие с измененным.


Спасибо!
Жаль, что теперь только во вторник смогу это попробовать.

С наступающим Днем Победы!