mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-23 07:43:01 +00:00
//subdivide: reimplement count_chunks
this does the maths properly, so we'e going from O(n³) to O(1) :D //subdivide should get started *so much faster* now :D
This commit is contained in:
parent
85a715a0ea
commit
25e659321a
3 changed files with 91 additions and 10 deletions
|
@ -6,6 +6,8 @@ It's about time I started a changelog! This will serve from now on as the main c
|
||||||
- `//count`: Make numbers human-readable
|
- `//count`: Make numbers human-readable
|
||||||
- Tip: Use a monospace font for the chat window, and the columns will be aligned!
|
- Tip: Use a monospace font for the chat window, and the columns will be aligned!
|
||||||
- Add `//hollow` for hollowing out areas (a step towards parity with Minecraft WorldEdit)
|
- Add `//hollow` for hollowing out areas (a step towards parity with Minecraft WorldEdit)
|
||||||
|
- `//subdivide`: Improve performance of initial chunk counting algorithm - it should get started on the job _much_ quicker now (especially on large regions)
|
||||||
|
- Bugfix: Fix obscure crash in calls to `human_size` ("unknown" will now be returned if passed junk)
|
||||||
|
|
||||||
|
|
||||||
## v1.10 (16th January 2021)
|
## v1.10 (16th January 2021)
|
||||||
|
|
76
test_count_chunks.lua
Normal file
76
test_count_chunks.lua
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
--[[
|
||||||
|
test_count_chunks
|
||||||
|
|
||||||
|
Test script for the new count_chunks implementation for //subdivide.
|
||||||
|
The new implementation does the maths properly and is functionally identical to
|
||||||
|
the previous algorithm - we've tested it with 1000 totally random pos1, pos2,
|
||||||
|
and chunk_size values.
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local function count_chunks(pos1, pos2, chunk_size)
|
||||||
|
local count = 0
|
||||||
|
for z = pos2.z, pos1.z, -chunk_size.z do
|
||||||
|
for y = pos2.y, pos1.y, -chunk_size.y do
|
||||||
|
for x = pos2.x, pos1.x, -chunk_size.x do
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
local function count_chunks_new(pos1, pos2, chunk_size)
|
||||||
|
-- Assume pos1 & pos2 are sorted
|
||||||
|
local dimensions = {
|
||||||
|
x = pos2.x - pos1.x + 1,
|
||||||
|
y = pos2.y - pos1.y + 1,
|
||||||
|
z = pos2.z - pos1.z + 1,
|
||||||
|
}
|
||||||
|
-- print("[new] dimensions", dimensions.x, dimensions.y, dimensions.z)
|
||||||
|
return math.ceil(dimensions.x / chunk_size.x)
|
||||||
|
* math.ceil(dimensions.y / chunk_size.y)
|
||||||
|
* math.ceil(dimensions.z / chunk_size.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local pos1 = { x = 16000, y = 0, z = 16000 }
|
||||||
|
local pos2 = { x = 16100, y = 100, z = 16100 }
|
||||||
|
local count = { x = 7, y = 9, z = 10 }
|
||||||
|
|
||||||
|
print("Reference: ", count_chunks(pos1, pos2, count))
|
||||||
|
print("New: ", count_chunks_new(pos1, pos2, count))
|
||||||
|
|
||||||
|
local ok = 0
|
||||||
|
local failed = false
|
||||||
|
for i=1,1000 do
|
||||||
|
pos1.x = 16000 + math.floor(math.random() * 99)
|
||||||
|
pos1.y = 16000 + math.floor(math.random() * 99)
|
||||||
|
pos1.z = 16000 + math.floor(math.random() * 99)
|
||||||
|
|
||||||
|
pos2.x = 16100 + math.floor(math.random() * 2000)
|
||||||
|
pos2.y = 16100 + math.floor(math.random() * 2000)
|
||||||
|
pos2.z = 16100 + math.floor(math.random() * 2000)
|
||||||
|
|
||||||
|
count.x = math.floor(math.random() * 25) + 1
|
||||||
|
count.y = math.floor(math.random() * 25) + 1
|
||||||
|
count.z = math.floor(math.random() * 25) + 1
|
||||||
|
|
||||||
|
io.write(ok..": ( "..pos1.x..", "..pos1.y..", "..pos1.z.." ) - ( "..pos2.x..", "..pos2.y..", "..pos2.z.." ), size ( ", count.x, ", ", count.y, ", ", count.z, " ) | ")
|
||||||
|
|
||||||
|
local val_ref = count_chunks(pos1, pos2, count)
|
||||||
|
local val_new = count_chunks_new(pos1, pos2, count)
|
||||||
|
|
||||||
|
if val_ref == val_new then
|
||||||
|
print("OK")
|
||||||
|
ok = ok + 1
|
||||||
|
else
|
||||||
|
print("FAIL! ( "..val_ref.." / "..val_new.." )")
|
||||||
|
failed = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
io.write(ok.." ok")
|
||||||
|
if failed then io.write(", 1 failed") end
|
||||||
|
print()
|
|
@ -6,19 +6,22 @@
|
||||||
local wea = worldeditadditions
|
local wea = worldeditadditions
|
||||||
|
|
||||||
-- Counts the number of chunks in the given area.
|
-- Counts the number of chunks in the given area.
|
||||||
-- TODO: Do the maths properly here instead of using a loop - the loop is *very* inefficient - especially for large areas
|
-- Maths is now done properly. Values from this new implementation were tested
|
||||||
|
-- with 1000 random pos1, pos2, and chunk_size combinations and found to be identical.
|
||||||
local function count_chunks(pos1, pos2, chunk_size)
|
local function count_chunks(pos1, pos2, chunk_size)
|
||||||
local count = 0
|
-- Assume pos1 & pos2 are sorted
|
||||||
for z = pos2.z, pos1.z, -chunk_size.z do
|
local dimensions = {
|
||||||
for y = pos2.y, pos1.y, -chunk_size.y do
|
x = pos2.x - pos1.x + 1,
|
||||||
for x = pos2.x, pos1.x, -chunk_size.x do
|
y = pos2.y - pos1.y + 1,
|
||||||
count = count + 1
|
z = pos2.z - pos1.z + 1,
|
||||||
end
|
}
|
||||||
end
|
-- print("[new] dimensions", dimensions.x, dimensions.y, dimensions.z)
|
||||||
end
|
return math.ceil(dimensions.x / chunk_size.x)
|
||||||
return count
|
* math.ceil(dimensions.y / chunk_size.y)
|
||||||
|
* math.ceil(dimensions.z / chunk_size.z)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function merge_stats(a, b)
|
local function merge_stats(a, b)
|
||||||
for key,value in pairs(a) do
|
for key,value in pairs(a) do
|
||||||
if not b[key] then b[key] = 0 end
|
if not b[key] then b[key] = 0 end
|
||||||
|
|
Loading…
Reference in a new issue