Home | History | Annotate | Download | only in image
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package image
      6 
      7 import (
      8 	"fmt"
      9 	"testing"
     10 )
     11 
     12 func TestRectangle(t *testing.T) {
     13 	// in checks that every point in f is in g.
     14 	in := func(f, g Rectangle) error {
     15 		if !f.In(g) {
     16 			return fmt.Errorf("f=%s, f.In(%s): got false, want true", f, g)
     17 		}
     18 		for y := f.Min.Y; y < f.Max.Y; y++ {
     19 			for x := f.Min.X; x < f.Max.X; x++ {
     20 				p := Point{x, y}
     21 				if !p.In(g) {
     22 					return fmt.Errorf("p=%s, p.In(%s): got false, want true", p, g)
     23 				}
     24 			}
     25 		}
     26 		return nil
     27 	}
     28 
     29 	rects := []Rectangle{
     30 		Rect(0, 0, 10, 10),
     31 		Rect(1, 2, 3, 4),
     32 		Rect(4, 6, 10, 10),
     33 		Rect(2, 3, 12, 5),
     34 		Rect(-1, -2, 0, 0),
     35 		Rect(-1, -2, 4, 6),
     36 		Rect(-10, -20, 30, 40),
     37 		Rect(8, 8, 8, 8),
     38 		Rect(88, 88, 88, 88),
     39 		Rect(6, 5, 4, 3),
     40 	}
     41 
     42 	// r.Eq(s) should be equivalent to every point in r being in s, and every
     43 	// point in s being in r.
     44 	for _, r := range rects {
     45 		for _, s := range rects {
     46 			got := r.Eq(s)
     47 			want := in(r, s) == nil && in(s, r) == nil
     48 			if got != want {
     49 				t.Errorf("Eq: r=%s, s=%s: got %t, want %t", r, s, got, want)
     50 			}
     51 		}
     52 	}
     53 
     54 	// The intersection should be the largest rectangle a such that every point
     55 	// in a is both in r and in s.
     56 	for _, r := range rects {
     57 		for _, s := range rects {
     58 			a := r.Intersect(s)
     59 			if err := in(a, r); err != nil {
     60 				t.Errorf("Intersect: r=%s, s=%s, a=%s, a not in r: %v", r, s, a, err)
     61 			}
     62 			if err := in(a, s); err != nil {
     63 				t.Errorf("Intersect: r=%s, s=%s, a=%s, a not in s: %v", r, s, a, err)
     64 			}
     65 			if a.Empty() == r.Overlaps(s) {
     66 				t.Errorf("Intersect: r=%s, s=%s, a=%s: empty=%t same as overlaps=%t",
     67 					r, s, a, a.Empty(), r.Overlaps(s))
     68 			}
     69 			largerThanA := [4]Rectangle{a, a, a, a}
     70 			largerThanA[0].Min.X--
     71 			largerThanA[1].Min.Y--
     72 			largerThanA[2].Max.X++
     73 			largerThanA[3].Max.Y++
     74 			for i, b := range largerThanA {
     75 				if b.Empty() {
     76 					// b isn't actually larger than a.
     77 					continue
     78 				}
     79 				if in(b, r) == nil && in(b, s) == nil {
     80 					t.Errorf("Intersect: r=%s, s=%s, a=%s, b=%s, i=%d: intersection could be larger",
     81 						r, s, a, b, i)
     82 				}
     83 			}
     84 		}
     85 	}
     86 
     87 	// The union should be the smallest rectangle a such that every point in r
     88 	// is in a and every point in s is in a.
     89 	for _, r := range rects {
     90 		for _, s := range rects {
     91 			a := r.Union(s)
     92 			if err := in(r, a); err != nil {
     93 				t.Errorf("Union: r=%s, s=%s, a=%s, r not in a: %v", r, s, a, err)
     94 			}
     95 			if err := in(s, a); err != nil {
     96 				t.Errorf("Union: r=%s, s=%s, a=%s, s not in a: %v", r, s, a, err)
     97 			}
     98 			if a.Empty() {
     99 				// You can't get any smaller than a.
    100 				continue
    101 			}
    102 			smallerThanA := [4]Rectangle{a, a, a, a}
    103 			smallerThanA[0].Min.X++
    104 			smallerThanA[1].Min.Y++
    105 			smallerThanA[2].Max.X--
    106 			smallerThanA[3].Max.Y--
    107 			for i, b := range smallerThanA {
    108 				if in(r, b) == nil && in(s, b) == nil {
    109 					t.Errorf("Union: r=%s, s=%s, a=%s, b=%s, i=%d: union could be smaller",
    110 						r, s, a, b, i)
    111 				}
    112 			}
    113 		}
    114 	}
    115 }
    116