I have implemented a quadtree in Mathematica. I am new to coding in a functional programming language like Mathematica, and I was wondering if I could improve this or make i
Here is a more compact version. It uses the same data structure as the original version. The functions splitBox
and insideBox
are essentially the same as well (just written in a slightly different way).
Instead of adding points one-by-one, the initial box contains all the points at the beginning so there is no need for the qtInsert
routines. In each recursion step, the boxes containing more than one point are split and the points are distributed over the sub-boxes. This means that all nodes with more than one point are leafs so there is no need to check for that either.
qtMakeNode[bb_, pts_] := {{}, {}, {}, {}, qtbb @@ bb, pts}
splitBox[bx_] := splitBox[{min_, max_}] := {min + #, max + #}/2 & /@
Tuples[Transpose[{min, max}]]
insideBox[pt_, bb_] := bb[[1, 1]] <= pt[[1]] <= bb[[2, 1]] &&
bb[[1, 2]] <= pt[[2]] <= bb[[2, 2]]
distribute[qtree_] := Which[
Length[qtree[[6]]] == 1,
(* no points in node -> return node unchanged *)
qtree,
Length[qtree[[6]]] == 1,
(* one point in node -> replace head of point with qtpt and return node *)
ReplacePart[qtree, 6 -> qtpt @@ qtree[[6, 1]]],
Length[qtree[[6]]] > 1,
(* multiple points in node -> create sub-nodes and distribute points *)
(* apply distribute to sub-nodes *)
Module[{spl = splitBox[qtree[[5]]], div, newtreelist},
div = Cases[qtree[[6]], a_ /; insideBox[a, #], 1] & /@ spl;
ReplacePart[qtree,
Join[Table[i -> distribute[qtMakeNode[spl[[i]], div[[i]]]], {i, 4}],
{6 -> {}}]]]]
Example (using the original version of qtDraw
):
len = 50;
pts = RandomReal[{0, 2}, {len, 2}];
qt = makeTree[qtMakeNode[{{0.0, 0.0}, {2.0, 2.0}}, pts]];
qtDraw[qt]
Result: