fixing line intersect function
This commit is contained in:
parent
c3e69c4f35
commit
83c62a0313
56
geometry.go
56
geometry.go
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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)},
|
||||
|
|
Loading…
Reference in New Issue