Just for fun, how does a 3D Hilbert curve sample the 3D colourspace of RGB? and can it be used to sort colours?
HilbertCurve3D[n]
generates a 3D Hilbert curve of order n
. The code is by Michael Trott from page 93 of The Mathematica Guidebook for Programming.
HilbertCurve3D[n_Integer?Positive] :=
Module[{axiom = "X", recursion = "X" -> {"t", "c", "X", "F", "t", "c", "X", "F",
"X", "q", "F", "t", "d", "d", "X", "F", "X", "w", "F", "p", "d",
"d", "X", "F", "X", "q", "F", "d", "X", "q", "d"},
r = {0, 0, 0}, m = IdentityMatrix[3]},
Prepend[ DeleteCases[ Which[ (*the movements*)
# == "F", r = r + (First /@ m),
# == "B", r = r - (First /@ m);,
# == "w", m = m.{{0, 0, 1}, {0, 1, 0}, {-1, 0, 0}};,
# == "t", m = m.{{0, 0, -1}, {0, 1, 0}, {1, 0, 0}};,
# == "p", m = m.{{0, -1, 0}, {1, 0, 0}, {0, 0, 1}};,
# == "q", m = m.{{0, 1, 0}, {-1, 0, 0}, {0, 0, 1}};,
# == "c", m = m.{{1, 0, 0}, {0, 0, 1}, {0, -1, 0}};,
# == "d", m = m.{{1, 0, 0}, {0, 0, -1}, {0, 1, 0}};,
True, Null] & /@ Flatten[Nest[# /. recursion &,
Characters[axiom], n]], Null], {0, 0, 0}]]
HilberCurve3D[n]
returns all points with integer coordinates within a cube spanning $\{0,0,0\}$ to $(2^n-1)*\{1,1,1\}$. Normalize by dividing by $2^n-1$ so that all coordinates range between 0 and 1. The number of samples in HilbertCurve3D[n]
is $2^{3n}$.
The following code finds points on the Hilbert curve nearest the random colours, and sorts the colours based on the point position along the curve.
Block[{randomColours, rgbList, n = 3, hcurve, nearestFunction,
nearestHilbertIndex, sortedColours},
(* make random colours *)
randomColours = RandomColor[RGBColor[_, _, _], 500];
(* create triples of rgb values, ranging 0 to 1 *)
rgbList = Apply[List, randomColours, 1];
(* normalized 3D Hilbert curve ranging 0 to 1 *)
hcurve = HilbertCurve3D[n]/(2^n-1.);
(* form nearest function for Hilbert curve *)
nearestFunction = Nearest[hcurve -> Automatic];
(* find index of Hilbert point nearest each random colour *)
nearestHilbertIndex = Flatten[nearestFunction[rgbList], 1];
(* sort random colours *)
sortedColours = SortBy[
Transpose[{randomColours, nearestHilbertIndex}], Last][[All, 1]];
(* display random and sorted colours *)
{Image[Table[randomColours, {100}], ImageSize -> 400],
Image[Table[sortedColours, {100}], ImageSize -> 400]} // Column
]

