/**
 * A version of #BLI_kdtree_range_search which runs a callback
 * instead of allocating an array.
 *
 * \param search_cb: Called for every node found in \a range, false return value performs an early exit.
 *
 * \note the order of calls isn't sorted based on distance.
 */
void BLI_kdtree_range_search_cb(
        const KDTree *tree, const float co[3], float range,
        bool (*search_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data)
{
	const KDTreeNode *nodes = tree->nodes;

	uint *stack, defaultstack[KD_STACK_INIT];
	float range_sq = range * range, dist_sq;
	uint totstack, cur = 0;

#ifdef DEBUG
	BLI_assert(tree->is_balanced == true);
#endif

	if (UNLIKELY(tree->root == KD_NODE_UNSET))
		return;

	stack = defaultstack;
	totstack = KD_STACK_INIT;

	stack[cur++] = tree->root;

	while (cur--) {
		const KDTreeNode *node = &nodes[stack[cur]];

		if (co[node->d] + range < node->co[node->d]) {
			if (node->left != KD_NODE_UNSET)
				stack[cur++] = node->left;
		}
		else if (co[node->d] - range > node->co[node->d]) {
			if (node->right != KD_NODE_UNSET)
				stack[cur++] = node->right;
		}
		else {
			dist_sq = len_squared_v3v3(node->co, co);
			if (dist_sq <= range_sq) {
				if (search_cb(user_data, node->index, node->co, dist_sq) == false) {
					goto finally;
				}
			}

			if (node->left != KD_NODE_UNSET)
				stack[cur++] = node->left;
			if (node->right != KD_NODE_UNSET)
				stack[cur++] = node->right;
		}

		if (UNLIKELY(cur + 3 > totstack)) {
			stack = realloc_nodes(stack, &totstack, defaultstack != stack);
		}
	}

finally:
	if (stack != defaultstack)
		MEM_freeN(stack);
}
Exemple #2
0
void
rb_podcast_add_dialog_reset (RBPodcastAddDialog *dialog, const char *text, gboolean load)
{
	dialog->priv->reset_count++;
	remove_all_feeds (dialog);
	rhythmdb_entry_delete_by_type (dialog->priv->db, RHYTHMDB_ENTRY_TYPE_PODCAST_SEARCH);
	rhythmdb_commit (dialog->priv->db);

	rb_search_entry_set_text (dialog->priv->search_entry, text);

	if (load) {
		search_cb (dialog->priv->search_entry, text, dialog);
	} else {
		rb_search_entry_grab_focus (dialog->priv->search_entry);
	}
}