...
Source file src/image/geom.go
1
2
3
4
5 package image
6
7 import (
8 "image/color"
9 "strconv"
10 )
11
12
13 type Point struct {
14 X, Y int
15 }
16
17
18 func (p Point) String() string {
19 return "(" + strconv.Itoa(p.X) + "," + strconv.Itoa(p.Y) + ")"
20 }
21
22
23 func (p Point) Add(q Point) Point {
24 return Point{p.X + q.X, p.Y + q.Y}
25 }
26
27
28 func (p Point) Sub(q Point) Point {
29 return Point{p.X - q.X, p.Y - q.Y}
30 }
31
32
33 func (p Point) Mul(k int) Point {
34 return Point{p.X * k, p.Y * k}
35 }
36
37
38 func (p Point) Div(k int) Point {
39 return Point{p.X / k, p.Y / k}
40 }
41
42
43 func (p Point) In(r Rectangle) bool {
44 return r.Min.X <= p.X && p.X < r.Max.X &&
45 r.Min.Y <= p.Y && p.Y < r.Max.Y
46 }
47
48
49
50 func (p Point) Mod(r Rectangle) Point {
51 w, h := r.Dx(), r.Dy()
52 p = p.Sub(r.Min)
53 p.X = p.X % w
54 if p.X < 0 {
55 p.X += w
56 }
57 p.Y = p.Y % h
58 if p.Y < 0 {
59 p.Y += h
60 }
61 return p.Add(r.Min)
62 }
63
64
65 func (p Point) Eq(q Point) bool {
66 return p == q
67 }
68
69
70
71
72 var ZP Point
73
74
75 func Pt(X, Y int) Point {
76 return Point{X, Y}
77 }
78
79
80
81
82
83
84
85
86
87 type Rectangle struct {
88 Min, Max Point
89 }
90
91
92 func (r Rectangle) String() string {
93 return r.Min.String() + "-" + r.Max.String()
94 }
95
96
97 func (r Rectangle) Dx() int {
98 return r.Max.X - r.Min.X
99 }
100
101
102 func (r Rectangle) Dy() int {
103 return r.Max.Y - r.Min.Y
104 }
105
106
107 func (r Rectangle) Size() Point {
108 return Point{
109 r.Max.X - r.Min.X,
110 r.Max.Y - r.Min.Y,
111 }
112 }
113
114
115 func (r Rectangle) Add(p Point) Rectangle {
116 return Rectangle{
117 Point{r.Min.X + p.X, r.Min.Y + p.Y},
118 Point{r.Max.X + p.X, r.Max.Y + p.Y},
119 }
120 }
121
122
123 func (r Rectangle) Sub(p Point) Rectangle {
124 return Rectangle{
125 Point{r.Min.X - p.X, r.Min.Y - p.Y},
126 Point{r.Max.X - p.X, r.Max.Y - p.Y},
127 }
128 }
129
130
131
132
133 func (r Rectangle) Inset(n int) Rectangle {
134 if r.Dx() < 2*n {
135 r.Min.X = (r.Min.X + r.Max.X) / 2
136 r.Max.X = r.Min.X
137 } else {
138 r.Min.X += n
139 r.Max.X -= n
140 }
141 if r.Dy() < 2*n {
142 r.Min.Y = (r.Min.Y + r.Max.Y) / 2
143 r.Max.Y = r.Min.Y
144 } else {
145 r.Min.Y += n
146 r.Max.Y -= n
147 }
148 return r
149 }
150
151
152
153 func (r Rectangle) Intersect(s Rectangle) Rectangle {
154 if r.Min.X < s.Min.X {
155 r.Min.X = s.Min.X
156 }
157 if r.Min.Y < s.Min.Y {
158 r.Min.Y = s.Min.Y
159 }
160 if r.Max.X > s.Max.X {
161 r.Max.X = s.Max.X
162 }
163 if r.Max.Y > s.Max.Y {
164 r.Max.Y = s.Max.Y
165 }
166
167
168
169
170 if r.Empty() {
171 return ZR
172 }
173 return r
174 }
175
176
177 func (r Rectangle) Union(s Rectangle) Rectangle {
178 if r.Empty() {
179 return s
180 }
181 if s.Empty() {
182 return r
183 }
184 if r.Min.X > s.Min.X {
185 r.Min.X = s.Min.X
186 }
187 if r.Min.Y > s.Min.Y {
188 r.Min.Y = s.Min.Y
189 }
190 if r.Max.X < s.Max.X {
191 r.Max.X = s.Max.X
192 }
193 if r.Max.Y < s.Max.Y {
194 r.Max.Y = s.Max.Y
195 }
196 return r
197 }
198
199
200 func (r Rectangle) Empty() bool {
201 return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y
202 }
203
204
205
206 func (r Rectangle) Eq(s Rectangle) bool {
207 return r == s || r.Empty() && s.Empty()
208 }
209
210
211 func (r Rectangle) Overlaps(s Rectangle) bool {
212 return !r.Empty() && !s.Empty() &&
213 r.Min.X < s.Max.X && s.Min.X < r.Max.X &&
214 r.Min.Y < s.Max.Y && s.Min.Y < r.Max.Y
215 }
216
217
218 func (r Rectangle) In(s Rectangle) bool {
219 if r.Empty() {
220 return true
221 }
222
223
224 return s.Min.X <= r.Min.X && r.Max.X <= s.Max.X &&
225 s.Min.Y <= r.Min.Y && r.Max.Y <= s.Max.Y
226 }
227
228
229
230 func (r Rectangle) Canon() Rectangle {
231 if r.Max.X < r.Min.X {
232 r.Min.X, r.Max.X = r.Max.X, r.Min.X
233 }
234 if r.Max.Y < r.Min.Y {
235 r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y
236 }
237 return r
238 }
239
240
241 func (r Rectangle) At(x, y int) color.Color {
242 if (Point{x, y}).In(r) {
243 return color.Opaque
244 }
245 return color.Transparent
246 }
247
248
249 func (r Rectangle) Bounds() Rectangle {
250 return r
251 }
252
253
254 func (r Rectangle) ColorModel() color.Model {
255 return color.Alpha16Model
256 }
257
258
259
260
261 var ZR Rectangle
262
263
264
265
266 func Rect(x0, y0, x1, y1 int) Rectangle {
267 if x0 > x1 {
268 x0, x1 = x1, x0
269 }
270 if y0 > y1 {
271 y0, y1 = y1, y0
272 }
273 return Rectangle{Point{x0, y0}, Point{x1, y1}}
274 }
275
View as plain text