2022-07-23 08:55:44 +00:00
|
|
|
-- Copyright (c) 2019-2022 David Vogel
|
2019-11-02 20:37:10 +00:00
|
|
|
--
|
|
|
|
-- This software is released under the MIT License.
|
|
|
|
-- https://opensource.org/licenses/MIT
|
|
|
|
|
2022-07-23 08:55:44 +00:00
|
|
|
---@class HilbertLib
|
|
|
|
local Hilbert = {}
|
|
|
|
|
|
|
|
---Rotate/flip quadrant.
|
|
|
|
---@param n integer
|
|
|
|
---@param x integer
|
|
|
|
---@param y integer
|
|
|
|
---@param rx boolean
|
|
|
|
---@param ry boolean
|
|
|
|
---@return integer
|
|
|
|
---@return integer
|
2019-11-02 20:37:10 +00:00
|
|
|
local function hilbertRotate(n, x, y, rx, ry)
|
|
|
|
if not ry then
|
|
|
|
if rx then
|
|
|
|
x = n - 1 - x
|
|
|
|
y = n - 1 - y
|
|
|
|
end
|
|
|
|
|
|
|
|
x, y = y, x
|
|
|
|
end
|
|
|
|
return x, y
|
|
|
|
end
|
|
|
|
|
2022-07-23 08:55:44 +00:00
|
|
|
---Maps t in the range of [0, (2^potSize)^2-1] to a position on the hilbert curve with the side length of 2^potSize (Power of two size).
|
|
|
|
---@param t integer
|
|
|
|
---@param potSize integer
|
|
|
|
---@return integer
|
|
|
|
---@return integer
|
|
|
|
function Hilbert.Map(t, potSize)
|
2019-11-02 20:37:10 +00:00
|
|
|
local size = math.pow(2, potSize)
|
|
|
|
local x, y = 0, 0
|
|
|
|
|
|
|
|
if t < 0 or t >= size * size then
|
2022-07-23 08:55:44 +00:00
|
|
|
error("variable t is outside of the range")
|
2019-11-02 20:37:10 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
for i = 0, potSize - 1, 1 do
|
|
|
|
local iPOT = math.pow(2, i)
|
|
|
|
local rx = bit.band(t, 2) == 2
|
|
|
|
local ry = bit.band(t, 1) == 1
|
|
|
|
if rx then
|
|
|
|
ry = not ry
|
|
|
|
end
|
|
|
|
|
|
|
|
x, y = hilbertRotate(iPOT, x, y, rx, ry)
|
|
|
|
|
|
|
|
if rx then
|
|
|
|
x = x + iPOT
|
|
|
|
end
|
|
|
|
if ry then
|
|
|
|
y = y + iPOT
|
|
|
|
end
|
|
|
|
|
|
|
|
t = math.floor(t / 4)
|
|
|
|
end
|
|
|
|
|
|
|
|
return x, y
|
|
|
|
end
|
2022-07-23 08:55:44 +00:00
|
|
|
|
|
|
|
return Hilbert
|