github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/image/geom.go (about) 1 // Copyright 2010 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 "strconv" 9 ) 10 11 // A Point is an X, Y coordinate pair. The axes increase right and down. 12 type Point struct { 13 X, Y int 14 } 15 16 // String returns a string representation of p like "(3,4)". 17 func (p Point) String() string { 18 return "(" + strconv.Itoa(p.X) + "," + strconv.Itoa(p.Y) + ")" 19 } 20 21 // Add returns the vector p+q. 22 func (p Point) Add(q Point) Point { 23 return Point{p.X + q.X, p.Y + q.Y} 24 } 25 26 // Sub returns the vector p-q. 27 func (p Point) Sub(q Point) Point { 28 return Point{p.X - q.X, p.Y - q.Y} 29 } 30 31 // Mul returns the vector p*k. 32 func (p Point) Mul(k int) Point { 33 return Point{p.X * k, p.Y * k} 34 } 35 36 // Div returns the vector p/k. 37 func (p Point) Div(k int) Point { 38 return Point{p.X / k, p.Y / k} 39 } 40 41 // In reports whether p is in r. 42 func (p Point) In(r Rectangle) bool { 43 return r.Min.X <= p.X && p.X < r.Max.X && 44 r.Min.Y <= p.Y && p.Y < r.Max.Y 45 } 46 47 // Mod returns the point q in r such that p.X-q.X is a multiple of r's width 48 // and p.Y-q.Y is a multiple of r's height. 49 func (p Point) Mod(r Rectangle) Point { 50 w, h := r.Dx(), r.Dy() 51 p = p.Sub(r.Min) 52 p.X = p.X % w 53 if p.X < 0 { 54 p.X += w 55 } 56 p.Y = p.Y % h 57 if p.Y < 0 { 58 p.Y += h 59 } 60 return p.Add(r.Min) 61 } 62 63 // Eq reports whether p and q are equal. 64 func (p Point) Eq(q Point) bool { 65 return p.X == q.X && p.Y == q.Y 66 } 67 68 // ZP is the zero Point. 69 var ZP Point 70 71 // Pt is shorthand for Point{X, Y}. 72 func Pt(X, Y int) Point { 73 return Point{X, Y} 74 } 75 76 // A Rectangle contains the points with Min.X <= X < Max.X, Min.Y <= Y < Max.Y. 77 // It is well-formed if Min.X <= Max.X and likewise for Y. Points are always 78 // well-formed. A rectangle's methods always return well-formed outputs for 79 // well-formed inputs. 80 type Rectangle struct { 81 Min, Max Point 82 } 83 84 // String returns a string representation of r like "(3,4)-(6,5)". 85 func (r Rectangle) String() string { 86 return r.Min.String() + "-" + r.Max.String() 87 } 88 89 // Dx returns r's width. 90 func (r Rectangle) Dx() int { 91 return r.Max.X - r.Min.X 92 } 93 94 // Dy returns r's height. 95 func (r Rectangle) Dy() int { 96 return r.Max.Y - r.Min.Y 97 } 98 99 // Size returns r's width and height. 100 func (r Rectangle) Size() Point { 101 return Point{ 102 r.Max.X - r.Min.X, 103 r.Max.Y - r.Min.Y, 104 } 105 } 106 107 // Add returns the rectangle r translated by p. 108 func (r Rectangle) Add(p Point) Rectangle { 109 return Rectangle{ 110 Point{r.Min.X + p.X, r.Min.Y + p.Y}, 111 Point{r.Max.X + p.X, r.Max.Y + p.Y}, 112 } 113 } 114 115 // Sub returns the rectangle r translated by -p. 116 func (r Rectangle) Sub(p Point) Rectangle { 117 return Rectangle{ 118 Point{r.Min.X - p.X, r.Min.Y - p.Y}, 119 Point{r.Max.X - p.X, r.Max.Y - p.Y}, 120 } 121 } 122 123 // Inset returns the rectangle r inset by n, which may be negative. If either 124 // of r's dimensions is less than 2*n then an empty rectangle near the center 125 // of r will be returned. 126 func (r Rectangle) Inset(n int) Rectangle { 127 if r.Dx() < 2*n { 128 r.Min.X = (r.Min.X + r.Max.X) / 2 129 r.Max.X = r.Min.X 130 } else { 131 r.Min.X += n 132 r.Max.X -= n 133 } 134 if r.Dy() < 2*n { 135 r.Min.Y = (r.Min.Y + r.Max.Y) / 2 136 r.Max.Y = r.Min.Y 137 } else { 138 r.Min.Y += n 139 r.Max.Y -= n 140 } 141 return r 142 } 143 144 // Intersect returns the largest rectangle contained by both r and s. If the 145 // two rectangles do not overlap then the zero rectangle will be returned. 146 func (r Rectangle) Intersect(s Rectangle) Rectangle { 147 if r.Min.X < s.Min.X { 148 r.Min.X = s.Min.X 149 } 150 if r.Min.Y < s.Min.Y { 151 r.Min.Y = s.Min.Y 152 } 153 if r.Max.X > s.Max.X { 154 r.Max.X = s.Max.X 155 } 156 if r.Max.Y > s.Max.Y { 157 r.Max.Y = s.Max.Y 158 } 159 if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y { 160 return ZR 161 } 162 return r 163 } 164 165 // Union returns the smallest rectangle that contains both r and s. 166 func (r Rectangle) Union(s Rectangle) Rectangle { 167 if r.Min.X > s.Min.X { 168 r.Min.X = s.Min.X 169 } 170 if r.Min.Y > s.Min.Y { 171 r.Min.Y = s.Min.Y 172 } 173 if r.Max.X < s.Max.X { 174 r.Max.X = s.Max.X 175 } 176 if r.Max.Y < s.Max.Y { 177 r.Max.Y = s.Max.Y 178 } 179 return r 180 } 181 182 // Empty reports whether the rectangle contains no points. 183 func (r Rectangle) Empty() bool { 184 return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y 185 } 186 187 // Eq reports whether r and s are equal. 188 func (r Rectangle) Eq(s Rectangle) bool { 189 return r.Min.X == s.Min.X && r.Min.Y == s.Min.Y && 190 r.Max.X == s.Max.X && r.Max.Y == s.Max.Y 191 } 192 193 // Overlaps reports whether r and s have a non-empty intersection. 194 func (r Rectangle) Overlaps(s Rectangle) bool { 195 return r.Min.X < s.Max.X && s.Min.X < r.Max.X && 196 r.Min.Y < s.Max.Y && s.Min.Y < r.Max.Y 197 } 198 199 // In reports whether every point in r is in s. 200 func (r Rectangle) In(s Rectangle) bool { 201 if r.Empty() { 202 return true 203 } 204 // Note that r.Max is an exclusive bound for r, so that r.In(s) 205 // does not require that r.Max.In(s). 206 return s.Min.X <= r.Min.X && r.Max.X <= s.Max.X && 207 s.Min.Y <= r.Min.Y && r.Max.Y <= s.Max.Y 208 } 209 210 // Canon returns the canonical version of r. The returned rectangle has minimum 211 // and maximum coordinates swapped if necessary so that it is well-formed. 212 func (r Rectangle) Canon() Rectangle { 213 if r.Max.X < r.Min.X { 214 r.Min.X, r.Max.X = r.Max.X, r.Min.X 215 } 216 if r.Max.Y < r.Min.Y { 217 r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y 218 } 219 return r 220 } 221 222 // ZR is the zero Rectangle. 223 var ZR Rectangle 224 225 // Rect is shorthand for Rectangle{Pt(x0, y0), Pt(x1, y1)}. 226 func Rect(x0, y0, x1, y1 int) Rectangle { 227 if x0 > x1 { 228 x0, x1 = x1, x0 229 } 230 if y0 > y1 { 231 y0, y1 = y1, y0 232 } 233 return Rectangle{Point{x0, y0}, Point{x1, y1}} 234 }