added rect-circle intersection functions
This commit is contained in:
parent
fdc068e855
commit
9a32601c6b
32
geometry.go
32
geometry.go
|
@ -310,6 +310,16 @@ func (r Rect) Intersect(s Rect) Rect {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IntersectsCircle returns whether the Circle and the Rect intersect.
|
||||||
|
//
|
||||||
|
// This function will return true if:
|
||||||
|
// - The Rect contains the Circle, partially or fully
|
||||||
|
// - The Circle contains the Rect, partially of fully
|
||||||
|
// - An edge of the Rect is a tangent to the Circle
|
||||||
|
func (r Rect) IntersectsCircle(c Circle) bool {
|
||||||
|
return c.IntersectsRect(r)
|
||||||
|
}
|
||||||
|
|
||||||
// Circle is a 2D circle. It is defined by two properties:
|
// Circle is a 2D circle. It is defined by two properties:
|
||||||
// - Radius float64
|
// - Radius float64
|
||||||
// - Center vector
|
// - Center vector
|
||||||
|
@ -462,6 +472,28 @@ func (c Circle) Intersect(d Circle) Circle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IntersectsRect returns whether the Circle and the Rect intersect.
|
||||||
|
//
|
||||||
|
// This function will return true if:
|
||||||
|
// - The Rect contains the Circle, partially or fully
|
||||||
|
// - The Circle contains the Rect, partially of fully
|
||||||
|
// - An edge of the Rect is a tangent to the Circle
|
||||||
|
func (c Circle) IntersectsRect(r Rect) bool {
|
||||||
|
// Checks if the c.Center is not in the diagonal quadrants of the rectangle
|
||||||
|
var grownR Rect
|
||||||
|
if (r.Min.X <= c.Center.X && c.Center.X <= r.Max.X) || (r.Min.Y <= c.Center.Y && c.Center.Y <= r.Max.Y) {
|
||||||
|
// 'grow' the Rect by c.Radius in each diagonal
|
||||||
|
grownR = Rect{
|
||||||
|
Min: r.Min.Sub(V(c.Radius, c.Radius)),
|
||||||
|
Max: r.Max.Add(V(c.Radius, c.Radius)),
|
||||||
|
}
|
||||||
|
|
||||||
|
return grownR.Contains(c.Center)
|
||||||
|
}
|
||||||
|
// The center is in the diagonal quadrants
|
||||||
|
return c.Center.To(r.Min).Len() <= c.Radius || c.Center.To(r.Max).Len() <= c.Radius
|
||||||
|
}
|
||||||
|
|
||||||
// Matrix is a 2x3 affine matrix that can be used for all kinds of spatial transforms, such
|
// Matrix is a 2x3 affine matrix that can be used for all kinds of spatial transforms, such
|
||||||
// as movement, scaling and rotations.
|
// as movement, scaling and rotations.
|
||||||
//
|
//
|
||||||
|
|
|
@ -492,3 +492,73 @@ func TestCircle_Intersect(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRect_IntersectsCircle(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
Min pixel.Vec
|
||||||
|
Max pixel.Vec
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
c pixel.Circle
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Rect.IntersectsCircle(): no overlap",
|
||||||
|
fields: fields{Min: pixel.V(0, 0), Max: pixel.V(10, 10)},
|
||||||
|
args: args{c: pixel.C(1, pixel.V(50, 50))},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rect.IntersectsCircle(): circle contains rect",
|
||||||
|
fields: fields{Min: pixel.V(0, 0), Max: pixel.V(10, 10)},
|
||||||
|
args: args{c: pixel.C(10, pixel.V(5, 5))},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rect.IntersectsCircle(): rect contains circle",
|
||||||
|
fields: fields{Min: pixel.V(0, 0), Max: pixel.V(10, 10)},
|
||||||
|
args: args{c: pixel.C(1, pixel.V(5, 5))},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rect.IntersectsCircle(): circle overlaps one corner",
|
||||||
|
fields: fields{Min: pixel.V(0, 0), Max: pixel.V(10, 10)},
|
||||||
|
args: args{c: pixel.C(1, pixel.V(0, 0))},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rect.IntersectsCircle(): circle overlaps two corner",
|
||||||
|
fields: fields{Min: pixel.V(0, 0), Max: pixel.V(10, 10)},
|
||||||
|
args: args{c: pixel.C(11, pixel.V(0, 5))},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rect.IntersectsCircle(): circle overlaps one edge",
|
||||||
|
fields: fields{Min: pixel.V(0, 0), Max: pixel.V(10, 10)},
|
||||||
|
args: args{c: pixel.C(1, pixel.V(0, 5))},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rect.IntersectsCircle(): edge is tangent",
|
||||||
|
fields: fields{Min: pixel.V(0, 0), Max: pixel.V(10, 10)},
|
||||||
|
args: args{c: pixel.C(1, pixel.V(-1, 5))},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := pixel.Rect{
|
||||||
|
Min: tt.fields.Min,
|
||||||
|
Max: tt.fields.Max,
|
||||||
|
}
|
||||||
|
if got := r.IntersectsCircle(tt.args.c); got != tt.want {
|
||||||
|
t.Errorf("Rect.IntersectsCircle() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue