github.com/kaydxh/golang@v0.0.131/pkg/gocv/rect.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package gocv 23 24 type Rect struct { 25 X int32 26 Y int32 27 Width int32 28 Height int32 29 } 30 31 var ZR Rect 32 33 func (r Rect) Scale(factor float32) Rect { 34 ox := r.X + r.Width/2 35 oy := r.Y + r.Height/2 36 r.X = ox + int32(float32((r.X-ox))*factor) 37 r.Y = oy + int32(float32((r.Y-oy))*factor) 38 r.Width = int32(float32(r.Width) * factor) 39 r.Height = int32(float32(r.Height) * factor) 40 41 return r 42 } 43 44 // Empty reports whether the rectangle contains no points. 45 func (r Rect) Empty() bool { 46 return r.Width <= 0 || r.Height <= 0 47 } 48 49 func (r Rect) Area() int32 { 50 return r.Width * r.Height 51 } 52 53 func (r Rect) Intersect(s Rect) Rect { 54 rMaxX := r.X + r.Width 55 sMaxX := s.X + s.Width 56 if rMaxX > sMaxX { 57 rMaxX = sMaxX 58 } 59 r.Width = rMaxX - r.X 60 61 rMaxY := r.Y + r.Height 62 sMaxY := s.Y + s.Height 63 if rMaxY > sMaxY { 64 rMaxY = sMaxY 65 } 66 67 if r.X < s.X { 68 r.X = s.X 69 } 70 r.Width = rMaxX - r.X 71 72 if r.Y < s.Y { 73 r.Y = s.Y 74 } 75 if rMaxY > sMaxY { 76 rMaxY = sMaxY 77 } 78 r.Height = rMaxY - r.Y 79 80 // Letting r0 and s0 be the values of r and s at the time that the method 81 // is called, this next line is equivalent to: 82 // 83 // if max(r0.Min.X, s0.Min.X) >= min(r0.Max.X, s0.Max.X) || likewiseForY { etc } 84 if r.Empty() { 85 return ZR 86 } 87 return r 88 } 89 90 // Union returns the smallest rect that contains both r and s. 91 func (r Rect) Union(s Rect) Rect { 92 if r.Empty() { 93 return s 94 } 95 if s.Empty() { 96 return r 97 } 98 if r.X > s.X { 99 r.X = s.X 100 } 101 if r.Y > s.Y { 102 r.Y = s.Y 103 } 104 105 rMaxX := r.X + r.Width 106 sMaxX := s.X + s.Width 107 if rMaxX < sMaxX { 108 rMaxX = sMaxX 109 } 110 r.Width = rMaxX - r.X 111 112 rMaxY := r.Y + r.Height 113 sMaxY := s.Y + s.Height 114 if rMaxY < sMaxY { 115 rMaxY = sMaxY 116 } 117 r.Height = rMaxY - r.Y 118 return r 119 } 120 121 // In reports whether every point in r is in s. 122 // true means s is larger than r 123 func (r Rect) In(s Rect) bool { 124 if r.Empty() { 125 return true 126 } 127 // Note that r.Max is an exclusive bound for r, so that r.In(s) 128 // does not require that r.Max.In(s). 129 return s.X <= r.X && r.Y <= s.Y && 130 s.Width <= r.Width && r.Height <= s.Height 131 } 132 133 // return closest rect 134 func (r Rect) Closest(rects ...Rect) (float32, Rect) { 135 if len(rects) == 0 { 136 return 0, ZR 137 } 138 if r.Empty() { 139 return 0, ZR 140 } 141 142 var ( 143 maxAreaRatio float32 144 closestRect Rect 145 ) 146 for _, s := range rects { 147 var areaRatio float32 148 ia := r.Intersect(s) 149 if !ia.Empty() { 150 areaRatio = float32(ia.Area()) / float32(r.Area()) 151 if maxAreaRatio < areaRatio { 152 maxAreaRatio = areaRatio 153 closestRect = s 154 } 155 } 156 157 } 158 159 return maxAreaRatio, closestRect 160 }