mp_mosaics
Monstrous Mosaics
|
KDTree class: implemented using Points in Dim dimensional space (given by the template parameter). More...
#include <kdtree.h>
Public Member Functions | |
KDTree (const vector< Point< Dim >> &newPoints) | |
Constructs a KDTree from a vector of Points, each having dimension Dim. More... | |
KDTree (const KDTree< Dim > &other) | |
Copy constructor for KDTree. More... | |
KDTree const & | operator= (const KDTree< Dim > &rhs) |
Assignment operator for KDTree. More... | |
~KDTree () | |
Destructor for KDTree. More... | |
Point< Dim > | findNearestNeighbor (const Point< Dim > &query) const |
Finds the closest point to the parameter point in the KDTree. More... | |
void | printTree (ostream &out=cout, colored_out::enable_t enable_bold=colored_out::COUT, int modWidth=-1) const |
You do not need to modify this function. More... | |
KDTree class: implemented using Points in Dim dimensional space (given by the template parameter).
Constructs a KDTree from a vector of Points, each having dimension Dim.
You need to handle the case that the vector has no Point in it. It should build the tree using recursive helper functions.
Since we know the size of the KDTree at construction, we can represent the tree as a linear structure and building the tree nodes based off this structure efficiently. For testing, we require the following:
KD-trees are created recursively; at any stage of the construction, the median value in the current dimension is selected and a node is created based on it. Then, all the elements in the current subtree are divided up into elements which are less than the median, or greater than the median, and then the subtrees are created recursively. The children pick the median in the next dimension, and repeat until the entire set of inputs has been processed. Successive levels of the tree split on increasing dimensions, modulo the total number: a 3D tree will have levels split by dimension 0, 1, 2, 0, 1, 2, etc.
You will probably want to write a helper function which performs the median selection and partitioning. Maybe you can use a function you already wrote...
newPoints | The vector of points to build your KDTree off of. |
Point< Dim > KDTree< Dim >::findNearestNeighbor | ( | const Point< Dim > & | query | ) | const |
Finds the closest point to the parameter point in the KDTree.
This function takes a reference to a template parameter Point and returns the Point closest to it in the tree. We are defining closest here to be the minimum Euclidean distance between elements. Again, if there are ties (this time in distance), they must be decided using Point::operator<(). Recall that an HSLAPixel is defined by three components: hue, saturation, and luminance.
The findNearestNeighbor() search is done in two steps: a search to find the smallest hyperrectangle that contains the target element, and then a back traversal to see if any other hyperrectangle could contain a closer point, which may be a point with smaller distance or a point with equal distance, but a "smaller" point (as defined by operator< in the point class). In the first step, you must recursively traverse down the tree, at each level choosing the subtree which represents the region containing the search element (another place to save some duplicate code?). When you reach the lowest bounding hyperrectangle, then the corresponding node is effectively the "current best" neighbor.
However, it may be the case that a better match exists outside of the containing hyperrectangle. At then end of first step of the search, we start traversing back up the kdtree to the parent node. The current best distance defines a radius which contains the nearest neighbor. During the back-traversal (i.e., stepping out of the recursive calls), you must first check if the distance to the parent node is less than the current radius. If so, then that distance now defines the radius, and we replace the "current best" match. Next, it is necessary to check to see if the current splitting plane's distance from search node is within the current radius. If so, then the opposite subtree could contain a closer node, and must also be searched recursively.
During the back-traversal, it is important to only check the subtrees that are within the current radius, or else the efficiency of the kdtree is lost. If the distance from the search node to the splitting plane is greater than the current radius, then there cannot possibly be a better nearest neighbor in the subtree, so the subtree can be skipped entirely.
You can assume that findNearestNeighbor will only be called on a valid kd-tree.
query | The point we wish to find the closest neighbor to in the tree. |
void KDTree< Dim >::printTree | ( | ostream & | out = cout , |
colored_out::enable_t | enable_bold = colored_out::COUT , |
||
int | modWidth = -1 |
||
) | const |
You do not need to modify this function.
Its implementation is in kdtree_extras.cpp. Prints the KDTree to the terminal in a pretty way.