added test for all implementations
This commit is contained in:
97
internal/bsp/build_test.go
Normal file
97
internal/bsp/build_test.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package bsp
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"bspviz/internal/geom"
|
||||
)
|
||||
|
||||
func TestStopUsesDefaults(t *testing.T) {
|
||||
segs := make([]geom.Seg, 13)
|
||||
if stop(segs, 0, Params{}) {
|
||||
t.Fatalf("stop should continue when using default LeafMax with 13 segs")
|
||||
}
|
||||
if !stop(segs, 33, Params{}) {
|
||||
t.Fatalf("stop should trigger when depth exceeds default MaxDepth")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvalCostSplitsAndBalance(t *testing.T) {
|
||||
line := []geom.Seg{
|
||||
{A: geom.V(-1, 1), B: geom.V(1, 1)},
|
||||
{A: geom.V(-1, -1), B: geom.V(1, -1)},
|
||||
{A: geom.V(-1, -1), B: geom.V(1, 1)},
|
||||
}
|
||||
p := Params{Alpha: 10, Beta: 2, Eps: geom.EPS}
|
||||
splits, balance, cost := evalCost(line, geom.V(0, 0), geom.V(1, 0), p)
|
||||
if splits != 1 {
|
||||
t.Fatalf("splits=%d want 1", splits)
|
||||
}
|
||||
if balance != 0 {
|
||||
t.Fatalf("balance=%d want 0", balance)
|
||||
}
|
||||
if cost != 10 {
|
||||
t.Fatalf("cost=%v want 10", cost)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitAllProducesFrontAndBack(t *testing.T) {
|
||||
segs := []geom.Seg{{A: geom.V(-1, -1), B: geom.V(1, 1)}}
|
||||
left, right, splits := splitAll(segs, geom.V(0, 0), geom.V(1, 0), Params{Eps: geom.EPS})
|
||||
if splits != 1 {
|
||||
t.Fatalf("splits=%d want 1", splits)
|
||||
}
|
||||
if len(left) != 1 || len(right) != 1 {
|
||||
t.Fatalf("expected split into two segments, left=%d right=%d", len(left), len(right))
|
||||
}
|
||||
share := func(a, b geom.Vec) bool {
|
||||
return math.Abs(a.X-b.X) < geom.EPS && math.Abs(a.Y-b.Y) < geom.EPS
|
||||
}
|
||||
if !share(left[0].A, right[0].B) && !share(left[0].B, right[0].A) {
|
||||
t.Fatalf("split point mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRespectsLeafAndDepth(t *testing.T) {
|
||||
segs := []geom.Seg{
|
||||
{A: geom.V(-2, -2), B: geom.V(2, -2)},
|
||||
{A: geom.V(2, -2), B: geom.V(2, 2)},
|
||||
{A: geom.V(2, 2), B: geom.V(-2, 2)},
|
||||
{A: geom.V(-2, 2), B: geom.V(-2, -2)},
|
||||
{A: geom.V(-2, -2), B: geom.V(2, 2)},
|
||||
{A: geom.V(-2, 2), B: geom.V(2, -2)},
|
||||
}
|
||||
p := Params{LeafMax: 2, MaxDepth: 3, Seed: 1, Cands: 4, Alpha: 5, Beta: 1, Eps: geom.EPS}
|
||||
root := Build(segs, p)
|
||||
if root == nil {
|
||||
t.Fatalf("Build returned nil")
|
||||
}
|
||||
|
||||
stats := Measure(root)
|
||||
if stats.MaxDepth > p.MaxDepth {
|
||||
t.Fatalf("MaxDepth=%d exceeds limit %d", stats.MaxDepth, p.MaxDepth)
|
||||
}
|
||||
if stats.Leaves == 0 {
|
||||
t.Fatalf("expected some leaves in tree")
|
||||
}
|
||||
verifyLeaves(t, root, 0, p)
|
||||
}
|
||||
|
||||
func verifyLeaves(t *testing.T, n *Node, depth int, p Params) {
|
||||
t.Helper()
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if n.Leaf != nil {
|
||||
if depth < p.MaxDepth && len(n.Leaf.Segs) > p.LeafMax {
|
||||
t.Fatalf("leaf at depth %d has %d segs (limit %d)", depth, len(n.Leaf.Segs), p.LeafMax)
|
||||
}
|
||||
return
|
||||
}
|
||||
if depth >= p.MaxDepth {
|
||||
t.Fatalf("internal node at depth %d exceeds MaxDepth %d", depth, p.MaxDepth)
|
||||
}
|
||||
verifyLeaves(t, n.Left, depth+1, p)
|
||||
verifyLeaves(t, n.Right, depth+1, p)
|
||||
}
|
||||
Reference in New Issue
Block a user