## Настройка запроса на поиск столкновений Если возможности настроек структуры cdet_collided_faces не достаточны, пользователь геометрического ядра C3D может реализовать собственный запрос. Для этого необходимо определить наследника класса cdet_query и реализовать для него специальную функцию обратного вызова (call-back функцию) вида: ```cpp typedef cback_res (*cback_func)(cdet_query *, message, cback_data &). ``` Ниже приведен пример реализации на языке программирования С++ структуры cdet_query_result, являющейся наследником структуры запроса cdet_query. Пример задает поиск до первого найденного пересечения и определяет, есть ли хотя бы одно пересечение в контрольном наборе тел. Пример можно найти в файле **cdet_data.h**. ```cpp //------------------------------------------------------------ struct cdet_query_result: public cdet_query { cdet_result result; cdet_query_result() : cdet_query(QueryFunc) , result(CDM_RESULT_NoCollisionDetected) {} private: static cback_res QueryFunc(cdet_query * query, message code, cback_data &) { cdet_query_result * q = static_cast(query); switch( code ) { case CDET_QUERY_STARTED: // The collision query is started for all solids of the set { q->result = CDM_RESULT_NoCollisionDetected; return CBACK_VOID_RESULT; } case CDET_INTERSECTED: // First intersection is founded. { q->result = CDM_RESULT_CollisionDetected; return CBACK_SUFFICIENT; } case CDET_FINISHED: // A pair of solids is finished. return (q->result == CDM_RESULT_CollisionDetected) ? CBACK_BREAK:CBACK_VOID_RESULT; default: return CBACK_VOID; } } }; ``` В основе запроса лежит функция обратного вызова ```cpp static cback_res QueryFunc(cdet_query * query, message code, cback_data & cData), ``` которую пользователь может реализовать на свое усмотрение. Данная функция передается в алгоритм **CheckCollisions** через структуру cdet_query и будет вызываться при наступлении одного из следующих событий (enum cdet_query::message): - CDET_QUERY_STARTED (начат поиск столкновений в контрольной группе тел), - CDET_STARTED (начат поиск столкновений для пары объектов), - CDET_FINISHED (завершен поиск столкновений для пары объектов), - CDET_INTERSECTED (найдено пересечение граней от пары объектов), - CDET_TOUCHED (найдены соприкасающиеся грани пары объектов). Входными параметрами функции QueryFunc являются: - **query** -- указатель на структуру запроса, - *code* -- целочисленное значение, кодирующее событие поиска, - **cData** -- структура передачи данных. Функция возвращает одно из значений перечисления cback_res: - CBACK_SUFFICIENT (Реакция клиентского приложения на события CDET_INTERSECTED или CDET_TOUCHED. Прерывает поиск для данной пары тел, но продолжает поиск столкновений других пар из контрольного набора тел), - CBACK_SKIP (Пропустить поиск для данной пары тел по событию CDET_STARTED: Поиск для других пар из набора будет продолжен), - CBACK_BREAK (Прерывает дальнейший поиск пересечений для всех событий), - CBACK_VOID (Не оказывает влияния на запрос столкновений, продолжает поиск), которое передает клиентское приложение ядру C3D для настройки алгоритма поиска. Целочисленное значение *code* определяет событие поиска и может принимать одно из значений: - CDET_QUERY_STARTED, - CDET_STARTED, - CDET_FINISHED, - CDET_INTERSECTED, - CDET_TOUCHED, Структура данных **cData** предназначена для передачи пары элементов типа cdet_query::geom_element и должна иметь вид: ```cpp struct cback_data { geom_element first, second; }; ``` где элемент пары cdet_query::geom_element -- это структура деталей поиска, содержащая следующие: - geom_element::**appItem** -- геометрический объект клиентского приложения, - geom_element::**refItem** -- геометрический объект типа MbRefItem, как правило это грань MbFace, - geom_element::**wMatrix** -- матрица перехода в общую, мировую СК из локальной СК тела. Различная реализация метода обратного вызова **QueryFunc** позволяет выполнять следующие настройки процесса поиска: - Собрать все пары граней, участвующих в столкновении тел; - В любой момент исключать из рассмотрения определенные тела или пары тел; - Различать случай пересечения и касания граней; - Прерывать поиск всех пересечений при достижении определенного результата; - Прерывать поиск при обнаружении пересечения или касания; - Группировать тела, чтобы в пределах группы пересечения не искались.