github.com/searKing/golang/go@v1.2.117/exp/image/rectangle_test.go (about)

     1  // Copyright 2023 The searKing Author. 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_test
     6  
     7  import (
     8  	"fmt"
     9  	"strconv"
    10  	"testing"
    11  
    12  	image_ "github.com/searKing/golang/go/exp/image"
    13  )
    14  
    15  func TestRectangle(t *testing.T) {
    16  	// in checks that every point in f is in g.
    17  	in := func(f, g image_.Rectangle[float32]) error {
    18  		if !f.In(g) {
    19  			return fmt.Errorf("f=%s, f.In(%s): got false, want true", f, g)
    20  		}
    21  		for y := f.Min.Y; y < f.Max.Y; y++ {
    22  			for x := f.Min.X; x < f.Max.X; x++ {
    23  				p := image_.Pt[float32](x, y)
    24  				if !p.In(g) {
    25  					return fmt.Errorf("p=%s, p.In(%s): got false, want true", p, g)
    26  				}
    27  			}
    28  		}
    29  		return nil
    30  	}
    31  
    32  	rects := []image_.Rectangle[float32]{
    33  		image_.Rect[float32](0, 0, 10, 10),
    34  		image_.Rect[float32](10, 0, 20, 10),
    35  		image_.Rect[float32](1, 2, 3, 4),
    36  		image_.Rect[float32](4, 6, 10, 10),
    37  		image_.Rect[float32](2, 3, 12, 5),
    38  		image_.Rect[float32](-1, -2, 0, 0),
    39  		image_.Rect[float32](-1, -2, 4, 6),
    40  		image_.Rect[float32](-10, -20, 30, 40),
    41  		image_.Rect[float32](8, 8, 8, 8),
    42  		image_.Rect[float32](88, 88, 88, 88),
    43  		image_.Rect[float32](6, 5, 4, 3),
    44  	}
    45  
    46  	// r.Eq(s) should be equivalent to every point in r being in s, and every
    47  	// point in s being in r.
    48  	for _, r := range rects {
    49  		for _, s := range rects {
    50  			got := r.Eq(s)
    51  			want := in(r, s) == nil && in(s, r) == nil
    52  			if got != want {
    53  				t.Errorf("Eq: r=%s, s=%s: got %t, want %t", r, s, got, want)
    54  			}
    55  		}
    56  	}
    57  
    58  	// The intersection should be the largest rectangle a such that every point
    59  	// in a is both in r and in s.
    60  	for _, r := range rects {
    61  		for _, s := range rects {
    62  			a := r.Intersect(s)
    63  			if err := in(a, r); err != nil {
    64  				t.Errorf("Intersect: r=%s, s=%s, a=%s, a not in r: %v", r, s, a, err)
    65  			}
    66  			if err := in(a, s); err != nil {
    67  				t.Errorf("Intersect: r=%s, s=%s, a=%s, a not in s: %v", r, s, a, err)
    68  			}
    69  			if isZero, overlaps := a == (image_.Rectangle[float32]{}), r.Overlaps(s); isZero == overlaps {
    70  				t.Errorf("Intersect: r=%s, s=%s, a=%s: isZero=%t same as overlaps=%t",
    71  					r, s, a, isZero, overlaps)
    72  			}
    73  			largerThanA := [4]image_.Rectangle[float32]{a, a, a, a}
    74  			largerThanA[0].Min.X--
    75  			largerThanA[1].Min.Y--
    76  			largerThanA[2].Max.X++
    77  			largerThanA[3].Max.Y++
    78  			for i, b := range largerThanA {
    79  				if b.Empty() {
    80  					// b isn't actually larger than a.
    81  					continue
    82  				}
    83  				if in(b, r) == nil && in(b, s) == nil {
    84  					t.Errorf("Intersect: r=%s, s=%s, a=%s, b=%s, i=%d: intersection could be larger",
    85  						r, s, a, b, i)
    86  				}
    87  			}
    88  		}
    89  	}
    90  
    91  	// The union should be the smallest rectangle a such that every point in r
    92  	// is in a and every point in s is in a.
    93  	for _, r := range rects {
    94  		for _, s := range rects {
    95  			a := r.Union(s)
    96  			if err := in(r, a); err != nil {
    97  				t.Errorf("Union: r=%s, s=%s, a=%s, r not in a: %v", r, s, a, err)
    98  			}
    99  			if err := in(s, a); err != nil {
   100  				t.Errorf("Union: r=%s, s=%s, a=%s, s not in a: %v", r, s, a, err)
   101  			}
   102  			if a.Empty() {
   103  				// You can't get any smaller than a.
   104  				continue
   105  			}
   106  			smallerThanA := [4]image_.Rectangle[float32]{a, a, a, a}
   107  			smallerThanA[0].Min.X++
   108  			smallerThanA[1].Min.Y++
   109  			smallerThanA[2].Max.X--
   110  			smallerThanA[3].Max.Y--
   111  			for i, b := range smallerThanA {
   112  				if in(r, b) == nil && in(s, b) == nil {
   113  					t.Errorf("Union: r=%s, s=%s, a=%s, b=%s, i=%d: union could be smaller",
   114  						r, s, a, b, i)
   115  				}
   116  			}
   117  		}
   118  	}
   119  }
   120  
   121  func TestRectangle_Border(t *testing.T) {
   122  	r := image_.Rect(100, 200, 400, 300)
   123  
   124  	insets := []int{
   125  		-100,
   126  		-1,
   127  		+0,
   128  		+1,
   129  		+20,
   130  		+49,
   131  		+50,
   132  		+51,
   133  		+149,
   134  		+150,
   135  		+151,
   136  	}
   137  
   138  	for _, inset := range insets {
   139  		border := r.Border(inset)
   140  
   141  		outer, inner := r, r.Inset(inset)
   142  		if inset < 0 {
   143  			outer, inner = inner, outer
   144  		}
   145  
   146  		got := 0
   147  		for _, b := range border {
   148  			got += b.Area()
   149  		}
   150  		want := outer.Area() - inner.Area()
   151  		if got != want {
   152  			t.Errorf("inset=%d: total area: got %d, want %d", inset, got, want)
   153  		}
   154  
   155  		for i, bi := range border {
   156  			for j, bj := range border {
   157  				if i <= j {
   158  					continue
   159  				}
   160  				if !bi.Intersect(bj).Empty() {
   161  					t.Errorf("inset=%d: %v and %v overlap", inset, bi, bj)
   162  				}
   163  			}
   164  		}
   165  
   166  		for _, b := range border {
   167  			if got := outer.Intersect(b); got != b {
   168  				t.Errorf("inset=%d: outer intersection: got %v, want %v", inset, got, b)
   169  			}
   170  			if got := inner.Intersect(b); !got.Empty() {
   171  				t.Errorf("inset=%d: inner intersection: got %v, want empty", inset, got)
   172  			}
   173  		}
   174  	}
   175  }
   176  
   177  func TestRectangle_BorderPoint(t *testing.T) {
   178  	r := image_.Rect(100, 200, 400, 300)
   179  
   180  	insets := []image_.Point[int]{
   181  		image_.Pt(-100, -100),
   182  		image_.Pt(-1, -1),
   183  		image_.Pt(+0, +0),
   184  		image_.Pt(+1, +1),
   185  		image_.Pt(+20, +20),
   186  		image_.Pt(+49, +49),
   187  		image_.Pt(+50, +50),
   188  		image_.Pt(+51, +51),
   189  		image_.Pt(+149, +149),
   190  		image_.Pt(+150, +150),
   191  		image_.Pt(+151, +151),
   192  	}
   193  
   194  	for _, inset := range insets {
   195  		border := r.BorderPoint(inset)
   196  
   197  		outer, inner := r, r.InsetPoint(inset)
   198  		if outer.Area() < inner.Area() {
   199  			outer, inner = inner, outer
   200  		}
   201  
   202  		got := 0
   203  		for _, b := range border {
   204  			got += b.Area()
   205  		}
   206  		want := outer.Area() - inner.Area()
   207  		if got != want {
   208  			t.Errorf("inset=%d: total area: got %d, want %d", inset, got, want)
   209  		}
   210  
   211  		for i, bi := range border {
   212  			for j, bj := range border {
   213  				if i <= j {
   214  					continue
   215  				}
   216  				if !bi.Intersect(bj).Empty() {
   217  					t.Errorf("inset=%d: %v and %v overlap", inset, bi, bj)
   218  				}
   219  			}
   220  		}
   221  
   222  		for _, b := range border {
   223  			if got := outer.Intersect(b); got != b {
   224  				t.Errorf("inset=%d: outer intersection: got %v, want %v", inset, got, b)
   225  			}
   226  			if got := inner.Intersect(b); !got.Empty() {
   227  				t.Errorf("inset=%d: inner intersection: got %v, want empty", inset, got)
   228  			}
   229  		}
   230  	}
   231  }
   232  
   233  func TestRectangle_BorderRectangle(t *testing.T) {
   234  	r := image_.Rect(100, 200, 400, 300)
   235  
   236  	insets := []image_.Rectangle[int]{
   237  		image_.Rect(-100, -100, -100, -100),
   238  		image_.Rect(-1, -1, -1, -1),
   239  		image_.Rect(+0, +0, +0, +0),
   240  		image_.Rect(+1, +1, +1, +1),
   241  		image_.Rect(+20, +20, +20, +20),
   242  		image_.Rect(+49, +49, +49, +49),
   243  		image_.Rect(+50, +50, +50, +50),
   244  		image_.Rect(+51, +51, +51, +51),
   245  		image_.Rect(+149, +149, +149, +149),
   246  		image_.Rect(+150, +150, +150, +150),
   247  		image_.Rect(+151, +151, +151, +151),
   248  	}
   249  
   250  	for _, inset := range insets {
   251  		border := r.BorderRectangle(inset)
   252  
   253  		outer, inner := r, r.InsetRectangle(inset)
   254  		if outer.Area() < inner.Area() {
   255  			outer, inner = inner, outer
   256  		}
   257  
   258  		got := 0
   259  		for _, b := range border {
   260  			got += b.Area()
   261  		}
   262  		want := outer.Area() - inner.Area()
   263  		if got != want {
   264  			t.Errorf("inset=%d: total area: got %d, want %d", inset, got, want)
   265  		}
   266  
   267  		for i, bi := range border {
   268  			for j, bj := range border {
   269  				if i <= j {
   270  					continue
   271  				}
   272  				if !bi.Intersect(bj).Empty() {
   273  					t.Errorf("inset=%d: %v and %v overlap", inset, bi, bj)
   274  				}
   275  			}
   276  		}
   277  
   278  		for _, b := range border {
   279  			if got := outer.Intersect(b); got != b {
   280  				t.Errorf("inset=%d: outer intersection: got %v, want %v", inset, got, b)
   281  			}
   282  			if got := inner.Intersect(b); !got.Empty() {
   283  				t.Errorf("inset=%d: inner intersection: got %v, want empty", inset, got)
   284  			}
   285  		}
   286  	}
   287  }
   288  
   289  func TestRectangle_FlexIn(t *testing.T) {
   290  	tests := []struct {
   291  		r    image_.Rectangle[int]
   292  		box  image_.Rectangle[int]
   293  		want image_.Rectangle[int]
   294  	}{
   295  		{image_.Rectangle[int]{}, image_.Rectangle[int]{}, image_.Rectangle[int]{}},
   296  		{image_.Rect(0, 0, 10, 10), image_.Rectangle[int]{}, image_.Rectangle[int]{}},
   297  		{image_.Rect(0, 0, 10, 10), image_.Rect(1, 2, 3, 4), image_.Rect(1, 2, 3, 4)},
   298  		{image_.Rect(0, 0, 10, 10), image_.Rect(-1, -2, 13, 14), image_.Rect(0, 0, 10, 10)},
   299  		{image_.Rect(0, 0, 10, 10), image_.Rect(1, -2, 3, 14), image_.Rect(1, 0, 3, 10)},
   300  		{image_.Rect(0, 0, 10, 10), image_.Rect(1, 2, 13, 14), image_.Rect(1, 2, 11, 12)},
   301  		{image_.Rect(0, 0, 10, 10), image_.Rect(1, 2, 13, 10), image_.Rect(1, 2, 11, 10)},
   302  		{image_.Rect(0, 0, 10, 10), image_.Rect(20, 20, 20, 20), image_.Rect(20, 20, 20, 20)},
   303  		{image_.Rect(0, 0, 10, 10), image_.Rect(1, 20, 3, 20), image_.Rect(1, 20, 3, 20)},
   304  	}
   305  	for i, tt := range tests {
   306  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   307  			got := tt.r.FlexIn(tt.box)
   308  			if got != tt.want {
   309  				t.Errorf("(%v).FlexIn(%v) got (%v), want (%v)", tt.r, tt.box, got, tt.want)
   310  			}
   311  		})
   312  	}
   313  }