package world import ( "testing" "github.com/stretchr/testify/require" ) func TestCircles_WrapCopies_AppearInsideViewportWhenViewportEqualsWorld(t *testing.T) { t.Parallel() // World 10x10 units => 10px at zoom=1 when viewport==world. w := NewWorld(10, 10) w.SetCircleRadiusScaleFp(SCALE) w.resetGrid(2 * SCALE) type tc struct { name string x, y float64 r float64 wantCenters [][2]float64 // expected (cx,cy) in canvas px for zoom=1, worldRect min = 0 } // Camera is centered => expanded world rect equals [0..W)x[0..H) when margin=0. params := RenderParams{ ViewportWidthPx: 10, ViewportHeightPx: 10, MarginXPx: 0, MarginYPx: 0, CameraXWorldFp: 5 * SCALE, CameraYWorldFp: 5 * SCALE, CameraZoom: 1.0, } tests := []tc{ { name: "bottom boundary wraps to top", x: 5, y: 9, r: 2, // Centers: original at y=9, copy at y=-1. wantCenters: [][2]float64{{5, 9}, {5, -1}}, }, { name: "right boundary wraps to left", x: 9, y: 5, r: 2, wantCenters: [][2]float64{{9, 5}, {-1, 5}}, }, { name: "corner wraps to three extra copies", x: 9, y: 9, r: 2, wantCenters: [][2]float64{{9, 9}, {-1, 9}, {9, -1}, {-1, -1}}, }, { name: "no wrap inside", x: 5, y: 5, r: 2, wantCenters: [][2]float64{{5, 5}}, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() w2 := NewWorld(10, 10) w2.resetGrid(2 * SCALE) _, err := w2.AddCircle(tt.x, tt.y, tt.r) require.NoError(t, err) for _, obj := range w2.objects { w2.indexObject(obj) } plan, err := w2.buildRenderPlanStageA(params) require.NoError(t, err) d := &fakePrimitiveDrawer{} drawCirclesFromPlan(d, plan, w2.W, w2.H, true, w.circleRadiusScaleFp) cmds := d.CommandsByName("AddCircle") require.Len(t, cmds, len(tt.wantCenters)) // Collect centers (ignore radius for this test). got := make([][2]float64, 0, len(cmds)) for _, c := range cmds { require.Len(t, c.Args, 3) got = append(got, [2]float64{c.Args[0], c.Args[1]}) } // Order is deterministic with our shift generation and tile iteration for margin=0: single tile. require.ElementsMatch(t, tt.wantCenters, got) }) } }