From 40115fbc8c7899f8a3a89ef8a3347644862125bb Mon Sep 17 00:00:00 2001 From: Fraser Graham Date: Fri, 27 Sep 2013 01:31:35 -0700 Subject: [PATCH] rect intersections tests --- govector_test.go | 67 +++++++++++++++++++++++++++++++++++++++++++++--- vectorpoint.go | 42 ++++++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/govector_test.go b/govector_test.go index e0a458d..037d64d 100644 --- a/govector_test.go +++ b/govector_test.go @@ -139,7 +139,7 @@ func TestAngle(t *testing.T) { a := Angle(v2, v1) fmt.Printf("%v %v %f\n", v1, v2, a*Rad2deg) - if math.Abs(a)-math.Pi/2 > epsilon { + if math.Abs(a)-math.Pi/2 > Epsilon { t.Errorf("Angle Error") } @@ -150,7 +150,7 @@ func TestAngle(t *testing.T) { fmt.Printf("%v %v %f\n", v1, v2, a*Rad2deg) - if math.Abs(a)-math.Pi/4 > epsilon { + if math.Abs(a)-math.Pi/4 > Epsilon { t.Errorf("Angle Error") } @@ -161,7 +161,7 @@ func TestRotate(t *testing.T) { v2 := v1.Rotate(math.Pi / 2) fmt.Printf("%v %v\n", v1, v2) - if v2.X > epsilon || v2.Y-10 > epsilon { + if v2.X > Epsilon || v2.Y-10 > Epsilon { t.Errorf("Rotate Error") } @@ -169,7 +169,66 @@ func TestRotate(t *testing.T) { v2 = v1.Rotate(-30 * Deg2rad) fmt.Printf("%v %v\n", v1, v2) - if v2.X-0.866025403784438 > epsilon || v2.Y+0.5 > epsilon { + if v2.X-0.866025403784438 > Epsilon || v2.Y+0.5 > Epsilon { t.Errorf("Rotate Error") } } + +func TestPtInRect(t *testing.T) { + p1 := Point2d{10, 0} + p2 := Point2d{10, 10} + p3 := Point2d{11, 10000} + p4 := Point2d{0, 0} + + pA := Point2d{5, 5} + pB := Point2d{15, 15} + r := Rect2d{ + A: pA, + B: pB, + } + + fmt.Printf("%v %v\n", p1, r) + out := PointInRect(p1, r) + if out != false { + t.Errorf("PointInRect Error") + } + out = PointInRect(p2, r) + if out != true { + t.Errorf("PointInRect Error") + } + out = PointInRect(p3, r) + if out != false { + t.Errorf("PointInRect Error") + } + out = PointInRect(p4, r) + if out != false { + t.Errorf("PointInRect Error") + } +} + +func TestRectIntersect(t *testing.T) { + p1 := Point2d{10, 0} + v1 := Vector2d{0, 10} + + pA := Point2d{5, 5} + pB := Point2d{15, 15} + r := Rect2d{ + A: pA, + B: pB, + } + + fmt.Printf("%v %v\n", p1, r) + coll, inside, pos := RectIntersection(r, p1, v1) + if coll != true { + fmt.Printf("Coll Err %v %v %v\n", inside, coll, pos) + t.Errorf("RectIntersection Error") + } + if inside != false { + fmt.Printf("Inside Err %v %v %v\n", inside, coll, pos) + t.Errorf("RectIntersection Error") + } + if pos.X != 10 && pos.Y != 5 { + fmt.Printf("Pos Err %v %v %v\n", inside, coll, pos) + t.Errorf("RectIntersection Error") + } +} diff --git a/vectorpoint.go b/vectorpoint.go index e5e204f..8f38a1d 100644 --- a/vectorpoint.go +++ b/vectorpoint.go @@ -5,10 +5,8 @@ import ( ) type Rect2d struct { - X1 float64 `json:"x1"` - Y1 float64 `json:"y1"` - X2 float64 `json:"x2"` - Y2 float64 `json:"y2"` + A Point2d `json:A` + B Point2d `json:B` } type Vector2d struct { @@ -21,7 +19,7 @@ type Point2d struct { Y float64 `json:"y"` } -const epsilon = 1e-7 +const Epsilon = 1e-7 const Rad2deg = 180 / math.Pi const Deg2rad = math.Pi / 180 @@ -69,6 +67,40 @@ func Intersection(p1, p2 Point2d, v1, v2 Vector2d) (bool, Point2d) { return false, Point2d{0, 0} } +func PointInRect(p Point2d, r Rect2d) bool { + return (p.X > r.A.X) && (p.X < r.B.X) && (p.Y > r.A.Y) && (p.Y < r.B.Y) +} + +func RectIntersection(r Rect2d, p Point2d, v Vector2d) (bool, bool, Point2d) { + collision := false + inside := false + start_inside := PointInRect(p, r) + end_inside := PointInRect(p.Add(v), r) + if start_inside && end_inside { + inside = true + return collision, inside, Point2d{X: 0, Y: 0} + } else { + wall_left, col1 := Intersection(p, r.A, v, Vector2d{X: 0, Y: r.B.Y}) + if wall_left { + return wall_left, inside, col1 + } + wall_top, col2 := Intersection(p, r.A, v, Vector2d{X: r.B.X, Y: 0}) + if wall_top { + return wall_top, inside, col2 + } + wall_right, col3 := Intersection(p, r.B, v, Vector2d{X: 0, Y: -r.B.Y}) + if wall_right { + return wall_right, inside, col3 + } + wall_bottom, col4 := Intersection(p, r.B, v, Vector2d{X: -r.B.X, Y: 0}) + if wall_bottom { + return wall_bottom, inside, col4 + } + + return false, false, Point2d{X: 0, Y: 0} + } +} + func (v Vector2d) Normalize() Vector2d { if v.X == 0 && v.Y == 0 { return v