Quad Trees
Quad Trees
QuadTrees
3. If a box does not contain any points, do not create a child for it
QuadTrees 1
dimensional area. For instance, if you wanted to find the closest
point to given coordinates, you can do it using quadtrees.
(https://www.geeksforgeeks.org/quad-tree/)
https://en.wikipedia.org/wiki/Quadtree#/media/File:Quadtree_compression_of_an
_image.gif
A cool structure that comes helpful is a tree, expecially one that divides the space is
four equal regions.
QuadTrees 2
Definitions
Quad tree
A quad tree is a tree where each inner node has 4 children and each of them
corresponds to a square. It is an unbalanced structure, meaning that every node must
either be an inner node and have exactly 4 children, or a leaf node and have 0 children
The actual subdivision is made fom the top left corner spinning in anti-clockwise verse
QuadTrees 3
Square of a node
Given a node v, q(v) = [xv , x′v ] × [yv , yv′ ], so the square of a node is the actual
region of the space inside the actual square formed by [xv , x′v ] × [yv , yv′ ]
Q(P ) := node v : {
v is leave if ∣P ∣ ≤ 1
v is inner node else
With childrens:
VUL = {p ∈ P : xp < 12 (xv − x′v ), yp < 12 (yv − yv′ )}
VU R = {p ∈ P : xp > 12 (xv − x′v ), yp < 12 (yv − yv′ )}
1 1
QuadTrees 4
VB L = {p ∈ P : xp < 12 (xv − x′v ), yp > 12 (yv − yv′ )}
VBR = {p ∈ P : xp > 12 (xv − x′v ), yp > 12 (yv − yv′ )}
In the second case it’s possible to use a less deep tree, since the points are more
uniformely scattered around, in the first case it’s impossible to locate the position of a
point without using almost a depth 3
Lemma
Let P be a set of points in R2 , s be the side length of q(Root), and c ∈ R s.t.:
c = min{∥pi − pj ∥ : pi , pj ∈ P , i =
j}, so c is the maximum distance between 2
points in a node, or also the distance between the 2 closest points, then, it follows for
the depth d of the tree:
3
d ≤ log 2 ( sc ) + 2
Proof
QuadTrees 5
if we split in half a square with side lenght s a number i of times, the side of each sub
square is long exactly 2si
so we can say that the maximum distance between two points in the same square
occours when they are in the deepest division(last level)and they are on the opposite
vertices of the square, this distance is the diagonal of the square, having size 2⋅
2s
edgeLen, and since edgeLen is 2si , we obtain 2i
. if we now take every other
′
disctance between points c we can say that
2s 2s 2s
2i
≥ c′ ≥ c ⇒ c
≥ 2i ⇒ i ≤ log 2 c
⇒ i ≤ log 2 s
c
+ log 2 2⇒i≤
log 2 sc + 12
this is true for inner nodes, but in the leaves we need to add another subdivision to i,
bringing the depth to i ≤ log 2 sc + 12 + 1 = log 2 sc + 32
QuadTrees 6
∀v, v′ s.t. v′ is a neighbor of v, ∣depth(v′ ) − depth(v)∣ ≤ 1
turning a general quad tree to a balanced one can be done in the same time of building
a quad tree, so the conversion can be done also after the creation, since
In order to make a tree balanced we need to check for every leaf if it needs to be split,
comparing its depth with the neighbors depth, then check if its neighbors should be split
too and in case apply the split
Lemma
^ is the balanced quad tree for Q, then Q
Let Q be a quad tree with m nodes, Q ^ has
O(m) nodes that could be constructed in time O(m(d+1))
Proof
QuadTrees 7
being D(v) the depth of the subtree with root the node v, we can assume that
D(leafNode) = 0. For each node with D(v) ≥ 2 we need to split every neighbor
node with depth < 2 only one time. the splitting will always be propagated in the
direction of the node we mentioned, so we are never propagating the splitting operation
through the not neighbors nodes, resultingin a maximum number of splits of m.
for the time complexity we can affirm that every “old node” that gets split introduces a
number of “new nodes”≤ 8 ⋅ 4, where 4 is the number of children per node, and 8 is the
maximm number of neighbors a node can have. ath this point the number of splits
depends from the depth of the tree, including the number of leaves, so d+1, so the worst
possible case is when we have to traverse for every node the whole tree, bringing us to
a complexity of O(m(d+1))
Complexity
A quad tree with depth d and n points has a time complexity of O((d+1)n) and a space
complexity of O((d+1)n)
Proof
Space complexity
In the worst case we will build a tree with 4 children for each node, until the leaves, and
have all the leaves balanced on the same level. let’s consider the number of nodes for
each level
0 1 1
1 4 1+4=5
2 16 5+16=21
3 64 21+64=85
… … …
d−1
d-1 4 d−1 ∑ 4i
i=0
QuadTrees 8
#nodesInLeveli = 3 ⋅ #sumOfNodesUntilLevel(i − 1) + 1
and then going through all the levels until level d-1 we obtain that #nodes ≤ n(d −
1) + 2n, where the 2n is because the quadruplet to exist needs to have minimum 2
levels with almost a point inside each
Time complexity
Given m points inside the square q(v) of a node v the time to reach the node T(v)=O(m)
and since the number of points in each level must be ≤ n, being n the total number of
points, and we have d-1 levels the time complexity is O((d-1)n).
Neighbors finding
Given a node v we want to find one neighbor north, south, west or east v’ of v, fordoing
so we search for a neighbor such that depth(v’) ≤ depth(v)
def northNeighbor(v):
if v is root: #base step
return null
#at this point we know the parent of v exist
if parent(v).LLChild == v:
return parent(v).ULChild
if parent(v).LRChild == v:
return parent(v).URChild
#at this point we know that the neighbor of v is not child of the same parent
u = northNeighbor(parent(v))
if u is null or isLeaf(u):
return u #will eventually reach the base step if v is on the top edge
if parent(v).ULChild == v:
return u.LLChid
if parent(v).URChild == v:
return u.LRChid
#this method does not have a return for every path, also if programmatically incorrect,
#it's almost impossible to reach this point
def southNeighbor(v):
if v is root: #base step
return null
#at this point we know the parent of v exist
if parent(v).ULChild == v:
return parent(v).LLChild
QuadTrees 9
if parent(v).URChild == v:
return parent(v).LRChild
#at this point we know that the neighbor of v is not child of the same parent
u = southNeighbor(parent(v))
if u is null or isLeaf(u):
return u #will eventually reach the base step if v is on the top edge
if parent(v).LLChild == v:
return u.ULChid
if parent(v).LRChild == v:
return u.URChid
#this method does not have a return for every path, also if programmatically incorrect,
#it's almost impossible to reach this point
def eastNeighbor(v):
if v is root: #base step
return null
#at this point we know the parent of v exist
if parent(v).LLChild == v:
return parent(v).LRChild
if parent(v).ULChild == v:
return parent(v).URChild
#at this point we know that the neighbor of v is not child of the same parent
u = eastNeighbor(parent(v))
if u is null or isLeaf(u):
return u #will eventually reach the base step if v is on the top edge
if parent(v).URChild == v:
return u.ULChid
if parent(v).LRChild == v:
return u.LLChid
#this method does not have a return for every path, also if programmatically incorrect,
#it's almost impossible to reach this point
def westNeighbor(v):
if v is root: #base step
return null
#at this point we know the parent of v exist
if parent(v).LRChild == v:
return parent(v).LLChild
if parent(v).URChild == v:
return parent(v).ULChild
#at this point we know that the neighbor of v is not child of the same parent
u = westNeighbor(parent(v))
if u is null or isLeaf(u):
return u #will eventually reach the base step if v is on the top edge
if parent(v).ULChild == v:
return u.URChid
if parent(v).LLChild == v:
return u.LRChid
QuadTrees 10
#this method does not have a return for every path, also if programmatically incorrect,
#it's almost impossible to reach this point
Quad-Trees in higher
dimension
According to the dimension we can
define:
2 dimensions: QuadTree
3 dimensions OctTree
BinTree
every node has 2 children, so the tree is a binary tree. We split horizontally/vertically in
an alternate manner, in this case for every 2 node layers we have a node in the original
quadtree
QuadTrees 11
N 2 -Tree
generalization of the binTree, evey time we split the tree in N equal children
QuadTrees 12
it could be considered as the missing ring between a quad tree and a full grid
QuadTrees 13
it is really well suited to generate hierarchical partitioning of spheres in 3d, since we can
inscribe a sphere in a tetrahedron, then project the sphere points on the tethraedron
and we obtain a triangle quad tree and have the minimum distorsion possible
QuadTrees 14
Storing of a QuadTree
The simplest way to store a quad tree is to use the bottom left vertex. we can store the
coordinates of the point and its level, so for every node we will have: v =
(x, y, l), x, y ∈ [0, U], where U is the side lenght of the quare of the root
in this fashon we will need 2d + log 2 d bits per each node
QuadTrees usages
🗓 Image compression
🪆 Dynamic meshing
⚾ IsoSurfaces
Good resources
https://jimkang.com/quadtreevis/
https://www.geeksforgeeks.org/quad-tree/
https://graphics.stanford.edu/courses/cs468-06-fall/Slides/steve.pdf
https://i11www.iti.kit.edu/_media/teaching/winter2015/compgeom/algogeom-ws15-vl11-
printable.pdf
https://www.jordansavant.com/book/algorithms/quadtree.md
https://iq.opengenus.org/quadtree/
https://personal.us.es/almar/cg/09quadtrees.pdf
https://ls11-www.cs.tu-dortmund.de/_media/buchin/teaching/akda_ws21/quadtrees.pdf
QuadTrees 15