Перейти к публикации

Open API. с++. Фильтры выбора.


torvald

Рекомендованные сообщения

Добрый день! Уже не один день ломаю голову над задачей отбора объектов(кривая, ребро, твердое тело) с заданным атрибутом.

Коротко введение:

Интерфейс Block Styler, в нем присутствует селектор типа "Select Object". Так вот, нужно задать условие наличия атрибута в любом выделенном объекте. Один из вариантов- пролистывать массив выделенных объектов, через try{}catch(...){} отлавливать все объекты в которых есть данный атрибут (пытаясь получить доступ к данному атрибуту в блоке try{}, если атрибут отсутствует, обрывается try и выкидывает в catch). Но это занимает много времени, т.к. три типа объектов, 3 раза отлавливаем ошибку, а граней, кривых и т.д. за тысячу.

Вот другое дело настройка фильтра по атрибутам в NX(например NX7.5). Edit->Selection->User Attributes. выбираю тип- string, ввожу наименование атрибута- weld, и никакого перебора... моментально выбрало все нужные объекты, независимо от их типа. Но организовать это у меня не получилось.

Максимум- фильтр выбора по типу объекта, да и там руки связаны. Пример фильтра граней в коллбэке filter_cb:

std::vector<NXOpen::Selection::MaskTriple> maskTriple1(1);

maskTriple1[0].Type=3;

maskTriple1[0].Subtype=0;

maskTriple1[0].SolidBodySubtype=0;

selection0->GetProperties()->SetSelectionFilter("SelectionFilter",Selection::SelectionActionClearAndEnableSpecific,maskTriple1);

Собственно к делу! Если кто-нибудь работал с похожими задачами, или же заинтересован проблемой, давайте общаться!

Ссылка на сообщение
Поделиться на других сайтах


Ну все правильно, вроде.

* Если тебе надо найти ВСЕ объекты (любого типа) с атрибутом MY_ATTR=MY_VALUE, то берем UF_OBJ_cycle_all и шпарим по всем объектам в части (неважно скрыты они или нет) и у каждого спрашиваем UF_ATTR_find_attribute и, если нашли - то UF_ATTR_read_value.

UF_ATTR_find_attribute/UF_ATTR_read_value можно смело заменить на :

NXOpen::NXObject * obj = dynamic_cast < NXOpen::NXObject * > ( NXOpen::NXObjectManager::Get (tag_t ) );

if (obj) {

obj->GetAttributeTitlesByType();

ну и т.д.

}

* Если же тебе надо найти ТОЛЬКО ВИДИМЫЕ объекты с атрибутом MY_ATTR=MY_VALUE, то берем UF_VIEW_ask_work_view и далее шпарим по объектам при помощи UF_VIEW_cycle_objects (собирая атрибуты ткаим же способом, как ив первом пункте).

UF_VIEW_cycle_objects можно смело заменить на NXOpen::View::AskVisibleObjects

* Для selection блока в blockstyler-e есть доп опция : фильтр (см. скриншот)

в этот фильтр будут приезжать объекты, поверх которых пользователь елозит мышкой (но НЕ выбирает). Соотвветственно в этом фильтре можно отсекать объекты, не имеющие атрибут/значение.

PS Чтобы не просаживалась производительность при stack unwinding (когда в catch попадаешь), рекомендую сначала проверить, есть ли атрибут у объекта, и правильного ли он (атрибут) типа, и только потом спрашивать значение.

Regardzzz ...

post-646-1317727963_thumb.png

Ссылка на сообщение
Поделиться на других сайтах

Ну все правильно, вроде.

* Если тебе надо найти ВСЕ объекты (любого типа) с атрибутом MY_ATTR=MY_VALUE, то берем UF_OBJ_cycle_all и шпарим по всем объектам в части (неважно скрыты они или нет) и у каждого спрашиваем UF_ATTR_find_attribute и, если нашли - то UF_ATTR_read_value.

UF_ATTR_find_attribute/UF_ATTR_read_value можно смело заменить на :

NXOpen::NXObject * obj = dynamic_cast < NXOpen::NXObject * > ( NXOpen::NXObjectManager::Get (tag_t ) );

if (obj) {

obj->GetAttributeTitlesByType();

ну и т.д.

}

* Если же тебе надо найти ТОЛЬКО ВИДИМЫЕ объекты с атрибутом MY_ATTR=MY_VALUE, то берем UF_VIEW_ask_work_view и далее шпарим по объектам при помощи UF_VIEW_cycle_objects (собирая атрибуты ткаим же способом, как ив первом пункте).

UF_VIEW_cycle_objects можно смело заменить на NXOpen::View::AskVisibleObjects

* Для selection блока в blockstyler-e есть доп опция : фильтр (см. скриншот)

в этот фильтр будут приезжать объекты, поверх которых пользователь елозит мышкой (но НЕ выбирает). Соотвветственно в этом фильтре можно отсекать объекты, не имеющие атрибут/значение.

PS Чтобы не просаживалась производительность при stack unwinding (когда в catch попадаешь), рекомендую сначала проверить, есть ли атрибут у объекта, и правильного ли он (атрибут) типа, и только потом спрашивать значение.

Regardzzz ...

Огромное спасибо за быстрый и полезный ответ! Я что то и не подумал, что вместо перебора массива в селекторе можно в калбэк фильтра засунуть проверку =).

и еще вопросик... Подскажите плз как организовать "выделить все". Еще раз спасибо!

Ссылка на сообщение
Поделиться на других сайтах

Ну все правильно, вроде.

* Если тебе надо найти ВСЕ объекты (любого типа) с атрибутом MY_ATTR=MY_VALUE, то берем UF_OBJ_cycle_all и шпарим по всем объектам в части (неважно скрыты они или нет) и у каждого спрашиваем UF_ATTR_find_attribute и, если нашли - то UF_ATTR_read_value.

UF_ATTR_find_attribute/UF_ATTR_read_value можно смело заменить на :

NXOpen::NXObject * obj = dynamic_cast < NXOpen::NXObject * > ( NXOpen::NXObjectManager::Get (tag_t ) );

if (obj) {

obj->GetAttributeTitlesByType();

ну и т.д.

}

* Если же тебе надо найти ТОЛЬКО ВИДИМЫЕ объекты с атрибутом MY_ATTR=MY_VALUE, то берем UF_VIEW_ask_work_view и далее шпарим по объектам при помощи UF_VIEW_cycle_objects (собирая атрибуты ткаим же способом, как ив первом пункте).

UF_VIEW_cycle_objects можно смело заменить на NXOpen::View::AskVisibleObjects

* Для selection блока в blockstyler-e есть доп опция : фильтр (см. скриншот)

в этот фильтр будут приезжать объекты, поверх которых пользователь елозит мышкой (но НЕ выбирает). Соотвветственно в этом фильтре можно отсекать объекты, не имеющие атрибут/значение.

PS Чтобы не просаживалась производительность при stack unwinding (когда в catch попадаешь), рекомендую сначала проверить, есть ли атрибут у объекта, и правильного ли он (атрибут) типа, и только потом спрашивать значение.

Regardzzz ...

Огромное спасибо за быстрый и полезный ответ! Я что то и не подумал, что вместо перебора массива в селекторе можно в калбэк фильтра засунуть проверку =).

Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте еще раз! Снова понадобилась помощь:

Пытаюсь пройтись по всем элементам партов, но почему то переход object_tag не осуществляется. Нашел несколько примеров, в которых функцию UF_OBJ_cycle_all используют так, как написано ниже.

int i=0;

tag_t object_tag= NULL_TAG;

tag_t part_tag = UF_PART_ask_nth_part(y);

while((object_tag = UF_OBJ_cycle_all(part_tag, object_tag)) != NULL_TAG)

{

object_list = object_tag;

i++;

}

Пробовал мониторить object_tag прямо в цикле- значение не изменяется.

Может ли это быть вызвано различием в версиях NX (примеры я нашел для NX4, тестирую на NX6, NX7.5). Спасибо!

Ссылка на сообщение
Поделиться на других сайтах

Разобрался в чем дело. Ниже код функции, которая возвращает тэги всех объектов у которых есть атрибут "weld_length". h- переменная выделения. При 1- объекты выделены, при 0- снятие выделения. n- количество объектов.

tag_t *selection(int *n,int h){

tag_t *object_list=(tag_t *) malloc(sizeof(tag_t));

int y=0;int i;

int attr_type;UF_ATTR_value_p_t atr_value;

int num_parts = UF_PART_ask_num_parts ( );

for (y=0; y<num_parts; y++)

{

i=0;

tag_t object_tag= NULL_TAG;

tag_t part_tag = UF_PART_ask_nth_part(y);

while((object_tag = UF_OBJ_cycle_all(part_tag, object_tag)) != NULL_TAG)

{

UF_ATTR_find_attribute(object_tag,UF_ATTR_string,"Weld_length",&attr_type);

if (attr_type == 5){

UF_DISP_set_highlight(object_tag,h);

object_list = object_tag;

i++;

object_list = (tag_t *) realloc(object_list, sizeof(tag_t)*(i+1));

}

}

}

*n=i-1;

return object_list;

}

Спасибо! Считаю тему закрытой =)

Ссылка на сообщение
Поделиться на других сайтах

Считаю тему не закрытой, ибо код изобилует косяками (несколько косяков - смертельные, несколько - в виде "warning").

tag_t *selection(int *n,int h) {



  //вспоминаем, ЧЕМ инициализируются значения при malloc

  //HINT: значения будут undetermined - т.е. мусор.

  //вот теперь представь, что ты НЕ НАШЕЛ ни одного атриба Weld_length в частях. И возвращаешь указатель на один (или не один  ... см. косяк с int i ) tag_t

  //и теперь представь, что ты обрабатываешь возвращенный массив в вызывающей ф-ции :) 

  //+++ начало бага +++

  tag_t *object_list=(tag_t *) malloc(sizeof(tag_t));

  //+++ конец бага +++

  

  //ok

  int y=0;

	

  //а кто будет нулем тут инициализировать переменную, а?

  //вот попробуй распечатай значение i после его объявления (на *nix может и прокатит, но для Win* - НЕТ )

  //БОЛЕЕ ТОГО. ты получишь мощщщщнейший выстрел при попытке обратиться в вызывающей ф-ции к элементу массива (который "возвращаешь") при условиях:

  //1. ты не иниицализировал i нулем

  //2. количество загруженных частей y == 0;

  //3. ты в вызывающей ф-ции побежал по object_list (возврату) *n раз :) 

  //+++ начало бага +++

  int i;  

  //+++ конец бага +++

  

  //в данном контексте - не страшно (не определенная переменная), но я бы занулил :) 

  int attr_type;



  //а напуркуа оно здесь, если ниже по коду не используется ...	

  UF_ATTR_value_p_t atr_value;

  

  //ok

  int num_parts = UF_PART_ask_num_parts ( );



  //ok

  for (y=0; y<num_parts; y++) {

	

	//ай-ай-ай! 

	//вот представь, что у нас 5 загруженных частей и в данный момент y==0 

	//вот мы нашли 10 объектов (в цикле ниже), у которых есть атриб Weld_length

	//и вот мы перешли на y=1

	//угадай, поверх чего мы сейчас будем писать новые значения, при условии нахождения в части "y" объектов с атрибом Weld_length ??? 

	//HINT: правильный ответ - поверх УЖЕ НАЙДЕННЫХ тегов объектов в части "y-1" 

	//+++ начало бага +++	 

	i=0;

	//+++ конец бага +++

	

	//ok

	tag_t object_tag= NULL_TAG;

	

	//ok

	tag_t part_tag = UF_PART_ask_nth_part(y);

	

	//ok

	while((object_tag = UF_OBJ_cycle_all(part_tag, object_tag)) != NULL_TAG) {

	  

	  //а кто ошибку (код возврата) будет проверять, а? в данном случае не смертельно, но надо себя приучать к надежному коду ... 

	  //+++ начало бага +++  

	  UF_ATTR_find_attribute(object_tag,UF_ATTR_string,"Weld_length",&attr_type);

	  //+++ конец бага +++

	  

	  //тоже достаточно спорное решение, я бы заменил сравнение attr_type с 5 на UF_ATTR_string

	  //+++ начало бага +++

	  if (attr_type == 5) {

	  //+++ конец бага +++

	  

		//а кто ошибку (код возврата) будет проверять, а? в данном случае не смертельно, но надо себя приучать к надежному коду ...

		//+ я бы не стал уповать на разумное поведение ф-ции при значениях второго аргумента отличных от 0 или 1 (в твоем коде нет проверки на 0/1 значения входного параметра 'h' ) 

		//+++ начало бага +++		

		UF_DISP_set_highlight(object_tag,h);

		//+++ конец бага +++

		

		//ok

		object_list[i] = object_tag;

		//ok (в данном случае), но преинкремент, т.е. ++i в общем случае "правильнее". гуглить по слову "преинкремент/постинкремент"

		i++;

		//ok (с оговорками про int i :) )

		object_list = (tag_t *) realloc(object_list, sizeof(tag_t)*(i+1));

	  }

	}

  }



  //а кто будет проверять значение указателя, который нам передали на NULL ?

  //я могу вызавать ф-цию вот так :  tag_t some_tags = selection (NULL, 1);

  //соответственно, получим разыменование нулевого указателя :)	 

  *n=i-1;

	

  //ok

  return object_list;

}

Regardzzz ...

PS Итого:

0. Сорри длинные объяснения и КАПСЫ.

1. За стремление кодить для NX - пять.

2. За реализацию алгоритма - кол (хотел поставить два с минусом).

PPS - ВНИМАТЕЛЬНО следить за логикой ф-ции.

PPPS - НАСТОЯТЕЛЬНО рекомендую изучить возможности STL (ассоциативных контейнеров типа std::vector / std::set и т.д. для того, чтобы не мучаться с памятью (malloc/calloc/realloc) )

PPPPS - Анализ проводился без проверок на тестовом коде, так что в этом анализе тоже могут быть "недочеты" :)

Regardzzz ещё раз...

Ссылка на сообщение
Поделиться на других сайтах

Спасибо! Учел ваши советы. Код после компиляции в "накосяченом виде" работал, но спустя некоторое время я снова запустил приложение и огорчился. Программа работает до момента for (y=0; y<num_parts; ++y).

проверил num_parts:

num_parts = UF_PART_ask_num_parts ( );

char tmp[10];

itoa(num_parts,tmp,10);

weld_calc::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, tmp);

num_parts=0, но я так и не понял почему... соответственно выполнение прерывается. Я что то не учел при использовании UF_PART_ask_num_parts ( )?

Ссылка на сообщение
Поделиться на других сайтах

Спасибо! Учел ваши советы. Код после компиляции в "накосяченом виде" работал, но спустя некоторое время я снова запустил приложение и огорчился. Программа работает до момента for (y=0; y<num_parts; ++y).

проверил num_parts:

num_parts = UF_PART_ask_num_parts ( );

char tmp[10];

itoa(num_parts,tmp,10);

weld_calc::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, tmp);

num_parts=0, но я так и не понял почему... соответственно выполнение прерывается. Я что то не учел при использовании UF_PART_ask_num_parts ( )?

Массив char tmp[10]; проинициализируй (хотябы первый элемент)

Если бы Ты читал внимательно стандары "c" - то знал бы что практически все с-шные

функции которые работают со строками требуют завершающего 0

Где он у Тебя - по стандарту то что находится в обласи памяти tmp[10]

никак не определено - на усмотрение разработкика компилятора

соответственно так же не определено будет работать Твоя программа

Посмотри хотя бы

<noindex>itoa</noindex>

- где написано что на c рекомендуется пользоваться sprintf

На c++ есть еще более безопасный вариант

#include <strstream>

#include <iostream>

#include <sstream>

#include <iomanip>



std::string pse_component::str(int n)

{ std::string ret;

  std::ostrstream os; 

	os<<n<<'\0';

	ret=os.str();

return ret;

}
Ссылка на сообщение
Поделиться на других сайтах

мм... первое что пришло на ум для конвертации. это недоразумение не влияет на выполнение функции UF_PART_ask_num_parts ( ). Я учел ваш, nut888, совет, спасибо.

Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

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

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу.




×
×
  • Создать...