package geospatial import ( "testing" ) func TestCalculateBoundingBox(t *testing.T) { calc := NewBoundingBoxCalculator(DefaultConfig()) tests := []struct { name string points []Point wantNE Point wantSW Point }{ { name: "Two points", points: []Point{ {Latitude: 52.0, Longitude: 13.0}, {Latitude: 53.0, Longitude: 14.0}, }, wantNE: Point{Latitude: 53.0, Longitude: 14.0}, wantSW: Point{Latitude: 52.0, Longitude: 13.0}, }, { name: "Multiple points", points: []Point{ {Latitude: 52.0, Longitude: 13.0}, {Latitude: 53.0, Longitude: 14.0}, {Latitude: 51.5, Longitude: 12.5}, {Latitude: 52.5, Longitude: 14.5}, }, wantNE: Point{Latitude: 53.0, Longitude: 14.5}, wantSW: Point{Latitude: 51.5, Longitude: 12.5}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := calc.CalculateBoundingBox(tt.points) if err != nil { t.Fatalf("CalculateBoundingBox() error = %v", err) } if got.NorthEast.Latitude != tt.wantNE.Latitude { t.Errorf("CalculateBoundingBox() NorthEast.Latitude = %v, want %v", got.NorthEast.Latitude, tt.wantNE.Latitude) } if got.NorthEast.Longitude != tt.wantNE.Longitude { t.Errorf("CalculateBoundingBox() NorthEast.Longitude = %v, want %v", got.NorthEast.Longitude, tt.wantNE.Longitude) } if got.SouthWest.Latitude != tt.wantSW.Latitude { t.Errorf("CalculateBoundingBox() SouthWest.Latitude = %v, want %v", got.SouthWest.Latitude, tt.wantSW.Latitude) } if got.SouthWest.Longitude != tt.wantSW.Longitude { t.Errorf("CalculateBoundingBox() SouthWest.Longitude = %v, want %v", got.SouthWest.Longitude, tt.wantSW.Longitude) } }) } } func TestCalculateBoundingBox_EmptyList(t *testing.T) { calc := NewBoundingBoxCalculator(DefaultConfig()) _, err := calc.CalculateBoundingBox([]Point{}) if err == nil { t.Error("CalculateBoundingBox() expected error for empty point list") } } func TestIsPointInBoundingBox(t *testing.T) { calc := NewBoundingBoxCalculator(DefaultConfig()) bbox := BoundingBox{ NorthEast: Point{Latitude: 53.0, Longitude: 14.0}, SouthWest: Point{Latitude: 52.0, Longitude: 13.0}, } tests := []struct { name string point Point want bool }{ { name: "Point inside", point: Point{Latitude: 52.5, Longitude: 13.5}, want: true, }, { name: "Point on north edge", point: Point{Latitude: 53.0, Longitude: 13.5}, want: true, }, { name: "Point on south edge", point: Point{Latitude: 52.0, Longitude: 13.5}, want: true, }, { name: "Point outside - north", point: Point{Latitude: 54.0, Longitude: 13.5}, want: false, }, { name: "Point outside - south", point: Point{Latitude: 51.0, Longitude: 13.5}, want: false, }, { name: "Point outside - east", point: Point{Latitude: 52.5, Longitude: 15.0}, want: false, }, { name: "Point outside - west", point: Point{Latitude: 52.5, Longitude: 12.0}, want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := calc.IsPointInBoundingBox(tt.point, bbox) if got != tt.want { t.Errorf("IsPointInBoundingBox() = %v, want %v", got, tt.want) } }) } } func TestExpandBoundingBox(t *testing.T) { calc := NewBoundingBoxCalculator(DefaultConfig()) bbox := BoundingBox{ NorthEast: Point{Latitude: 52.5, Longitude: 13.5}, SouthWest: Point{Latitude: 52.0, Longitude: 13.0}, } expanded, err := calc.ExpandBoundingBox(bbox, 5.0) // Expand by 5 km if err != nil { t.Fatalf("ExpandBoundingBox() error = %v", err) } // Expanded box should be larger if expanded.NorthEast.Latitude <= bbox.NorthEast.Latitude { t.Error("ExpandBoundingBox() should expand north") } if expanded.NorthEast.Longitude <= bbox.NorthEast.Longitude { t.Error("ExpandBoundingBox() should expand east") } if expanded.SouthWest.Latitude >= bbox.SouthWest.Latitude { t.Error("ExpandBoundingBox() should expand south") } if expanded.SouthWest.Longitude >= bbox.SouthWest.Longitude { t.Error("ExpandBoundingBox() should expand west") } } func TestBoundingBoxArea(t *testing.T) { calc := NewBoundingBoxCalculator(DefaultConfig()) bbox := BoundingBox{ NorthEast: Point{Latitude: 52.5, Longitude: 13.5}, SouthWest: Point{Latitude: 52.0, Longitude: 13.0}, } area, err := calc.BoundingBoxArea(bbox) if err != nil { t.Fatalf("BoundingBoxArea() error = %v", err) } // Area should be positive if area <= 0 { t.Error("BoundingBoxArea() should return positive area") } // Rough check: area should be approximately (0.5 deg lat) * (0.5 deg lon) * cos(lat) * R² // At 52° latitude, 0.5° ≈ 55.5 km, so area ≈ 55.5 * 55.5 * cos(52°) ≈ 2000 km² expectedMin := 1000.0 expectedMax := 5000.0 if area < expectedMin || area > expectedMax { t.Errorf("BoundingBoxArea() = %v, expected between %v and %v", area, expectedMin, expectedMax) } }