doxygen classify/kdtree.cpp

This commit is contained in:
Jim O'Regan 2015-07-20 16:28:59 +01:00
parent 5668a52670
commit 84788d49a0

View File

@ -48,7 +48,7 @@ static int NextLevel(KDTREE *tree, int level) {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Store the k smallest-keyed key-value pairs. /** Store the k smallest-keyed key-value pairs. */
template<typename Key, typename Value> template<typename Key, typename Value>
class MinK { class MinK {
public: public:
@ -70,11 +70,11 @@ class MinK {
const Element* elements() { return elements_; } const Element* elements() { return elements_; }
private: private:
const Key max_key_; // the maximum possible Key const Key max_key_; //< the maximum possible Key
Element* elements_; // unsorted array of elements Element* elements_; //< unsorted array of elements
int elements_count_; // the number of results collected so far int elements_count_; //< the number of results collected so far
int k_; // the number of results we want from the search int k_; //< the number of results we want from the search
int max_index_; // the index of the result with the largest key int max_index_; //< the index of the result with the largest key
}; };
template<typename Key, typename Value> template<typename Key, typename Value>
@ -117,13 +117,13 @@ bool MinK<Key, Value>::insert(Key key, Value value) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Helper class for searching for the k closest points to query_point in tree. /** Helper class for searching for the k closest points to query_point in tree. */
class KDTreeSearch { class KDTreeSearch {
public: public:
KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest); KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest);
~KDTreeSearch(); ~KDTreeSearch();
// Return the k nearest points' data. /** Return the k nearest points' data. */
void Search(int *result_count, FLOAT32 *distances, void **results); void Search(int *result_count, FLOAT32 *distances, void **results);
private: private:
@ -133,8 +133,8 @@ class KDTreeSearch {
KDTREE *tree_; KDTREE *tree_;
FLOAT32 *query_point_; FLOAT32 *query_point_;
MinK<FLOAT32, void *>* results_; MinK<FLOAT32, void *>* results_;
FLOAT32 *sb_min_; // search box minimum FLOAT32 *sb_min_; //< search box minimum
FLOAT32 *sb_max_; // search box maximum FLOAT32 *sb_max_; //< search box maximum
}; };
KDTreeSearch::KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest) : KDTreeSearch::KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest) :
@ -151,8 +151,8 @@ KDTreeSearch::~KDTreeSearch() {
delete[] sb_max_; delete[] sb_max_;
} }
// Locate the k_closest points to query_point_, and return their distances and /// Locate the k_closest points to query_point_, and return their distances and
// data into the given buffers. /// data into the given buffers.
void KDTreeSearch::Search(int *result_count, void KDTreeSearch::Search(int *result_count,
FLOAT32 *distances, FLOAT32 *distances,
void **results) { void **results) {
@ -176,11 +176,9 @@ void KDTreeSearch::Search(int *result_count,
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
Public Code Public Code
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /// @return a new KDTREE based on the specified parameters.
/// Return a new KDTREE based on the specified parameters. /// @param KeySize # of dimensions in the K-D tree
/// Parameters: /// @param KeyDesc array of params to describe key dimensions
/// KeySize # of dimensions in the K-D tree
/// KeyDesc array of params to describe key dimensions
KDTREE *MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[]) { KDTREE *MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[]) {
KDTREE *KDTree = (KDTREE *) Emalloc( KDTREE *KDTree = (KDTREE *) Emalloc(
sizeof(KDTREE) + (KeySize - 1) * sizeof(PARAM_DESC)); sizeof(KDTREE) + (KeySize - 1) * sizeof(PARAM_DESC));
@ -205,8 +203,6 @@ KDTREE *MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[]) {
} }
/*---------------------------------------------------------------------------*/
void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data) {
/** /**
* This routine stores Data in the K-D tree specified by Tree * This routine stores Data in the K-D tree specified by Tree
* using Key as an access key. * using Key as an access key.
@ -219,6 +215,7 @@ void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data) {
* @note History: 3/10/89, DSJ, Created. * @note History: 3/10/89, DSJ, Created.
* 7/13/89, DSJ, Changed return to void. * 7/13/89, DSJ, Changed return to void.
*/ */
void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data) {
int Level; int Level;
KDNODE *Node; KDNODE *Node;
KDNODE **PtrToNode; KDNODE **PtrToNode;
@ -245,7 +242,6 @@ void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data) {
} /* KDStore */ } /* KDStore */
/*---------------------------------------------------------------------------*/
/** /**
* This routine deletes a node from Tree. The node to be * This routine deletes a node from Tree. The node to be
* deleted is specified by the Key for the node and the Data * deleted is specified by the Key for the node and the Data
@ -303,39 +299,36 @@ KDDelete (KDTREE * Tree, FLOAT32 Key[], void *Data) {
} /* KDDelete */ } /* KDDelete */
/*---------------------------------------------------------------------------*/ /**
* This routine searches the K-D tree specified by Tree and
* finds the QuerySize nearest neighbors of Query. All neighbors
* must be within MaxDistance of Query. The data contents of
* the nearest neighbors
* are placed in NBuffer and their distances from Query are
* placed in DBuffer.
* @param Tree ptr to K-D tree to be searched
* @param Query ptr to query key (point in D-space)
* @param QuerySize number of nearest neighbors to be found
* @param MaxDistance all neighbors must be within this distance
* @param NBuffer ptr to QuerySize buffer to hold nearest neighbors
* @param DBuffer ptr to QuerySize buffer to hold distances
* from nearest neighbor to query point
* @return Number of nearest neighbors actually found
* @note Exceptions: none
* @note History:
* - 3/10/89, DSJ, Created.
* - 7/13/89, DSJ, Return contents of node instead of node itself.
*/
void KDNearestNeighborSearch( void KDNearestNeighborSearch(
KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance, KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance,
int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[]) { int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[]) {
/*
** Parameters:
** Tree ptr to K-D tree to be searched
** Query ptr to query key (point in D-space)
** QuerySize number of nearest neighbors to be found
** MaxDistance all neighbors must be within this distance
** NBuffer ptr to QuerySize buffer to hold nearest neighbors
** DBuffer ptr to QuerySize buffer to hold distances
** from nearest neighbor to query point
** Operation:
** This routine searches the K-D tree specified by Tree and
** finds the QuerySize nearest neighbors of Query. All neighbors
** must be within MaxDistance of Query. The data contents of
** the nearest neighbors
** are placed in NBuffer and their distances from Query are
** placed in DBuffer.
** Return: Number of nearest neighbors actually found
** Exceptions: none
** History:
** 3/10/89, DSJ, Created.
** 7/13/89, DSJ, Return contents of node instead of node itself.
*/
KDTreeSearch search(Tree, Query, QuerySize); KDTreeSearch search(Tree, Query, QuerySize);
search.Search(NumberOfResults, DBuffer, NBuffer); search.Search(NumberOfResults, DBuffer, NBuffer);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
// Walk a given Tree with action. /** Walk a given Tree with action. */
void KDWalk(KDTREE *Tree, void_proc action, void *context) { void KDWalk(KDTREE *Tree, void_proc action, void *context) {
if (Tree->Root.Left != NULL) if (Tree->Root.Left != NULL)
Walk(Tree, action, context, Tree->Root.Left, NextLevel(Tree, -1)); Walk(Tree, action, context, Tree->Root.Left, NextLevel(Tree, -1));
@ -343,22 +336,19 @@ void KDWalk(KDTREE *Tree, void_proc action, void *context) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void FreeKDTree(KDTREE *Tree) { /**
/* * This routine frees all memory which is allocated to the
** Parameters: * specified KD-tree. This includes the data structure for
** Tree tree data structure to be released * the kd-tree itself plus the data structures for each node
** Operation: * in the tree. It does not include the Key and Data items
** This routine frees all memory which is allocated to the * which are pointed to by the nodes. This memory is left
** specified KD-tree. This includes the data structure for * untouched.
** the kd-tree itself plus the data structures for each node * @param Tree tree data structure to be released
** in the tree. It does not include the Key and Data items * @return none
** which are pointed to by the nodes. This memory is left * @note Exceptions: none
** untouched. * @note History: 5/26/89, DSJ, Created.
** Return: none
** Exceptions: none
** History:
** 5/26/89, DSJ, Created.
*/ */
void FreeKDTree(KDTREE *Tree) {
FreeSubTree(Tree->Root.Left); FreeSubTree(Tree->Root.Left);
memfree(Tree); memfree(Tree);
} /* FreeKDTree */ } /* FreeKDTree */
@ -368,25 +358,20 @@ void FreeKDTree(KDTREE *Tree) {
Private Code Private Code
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
KDNODE *MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index) { /**
/* * This routine allocates memory for a new K-D tree node
** Parameters: * and places the specified Key and Data into it. The
** tree The tree to create the node for * left and right subtree pointers for the node are
** Key Access key for new node in KD tree * initialized to empty subtrees.
** Data ptr to data to be stored in new node * @param tree The tree to create the node for
** Index index of Key to branch on * @param Key Access key for new node in KD tree
** Operation: * @param Data ptr to data to be stored in new node
** This routine allocates memory for a new K-D tree node * @param Index index of Key to branch on
** and places the specified Key and Data into it. The * @return pointer to new K-D tree node
** left and right subtree pointers for the node are * @note Exceptions: None
** initialized to empty subtrees. * @note History: 3/11/89, DSJ, Created.
** Return:
** pointer to new K-D tree node
** Exceptions:
** None
** History:
** 3/11/89, DSJ, Created.
*/ */
KDNODE *MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index) {
KDNODE *NewNode; KDNODE *NewNode;
NewNode = (KDNODE *) Emalloc (sizeof (KDNODE)); NewNode = (KDNODE *) Emalloc (sizeof (KDNODE));
@ -410,10 +395,11 @@ void FreeKDNode(KDNODE *Node) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
// Recursively accumulate the k_closest points to query_point_ into results_. /**
// Parameters: * Recursively accumulate the k_closest points to query_point_ into results_.
// Level level in tree of sub-tree to be searched * @param Level level in tree of sub-tree to be searched
// SubTree sub-tree to be searched * @param SubTree sub-tree to be searched
*/
void KDTreeSearch::SearchRec(int level, KDNODE *sub_tree) { void KDTreeSearch::SearchRec(int level, KDNODE *sub_tree) {
if (level >= tree_->KeySize) if (level >= tree_->KeySize)
level = 0; level = 0;
@ -456,12 +442,13 @@ void KDTreeSearch::SearchRec(int level, KDNODE *sub_tree) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
// Returns the Euclidean distance squared between p1 and p2 for all essential /**
// dimensions. *Returns the Euclidean distance squared between p1 and p2 for all essential
// Parameters: * dimensions.
// k keys are in k-space * @param k keys are in k-space
// dim dimension descriptions (essential, circular, etc) * @param dim dimension descriptions (essential, circular, etc)
// p1,p2 two different points in K-D space * @param p1,p2 two different points in K-D space
*/
FLOAT32 DistanceSquared(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[]) { FLOAT32 DistanceSquared(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[]) {
FLOAT32 total_distance = 0; FLOAT32 total_distance = 0;
@ -488,10 +475,10 @@ FLOAT32 ComputeDistance(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[]) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
// Return whether the query region (the smallest known circle about /// Return whether the query region (the smallest known circle about
// query_point_ containing results->k_ points) intersects the box specified /// query_point_ containing results->k_ points) intersects the box specified
// between lower and upper. For circular dimensions, we also check the point /// between lower and upper. For circular dimensions, we also check the point
// one wrap distance away from the query. /// one wrap distance away from the query.
bool KDTreeSearch::BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper) { bool KDTreeSearch::BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper) {
FLOAT32 *query = query_point_; FLOAT32 *query = query_point_;
FLOAT64 total_distance = 0.0; FLOAT64 total_distance = 0.0;
@ -530,20 +517,21 @@ bool KDTreeSearch::BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
// Walk a tree, calling action once on each node. /**
// * Walk a tree, calling action once on each node.
// Parameters: *
// tree root of the tree being walked. * Operation:
// action action to be performed at every node * This routine walks thru the specified sub_tree and invokes action
// context action's context * action at each node as follows:
// sub_tree ptr to root of subtree to be walked * action(context, data, level)
// level current level in the tree for this node * data the data contents of the node being visited,
// Operation: * level is the level of the node in the tree with the root being level 0.
// This routine walks thru the specified sub_tree and invokes action * @param tree root of the tree being walked.
// action at each node as follows: * @param action action to be performed at every node
// action(context, data, level) * @param context action's context
// data the data contents of the node being visited, * @param sub_tree ptr to root of subtree to be walked
// level is the level of the node in the tree with the root being level 0. * @param level current level in the tree for this node
*/
void Walk(KDTREE *tree, void_proc action, void *context, void Walk(KDTREE *tree, void_proc action, void *context,
KDNODE *sub_tree, inT32 level) { KDNODE *sub_tree, inT32 level) {
(*action)(context, sub_tree->Data, level); (*action)(context, sub_tree->Data, level);
@ -554,7 +542,7 @@ void Walk(KDTREE *tree, void_proc action, void *context,
} }
// Given a subtree nodes, insert all of its elements into tree. /** Given a subtree nodes, insert all of its elements into tree. */
void InsertNodes(KDTREE *tree, KDNODE *nodes) { void InsertNodes(KDTREE *tree, KDNODE *nodes) {
if (nodes == NULL) if (nodes == NULL)
return; return;
@ -564,11 +552,11 @@ void InsertNodes(KDTREE *tree, KDNODE *nodes) {
InsertNodes(tree, nodes->Right); InsertNodes(tree, nodes->Right);
} }
// Free all of the nodes of a sub tree. /** Free all of the nodes of a sub tree. */
void FreeSubTree(KDNODE *sub_tree) { void FreeSubTree(KDNODE *sub_tree) {
if (sub_tree != NULL) { if (sub_tree != NULL) {
FreeSubTree(sub_tree->Left); FreeSubTree(sub_tree->Left);
FreeSubTree(sub_tree->Right); FreeSubTree(sub_tree->Right);
memfree(sub_tree); memfree(sub_tree);
} }
} /* FreeSubTree */ }