Given a set of 3D points, the problem of range search takes a 3D range, such as a 3D box or a 3D ball, and reports all points inside the range. In this assignment, you will implement a data structure called range tree. Wikipedia provides a pretty good introduction on range tree, which in nutshell is a k-dimensional binary tree. In this assignment k=3. Range tree allows efficient orthogonal range search.
This picture shows an example of 2D range search.
1D range tree is basically a balanced binary search tree.
Searching in a range tree requires you to determine the split node where the paths to x and x' splits. Here x and x' are the lower and upper bound of the range. The example below shows the range search of [6, 16]. The split node is node 14.
An example of a 2D range tree is shown below. 2D Range tree has two levels
We can perform the 2D range query similarly by only visiting the associated binary search tree on y-coordinate of the sub-tree of v, whose x-coordinate lies in the x-interval of the query rectangle
Example input. This will be stored in a file.
Format
10 0.366 0.136 0.009 0.082 0.791 0.832 0.138 0.968 0.391 0.414 0.785 0.883 0.546 0.044 0.133 0.513 0.612 0.466 0.415 0.640 0.099 0.199 0.999 0.086 0.896 0.835 0.860 0.091 0.719 0.772 0.25 0.75 0.25 0.75 0.25 0.75 0.75 0.25 0.8 0.1 0.9 0.1 0.95 1.75 0.1 0.01 0.1 0.2 exit
Example run.
java rtree < input_file Read in 10 points Query: 0.25 0.75 0.25 0.75 0.25 0.75 Found 1 point 0.513 0.612 0.466 Query: 0.75 0.25 0.8 0.1 0.9 0.1 Found 2 points 0.414 0.785 0.883 0.513 0.612 0.466 Query: 0.95 1.75 0.1 0.01 0.1 0.2 Found 0 point Query: exit bye
Here is a list of classes you should implement. You can add more methods and data members to each of these classes or even add additional classes if necessary.
public class Point3D<T> { public T position[3]; }
public class Range3D<T> { public T min_x, max_x, min_y, max_y, min_z, max_z; }
public class Node<T> { public Node<T> left, right, next_level; public T data; public int dimension; //x:0, y:1, z:2 }
public class RangeTree<T> { private Node< Point3D<T> > root; public void build( Point3D<T> [] points); public LinkedList< Point3D<T> > search( Range3D<T> query ); private Node< Point3D<T> > FindSplitNode( T min, T max); }
In general, it will be useful if you implement 1D range tree first, and then generalized it to 2D and then 3D.
Output format: Find split node Finding the split node for a given range for a given tree
Input: Two values x and x' with x <= x' Output: The node v where the paths to x and x' splits, or the leaf where both paths end. 1. v <- root 2. while v is not a leaf and (x' <= xv or x > xv) { 3. if x' <= xv 4. then v <- lc(v) // left child of the node v 5. else v <- rc(v) // right child of the node v 6. } 7. return v
1D Range Search
Input: A range tree T and a range [x:x'] Output: All points that lie in the range. 1. vsplit <- FindSplitNode(x, x') 2. if vsplit is a leaf 3. then Check if the point stored at vsplit must be reported 4. else // Follow the path to x and report the points in subtrees right of the path 5. v <- leftchild(vsplit) 6. while v is not a leaf 7. do if x <= xv 8. then ReportSubTree(rc(v)) 9. v <- lc(v) 10. else v <- rc(v) 11. Check if the point stored at leaf v must be reported 12. Similarly, follow the path to x'
Build 2D Range Tree
Input: A set P of points in the plane. Output: The root of 2-dimensional tree. 1. if P contains only 1 point 2. then Create a leaf v storing this point and make T the associated structure of v. 3. else Split P into 2 subsets: P_left containing points with x-coordinate <= x_mid, the median x-coordinate, and P_right containing points with x-coordinate >= x_mid 4. vleft <- Build2DRangeTree(Pleft) 5. vright <- Build2DRangeTree(Pright) 6. Create a node v storing xmid, make vleft left child of v & vright right child of v, and make T the associated structure of v 7. v.next_level = a binary search tree T buily on the set Py of y-coordinates of the points in P. Store at leaves of T the points themselves. 8. return v
Build 3D Range Tree
Build3DRangeTree Input: A set P of points in the plane and current dimension D Output: The root of range tree 1. if P contains only 1 point 2. then Create a leaf v storing this point return v 3. else Split P into 2 subsets: mid = the median D-coordinate of P, where D=0 (x), 1 (y), or 2 (z) P_left containing points with D-coordinate <= mid P_right containing points with D-coordinate > mid 4. Create a node v storing mid 5. v.left = Build3DRangeTree(Pleft, D) 6. v.right = Build3DRangeTree(Pright, D) 7. if(D<2) v.next_level = Build2DRangeTree(P, D+1) 8. return v
3D Range Search
search Input: A range R=[x:x', y:y', z:z'] Output: All points that lie in the range. 1. vsplit = FindSplitNode(R) 2. if vsplit is a leaf 3. then Check if the point stored at vsplit must be reported 4. else { // Follow the path to x and report the points in subtrees right of the path 5. v = vsplit.left 6. while(v is not a leaf) do { 7. if R[D*2] <= v.position[D]{ //R[D*2] is the lower bound of dimension D 8. if(D==2) ReportSubTree(v.right) //Z tree 9. else if(v.right is not a leaf) { v.right.next_level.search(R) } else Check if the point stored at leaf v.right must be reported 10. v = v.left } 11. else{ v = v.right} } //end while 12. Check if the point stored at leaf v must be reported 13. v = vsplit.right 14. while(v is not a leaf) do{ 15. if R[D*2+1] >= v.position[D]{ //R[D*2+1] is the upper bound of dimension D 16. if(D==2) ReportSubTree(v.left) //Z tree 17. else if(v.left is not a leaf) v.left.next_level.search(R) else Check if the point stored at leaf v.left must be reported 18. v= v.right} 19. else{ v = v.left } } //end while 20. Check if the point stored at leaf v must be reported 21. }//end if/else
You will submit on blackboard.