KD Trees
KD Trees
KD-Trees
We are given a set of points P = {p1 , p2 , … , pn } ⊆ Rd and we wanto to construct a
structure for storing, analyzing and managing points efficiently.We can construct a KD-
Tree in the following manner:
P + = {p ∈ P : pi > m}
P − = {p ∈ P : pi ≤ m}
recursively apply the same to P + and P −
contstruct the node v that stores the pointer to the children, m, i and maybe the
bounding box of P
stopping criterion ∣P ∣ =1
Note: i is called the discriminator, the couple (m, i) defines the splitting plane
KD-Trees 1
since we take every time the median, so we spliit in half, given n points the depth of the
tree is O(logn)
Construction complexity
we are splitting along the median on the discriminator axis, but every time we need to
keep a list of nodes coordinates for every axis sorted and linked between them. this
means that when we split we need to sort the lists again. we have to make d sorting,
and a standard quick algorithm for sorting need O(n log n), this gives us a complexity
of O(d ⋅ n log n). when we apply the recursion we need a time O(dn) for the creation
of the lists and then the recursive step is applied 2 times to the halves of the set, so we
n
get T (n) = O(dn) + 2T ( 2 ), summing up the 2 parts we get that T (n) = O(d ⋅
n log n). More, to store the tree we just need to store the points, so we get a space
complexity of O(n)
longest side kd-tree: we can split along the largest extent of P (v)
KD-Trees 2
NOTE: P (v) is the set of points into the region of the node v, in a certain way like the
square of a point for the octrees
Applications
the nearest neighbors problem
The nearest neighbor problem is a classic problem in computational geometry, which
asks for the closest point to a given point in a set of points. In other words, given a set
of points in some space P ⊆ Rd , and a query point q ∈ Rd , the nearest neighbor
problem is to determine which point in the set p∗ is closest to the query point, i.e. p∗ ∈
P ∣∀p ∈ P : ∥p∗ − q∥ ≤ ∥p − q∥.
ANSATZ
1. Start with a ball centered at the query point with an infinitely large radius.
2. Begin at the root node and move down the tree. At each node, first check if the
point in that node is closer to the query point than the radius of the ball. If it is,
KD-Trees 3
update the radius of the ball to be the distance from the query point to the current
node.
3. Decide which of the two child nodes to move to by comparing the splitting
coordinate of the current node with the corresponding coordinate of the query point.
If the point's coordinate is less than the current node's, move to the left child,
otherwise move to the right.
4. After reaching a leaf node, backtrack to check the other half-space, but only if it
could intersect with your ball. we can quickly determine this by seeing if the distance
from the splitting coordinate to the query point is less than the radius of the ball.
5. Repeat this process until we have traversed all relevant areas of the tree. The
current best match is the nearest neighbor, and the final radius of the ball is the
distance to the nearest neighbor.
This process is also known as a "priority search". The ball shrinks as better matches
are found, and this shrinking ball helps to avoid unnecessary searches of branches of
the tree that fall outside of the ball. This can drastically improve performance, especially
in higher dimensions.
NN(v, p, r):
input: p=current candidate, r=ball radius
output: new candidate(p, r)
precondition:Ball(q, r) overlaps R(v)
if v is leaf:
p':=nearest neighbor of P(v) to q
r':= ||p'-q||
if r'<r:return (p', r')
if qi<=m:
p, r = NN(vl, p, r)
if Ball(q, r) overlaps R(vr):
p, r =NN(vr, p, r)
else:
p, r = NN(vr, p, r)
if Ball(q, r) overlaps R(vl):
p, r =NN(vl, p, r)
KD-Trees 4
Texture syntesis
Given a texture I , i.e. an image where we can zoom in a particular window and obtain
the same image we want to obtain a bigger texture T
We can define an input pixel pi and an output pixel po , N(p) is the neighborhood
around p
To compute d(N(pi), N(po)) we can use an euclidean metric, and to find the pi in the
third line we can use a KD-tree over the vector of pixels of N(pi )
T
Vector of pixels: [r1 g1 b1 … rn gn bn ]
Some observations:
KD-Trees 5
Possible solution: image pyramid
The scan order and the shape of the neighborhoods should match
def pushDownRope(v,w,d)
if the splitting plane of w is perpendicular to d:
if d in {right, top, back}:
return w1
else:
return w2
else if the splitting plane of w is parallel to d:
if the side of R(w) is in direction opposite to d:
return w1
else: return w2
return w
KD-Trees 6
def propagateRows(v):
if v is leaf:
return v
for all d in D:
if a rope from v to w in d exists
w' =w
do until w''=w':
w''= pushdownrope(v,w', d)
replace the rope in v with the rope from v to w' in d
d=right, top or front if the splitting axe of v is x, y or x
v1/v2=left/right child of v
copy the existing ropes of v in v1/v2
set rhe ropes from v1 to v2 in d and its opposite
propagateRopesDown(v1)(v2)
def followRay():
p0 = start point of the ray
v = root, p=p0
while v is not null:
while v is an inner node:
if p is left of the split plane:
v=v1
else:
v=v2
p'=closest interception point of the ray wiith the triangles in v
if the interception exists and is inside R(v):
return p'
p=exit point of the ray out of v
d=direction of the exit
if exists a rope fron v to w in d:
v=w
else:
v=null
return null
Cool material
http://groups.csail.mit.edu/graphics/classes/6.838/S98/meetings/m13/kd.html
https://www.cse.iitd.ac.in/~ssen/cs852/scribe/RangeQueries.pdf
https://users.cs.utah.edu/~lifeifei/cs6931/kdtree.pdf
KD-Trees 7