changed permission on func and added maximum error

made sure that not all functions were public and changed some to private
that need not be exposed.

also added in maximum error to deal with floating point inaccuracies
This commit is contained in:
Derek McQuay 2016-08-27 20:46:32 -07:00
parent 3850bdc592
commit 9b908a8db1
4 changed files with 26 additions and 23 deletions

View File

@ -11,7 +11,7 @@ func distance(p1, p2 Point) float64 {
} }
func onLine(rp1, rp2, p Point) bool { func onLine(rp1, rp2, p Point) bool {
if distance(rp1, p)+distance(rp2, p) == distance(rp1, rp2) { if math.Abs(distance(rp1, p)+distance(rp2, p)-distance(rp1, rp2)) < ɛ {
minx, maxx := math.Min(rp1.X, rp2.X), math.Max(rp1.X, rp2.X) minx, maxx := math.Min(rp1.X, rp2.X), math.Max(rp1.X, rp2.X)
miny, maxy := math.Min(rp1.Y, rp2.Y), math.Max(rp1.Y, rp2.Y) miny, maxy := math.Min(rp1.Y, rp2.Y), math.Max(rp1.Y, rp2.Y)
if minx <= p.X && p.X <= maxx && miny <= p.Y && p.Y <= maxy { if minx <= p.X && p.X <= maxx && miny <= p.Y && p.Y <= maxy {

View File

@ -9,7 +9,10 @@ type Rectangle struct {
P1, P2, P3, P4 Point P1, P2, P3, P4 Point
} }
func (r Rectangle) IsRect() bool { // maximum error used for floating point math
var ɛ = 0.00001
func (r Rectangle) isRect() bool {
// make sure they aren't all just the same point // make sure they aren't all just the same point
if (r.P1.X == r.P2.X && r.P1.X == r.P3.X && r.P1.X == r.P4.X) && if (r.P1.X == r.P2.X && r.P1.X == r.P3.X && r.P1.X == r.P4.X) &&
(r.P1.Y == r.P2.Y && r.P1.Y == r.P3.Y && r.P1.Y == r.P4.Y) { (r.P1.Y == r.P2.Y && r.P1.Y == r.P3.Y && r.P1.Y == r.P4.Y) {
@ -23,39 +26,39 @@ func (r Rectangle) IsRect() bool {
dd2 := math.Sqrt(math.Abs(cx-r.P2.X)) + math.Sqrt(math.Abs(cy-r.P2.Y)) dd2 := math.Sqrt(math.Abs(cx-r.P2.X)) + math.Sqrt(math.Abs(cy-r.P2.Y))
dd3 := math.Sqrt(math.Abs(cx-r.P3.X)) + math.Sqrt(math.Abs(cy-r.P3.Y)) dd3 := math.Sqrt(math.Abs(cx-r.P3.X)) + math.Sqrt(math.Abs(cy-r.P3.Y))
dd4 := math.Sqrt(math.Abs(cx-r.P4.X)) + math.Sqrt(math.Abs(cy-r.P4.Y)) dd4 := math.Sqrt(math.Abs(cx-r.P4.X)) + math.Sqrt(math.Abs(cy-r.P4.Y))
return dd1 == dd2 && dd1 == dd3 && dd1 == dd4 return math.Abs(dd1-dd2) < ɛ && math.Abs(dd1-dd3) < ɛ && math.Abs(dd1-dd4) < ɛ
} }
func (r Rectangle) Neighbors(p Point) (Point, Point) { func (r Rectangle) neighbors(p Point) (Point, Point) {
keys := []float64{distance(r.P1, p), distance(r.P2, p), distance(r.P3, p), distance(r.P4, p)} keys := []float64{distance(r.P1, p), distance(r.P2, p), distance(r.P3, p), distance(r.P4, p)}
sort.Float64s(keys) sort.Float64s(keys)
n := []Point{} n := []Point{}
d := distance(r.P1, p) d := distance(r.P1, p)
if keys[1] == d || keys[2] == d { if math.Abs(keys[1]-d) < ɛ || math.Abs(keys[2]-d) < ɛ {
n = append(n, r.P1) n = append(n, r.P1)
} }
d = distance(r.P2, p) d = distance(r.P2, p)
if keys[1] == d || keys[2] == d { if math.Abs(keys[1]-d) < ɛ || math.Abs(keys[2]-d) < ɛ {
n = append(n, r.P2) n = append(n, r.P2)
} }
d = distance(r.P3, p) d = distance(r.P3, p)
if keys[1] == d || keys[2] == d { if math.Abs(keys[1]-d) < ɛ || math.Abs(keys[2]-d) < ɛ {
n = append(n, r.P3) n = append(n, r.P3)
} }
d = distance(r.P4, p) d = distance(r.P4, p)
if keys[1] == d || keys[2] == d { if math.Abs(keys[1]-d) < ɛ || math.Abs(keys[2]-d) < ɛ {
n = append(n, r.P4) n = append(n, r.P4)
} }
return n[0], n[1] return n[0], n[1]
} }
func (r Rectangle) Size() float64 { func (r Rectangle) size() float64 {
n1, n2 := r.Neighbors(r.P1) n1, n2 := r.neighbors(r.P1)
return distance(r.P1, n1) * distance(r.P1, n2) return distance(r.P1, n1) * distance(r.P1, n2)
} }
func (r Rectangle) inOrder() []Point { func (r Rectangle) inOrder() []Point {
n1, n2 := r.Neighbors(r.P1) n1, n2 := r.neighbors(r.P1)
accross := &Point{} accross := &Point{}
if r.P2 != n1 || r.P2 != n2 { if r.P2 != n1 || r.P2 != n2 {
accross = &r.P2 accross = &r.P2
@ -126,26 +129,26 @@ func Intersection(r1, r2 Rectangle) []Point {
} }
func sumOfTri(r Rectangle, p Point) bool { func sumOfTri(r Rectangle, p Point) bool {
n1, n2 := r.Neighbors(r.P1) n1, n2 := r.neighbors(r.P1)
x1, x2 := Point{}, Point{} x1, x2 := Point{}, Point{}
accross := &Point{} accross := &Point{}
if r.P2 != n1 || r.P2 != n2 { if r.P2 != n1 || r.P2 != n2 {
accross = &r.P2 accross = &r.P2
x1, x2 = r.Neighbors(r.P2) x1, x2 = r.neighbors(r.P2)
} }
if r.P3 != n1 || r.P3 != n2 { if r.P3 != n1 || r.P3 != n2 {
accross = &r.P3 accross = &r.P3
x1, x2 = r.Neighbors(r.P3) x1, x2 = r.neighbors(r.P3)
} }
if r.P4 != n1 || r.P4 != n2 { if r.P4 != n1 || r.P4 != n2 {
accross = &r.P4 accross = &r.P4
x1, x2 = r.Neighbors(r.P4) x1, x2 = r.neighbors(r.P4)
} }
sumTri := SizeTriangle(r.P1, n1, p) + sumTri := sizeTriangle(r.P1, n1, p) +
SizeTriangle(r.P1, n2, p) + sizeTriangle(r.P1, n2, p) +
SizeTriangle(*accross, x1, p) + sizeTriangle(*accross, x1, p) +
SizeTriangle(*accross, x2, p) sizeTriangle(*accross, x2, p)
if r.Size() == sumTri { if math.Abs(r.size()-sumTri) < ɛ {
return true return true
} }
return false return false
@ -153,7 +156,7 @@ func sumOfTri(r Rectangle, p Point) bool {
// Containment returns whether r2 is contained inside of r1 // Containment returns whether r2 is contained inside of r1
func Containment(r1, r2 Rectangle) bool { func Containment(r1, r2 Rectangle) bool {
if r1.Size() <= r2.Size() { if r1.size() <= r2.size() {
return false return false
} }
if sumOfTri(r1, r2.P1) && sumOfTri(r1, r2.P2) && sumOfTri(r1, r2.P3) && sumOfTri(r1, r2.P4) { if sumOfTri(r1, r2.P1) && sumOfTri(r1, r2.P2) && sumOfTri(r1, r2.P3) && sumOfTri(r1, r2.P4) {

View File

@ -2,6 +2,6 @@ package rect
import "math" import "math"
func SizeTriangle(p1, p2, p3 Point) float64 { func sizeTriangle(p1, p2, p3 Point) float64 {
return math.Abs((p1.X*p2.Y + p2.X*p3.Y + p3.X*p1.Y - p1.Y*p2.X - p2.Y*p3.X - p3.Y*p1.X) / 2) return math.Abs((p1.X*p2.Y + p2.X*p3.Y + p3.X*p1.Y - p1.Y*p2.X - p2.Y*p3.X - p3.Y*p1.X) / 2)
} }

View File

@ -12,7 +12,7 @@ func TestSizeTriangle(t *testing.T) {
{[]Point{Point{10, 14}, Point{20, 15}, Point{12, 52}}, 189}, {[]Point{Point{10, 14}, Point{20, 15}, Point{12, 52}}, 189},
} }
for _, rt := range sizeTriangleTests { for _, rt := range sizeTriangleTests {
actual := SizeTriangle(rt.pts[0], rt.pts[1], rt.pts[2]) actual := sizeTriangle(rt.pts[0], rt.pts[1], rt.pts[2])
if actual != rt.expected { if actual != rt.expected {
t.Errorf( t.Errorf(
"failed sizeTriangle:\n\texpected: %f\n\t actual: %f", "failed sizeTriangle:\n\texpected: %f\n\t actual: %f",