fixing line intersect function

This commit is contained in:
Ben Cragg 2019-04-03 16:21:57 +01:00
parent c3e69c4f35
commit 83c62a0313
2 changed files with 118 additions and 20 deletions

View File

@ -314,38 +314,26 @@ func (l Line) Intersect(k Line) (Vec, bool) {
return ZV, false
}
var x, y float64
if math.IsInf(math.Abs(lm), 1) || math.IsInf(math.Abs(km), 1) {
// One line is vertical
intersectM := lm
intersectB := lb
verticalLine := k
if math.IsInf(math.Abs(lm), 1) {
intersectM = km
intersectB = kb
verticalLine = l
}
maxVerticalY := verticalLine.A.Y
minVerticalY := verticalLine.B.Y
if verticalLine.B.Y > maxVerticalY {
maxVerticalY = verticalLine.B.Y
minVerticalY = verticalLine.A.Y
}
y := intersectM*l.A.X + intersectB
if y > maxVerticalY || y < minVerticalY {
// Point is not on the horizontal line
return ZV, false
}
return V(l.A.X, y), true
y = intersectM*l.A.X + intersectB
x = l.A.X
} else {
// Coordinates of intersect
x = (kb - lb) / (lm - km)
y = lm*x + lb
}
// Coordinates of intersect
x := (kb - lb) / (lm - km)
y := lm*x + lb
if l.Contains(V(x, y)) && k.Contains(V(x, y)) {
// The intersect point is on both line segments, they intersect.
return V(x, y), true
@ -619,6 +607,28 @@ func (r Rect) IntersectLine(l Line) Vec {
return l.IntersectRect(r).Scaled(-1)
}
// IntersectionPoints returns all the points where the Rect intersects with the line provided. This can be zero, one or
// two points, depending on the location of the shapes.
func (r Rect) IntersectionPoints(l Line) []Vec {
// Use map keys to ensure unique points
pointMap := make(map[Vec]struct{})
for _, edge := range r.Edges() {
if intersect, ok := edge.Intersect(l); ok {
fmt.Println(edge)
fmt.Println(l)
fmt.Println(intersect)
pointMap[intersect] = struct{}{}
}
}
points := make([]Vec, 0, len(pointMap))
for point := range pointMap {
points = append(points, point)
}
return points
}
// Vertices returns a slice of the four corners which make up the rectangle.
func (r Rect) Vertices() [4]Vec {
return [4]Vec{
@ -858,6 +868,12 @@ func (c Circle) IntersectRect(r Rect) Vec {
}
}
// IntersectionPoints returns all the points where the Circle intersects with the line provided. This can be zero, one or
// two points, depending on the location of the shapes.
func (c Circle) IntersectionPoints(l Line) []Vec {
return []Vec{}
}
// Matrix is a 2x3 affine matrix that can be used for all kinds of spatial transforms, such
// as movement, scaling and rotations.
//

View File

@ -609,6 +609,35 @@ func TestCircle_Intersect(t *testing.T) {
}
}
func TestCircle_IntersectPoints(t *testing.T) {
type fields struct {
Center pixel.Vec
Radius float64
}
type args struct {
l pixel.Line
}
tests := []struct {
name string
fields fields
args args
want []pixel.Vec
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := pixel.Circle{
Center: tt.fields.Center,
Radius: tt.fields.Radius,
}
if got := c.IntersectionPoints(tt.args.l); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Circle.IntersectPoints() = %v, want %v", got, tt.want)
}
})
}
}
func TestRect_IntersectCircle(t *testing.T) {
// closeEnough will shift the decimal point by the accuracy required, truncates the results and compares them.
// Effectively this compares two floats to a given decimal point.
@ -759,6 +788,52 @@ func TestRect_IntersectCircle(t *testing.T) {
}
}
func TestRect_IntersectionPoints(t *testing.T) {
type fields struct {
Min pixel.Vec
Max pixel.Vec
}
type args struct {
l pixel.Line
}
tests := []struct {
name string
fields fields
args args
want []pixel.Vec
}{
{
name: "No intersection points",
fields: fields{Min: pixel.V(1, 1), Max: pixel.V(5, 5)},
args: args{l: pixel.L(pixel.V(-5, 0), pixel.V(-2, 2))},
want: []pixel.Vec{},
},
// {
// name: "One intersection point",
// fields: fields{Min: pixel.V(1, 1), Max: pixel.V(5, 5)},
// args: args{l: pixel.L(pixel.V(2, 0), pixel.V(2, 2))},
// want: []pixel.Vec{pixel.V(2, 1)},
// },
// {
// name: "Two intersection points",
// fields: fields{Min: pixel.V(1, 1), Max: pixel.V(5, 5)},
// args: args{l: pixel.L(pixel.V(0, 2), pixel.V(6, 2))},
// want: []pixel.Vec{pixel.V(1, 2), pixel.V(5, 2)},
// },
}
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.IntersectionPoints(tt.args.l); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Rect.IntersectPoints() = %v, want %v", got, tt.want)
}
})
}
}
func TestLine_Bounds(t *testing.T) {
type fields struct {
A pixel.Vec
@ -1008,6 +1083,13 @@ func TestLine_Intersect(t *testing.T) {
want: pixel.V(5, 5),
want1: true,
},
{
name: "Lines intersect 2",
fields: fields{A: pixel.V(1, 1), B: pixel.V(1, 5)},
args: args{k: pixel.L(pixel.V(-5, 0), pixel.V(-2, 2))},
want: pixel.ZV,
want1: false,
},
{
name: "Line intersect with vertical",
fields: fields{A: pixel.V(5, 0), B: pixel.V(5, 10)},