From 847773c83cb3559c02d8a25280700eebb098b770 Mon Sep 17 00:00:00 2001 From: Roman Date: Mon, 18 Aug 2025 00:12:41 +0400 Subject: [PATCH] Update Go version and dependencies; add Angle method to Point type --- go.mod | 4 ++-- go.sum | 4 ++-- point.go | 19 ++++++++++++++-- point_test.go | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8090015..6f9a50e 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/kelindar/tile -go 1.24 +go 1.25 require ( github.com/kelindar/intmap v1.5.0 github.com/kelindar/iostream v1.4.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 ) require ( diff --git a/go.sum b/go.sum index f924de3..bce00af 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/kelindar/iostream v1.4.0 h1:ELKlinnM/K3GbRp9pYhWuZOyBxMMlYAfsOP+gauvZ github.com/kelindar/iostream v1.4.0/go.mod h1:MkjMuVb6zGdPQVdwLnFRO0xOTOdDvBWTztFmjRDQkXk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/point.go b/point.go index eb34f1e..0f4a04f 100644 --- a/point.go +++ b/point.go @@ -5,10 +5,9 @@ package tile import ( "fmt" + "math" ) -const invalid = int16(-1 << 15) - // ----------------------------------------------------------------------------- // Point represents a 2D coordinate. @@ -121,6 +120,22 @@ func (p Point) DistanceTo(other Point) uint32 { return abs(int32(p.X)-int32(other.X)) + abs(int32(p.Y)-int32(other.Y)) } +// Angle calculates the angle between two points +func (p Point) Angle(other Point) Direction { + dx := float64(other.X - p.X) + dy := float64(other.Y - p.Y) + + // Calculate the angle in radians + angle := math.Atan2(dy, dx) + alpha := angle + math.Pi/2 + if alpha < 0 { + alpha += 2 * math.Pi + } + + // Map to 8 directions (0-7) + return Direction(math.Round(alpha/(math.Pi/4))) % 8 +} + func abs(n int32) uint32 { if n < 0 { return uint32(-n) diff --git a/point_test.go b/point_test.go index e2e7bbb..4fc1f6d 100644 --- a/point_test.go +++ b/point_test.go @@ -73,6 +73,67 @@ func TestDirection_Empty(t *testing.T) { assert.Empty(t, dir.String()) } +func TestPointAngle(t *testing.T) { + tests := []struct { + name string + from Point + to Point + expected Direction + }{ + // Cardinal directions from origin + {"North", At(0, 0), At(0, -1), North}, + {"East", At(0, 0), At(1, 0), East}, + {"South", At(0, 0), At(0, 1), South}, + {"West", At(0, 0), At(-1, 0), West}, + + // Diagonal directions from origin + {"NorthEast", At(0, 0), At(1, -1), NorthEast}, + {"SouthEast", At(0, 0), At(1, 1), SouthEast}, + {"SouthWest", At(0, 0), At(-1, 1), SouthWest}, + {"NorthWest", At(0, 0), At(-1, -1), NorthWest}, + + // Same point (math.Atan2(0,0) = 0, which maps to East after transformation) + {"Same point", At(5, 5), At(5, 5), East}, + + // Non-origin starting points + {"From 10,10 North", At(10, 10), At(10, 5), North}, + {"From 10,10 East", At(10, 10), At(15, 10), East}, + {"From 10,10 South", At(10, 10), At(10, 15), South}, + {"From 10,10 West", At(10, 10), At(5, 10), West}, + {"From 10,10 NorthEast", At(10, 10), At(15, 5), NorthEast}, + {"From 10,10 SouthEast", At(10, 10), At(15, 15), SouthEast}, + {"From 10,10 SouthWest", At(10, 10), At(5, 15), SouthWest}, + {"From 10,10 NorthWest", At(10, 10), At(5, 5), NorthWest}, + + // Edge cases with larger distances + {"Far North", At(0, 0), At(0, -100), North}, + {"Far East", At(0, 0), At(100, 0), East}, + {"Far South", At(0, 0), At(0, 100), South}, + {"Far West", At(0, 0), At(-100, 0), West}, + + // Angles close to boundaries (testing rounding) + {"Near North boundary", At(0, 0), At(1, -10), North}, + {"Near NorthEast boundary", At(0, 0), At(10, -10), NorthEast}, + {"Near East boundary", At(0, 0), At(10, -1), East}, + {"Near SouthEast boundary", At(0, 0), At(10, 10), SouthEast}, + + // Negative coordinates + {"Negative coords North", At(-5, -5), At(-5, -10), North}, + {"Negative coords East", At(-5, -5), At(0, -5), East}, + {"Negative coords South", At(-5, -5), At(-5, 0), South}, + {"Negative coords West", At(-5, -5), At(-10, -5), West}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := tc.from.Angle(tc.to) + assert.Equal(t, tc.expected, result, + "Point %s to %s should be %s, got %s", + tc.from.String(), tc.to.String(), tc.expected.String(), result.String()) + }) + } +} + func TestMove(t *testing.T) { tests := []struct { dir Direction