mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-12-29 14:54:56 +00:00
95 lines
2.8 KiB
Lua
95 lines
2.8 KiB
Lua
|
--- Creates a (normalised) box convolutional kernel.
|
||
|
-- Larger box kernels will obviously be slower, but will produce a more blurred
|
||
|
-- effect (i.e. smoother terrain).
|
||
|
-- @param width number The width of the kernel.
|
||
|
-- @param height number The height of the kernel.
|
||
|
-- @return The resulting kernel as a ZERO-indexed list of numbers.
|
||
|
function worldeditadditions.conv.kernel_box(width, height)
|
||
|
local result = {}
|
||
|
local total = 0
|
||
|
for y = 0, height do
|
||
|
for x = 0, width do
|
||
|
result[(y*width) + x] = 1
|
||
|
total = total + 1
|
||
|
end
|
||
|
end
|
||
|
-- Ensure that everything sums up to 1
|
||
|
for i = 0, #result do
|
||
|
result[i] = result[i] / total
|
||
|
end
|
||
|
return result
|
||
|
end
|
||
|
|
||
|
--- Computes the Lth line of Pascal's triangle.
|
||
|
-- More information: https://en.wikipedia.org/wiki/Pascal%27s_triangle
|
||
|
-- There are probably more efficient ways to it that don't repeat themselves as
|
||
|
-- much, but this is my solution.
|
||
|
-- @param l number The 1-indexed row of Pascal's Triangle to return.
|
||
|
-- @return number[] A ZERO-indexed list of numbers in the specified row of Pascal's Triangle.
|
||
|
local function pascal(l)
|
||
|
local prev = {}
|
||
|
prev[0] = 1
|
||
|
if l == 1 then return prev end
|
||
|
prev[1] = 1
|
||
|
if l == 2 then return prev end
|
||
|
local length_last = 2
|
||
|
|
||
|
for n=3, l do
|
||
|
local next = {}
|
||
|
for i=0, length_last do
|
||
|
if i == 0 or i == length_last then
|
||
|
next[i] = 1
|
||
|
else
|
||
|
next[i] = prev[i - 1] + prev[i]
|
||
|
end
|
||
|
end
|
||
|
prev = next
|
||
|
length_last = length_last + 1
|
||
|
end
|
||
|
return prev
|
||
|
end
|
||
|
|
||
|
--- Creates a pascal convolutional kernel.
|
||
|
-- Larger pascal kernels will obviously be slower, but will produce a more blurred
|
||
|
-- effect (i.e. smoother terrain).
|
||
|
-- @param width number The width of the kernel.
|
||
|
-- @param height number The height of the kernel.
|
||
|
-- @param normalise=true bool Whether to normalise the resulting kernel (default: true)
|
||
|
-- @return The resulting kernel as a ZERO-indexed list of numbers.
|
||
|
function worldeditadditions.conv.kernel_pascal(width, height, normalise)
|
||
|
if normalise == nil then normalise = true end
|
||
|
|
||
|
local result = {}
|
||
|
local pascal_width = width
|
||
|
local height_middle = ((height - 2) / 2)
|
||
|
local total = 0
|
||
|
for y = 0, height-1 do
|
||
|
local pascal_numbers = pascal(pascal_width)
|
||
|
local pascal_start = (pascal_width - width) / 2
|
||
|
for x = 0, width - 1 do
|
||
|
result[(y*width) + x] = pascal_numbers[pascal_start + x]
|
||
|
total = total + pascal_numbers[pascal_start + x]
|
||
|
end
|
||
|
|
||
|
if y > height_middle then pascal_width = pascal_width - 2
|
||
|
else pascal_width = pascal_width + 2 end
|
||
|
end
|
||
|
|
||
|
if normalise then
|
||
|
for k,v in pairs(result) do
|
||
|
result[k] = result[k] / total
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return result
|
||
|
end
|
||
|
|
||
|
-- print("box, 5x5")
|
||
|
-- print_2d(kernel_box(5, 5), 5)
|
||
|
-- print("pascal, 5x5")
|
||
|
-- print_2d(kernel_pascal(5, 5), 5)
|
||
|
-- print("pascal, 7x7")
|
||
|
-- print_2d(kernel_pascal(7, 7), 7)
|
||
|
-- print("pascal, 9x9")
|
||
|
-- print_2d(kernel_pascal(9, 9), 9)
|