Bound2, bound3: Add tests and fix several major bugs so that those tests pass.

This commit is contained in:
mcc 2018-01-27 00:46:56 -05:00
parent c9cacf5d58
commit 7c18a65695
4 changed files with 416 additions and 9 deletions

View File

@ -8,10 +8,10 @@ local bound2 = {}
local bound2_mt = {}
-- Private constructor.
local function new(x, y)
local function new(min, max)
return setmetatable({
-- min: vec2, minimum value for each component
-- max: vec2, maximum value for each component
min=min, -- min: vec2, minimum value for each component
max=max, -- max: vec2, maximum value for each component
}, bound2_mt)
end
@ -25,7 +25,7 @@ if type(jit) == "table" and jit.status() then
end
end
vec2.zero = new(vec2.zero, vec2.zero)
bound2.zero = new(vec2.zero, vec2.zero)
--- The public constructor.
-- @param min Can be of two types: </br>
@ -74,7 +74,7 @@ end
-- @tparam vec2 new size
-- @treturn bound2 resized bound
function bound2.with_size(a, size)
return vec2.new(a.min, a.min + size)
return bound2.new(a.min, a.min + size)
end
--- Get half-size of bounding box as a vector. A more correct term for this is probably "apothem"
@ -96,7 +96,7 @@ end
-- @tparam vec2 new center
-- @treturn bound2 Bound with same size as input but different center
function bound2.with_center(a, center)
return bound2.offset(a, a:center() - center)
return bound2.offset(a, center - a:center())
end
--- Resize bounding box from center
@ -155,6 +155,10 @@ end
bound2_mt.__index = bound2
bound2_mt.__tostring = bound2.to_string
function bound2_mt.__call(_, a, b)
return bound2.new(a, b)
end
if status then
ffi.metatype(new, bound2_mt)
end

View File

@ -25,7 +25,7 @@ if type(jit) == "table" and jit.status() then
end
end
vec3.zero = new(vec3.zero, vec3.zero)
bound3.zero = new(vec3.zero, vec3.zero)
--- The public constructor.
-- @param min Can be of two types: </br>
@ -74,7 +74,7 @@ end
-- @tparam vec3 new size
-- @treturn bound3 resized bound
function bound3.with_size(a, size)
return vec3.new(a.min, a.min + size)
return bound3.new(a.min, a.min + size)
end
--- Get half-size of bounding box as a vector. A more correct term for this is probably "apothem"
@ -96,7 +96,7 @@ end
-- @tparam vec3 new center
-- @treturn bound3 Bound with same size as input but different center
function bound3.with_center(a, center)
return bound3.offset(a, a:center() - center)
return bound3.offset(a, center - a:center())
end
--- Resize bounding box from center
@ -155,6 +155,10 @@ end
bound3_mt.__index = bound3
bound3_mt.__tostring = bound3.to_string
function bound3_mt.__call(_, a, b)
return bound3.new(a, b)
end
if status then
ffi.metatype(new, bound3_mt)
end

180
spec/bound2_spec.lua Normal file
View File

@ -0,0 +1,180 @@
local bound2 = require "modules.bound2"
local vec2 = require "modules.vec2"
local DBL_EPSILON = require("modules.constants").DBL_EPSILON
describe("bound2:", function()
it("creates an empty bound2", function()
local a = bound2()
assert.is.equal(0, a.min.x)
assert.is.equal(0, a.min.y)
assert.is.equal(0, a.max.x)
assert.is.equal(0, a.max.y)
end)
it("creates a bound2 from vec2s", function()
local a = bound2(vec2(1,2), vec2(4,5))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
end)
it("creates a bound2 using new()", function()
local a = bound2.new(vec2(1,2), vec2(4,5))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
end)
it("creates a bound2 using at()", function()
local a = bound2.at(vec2(4,5), vec2(1,2))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
end)
it("clones a bound2", function()
local a = bound2(vec2(1,2), vec2(4,5))
local b = a:clone()
a.max = new vec2(9,9)
assert.is.equal(a.min, b.min)
assert.is.not_equal(a.max, b.max)
end)
it("uses bound2 check()", function()
local a = bound2(vec2(4,2), vec2(1,5)):check()
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
end)
it("queries a bound2 size", function()
local a = bound2(vec2(1,2), vec2(4,6))
local v = a:size()
local r = a:radius()
assert.is.equal(3, v.x)
assert.is.equal(4, v.y)
assert.is.equal(1.5, r.x)
assert.is.equal(2, r.y)
end)
it("sets a bound2 size", function()
local a = bound2(vec2(1,2), vec2(4,5))
local b = a:with_size(vec2(1,1))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
assert.is.equal(1, b.min.x)
assert.is.equal(2, b.min.y)
assert.is.equal(2, b.max.x)
assert.is.equal(3, b.max.y)
end)
it("queries a bound2 center", function()
local a = bound2(vec2(1,2), vec2(3,4))
local v = a:center()
assert.is.equal(2, v.x)
assert.is.equal(3, v.y)
end)
it("sets a bound2 center", function()
local a = bound2(vec2(1,2), vec2(3,4))
local b = a:with_center(vec2(1,1))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.max.x)
assert.is.equal(4, a.max.y)
assert.is.equal(0, b.min.x)
assert.is.equal(0, b.min.y)
assert.is.equal(2, b.max.x)
assert.is.equal(2, b.max.y)
end)
it("sets a bound2 size centered", function()
local a = bound2(vec2(1,2), vec2(3,4))
local b = a:with_size_centered(vec2(4,4))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.max.x)
assert.is.equal(4, a.max.y)
assert.is.equal(0, b.min.x)
assert.is.equal(1, b.min.y)
assert.is.equal(4, b.max.x)
assert.is.equal(5, b.max.y)
end)
it("insets a bound2", function()
local a = bound2(vec2(1,2), vec2(5,10))
local b = a:inset(vec2(1,2))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(5, a.max.x)
assert.is.equal(10, a.max.y)
assert.is.equal(2, b.min.x)
assert.is.equal(4, b.min.y)
assert.is.equal(4, b.max.x)
assert.is.equal(8, b.max.y)
end)
it("outsets a bound2", function()
local a = bound2(vec2(1,2), vec2(5,6))
local b = a:outset(vec2(1,2))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(5, a.max.x)
assert.is.equal(6, a.max.y)
assert.is.equal(0, b.min.x)
assert.is.equal(0, b.min.y)
assert.is.equal(6, b.max.x)
assert.is.equal(8, b.max.y)
end)
it("offsets a bound2", function()
local a = bound2(vec2(1,2), vec2(5,6))
local b = a:offset(vec2(1,2))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(5, a.max.x)
assert.is.equal(6, a.max.y)
assert.is.equal(2, b.min.x)
assert.is.equal(4, b.min.y)
assert.is.equal(6, b.max.x)
assert.is.equal(8, b.max.y)
end)
it("tests for points inside bound2", function()
local a = bound2(vec2(1,2), vec2(4,5))
assert.is_true(a:contains(vec2(2,3)))
assert.is_not_true(a:contains(vec2(0,3)))
assert.is_not_true(a:contains(vec2(5,3)))
assert.is_not_true(a:contains(vec2(2,1)))
assert.is_not_true(a:contains(vec2(2,6)))
assert.is_not_true(a:contains(vec2(2,3)))
assert.is_not_true(a:contains(vec2(2,3)))
end)
it("checks for bound2.zero", function()
assert.is.equal(0, bound2.zero.min.x)
assert.is.equal(0, bound2.zero.min.y)
assert.is.equal(0, bound2.zero.max.x)
assert.is.equal(0, bound2.zero.max.y)
end)
end)

219
spec/bound3_spec.lua Normal file
View File

@ -0,0 +1,219 @@
local bound3 = require "modules.bound3"
local vec3 = require "modules.vec3"
local DBL_EPSILON = require("modules.constants").DBL_EPSILON
describe("bound3:", function()
it("creates an empty bound3", function()
local a = bound3()
assert.is.equal(0, a.min.x)
assert.is.equal(0, a.min.y)
assert.is.equal(0, a.min.z)
assert.is.equal(0, a.max.x)
assert.is.equal(0, a.max.y)
assert.is.equal(0, a.max.z)
end)
it("creates a bound3 from vec3s", function()
local a = bound3(vec3(1,2,3), vec3(4,5,6))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
assert.is.equal(6, a.max.z)
end)
it("creates a bound3 using new()", function()
local a = bound3.new(vec3(1,2,3), vec3(4,5,6))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
assert.is.equal(6, a.max.z)
end)
it("creates a bound3 using at()", function()
local a = bound3.at(vec3(4,5,6), vec3(1,2,3))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
assert.is.equal(6, a.max.z)
end)
it("clones a bound3", function()
local a = bound3(vec3(1,2,3), vec3(4,5,6))
local b = a:clone()
a.max = new vec3(9,9,9)
assert.is.equal(a.min, b.min)
assert.is.not_equal(a.max, b.max)
end)
it("uses bound3 check()", function()
local a = bound3(vec3(4,2,6), vec3(1,5,3)):check()
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
assert.is.equal(6, a.max.z)
end)
it("queries a bound3 size", function()
local a = bound3(vec3(1,2,3), vec3(4,6,8))
local v = a:size()
local r = a:radius()
assert.is.equal(3, v.x)
assert.is.equal(4, v.y)
assert.is.equal(5, v.z)
assert.is.equal(1.5, r.x)
assert.is.equal(2, r.y)
assert.is.equal(2.5, r.z)
end)
it("sets a bound3 size", function()
local a = bound3(vec3(1,2,3), vec3(4,5,6))
local b = a:with_size(vec3(1,1,1))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(4, a.max.x)
assert.is.equal(5, a.max.y)
assert.is.equal(6, a.max.z)
assert.is.equal(1, b.min.x)
assert.is.equal(2, b.min.y)
assert.is.equal(3, b.min.z)
assert.is.equal(2, b.max.x)
assert.is.equal(3, b.max.y)
assert.is.equal(4, b.max.z)
end)
it("queries a bound3 center", function()
local a = bound3(vec3(1,2,3), vec3(3,4,5))
local v = a:center()
assert.is.equal(2, v.x)
assert.is.equal(3, v.y)
assert.is.equal(4, v.z)
end)
it("sets a bound3 center", function()
local a = bound3(vec3(1,2,3), vec3(3,4,5))
local b = a:with_center(vec3(1,1,1))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(3, a.max.x)
assert.is.equal(4, a.max.y)
assert.is.equal(5, a.max.z)
assert.is.equal(0, b.min.x)
assert.is.equal(0, b.min.y)
assert.is.equal(0, b.min.z)
assert.is.equal(2, b.max.x)
assert.is.equal(2, b.max.y)
assert.is.equal(2, b.max.z)
end)
it("sets a bound3 size centered", function()
local a = bound3(vec3(1,2,3), vec3(3,4,5))
local b = a:with_size_centered(vec3(4,4,4))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(3, a.max.x)
assert.is.equal(4, a.max.y)
assert.is.equal(5, a.max.z)
assert.is.equal(0, b.min.x)
assert.is.equal(1, b.min.y)
assert.is.equal(2, b.min.z)
assert.is.equal(4, b.max.x)
assert.is.equal(5, b.max.y)
assert.is.equal(6, b.max.z)
end)
it("insets a bound3", function()
local a = bound3(vec3(1,2,3), vec3(5,10,11))
local b = a:inset(vec3(1,2,3))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(5, a.max.x)
assert.is.equal(10, a.max.y)
assert.is.equal(11, a.max.z)
assert.is.equal(2, b.min.x)
assert.is.equal(4, b.min.y)
assert.is.equal(6, b.min.z)
assert.is.equal(4, b.max.x)
assert.is.equal(8, b.max.y)
assert.is.equal(8, b.max.z)
end)
it("outsets a bound3", function()
local a = bound3(vec3(1,2,3), vec3(5,6,7))
local b = a:outset(vec3(1,2,3))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(5, a.max.x)
assert.is.equal(6, a.max.y)
assert.is.equal(7, a.max.z)
assert.is.equal(0, b.min.x)
assert.is.equal(0, b.min.y)
assert.is.equal(0, b.min.z)
assert.is.equal(6, b.max.x)
assert.is.equal(8, b.max.y)
assert.is.equal(10, b.max.z)
end)
it("offsets a bound3", function()
local a = bound3(vec3(1,2,3), vec3(5,6,7))
local b = a:offset(vec3(1,2,3))
assert.is.equal(1, a.min.x)
assert.is.equal(2, a.min.y)
assert.is.equal(3, a.min.z)
assert.is.equal(5, a.max.x)
assert.is.equal(6, a.max.y)
assert.is.equal(7, a.max.z)
assert.is.equal(2, b.min.x)
assert.is.equal(4, b.min.y)
assert.is.equal(6, b.min.z)
assert.is.equal(6, b.max.x)
assert.is.equal(8, b.max.y)
assert.is.equal(10, b.max.z)
end)
it("tests for points inside bound3", function()
local a = bound3(vec3(1,2,3), vec3(4,5,6))
assert.is_true(a:contains(vec3(2,3,4)))
assert.is_not_true(a:contains(vec3(0,3,4)))
assert.is_not_true(a:contains(vec3(5,3,4)))
assert.is_not_true(a:contains(vec3(2,1,4)))
assert.is_not_true(a:contains(vec3(2,6,4)))
assert.is_not_true(a:contains(vec3(2,3,2)))
assert.is_not_true(a:contains(vec3(2,3,7)))
end)
it("checks for bound3.zero", function()
assert.is.equal(0, bound3.zero.min.x)
assert.is.equal(0, bound3.zero.min.y)
assert.is.equal(0, bound3.zero.min.z)
assert.is.equal(0, bound3.zero.max.x)
assert.is.equal(0, bound3.zero.max.y)
assert.is.equal(0, bound3.zero.max.z)
end)
end)