From 3d8e58a61c2ad7d6e2eb32eefddc99f8272dcb32 Mon Sep 17 00:00:00 2001 From: Derek McQuay Date: Sat, 27 Aug 2016 18:55:26 -0700 Subject: [PATCH] added function to get intersection of two lines --- point.go | 33 ++++++++++++++++++++++++++++++++- point_test.go | 23 +++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/point.go b/point.go index ce2881e..02ec13f 100644 --- a/point.go +++ b/point.go @@ -1,6 +1,9 @@ package rect -import "math" +import ( + "fmt" + "math" +) type Point struct { X, Y float64 @@ -25,6 +28,34 @@ func onLine(rp1, rp2, p Point) bool { return false } +func lineHelper(l line) (float64, float64, float64) { + a := l.pt2.Y - l.pt1.Y + b := l.pt1.X - l.pt2.X + c := a*l.pt1.X + b*l.pt1.Y + return a, b, c +} + +func lineIntersection(l1, l2 line) (Point, error) { + a1, b1, c1 := lineHelper(l1) + a2, b2, c2 := lineHelper(l2) + det := a1*b2 - a2*b1 + + if det != 0 { + x := ((b2*c1 - b1*c2) / det) + y := ((a1*c2 - a2*c1) / det) + minx1, maxx1 := math.Min(l1.pt1.X, l1.pt2.X), math.Max(l1.pt1.X, l1.pt2.X) + miny1, maxy1 := math.Min(l1.pt1.Y, l1.pt2.Y), math.Max(l1.pt1.Y, l1.pt2.Y) + minx2, maxx2 := math.Min(l2.pt1.X, l2.pt2.X), math.Max(l2.pt1.X, l2.pt2.X) + miny2, maxy2 := math.Min(l2.pt1.Y, l2.pt2.Y), math.Max(l2.pt1.Y, l2.pt2.Y) + if minx1 <= x && x <= maxx1 && miny1 <= y && y <= maxy1 { + if minx2 <= x && x <= maxx2 && miny2 <= y && y <= maxy2 { + return Point{x, y}, nil + } + } + } + return Point{}, fmt.Errorf("lines do not intersect") +} + func lineOnLine(l1, l2 line) bool { if onLine(l1.pt1, l1.pt2, l2.pt1) && onLine(l1.pt1, l1.pt2, l2.pt2) { return true diff --git a/point_test.go b/point_test.go index ede848b..954c82f 100644 --- a/point_test.go +++ b/point_test.go @@ -50,3 +50,26 @@ func TestOnLine(t *testing.T) { } } + +func TestLineIntersection(t *testing.T) { + var lineIntersectionTest = []struct { + l []line + expected Point + }{ + {[]line{line{Point{0, 0}, Point{2, 2}}, line{Point{2, 0}, Point{0, 2}}}, Point{1, 1}}, + {[]line{line{Point{0, 0}, Point{-2, -2}}, line{Point{-2, 0}, Point{0, -2}}}, Point{-1, -1}}, + {[]line{line{Point{0, 0}, Point{-2, -2}}, line{Point{1, 0}, Point{1, -7}}}, Point{0, 0}}, + {[]line{line{Point{5, 8}, Point{8, 5}}, line{Point{3, 7}, Point{7, 3}}}, Point{0, 0}}, + } + for _, rt := range lineIntersectionTest { + actual := lineIntersection(rt.l[0], rt.l[1]) + if actual != rt.expected { + t.Errorf( + "failed spiral:\n\texpected: %f\n\t actual: %f", + rt.expected, + actual, + ) + } + + } +}