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
|
return ZV, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var x, y float64
|
||||||
|
|
||||||
if math.IsInf(math.Abs(lm), 1) || math.IsInf(math.Abs(km), 1) {
|
if math.IsInf(math.Abs(lm), 1) || math.IsInf(math.Abs(km), 1) {
|
||||||
// One line is vertical
|
// One line is vertical
|
||||||
intersectM := lm
|
intersectM := lm
|
||||||
intersectB := lb
|
intersectB := lb
|
||||||
verticalLine := k
|
|
||||||
|
|
||||||
if math.IsInf(math.Abs(lm), 1) {
|
if math.IsInf(math.Abs(lm), 1) {
|
||||||
intersectM = km
|
intersectM = km
|
||||||
intersectB = kb
|
intersectB = kb
|
||||||
verticalLine = l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maxVerticalY := verticalLine.A.Y
|
y = intersectM*l.A.X + intersectB
|
||||||
minVerticalY := verticalLine.B.Y
|
x = l.A.X
|
||||||
if verticalLine.B.Y > maxVerticalY {
|
} else {
|
||||||
maxVerticalY = verticalLine.B.Y
|
// Coordinates of intersect
|
||||||
minVerticalY = verticalLine.A.Y
|
x = (kb - lb) / (lm - km)
|
||||||
}
|
y = lm*x + lb
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coordinates of intersect
|
|
||||||
x := (kb - lb) / (lm - km)
|
|
||||||
y := lm*x + lb
|
|
||||||
|
|
||||||
if l.Contains(V(x, y)) && k.Contains(V(x, y)) {
|
if l.Contains(V(x, y)) && k.Contains(V(x, y)) {
|
||||||
// The intersect point is on both line segments, they intersect.
|
// The intersect point is on both line segments, they intersect.
|
||||||
return V(x, y), true
|
return V(x, y), true
|
||||||
|
@ -619,6 +607,28 @@ func (r Rect) IntersectLine(l Line) Vec {
|
||||||
return l.IntersectRect(r).Scaled(-1)
|
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.
|
// Vertices returns a slice of the four corners which make up the rectangle.
|
||||||
func (r Rect) Vertices() [4]Vec {
|
func (r Rect) Vertices() [4]Vec {
|
||||||
return [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
|
// 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.
|
||||||
//
|
//
|
||||||
|
|
|
@ -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) {
|
func TestRect_IntersectCircle(t *testing.T) {
|
||||||
// closeEnough will shift the decimal point by the accuracy required, truncates the results and compares them.
|
// 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.
|
// 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) {
|
func TestLine_Bounds(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
A pixel.Vec
|
A pixel.Vec
|
||||||
|
@ -1008,6 +1083,13 @@ func TestLine_Intersect(t *testing.T) {
|
||||||
want: pixel.V(5, 5),
|
want: pixel.V(5, 5),
|
||||||
want1: true,
|
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",
|
name: "Line intersect with vertical",
|
||||||
fields: fields{A: pixel.V(5, 0), B: pixel.V(5, 10)},
|
fields: fields{A: pixel.V(5, 0), B: pixel.V(5, 10)},
|
||||||
|
|
Loading…
Reference in New Issue