VL_EXPORT vl_size vl_kdforest_query (VlKDForest * self, VlKDForestNeighbor * neighbors, vl_size numNeighbors, void const * query) { vl_uindex i, ti ; vl_bool exactSearch = (self->searchMaxNumComparisons == 0) ; VlKDForestSearchState * searchState ; vl_size numAddedNeighbors = 0 ; assert (neighbors) ; assert (numNeighbors > 0) ; assert (query) ; /* this number is used to differentiate a query from the next */ self -> searchId += 1 ; self -> searchNumRecursions = 0 ; if (! self -> searchHeapArray) { /* count number of tree nodes */ /* add support structures */ vl_size maxNumNodes = 0 ; for (ti = 0 ; ti < self->numTrees ; ++ti) { maxNumNodes += self->trees[ti]->numUsedNodes ; } self -> searchHeapArray = vl_malloc (sizeof(VlKDForestSearchState) * maxNumNodes) ; self -> searchIdBook = vl_calloc (sizeof(vl_uindex), self->numData) ; for (ti = 0 ; ti < self->numTrees ; ++ti) { double * searchBounds = vl_malloc(sizeof(double) * 2 * self->dimension) ; double * iter = searchBounds ; double * end = iter + 2 * self->dimension ; while (iter < end) { *iter++ = - VL_INFINITY_F ; *iter++ = + VL_INFINITY_F ; } vl_kdtree_calc_bounds_recursively (self->trees[ti], 0, searchBounds) ; vl_free (searchBounds) ; } } self->searchNumComparisons = 0 ; self->searchNumSimplifications = 0 ; /* put the root node into the search heap */ self->searchHeapNumNodes = 0 ; for (ti = 0 ; ti < self->numTrees ; ++ ti) { searchState = self->searchHeapArray + self->searchHeapNumNodes ; searchState -> tree = self->trees[ti] ; searchState -> nodeIndex = 0 ; searchState -> distanceLowerBound = 0 ; vl_kdforest_search_heap_push (self->searchHeapArray, &self->searchHeapNumNodes) ; } /* branch and bound */ while (exactSearch || self->searchNumComparisons < self->searchMaxNumComparisons) { /* pop the next optimal search node */ VlKDForestSearchState * searchState ; /* break if search space completed */ if (self->searchHeapNumNodes == 0) { break ; } searchState = self->searchHeapArray + vl_kdforest_search_heap_pop (self->searchHeapArray, &self->searchHeapNumNodes) ; /* break if no better solution may exist */ if (numAddedNeighbors == numNeighbors && neighbors[0].distance < searchState->distanceLowerBound) { self->searchNumSimplifications ++ ; break ; } vl_kdforest_query_recursively (self, searchState->tree, searchState->nodeIndex, neighbors, numNeighbors, &numAddedNeighbors, searchState->distanceLowerBound, query) ; } /* sort neighbors by increasing distance */ for (i = numAddedNeighbors ; i < numNeighbors ; ++ i) { neighbors[i].index = -1 ; neighbors[i].distance = VL_NAN_F ; } while (numAddedNeighbors) { vl_kdforest_neighbor_heap_pop (neighbors, &numAddedNeighbors) ; } return self->searchNumComparisons ; }
vl_size vl_kdforestsearcher_query (VlKDForestSearcher * self, VlKDForestNeighbor * neighbors, vl_size numNeighbors, void const * query) { vl_uindex i, ti ; vl_bool exactSearch = self->forest->searchMaxNumComparisons == 0 ; VlKDForestSearchState * searchState ; vl_size numAddedNeighbors = 0 ; assert (neighbors) ; assert (numNeighbors > 0) ; assert (query) ; /* this number is used to differentiate a query from the next */ self -> searchId += 1 ; self -> searchNumRecursions = 0 ; self->searchNumComparisons = 0 ; self->searchNumSimplifications = 0 ; /* put the root node into the search heap */ self->searchHeapNumNodes = 0 ; for (ti = 0 ; ti < self->forest->numTrees ; ++ ti) { searchState = self->searchHeapArray + self->searchHeapNumNodes ; searchState -> tree = self->forest->trees[ti] ; searchState -> nodeIndex = 0 ; searchState -> distanceLowerBound = 0 ; vl_kdforest_search_heap_push (self->searchHeapArray, &self->searchHeapNumNodes) ; } /* branch and bound */ while (exactSearch || self->searchNumComparisons < self->forest->searchMaxNumComparisons) { /* pop the next optimal search node */ VlKDForestSearchState * searchState ; /* break if search space completed */ if (self->searchHeapNumNodes == 0) { break ; } searchState = self->searchHeapArray + vl_kdforest_search_heap_pop (self->searchHeapArray, &self->searchHeapNumNodes) ; /* break if no better solution may exist */ if (numAddedNeighbors == numNeighbors && neighbors[0].distance < searchState->distanceLowerBound) { self->searchNumSimplifications ++ ; break ; } vl_kdforest_query_recursively (self, searchState->tree, searchState->nodeIndex, neighbors, numNeighbors, &numAddedNeighbors, searchState->distanceLowerBound, query) ; } /* sort neighbors by increasing distance */ for (i = numAddedNeighbors ; i < numNeighbors ; ++ i) { neighbors[i].index = -1 ; neighbors[i].distance = VL_NAN_F ; } while (numAddedNeighbors) { vl_kdforest_neighbor_heap_pop (neighbors, &numAddedNeighbors) ; } return self->searchNumComparisons ; }