package geom import ( "math" "testing" ) func TestSide(t *testing.T) { tests := []struct { name string P, O, D Vec want float64 }{ {"point left of line", V(1, 1), V(0, 0), V(1, 0), 1}, {"point right of line", V(1, -1), V(0, 0), V(1, 0), -1}, {"point on line", V(2, 0), V(0, 0), V(1, 0), 0}, } for _, tc := range tests { if got := Side(tc.P, tc.O, tc.D); got < tc.want-EPS || got > tc.want+EPS { t.Fatalf("%s: Side()=%v want %v", tc.name, got, tc.want) } } } func TestSegLineIntersect(t *testing.T) { O := V(0, 0) D := V(1, 0) tests := []struct { name string A, B Vec wantOK bool wantT float64 }{ {"hits interior", V(0, -1), V(0, 1), true, 0.5}, {"parallel", V(0, 1), V(1, 1), false, 0}, {"touches endpoint", V(0, 0), V(0, 1), false, 0}, } for _, tc := range tests { ok, tVal := SegLineIntersect(tc.A, tc.B, O, D) if ok != tc.wantOK { t.Fatalf("%s: ok=%v want %v", tc.name, ok, tc.wantOK) } if !ok { continue } if diff := tVal - tc.wantT; diff > 1e-6 || diff < -1e-6 { t.Fatalf("%s: t=%v want %v", tc.name, tVal, tc.wantT) } } } func TestSplitSeg(t *testing.T) { O := V(0, 0) D := V(1, 0) seg := Seg{A: V(0, -1), B: V(0, 1)} front, back := SplitSeg(seg, O, D) if len(front) != 1 || len(back) != 1 { t.Fatalf("expected split into two pieces got front=%d back=%d", len(front), len(back)) } share := func(a, b Vec) bool { return math.Abs(a.X-b.X) < EPS && math.Abs(a.Y-b.Y) < EPS } if !share(front[0].A, back[0].B) && !share(front[0].B, back[0].A) { t.Fatalf("split point mismatch: front=%v back=%v", front[0], back[0]) } sameSide := Seg{A: V(0, 1), B: V(1, 1)} front, back = SplitSeg(sameSide, O, D) if len(back) != 0 || len(front) != 1 { t.Fatalf("expected no split for same side got front=%d back=%d", len(front), len(back)) } } func TestBounds(t *testing.T) { pts := []Vec{V(-1, 2), V(3, -4), V(0, 0)} box := Bounds(pts) if box.Min != V(-1, -4) { t.Fatalf("Min=%v want (-1,-4)", box.Min) } if box.Max != V(3, 2) { t.Fatalf("Max=%v want (3,2)", box.Max) } }