Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix move view subscribers #11

Merged
merged 2 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v1
with:
go-version: 1.19
go-version: 1.23
- name: Check out code
uses: actions/checkout@v2
- name: Install dependencies
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module github.com/kelindar/tile

go 1.19
go 1.23

require (
github.com/kelindar/iostream v1.3.0
github.com/stretchr/testify v1.8.1
github.com/kelindar/iostream v1.4.0
github.com/stretchr/testify v1.9.0
)

require (
Expand Down
15 changes: 4 additions & 11 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kelindar/iostream v1.3.0 h1:Bz2qQabipZlF1XCk64bnxsGLete+iHtayGPeWVpbwbo=
github.com/kelindar/iostream v1.3.0/go.mod h1:MkjMuVb6zGdPQVdwLnFRO0xOTOdDvBWTztFmjRDQkXk=
github.com/kelindar/iostream v1.4.0 h1:ELKlinnM/K3GbRp9pYhWuZOyBxMMlYAfsOP+gauvZaY=
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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
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=
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.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
46 changes: 25 additions & 21 deletions grid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ import (
)

/*
cpu: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
BenchmarkGrid/each-8 862 1365740 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/neighbors-8 66562384 17.94 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/within-8 30012 40112 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/at-8 396362580 3.025 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/write-8 127712601 9.256 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/merge-8 125377372 9.410 ns/op 0 B/op 0 allocs/op
cpu: 13th Gen Intel(R) Core(TM) i7-13700K
BenchmarkGrid/each-24 1452 830268 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/neighbors-24 121583491 9.861 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/within-24 49360 24477 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/at-24 687659378 1.741 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/write-24 191272338 6.307 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/merge-24 162536985 7.332 ns/op 0 B/op 0 allocs/op
BenchmarkGrid/mask-24 158258084 7.601 ns/op 0 B/op 0 allocs/op
*/
func BenchmarkGrid(b *testing.B) {
var d Tile[uint32]
Expand Down Expand Up @@ -99,10 +100,10 @@ func BenchmarkGrid(b *testing.B) {
}

/*
cpu: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
BenchmarkState/range-8 11211600 103.4 ns/op 0 B/op 0 allocs/op
BenchmarkState/add-8 41380593 29.00 ns/op 0 B/op 0 allocs/op
BenchmarkState/del-8 54474884 21.79 ns/op 0 B/op 0 allocs/op
cpu: 13th Gen Intel(R) Core(TM) i7-13700K
BenchmarkState/range-24 17017800 71.14 ns/op 0 B/op 0 allocs/op
BenchmarkState/add-24 72639224 16.32 ns/op 0 B/op 0 allocs/op
BenchmarkState/del-24 82469125 13.65 ns/op 0 B/op 0 allocs/op
*/
func BenchmarkState(b *testing.B) {
m := NewGridOf[int](768, 768)
Expand Down Expand Up @@ -155,13 +156,12 @@ func TestWithin(t *testing.T) {
m.Within(At(1, 1), At(5, 5), func(p Point, tile Tile[string]) {
path = append(path, p.String())
})
assert.Equal(t, 25, len(path))
assert.Equal(t, 16, len(path))
assert.ElementsMatch(t, []string{
"1,1", "2,1", "1,2", "2,2", "3,1",
"4,1", "5,1", "3,2", "4,2", "5,2",
"1,3", "2,3", "1,4", "2,4", "1,5",
"2,5", "3,3", "4,3", "5,3", "3,4",
"4,4", "5,4", "3,5", "4,5", "5,5",
"1,1", "2,1", "1,2", "2,2",
"3,1", "4,1", "3,2", "4,2",
"1,3", "2,3", "1,4", "2,4",
"3,3", "4,3", "3,4", "4,4",
}, path)
}

Expand All @@ -179,18 +179,22 @@ func TestWithinCorner(t *testing.T) {
}, path)
}

func TestWithinXY(t *testing.T) {
assert.False(t, At(4, 8).WithinRect(NewRect(1, 6, 4, 10)))
}

func TestWithinOneSide(t *testing.T) {
m := NewGrid(9, 9)

var path []string
m.Within(At(1, 6), At(4, 10), func(p Point, tile Tile[string]) {
path = append(path, p.String())
})
assert.Equal(t, 12, len(path))
assert.Equal(t, 9, len(path))
assert.ElementsMatch(t, []string{
"1,6", "2,6", "3,6", "4,6",
"1,7", "2,7", "3,7", "4,7",
"1,8", "2,8", "3,8", "4,8",
"1,6", "2,6", "3,6",
"1,7", "2,7", "3,7",
"1,8", "2,8", "3,8",
}, path)
}

Expand Down
74 changes: 65 additions & 9 deletions point.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ func (p Point) DivideScalar(s int16) Point {

// Within checks if the point is within the specified bounding box.
func (p Point) Within(nw, se Point) bool {
return p.X >= nw.X && p.Y >= nw.Y && p.X <= se.X && p.Y <= se.Y
return Rect{Min: nw, Max: se}.Contains(p)
}

// WithinRect checks if the point is within the specified bounding box.
func (p Point) WithinRect(box Rect) bool {
return p.X >= box.Min.X && p.Y >= box.Min.Y && p.X <= box.Max.X && p.Y <= box.Max.Y
return box.Contains(p)
}

// WithinSize checks if the point is within the specified bounding box
Expand Down Expand Up @@ -143,23 +143,74 @@ func NewRect(left, top, right, bottom int16) Rect {
}

// Contains returns whether a point is within the rectangle or not.
func (r *Rect) Contains(p Point) bool {
return p.X >= r.Min.X && p.Y >= r.Min.Y && p.X <= r.Max.X && p.Y <= r.Max.Y
func (a Rect) Contains(p Point) bool {
return a.Min.X <= p.X && p.X < a.Max.X && a.Min.Y <= p.Y && p.Y < a.Max.Y
}

// Intersects returns whether a rectangle intersects with another rectangle or not.
func (r *Rect) Intersects(box Rect) bool {
return !(box.Max.X < r.Min.X || box.Min.X > r.Max.X || box.Max.Y < r.Min.Y || box.Min.Y > r.Max.Y)
func (a Rect) Intersects(b Rect) bool {
return b.Min.X < a.Max.X && a.Min.X < b.Max.X && b.Min.Y < a.Max.Y && a.Min.Y < b.Max.Y
}

// Size returns the size of the rectangle
func (r *Rect) Size() Point {
func (a *Rect) Size() Point {
return Point{
X: r.Max.X - r.Min.X,
Y: r.Max.Y - r.Min.Y,
X: a.Max.X - a.Min.X,
Y: a.Max.Y - a.Min.Y,
}
}

// IsZero returns true if the rectangle is zero-value
func (a Rect) IsZero() bool {
return a.Min.X == a.Max.X && a.Min.Y == a.Max.Y
}

// Difference calculates up to four non-overlapping regions in a that are not covered by b.
// If there are fewer than four distinct regions, the remaining Rects will be zero-value.
func (a Rect) Difference(b Rect) (result [4]Rect) {
if b.Contains(a.Min) && b.Contains(a.Max) {
return // Fully covered, return zero-value result
}

// Check for non-overlapping cases
if !a.Intersects(b) {
result[0] = a // No overlap, return A as is
return
}

left := min(a.Min.X, b.Min.X)
right := max(a.Max.X, b.Max.X)
top := min(a.Min.Y, b.Min.Y)
bottom := max(a.Max.Y, b.Max.Y)

result[0].Min = Point{X: left, Y: top}
result[0].Max = Point{X: right, Y: max(a.Min.Y, b.Min.Y)}

result[1].Min = Point{X: left, Y: min(a.Max.Y, b.Max.Y)}
result[1].Max = Point{X: right, Y: bottom}

result[2].Min = Point{X: left, Y: top}
result[2].Max = Point{X: max(a.Min.X, b.Min.X), Y: bottom}

result[3].Min = Point{X: min(a.Max.X, b.Max.X), Y: top}
result[3].Max = Point{X: right, Y: bottom}

if result[0].Size().X == 0 || result[0].Size().Y == 0 {
result[0] = Rect{}
}
if result[1].Size().X == 0 || result[1].Size().Y == 0 {
result[1] = Rect{}
}
if result[2].Size().X == 0 || result[2].Size().Y == 0 {
result[2] = Rect{}
}
if result[3].Size().X == 0 || result[3].Size().Y == 0 {
result[3] = Rect{}
}

return
}

// -----------------------------------------------------------------------------

// Diretion represents a direction
Expand Down Expand Up @@ -200,3 +251,8 @@ func (v Direction) String() string {
return ""
}
}

// Vector returns a direction vector with a given scale
func (v Direction) Vector(scale int16) Point {
return Point{}.MoveBy(v, scale)
}
71 changes: 65 additions & 6 deletions point_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import (
)

/*
cpu: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
BenchmarkPoint/within-8 1000000000 0.2697 ns/op 0 B/op 0 allocs/op
BenchmarkPoint/within-rect-8 1000000000 0.2928 ns/op 0 B/op 0 allocs/op
BenchmarkPoint/interleave-8 1000000000 0.8242 ns/op 0 B/op 0 allocs/op
cpu: 13th Gen Intel(R) Core(TM) i7-13700K
BenchmarkPoint/within-24 1000000000 0.09854 ns/op 0 B/op 0 allocs/op
BenchmarkPoint/within-rect-24 1000000000 0.09966 ns/op 0 B/op 0 allocs/op
*/
func BenchmarkPoint(b *testing.B) {
p := At(10, 20)
Expand Down Expand Up @@ -50,12 +49,18 @@ func TestPoint(t *testing.T) {
assert.Equal(t, "8,18", p.Subtract(p2).String())
assert.Equal(t, "20,40", p.Multiply(p2).String())
assert.Equal(t, "5,10", p.Divide(p2).String())
assert.True(t, p.Within(At(1, 1), At(10, 20)))
assert.True(t, p.WithinRect(NewRect(1, 1, 10, 20)))
assert.True(t, p.Within(At(1, 1), At(20, 30)))
assert.True(t, p.WithinRect(NewRect(1, 1, 20, 30)))
assert.False(t, p.WithinSize(At(10, 20)))
assert.True(t, p.WithinSize(At(20, 30)))
}

func TestIntersects(t *testing.T) {
assert.True(t, NewRect(0, 0, 2, 2).Intersects(NewRect(1, 0, 3, 2)))
assert.False(t, NewRect(0, 0, 2, 2).Intersects(NewRect(2, 0, 4, 2)))
assert.False(t, NewRect(10, 10, 12, 12).Intersects(NewRect(9, 12, 11, 14)))
}

func TestDirection(t *testing.T) {
for i := 0; i < 8; i++ {
dir := Direction(i)
Expand Down Expand Up @@ -88,3 +93,57 @@ func TestMove(t *testing.T) {
assert.Equal(t, tc.out, Point{}.Move(tc.dir), tc.dir.String())
}
}

func TestContains(t *testing.T) {
tests := map[Point]bool{
{X: 0, Y: 0}: true,
{X: 1, Y: 0}: true,
{X: 0, Y: 1}: true,
{X: 1, Y: 1}: true,
{X: 2, Y: 2}: false,
{X: 3, Y: 3}: false,
{X: 1, Y: 2}: false,
{X: 2, Y: 1}: false,
}

for point, expect := range tests {
r := NewRect(0, 0, 2, 2)
assert.Equal(t, expect, r.Contains(point), point.String())
}
}

func TestDiff_Right(t *testing.T) {
a := Rect{At(0, 0), At(2, 2)}
b := Rect{At(1, 0), At(3, 2)}

diff := a.Difference(b)
assert.Equal(t, Rect{At(0, 0), At(1, 2)}, diff[2])
assert.Equal(t, Rect{At(2, 0), At(3, 2)}, diff[3])
}

func TestDiff_Left(t *testing.T) {
a := Rect{At(0, 0), At(2, 2)}
b := Rect{At(-1, 0), At(1, 2)}

diff := a.Difference(b)
assert.Equal(t, Rect{At(-1, 0), At(0, 2)}, diff[2])
assert.Equal(t, Rect{At(1, 0), At(2, 2)}, diff[3])
}

func TestDiff_Up(t *testing.T) {
a := Rect{At(0, 0), At(2, 2)}
b := Rect{At(0, -1), At(2, 1)}

diff := a.Difference(b)
assert.Equal(t, Rect{At(0, -1), At(2, 0)}, diff[0])
assert.Equal(t, Rect{At(0, 1), At(2, 2)}, diff[1])
}

func TestDiff_Down(t *testing.T) {
a := Rect{At(0, 0), At(2, 2)}
b := Rect{At(0, 1), At(2, 3)}

diff := a.Difference(b)
assert.Equal(t, Rect{At(0, 0), At(2, 1)}, diff[0])
assert.Equal(t, Rect{At(0, 2), At(2, 3)}, diff[1])
}
Loading
Loading