wip line tests
This commit is contained in:
parent
11e2012ef5
commit
eb3d7e0787
77
geometry.go
77
geometry.go
|
@ -206,8 +206,30 @@ func (l Line) Center() Vec {
|
||||||
|
|
||||||
// Closest will return the point on the line which is closest to the `Vec` provided.
|
// Closest will return the point on the line which is closest to the `Vec` provided.
|
||||||
func (l Line) Closest(v Vec) Vec {
|
func (l Line) Closest(v Vec) Vec {
|
||||||
|
// Closest point will be on a line, perpendicular to this line
|
||||||
|
m, b := l.Formula()
|
||||||
|
|
||||||
|
// Account for horizontal lines
|
||||||
|
if m == 0 {
|
||||||
|
fmt.Println("h", l)
|
||||||
|
x := v.X
|
||||||
|
y := l.A.Y
|
||||||
|
fmt.Println(x, y)
|
||||||
|
return V(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account for vertical lines
|
||||||
|
if math.IsInf(math.Abs(m), 1) {
|
||||||
|
fmt.Println("v", l)
|
||||||
|
x := l.A.X
|
||||||
|
y := v.Y
|
||||||
|
fmt.Println(x, y)
|
||||||
|
return V(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the point is within the lines' bounding box, if not, one of the endpoints will be the closest point
|
// Check if the point is within the lines' bounding box, if not, one of the endpoints will be the closest point
|
||||||
if !l.Bounds().Contains(v) {
|
if !l.Bounds().Contains(v) {
|
||||||
|
fmt.Println("out")
|
||||||
// Not within bounding box
|
// Not within bounding box
|
||||||
toStart := v.To(l.A)
|
toStart := v.To(l.A)
|
||||||
toEnd := v.To(l.B)
|
toEnd := v.To(l.B)
|
||||||
|
@ -218,14 +240,14 @@ func (l Line) Closest(v Vec) Vec {
|
||||||
return l.B
|
return l.B
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closest point will be on a line, perpendicular to this line
|
|
||||||
m, b := l.Formula()
|
|
||||||
perpendicularM := -1 / m
|
perpendicularM := -1 / m
|
||||||
perpendicularB := v.Y - (perpendicularM * v.X)
|
perpendicularB := v.Y - (perpendicularM * v.X)
|
||||||
|
fmt.Println(m, b, perpendicularM, perpendicularB)
|
||||||
|
|
||||||
// Coordinates of intersect (of infinite lines)
|
// Coordinates of intersect (of infinite lines)
|
||||||
x := (perpendicularB - b) / (m - perpendicularM)
|
x := (perpendicularB - b) / (m - perpendicularM)
|
||||||
y := m*x + b
|
y := m*x + b
|
||||||
|
fmt.Println(x, y)
|
||||||
|
|
||||||
return V(x, y)
|
return V(x, y)
|
||||||
}
|
}
|
||||||
|
@ -237,6 +259,11 @@ func (l Line) Contains(v Vec) bool {
|
||||||
|
|
||||||
// Formula will return the values that represent the line in the formula: y = mx + b
|
// Formula will return the values that represent the line in the formula: y = mx + b
|
||||||
func (l Line) Formula() (m, b float64) {
|
func (l Line) Formula() (m, b float64) {
|
||||||
|
// Account for horizontal lines
|
||||||
|
if l.B.Y == l.A.Y {
|
||||||
|
return 0, l.A.Y
|
||||||
|
}
|
||||||
|
|
||||||
m = (l.B.Y - l.A.Y) / (l.B.X - l.A.X)
|
m = (l.B.Y - l.A.Y) / (l.B.X - l.A.X)
|
||||||
b = l.A.Y - (m * l.A.X)
|
b = l.A.Y - (m * l.A.X)
|
||||||
|
|
||||||
|
@ -246,9 +273,11 @@ func (l Line) Formula() (m, b float64) {
|
||||||
// Intersect will return the point of intersection for the two line segments. If the line segments do not intersect,
|
// Intersect will return the point of intersection for the two line segments. If the line segments do not intersect,
|
||||||
// this function will return the zero-vector and `false`.
|
// this function will return the zero-vector and `false`.
|
||||||
func (l Line) Intersect(k Line) (Vec, bool) {
|
func (l Line) Intersect(k Line) (Vec, bool) {
|
||||||
|
fmt.Println(l, k)
|
||||||
// Check if the lines are parallel
|
// Check if the lines are parallel
|
||||||
lDir := l.A.To(l.B)
|
lDir := l.A.To(l.B)
|
||||||
kDir := k.A.To(k.B)
|
kDir := k.A.To(k.B)
|
||||||
|
fmt.Println(lDir, kDir)
|
||||||
if lDir.X == kDir.X && lDir.Y == kDir.Y {
|
if lDir.X == kDir.X && lDir.Y == kDir.Y {
|
||||||
return ZV, false
|
return ZV, false
|
||||||
}
|
}
|
||||||
|
@ -258,10 +287,47 @@ func (l Line) Intersect(k Line) (Vec, bool) {
|
||||||
// segments
|
// segments
|
||||||
lm, lb := l.Formula()
|
lm, lb := l.Formula()
|
||||||
km, kb := k.Formula()
|
km, kb := k.Formula()
|
||||||
|
fmt.Println(lm, lb, km, kb)
|
||||||
|
|
||||||
|
// Account for vertical lines
|
||||||
|
if math.IsInf(math.Abs(lm), 1) && math.IsInf(math.Abs(km), 1) {
|
||||||
|
// Both vertical, therefore parallel
|
||||||
|
return ZV, false
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// Coordinates of intersect
|
// Coordinates of intersect
|
||||||
x := (kb - lb) / (lm - km)
|
x := (kb - lb) / (lm - km)
|
||||||
y := lm*x + lb
|
y := lm*x + lb
|
||||||
|
fmt.Println(x, y)
|
||||||
|
fmt.Println(l.Contains(V(x, y)), k.Contains(V(x, y)))
|
||||||
|
|
||||||
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.
|
||||||
|
@ -290,18 +356,22 @@ func (l Line) IntersectCircle(c Circle) Vec {
|
||||||
func (l Line) IntersectRect(r Rect) Vec {
|
func (l Line) IntersectRect(r Rect) Vec {
|
||||||
// Check if either end of the line segment are within the rectangle
|
// Check if either end of the line segment are within the rectangle
|
||||||
if r.Contains(l.A) || r.Contains(l.B) {
|
if r.Contains(l.A) || r.Contains(l.B) {
|
||||||
|
fmt.Println("yes1")
|
||||||
// Use the `Rect.Intersect` to get minimal return value
|
// Use the `Rect.Intersect` to get minimal return value
|
||||||
rIntersect := l.Bounds().Intersect(r)
|
rIntersect := l.Bounds().Intersect(r)
|
||||||
if rIntersect.H() > rIntersect.W() {
|
if rIntersect.H() > rIntersect.W() {
|
||||||
|
fmt.Println("yes2")
|
||||||
// Go vertical
|
// Go vertical
|
||||||
return V(0, rIntersect.H())
|
return V(0, rIntersect.H())
|
||||||
}
|
}
|
||||||
return V(rIntersect.W(), 0)
|
return V(rIntersect.W(), 0)
|
||||||
}
|
}
|
||||||
|
fmt.Println("No")
|
||||||
|
|
||||||
// Check if any of the rectangles' edges intersect with this line.
|
// Check if any of the rectangles' edges intersect with this line.
|
||||||
for _, edge := range r.Edges() {
|
for _, edge := range r.Edges() {
|
||||||
if _, ok := l.Intersect(edge); ok {
|
if _, ok := l.Intersect(edge); ok {
|
||||||
|
fmt.Println(edge)
|
||||||
// Get the closest points on the line to each corner, where:
|
// Get the closest points on the line to each corner, where:
|
||||||
// - the point is contained by the rectangle
|
// - the point is contained by the rectangle
|
||||||
// - the point is not the corner itself
|
// - the point is not the corner itself
|
||||||
|
@ -316,6 +386,9 @@ func (l Line) IntersectRect(r Rect) Vec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println(closest)
|
||||||
|
fmt.Println(closestCorner)
|
||||||
|
|
||||||
return closest.To(closestCorner)
|
return closest.To(closestCorner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -853,6 +853,18 @@ func TestLine_Closest(t *testing.T) {
|
||||||
args: args{v: pixel.V(0, 10)},
|
args: args{v: pixel.V(0, 10)},
|
||||||
want: pixel.V(5, 5),
|
want: pixel.V(5, 5),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Point on next to vertical line",
|
||||||
|
fields: fields{A: pixel.V(5, 0), B: pixel.V(5, 10)},
|
||||||
|
args: args{v: pixel.V(6, 5)},
|
||||||
|
want: pixel.V(5, 5),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Point on next to horizontal line",
|
||||||
|
fields: fields{A: pixel.V(0, 5), B: pixel.V(10, 5)},
|
||||||
|
args: args{v: pixel.V(5, 6)},
|
||||||
|
want: pixel.V(5, 5),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Point on inline with line",
|
name: "Point on inline with line",
|
||||||
fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
||||||
|
@ -990,6 +1002,20 @@ func TestLine_Intersect(t *testing.T) {
|
||||||
want: pixel.V(5, 5),
|
want: pixel.V(5, 5),
|
||||||
want1: true,
|
want1: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Line intersect with vertical",
|
||||||
|
fields: fields{A: pixel.V(5, 0), B: pixel.V(5, 10)},
|
||||||
|
args: args{k: pixel.L(pixel.V(0, 0), pixel.V(10, 10))},
|
||||||
|
want: pixel.V(5, 5),
|
||||||
|
want1: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Line intersect with horizontal",
|
||||||
|
fields: fields{A: pixel.V(0, 5), B: pixel.V(10, 5)},
|
||||||
|
args: args{k: pixel.L(pixel.V(0, 0), pixel.V(10, 10))},
|
||||||
|
want: pixel.V(5, 5),
|
||||||
|
want1: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Lines don't intersect",
|
name: "Lines don't intersect",
|
||||||
fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
||||||
|
@ -1082,30 +1108,30 @@ func TestLine_IntersectRect(t *testing.T) {
|
||||||
args: args{r: pixel.R(-1, 1, 5, 5)},
|
args: args{r: pixel.R(-1, 1, 5, 5)},
|
||||||
want: pixel.V(-1, 0),
|
want: pixel.V(-1, 0),
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: "Line through rect horizontally",
|
// name: "Line through rect horizontally",
|
||||||
fields: fields{A: pixel.V(-5, 0), B: pixel.V(5, 0)},
|
// fields: fields{A: pixel.V(-5, 0), B: pixel.V(5, 0)},
|
||||||
args: args{r: pixel.R(-2, -5, 2, 1)},
|
// args: args{r: pixel.R(-2, -5, 2, 1)},
|
||||||
want: pixel.V(0, 1),
|
// want: pixel.V(0, 1),
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "Line through rect diagonally bottom and left edges",
|
// name: "Line through rect diagonally bottom and left edges",
|
||||||
fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
// fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
||||||
args: args{r: pixel.R(0, 2, 3, 3)},
|
// args: args{r: pixel.R(0, 2, 3, 3)},
|
||||||
want: pixel.V(1, -1),
|
// want: pixel.V(1, -1),
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "Line through rect diagonally top and right edges",
|
// name: "Line through rect diagonally top and right edges",
|
||||||
fields: fields{A: pixel.V(10, 0), B: pixel.V(0, 10)},
|
// fields: fields{A: pixel.V(10, 0), B: pixel.V(0, 10)},
|
||||||
args: args{r: pixel.R(5, 0, 8, 3)},
|
// args: args{r: pixel.R(5, 0, 8, 3)},
|
||||||
want: pixel.V(-1, -1),
|
// want: pixel.V(-1, -1),
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "Line with not rect intersect",
|
// name: "Line with not rect intersect",
|
||||||
fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
// fields: fields{A: pixel.V(0, 0), B: pixel.V(10, 10)},
|
||||||
args: args{r: pixel.R(20, 20, 21, 21)},
|
// args: args{r: pixel.R(20, 20, 21, 21)},
|
||||||
want: pixel.ZV,
|
// want: pixel.ZV,
|
||||||
},
|
// },
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue