feat: hit on primitives

This commit is contained in:
IliaDenisov
2026-03-07 19:28:22 +02:00
parent e4b956232f
commit c076347d70
21 changed files with 1167 additions and 165 deletions
+43 -44
View File
@@ -4,7 +4,6 @@ import (
"fmt"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
)
@@ -17,7 +16,7 @@ func newTestWorld(wReal, hReal int) *World {
return NewWorld(wReal, hReal)
}
func countObjectInGrid(g *World, id uuid.UUID) int {
func countObjectInGrid(g *World, id PrimitiveID) int {
count := 0
for row := range g.grid {
for col := range g.grid[row] {
@@ -31,7 +30,7 @@ func countObjectInGrid(g *World, id uuid.UUID) int {
return count
}
func hasObjectInCell(g *World, row, col int, id uuid.UUID) bool {
func hasObjectInCell(g *World, row, col int, id PrimitiveID) bool {
for _, item := range g.grid[row][col] {
if item.ID() == id {
return true
@@ -283,7 +282,7 @@ func TestIndexPoint(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
p := Point{
Id: id,
X: 150 * SCALE,
@@ -300,7 +299,7 @@ func TestIndexPoint_WrapsNegativeCoordinates(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
p := Point{
Id: id,
X: -1,
@@ -317,7 +316,7 @@ func TestIndexCircle_WrapsAcrossLeftAndTopEdges(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
c := Circle{
Id: id,
X: 50 * SCALE,
@@ -344,7 +343,7 @@ func TestIndexCircle_NoWrap(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
c := Circle{
Id: id,
X: 300 * SCALE,
@@ -364,7 +363,7 @@ func TestIndexCircle_CoversWholeWorldWhenLargerThanWorld(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
c := Circle{
Id: id,
X: 300 * SCALE,
@@ -385,7 +384,7 @@ func TestIndexLine_HorizontalWrap(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
l := Line{
Id: id,
X1: 590 * SCALE,
@@ -405,7 +404,7 @@ func TestIndexLine_VerticalWrap(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
l := Line{
Id: id,
X1: 200 * SCALE,
@@ -424,7 +423,7 @@ func TestIndexLine_DiagonalWrapBothAxes(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
l := Line{
Id: id,
X1: 590 * SCALE,
@@ -443,7 +442,7 @@ func TestIndexLine_HorizontalNoWrap_DegenerateBBoxStillIndexes(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
l := Line{
Id: id,
X1: 100 * SCALE,
@@ -465,7 +464,7 @@ func TestIndexLine_VerticalNoWrap_DegenerateBBoxStillIndexes(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
l := Line{
Id: id,
X1: 200 * SCALE,
@@ -487,7 +486,7 @@ func TestIndexLine_ZeroLengthIndexesSingleCell(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
l := Line{
Id: id,
X1: 250 * SCALE,
@@ -506,7 +505,7 @@ func TestIndexLine_ExactlyOnCellBoundaryUsesHalfOpenInterval(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
l := Line{
Id: id,
X1: 200 * SCALE,
@@ -523,7 +522,7 @@ func TestIndexLine_ExactlyOnCellBoundaryUsesHalfOpenInterval(t *testing.T) {
require.False(t, hasObjectInCell(g, 1, 4, id))
}
func collectOccupiedCells(g *World, id uuid.UUID) []gridCell {
func collectOccupiedCells(g *World, id PrimitiveID) []gridCell {
var cells []gridCell
for row := range g.grid {
for col := range g.grid[row] {
@@ -548,7 +547,7 @@ func allGridCells(rows, cols int) []gridCell {
return cells
}
func requireIndexedExactlyInCells(t *testing.T, g *World, id uuid.UUID, want []gridCell) {
func requireIndexedExactlyInCells(t *testing.T, g *World, id PrimitiveID, want []gridCell) {
t.Helper()
got := collectOccupiedCells(g, id)
@@ -557,8 +556,8 @@ func requireIndexedExactlyInCells(t *testing.T, g *World, id uuid.UUID, want []g
t,
want,
got,
"unexpected indexed cells for object %s",
id.String(),
"unexpected indexed cells for object %d",
id,
)
}
@@ -577,7 +576,7 @@ func TestIndexObject_Point_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Point{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 150 * SCALE,
Y: 250 * SCALE,
},
@@ -591,7 +590,7 @@ func TestIndexObject_Point_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Point{
Id: uuid.New(),
Id: PrimitiveID(1),
X: -1,
Y: -1,
},
@@ -605,7 +604,7 @@ func TestIndexObject_Point_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Point{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 600 * SCALE,
Y: 600 * SCALE,
},
@@ -619,7 +618,7 @@ func TestIndexObject_Point_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Point{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 200 * SCALE,
Y: 300 * SCALE,
},
@@ -656,7 +655,7 @@ func TestIndexObject_Circle_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Circle{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 300 * SCALE,
Y: 300 * SCALE,
Radius: 50 * SCALE,
@@ -674,7 +673,7 @@ func TestIndexObject_Circle_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Circle{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 50 * SCALE,
Y: 50 * SCALE,
Radius: 75 * SCALE,
@@ -697,7 +696,7 @@ func TestIndexObject_Circle_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Circle{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 575 * SCALE,
Y: 300 * SCALE,
Radius: 50 * SCALE,
@@ -715,7 +714,7 @@ func TestIndexObject_Circle_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Circle{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 300 * SCALE,
Y: 575 * SCALE,
Radius: 50 * SCALE,
@@ -733,7 +732,7 @@ func TestIndexObject_Circle_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Circle{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 300 * SCALE,
Y: 300 * SCALE,
Radius: 400 * SCALE,
@@ -746,7 +745,7 @@ func TestIndexObject_Circle_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Circle{
Id: uuid.New(),
Id: PrimitiveID(1),
X: 300 * SCALE,
Y: 300 * SCALE,
Radius: 100 * SCALE, // bbox [200, 400) x [200, 400)
@@ -787,7 +786,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 100 * SCALE,
Y1: 200 * SCALE,
X2: 300 * SCALE,
@@ -805,7 +804,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 200 * SCALE,
Y1: 100 * SCALE,
X2: 200 * SCALE,
@@ -823,7 +822,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 590 * SCALE,
Y1: 200 * SCALE,
X2: 10 * SCALE,
@@ -840,7 +839,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 200 * SCALE,
Y1: 590 * SCALE,
X2: 200 * SCALE,
@@ -857,7 +856,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 590 * SCALE,
Y1: 590 * SCALE,
X2: 10 * SCALE,
@@ -876,7 +875,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 250 * SCALE,
Y1: 350 * SCALE,
X2: 250 * SCALE,
@@ -892,7 +891,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 200 * SCALE,
Y1: 100 * SCALE,
X2: 400 * SCALE,
@@ -910,7 +909,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 100 * SCALE,
Y1: 100 * SCALE,
X2: 300 * SCALE,
@@ -931,7 +930,7 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
worldH: 600,
cellSize: 100 * SCALE,
item: Line{
Id: uuid.New(),
Id: PrimitiveID(1),
X1: 600 * SCALE,
Y1: 100 * SCALE,
X2: 0,
@@ -960,9 +959,9 @@ func TestIndexObject_Line_TableDriven(t *testing.T) {
func TestIndexOnViewportChange_RebuildsGridAndIndexesObjects(t *testing.T) {
g := newTestWorld(600, 400)
pID := uuid.New()
cID := uuid.New()
lID := uuid.New()
pID := PrimitiveID(1)
cID := PrimitiveID(2)
lID := PrimitiveID(3)
g.objects[pID] = Point{
Id: pID,
@@ -1007,7 +1006,7 @@ func TestIndexOnViewportChange_RebuildsGridShapeForNonSquareWorld(t *testing.T)
func TestIndexOnViewportChange_ReindexesAfterCellSizeChange(t *testing.T) {
g := newTestWorld(600, 600)
id := uuid.New()
id := PrimitiveID(1)
g.objects[id] = Circle{
Id: id,
X: 300 * SCALE,
@@ -1041,7 +1040,7 @@ func TestPrimitiveIndexing_ErrorMessagesStayReadable(t *testing.T) {
g := newTestWorld(600, 600)
g.resetGrid(100 * SCALE)
id := uuid.New()
id := PrimitiveID(1)
p := Point{
Id: id,
X: 100 * SCALE,
@@ -1051,5 +1050,5 @@ func TestPrimitiveIndexing_ErrorMessagesStayReadable(t *testing.T) {
g.indexObject(p)
got := collectOccupiedCells(g, id)
require.NotEmpty(t, got, fmt.Sprintf("object %s should occupy at least one cell", id.String()))
require.NotEmpty(t, got, fmt.Sprintf("object %d should occupy at least one cell", id))
}