A visualization of a 3D Z-order curve. Doesn't really work on mobile - use the mouse to rotate the view.
A friend of mine asked me about optimizing matrix multiplication. One way to obtain better cache locality is to use space filling curves.
I made this visualization using WGLMakie and JSServe.jl in Julia.
We can convert between points in \(\{0,\ldots,2^{3 \cdot n}-1\}\) and \(\left(\{0,\ldots,2^n-1\}\right)^3\) by interleaving the bits.
This is described in more detail on the Wikipedia page.
The zoc2p
function implements this mapping.
function zoc2p(zoc, digits_per_coordinate, dim)
p = digits(zoc, base=2, pad=dim * digits_per_coordinate)
mapslices(reshape(p, :, digits_per_coordinate); dims=2) do x
sum(2^(i-1) * x for (i,x) in enumerate(x))
end
end
Here, dim
is the number of dimensions of the z-order curve and digits_per_coordinate
corresponds to \(n\).
We then enumerate all points in \(\{0,\ldots,2^{3 \cdot n}-1\}\) and send them through the function to obtain the corresponding point in 3D space:
v = vcat([zoc2p(i, digits_per_coordinate, dim)' for i=0:2^(digits_per_coordinate*dim)-1]...)
Here's the full plotting function:
function plt()
set_theme!(resolution=(800, 800))
app = App() do s::Session
digits_per_coordinate = 3
dim = 3
v = vcat([zoc2p(i, digits_per_coordinate, dim)' for i=0:2^(digits_per_coordinate*dim)-1]...)
xs = v[:, 1]
ys = v[:, 2]
zs = v[:, 3]
progress = (0:length(xs)-1)./(length(xs)-1)
fig, ax, splot = lines(xs, ys, zs, linewidth=50, color=progress, colormap=:rainbow)
DOM.div(fig)
end
page = Page(offline=true, exportable=true)
page_html = sprint() do io
show(io, MIME"text/html"(), page)
show(io, MIME"text/html"(), app)
end
write("export/index.html", page_html)
end
JSServe
then allows us to export the plot as a static webpage, and it's the one you see above embedded as an iframe
!