Skip to content

Commit

Permalink
More rectangle logic
Browse files Browse the repository at this point in the history
  • Loading branch information
mrsombre committed Jan 11, 2024
1 parent 0f1a79f commit fa425eb
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 46 deletions.
52 changes: 52 additions & 0 deletions geometry_rect.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ func (r Rect) Center() Point {
)
}

func (r Rect) Symmetric(width, height float64) Rect {
return Rect{
Xf: width - r.Xf,
Xt: width - r.Xt,
Yf: height - r.Yf,
Yt: height - r.Yt,
}
}

// IsContainsPoint tests if the Rect contains the Point.
func (r Rect) IsContainsPoint(c Point) bool {
return c.X >= r.Xf && c.X <= r.Xt && c.Y >= r.Yf && c.Y <= r.Yt
Expand All @@ -48,6 +57,49 @@ func (r Rect) IsContainsRectangle(t Rect) bool {
return r.Xf <= t.Xf && r.Xt >= t.Xt && r.Yf <= t.Yf && r.Yt >= t.Yt
}

// IsIntersectsRect tests if the Rect intersects the other Rect.
func (r Rect) IsIntersectsRect(t Rect) bool {
return !(r.Xt < t.Xf || r.Xf > t.Xt || r.Yt < t.Yf || r.Yf > t.Yt)
}

// RectsIntersection returns the intersection Rect of two Rects.
func (r Rect) RectsIntersection(t Rect) (Rect, bool) {
if !r.IsIntersectsRect(t) {
return Rect{}, false
}

ir := NewRectangle(
math.Max(r.Xf, t.Xf),
math.Min(r.Xt, t.Xt),
math.Max(r.Yf, t.Yf),
math.Min(r.Yt, t.Yt),
)
if ir.Width() == 0 || ir.Height() == 0 {
return Rect{}, false
}

return ir, true
}

func (r Rect) Vertices() Points {
return Points{
topLeft0: {r.Xf, r.Yt},
topRight0: {r.Xt, r.Yt},
bottomRight0: {r.Xt, r.Yf},
bottomLeft0: {r.Xf, r.Yf},
}
}

// Edges returns the Lines edges of the Rect.
func (r Rect) Edges() Lines {
return Lines{
top: {Point{r.Xf, r.Yt}, Point{r.Xt, r.Yt}},
right: {Point{r.Xt, r.Yf}, Point{r.Xt, r.Yt}},
bottom: {Point{r.Xf, r.Yf}, Point{r.Xt, r.Yf}},
left: {Point{r.Xf, r.Yf}, Point{r.Xf, r.Yt}},
}
}

func (r Rect) String() string {
return fmt.Sprintf("[X:%.f>%.f,Y:%.f>%.f]", r.Xf, r.Xt, r.Yf, r.Yt)
}
Expand Down
177 changes: 131 additions & 46 deletions geometry_rect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,81 +7,81 @@ import (
)

func TestRect_IsSame(t *testing.T) {
tests := []struct {
name string
a, b Rect
want bool
}{
{
name: `true`,
a: Rect{100, 200, 300, 400},
b: Rect{100, 200, 300, 400},
want: true,
},
{
name: `false`,
a: Rect{100, 200, 300, 400},
b: Rect{300, 400, 100, 200},
want: false,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.want, tc.a.IsSame(tc.b))
})
}
var r Rect
r = Rect{100, 200, 300, 400}
assert.True(t, r.IsSame(Rect{100, 200, 300, 400}))
r = Rect{100, 200, 300, 400}
assert.False(t, r.IsSame(Rect{300, 400, 100, 200}))
}

func TestRect_Width(t *testing.T) {
r := Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400}
r := Rect{100, 200, 300, 400}
assert.EqualValues(t, 100, r.Width())
}

func TestRect_Height(t *testing.T) {
r := Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400}
r := Rect{100, 200, 300, 400}
assert.EqualValues(t, 100, r.Height())
}

func TestRect_Area(t *testing.T) {
r := Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400}
r := Rect{100, 200, 300, 400}
assert.EqualValues(t, 10000, r.Area())
}

func TestRect_Center(t *testing.T) {
r := Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400}
r := Rect{100, 200, 300, 400}
assert.Equal(t, Point{150, 350}, r.Center())
}

func TestRect_Symmetric(t *testing.T) {
r := Rect{100, 200, 300, 400}
assert.Equal(t, Rect{900, 800, 700, 600}, r.Symmetric(1000, 1000))
}

func TestRect_IsContainsPoint(t *testing.T) {
var r Rect
r = Rect{100, 200, 300, 400}
assert.True(t, r.IsContainsPoint(Point{150, 350}))
r = Rect{100, 200, 300, 400}
assert.False(t, r.IsContainsPoint(Point{50, 250}))
}

func TestRect_IsContainsRectangle(t *testing.T) {
tests := []struct {
name string
r Rect
p Point
t Rect
want bool
}{
{
name: `true`,
r: Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400},
p: Point{150, 350},
r: Rect{100, 200, 300, 400},
t: Rect{120, 180, 320, 380},
want: true,
},
{
name: `false`,
r: Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400},
p: Point{50, 250},
r: Rect{100, 200, 300, 400},
t: Rect{150, 250, 350, 450},
want: false,
},
{
name: `same`,
r: Rect{100, 200, 300, 400},
t: Rect{100, 200, 300, 400},
want: true,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.want, tc.r.IsContainsPoint(tc.p))
assert.Equal(t, tc.want, tc.r.IsContainsRectangle(tc.t))
})
}
}

func TestRect_IsContainsRectangle(t *testing.T) {
func TestRect_IsIntersectsRect(t *testing.T) {
tests := []struct {
name string
r Rect
Expand All @@ -90,33 +90,118 @@ func TestRect_IsContainsRectangle(t *testing.T) {
}{
{
name: `true`,
r: Rect{Xf: 100, Xt: 300, Yf: 300, Yt: 500},
t: Rect{Xf: 150, Xt: 250, Yf: 350, Yt: 450},
r: Rect{100, 200, 300, 400},
t: Rect{150, 250, 350, 450},
want: true,
},
{
name: `false`,
r: Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400},
t: Rect{Xf: 150, Xt: 250, Yf: 350, Yt: 450},
r: Rect{100, 200, 300, 400},
t: Rect{300, 400, 500, 600},
want: false,
},
{
name: `same`,
r: Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400},
t: Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400},
r: Rect{100, 200, 300, 400},
t: Rect{100, 200, 300, 400},
want: true,
},
{
name: `inside`,
r: Rect{100, 200, 300, 400},
t: Rect{120, 180, 320, 380},
want: true,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.want, tc.r.IsContainsRectangle(tc.t))
assert.Equal(t, tc.want, tc.r.IsIntersectsRect(tc.t))
})
}
}

func TestRect_RectsIntersection(t *testing.T) {
tests := []struct {
name string
r Rect
t Rect
want Rect
ok bool
}{
{
name: `true`,
r: Rect{100, 200, 300, 400},
t: Rect{150, 250, 350, 450},
want: Rect{150, 200, 350, 400},
ok: true,
},
{
name: `same`,
r: Rect{100, 200, 300, 400},
t: Rect{100, 200, 300, 400},
want: Rect{100, 200, 300, 400},
ok: true,
},
{
name: `second>first`,
r: Rect{100, 200, 300, 400},
t: Rect{120, 180, 320, 380},
want: Rect{120, 180, 320, 380},
ok: true,
},
{
name: `first>second`,
r: Rect{100, 200, 300, 400},
t: Rect{80, 220, 280, 420},
want: Rect{100, 200, 300, 400},
ok: true,
},
{
name: `line`,
r: Rect{100, 200, 300, 400},
t: Rect{200, 300, 300, 400},
ok: false,
},
{
name: `point`,
r: Rect{100, 200, 300, 400},
t: Rect{200, 300, 200, 300},
ok: false,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got, ok := tc.r.RectsIntersection(tc.t)
assert.Equal(t, tc.ok, ok)
assert.Equal(t, tc.want, got)
})
}
}

func TestRectangle_String(t *testing.T) {
r := Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400}
func TestRect_Vertices(t *testing.T) {
r := Rect{100, 200, 300, 400}
assert.Equal(t, Points{
topLeft0: {100, 400},
topRight0: {200, 400},
bottomRight0: {200, 300},
bottomLeft0: {100, 300},
}, r.Vertices())
}

func TestRect_Edges(t *testing.T) {
r := Rect{100, 200, 300, 400}
assert.Equal(t, Lines{
top: {Point{100, 400}, Point{200, 400}},
right: {Point{200, 300}, Point{200, 400}},
bottom: {Point{100, 300}, Point{200, 300}},
left: {Point{100, 300}, Point{100, 400}},
}, r.Edges())
}

func TestRect_String(t *testing.T) {
r := Rect{100, 200, 300, 400}
assert.Equal(t, `[X:100>200,Y:300>400]`, r.String())
}

Expand All @@ -133,15 +218,15 @@ func TestNewRectangle(t *testing.T) {
xt: 200,
yf: 300,
yt: 400,
want: Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400},
want: Rect{100, 200, 300, 400},
},
{
name: `reverse`,
xf: 200,
xt: 100,
yf: 400,
yt: 300,
want: Rect{Xf: 100, Xt: 200, Yf: 300, Yt: 400},
want: Rect{100, 200, 300, 400},
},
}

Expand Down

0 comments on commit fa425eb

Please sign in to comment.