android: exit application on destroy request
[nit.git] / lib / geometry / boxes.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Provides interfaces and classes to represent basic geometry needs.
18 module boxes
19
20 import points_and_lines
21
22 # An 2d abstract bounded object
23 interface Boxed[N: Numeric]
24 # Left bound
25 #
26 # require: left <= right
27 fun left: N is abstract
28
29 # Right bound
30 #
31 # require: right >= left
32 fun right: N is abstract
33
34 # Top bound
35 #
36 # require: top >= bottom
37 fun top: N is abstract
38
39 # Bottom bound
40 #
41 # require: bottom <= top
42 fun bottom: N is abstract
43
44 # Is `other` contained within `self`?
45 #
46 # var a = new Box[Int].lbwh(1, 1, 4, 4)
47 # var b = new Box[Int].lbwh(2, 2, 2, 2)
48 # var c = new Box[Int].lbwh(0, 2, 8, 2)
49 # assert a.contains(b)
50 # assert not b.contains(a)
51 # assert c.contains(b)
52 # assert not b.contains(c)
53 # assert not a.contains(c)
54 # assert not c.contains(a)
55 fun contains(other: Boxed[N]): Bool
56 do
57 return self.top >= other.top and self.bottom <= other.bottom and
58 self.left <= other.left and self.right >= other.right
59 end
60
61 # Does `self` intersect with `other`?
62 #
63 # var a = new Box[Int].lbwh(0, 0, 2, 2)
64 # var b = new Box[Int].lbwh(1, 1, 8, 2)
65 # var c = new Box[Int].lbwh(3, 0, 2, 8)
66 # assert a.intersects(b)
67 # assert b.intersects(a)
68 # assert b.intersects(c)
69 # assert c.intersects(b)
70 # assert not c.intersects(a)
71 # assert not a.intersects(c)
72 fun intersects(other: Boxed[N]): Bool
73 do
74 return self.left <= other.right and other.left <= self.right and
75 self.top >= other.bottom and other.top >= self.bottom
76 end
77 end
78
79 # A 2d bounded object and an implementation of `Boxed`
80 #
81 # This class offers many constructors specialized for different usage. They are
82 # named according to the order of their arguments.
83 class Box[N: Numeric]
84 super Boxed[N]
85
86 redef var left: N
87 redef var right: N
88 redef var top: N
89 redef var bottom: N
90
91 # Create a `Box` covering all of the `boxed`
92 #
93 # var box = new Box[Int].around(new Point[Int](-4,-4), new Point[Int](4,4))
94 # assert box.left == -4 and box.bottom == -4
95 # assert box.right == 4 and box.top == 4
96 init around(boxed: Boxed[N]...)
97 do
98 assert not boxed.is_empty
99
100 var left: nullable N = null
101 var right: nullable N = null
102 var top: nullable N = null
103 var bottom: nullable N = null
104
105 for box in boxed do
106 if left == null or box.left < left then left = box.left
107 if right == null or box.right > right then right = box.right
108 if top == null or box.top > top then top = box.top
109 if bottom == null or box.bottom < bottom then bottom = box.bottom
110 end
111
112 assert left != null and right != null and top != null and bottom != null
113
114 self.left = left
115 self.right = right
116 self.top = top
117 self.bottom = bottom
118 end
119
120 # Create a `Box` using left, right, bottom and top
121 init lrbt(left, right, bottom, top: N)
122 do
123 self.left = left
124 self.right = right
125 self.top = top
126 self.bottom = bottom
127 end
128
129 # Create a `Box` using left, right, top and bottom
130 init lrtb(left, right, top, bottom: N)
131 do
132 self.left = left
133 self.right = right
134 self.top = top
135 self.bottom = bottom
136 end
137
138 # Create a `Box` using left, bottom, width and height
139 init lbwh(left, bottom, width, height: N)
140 do
141 self.left = left
142 self.bottom = bottom
143
144 self.right = left + width
145 self.top = bottom + height
146 end
147
148 # Create a `Box` using left, top, width and height
149 init ltwh(left, top, width, height: N)
150 do
151 self.left = left
152 self.top = top
153
154 self.right = left + width
155 self.bottom = top - height
156 end
157
158 redef fun to_s do return "<left: {left}, right: {right}, top: {top}, bottom: {bottom}>"
159 end
160
161 # An 3d abstract bounded object
162 interface Boxed3d[N: Numeric]
163 super Boxed[N]
164
165 # Front bound
166 #
167 # require: front >= back
168 fun front: N is abstract
169
170 # Back bound
171 #
172 # require: back <= bottom
173 fun back: N is abstract
174
175 # var a = new Box3d[Int].lbfwhd(1, 1, -1, 4, 4, 4)
176 # var b = new Box3d[Int].lbfwhd(2, 2, -2, 2, 2, 2)
177 # var c = new Box3d[Int].lbfwhd(2, 2, 0, 2, 2, 8)
178 # assert a.contains(b)
179 # assert not b.contains(a)
180 # assert c.contains(b)
181 # assert not b.contains(c)
182 # assert not a.contains(c)
183 # assert not c.contains(a)
184 redef fun contains(other)
185 do
186 return super and (not other isa Boxed3d[N] or
187 (self.front >= other.front and self.back <= other.back))
188 end
189
190 # var a = new Box3d[Int].lbfwhd(0, 0, 0, 2, 2, 2)
191 # var b = new Box3d[Int].lbfwhd(1, 1, 1, 8, 2, 2)
192 # var c = new Box3d[Int].lbfwhd(3, 0, 0, 2, 2, 8)
193 # assert a.intersects(b)
194 # assert b.intersects(a)
195 # assert b.intersects(c)
196 # assert c.intersects(b)
197 # assert not c.intersects(a)
198 # assert not a.intersects(c)
199 redef fun intersects(other)
200 do
201 return super and (not other isa Boxed3d[N] or
202 (self.back <= other.front and other.back <= self.front))
203 end
204 end
205
206 # A 3d bounded object and an implementation of Boxed
207 #
208 # This class offers many constructors specialized for different usage. They are
209 # named according to the order of their arguments.
210 class Box3d[N: Numeric]
211 super Boxed3d[N]
212 super Box[N]
213
214 redef var front: N
215 redef var back: N
216
217 # Create a `Box` covering all of the `boxed`
218 #
219 # var box = new Box[Int].around(new Point[Int](-4,-4), new Point[Int](4,4))
220 # assert box.left == -4 and box.bottom == -4
221 # assert box.right == 4 and box.top == 4
222 init around(boxed: Boxed3d[N]...)
223 do
224 assert not boxed.is_empty
225
226 var left: nullable N = null
227 var right: nullable N = null
228 var top: nullable N = null
229 var bottom: nullable N = null
230 var front: nullable N = null
231 var back: nullable N= null
232
233 for box in boxed do
234 if left == null or box.left < left then left = box.left
235 if right == null or box.right > right then right = box.right
236 if top == null or box.top > top then top = box.top
237 if bottom == null or box.bottom < bottom then bottom = box.bottom
238 if front == null or box.front > front then front = box.front
239 if back == null or box.back < back then back = box.back
240 end
241
242 assert left != null and right != null and top != null and bottom != null
243
244 self.left = left
245 self.right = right
246 self.top = top
247 self.bottom = bottom
248 end
249
250 # Create a `Box3d` using left, right, bottom, top, front and back
251 init lrbtfb(left, right, bottom, top, front, back: N)
252 do
253 lrbt(left, right, bottom, top)
254
255 self.front = front
256 self.back = back
257 end
258
259 # Create a `Box3d` using left, right, top, bottom, front and back
260 init lrtbfb(left, right, top, bottom, front, back: N)
261 do
262 lrtb(left, right, top, bottom)
263
264 self.front = front
265 self.back = back
266 end
267
268 # Create a `Box3d` using left, top, front, width, height and depth
269 init lbfwhd(left, bottom, front, width, height, depth: N)
270 do
271 lbwh(left, bottom, width, height)
272
273 self.front = front
274 self.back = front - depth
275 end
276
277 # Create a `Box3d` using left, top, front, width, height and depth
278 init ltfwhd(left, top, front, width, height, depth: N)
279 do
280 ltwh(left, top, width, height)
281
282 self.front = front
283 self.back = front - depth
284 end
285
286 redef fun to_s do return "<left: {left}, right: {right}, top: {top}, bottom: {bottom}, front: {front}, back: {back}"
287 end
288
289 redef class IPoint[N]
290 super Boxed[N]
291
292 redef fun left do return x
293 redef fun right do return x
294 redef fun top do return y
295 redef fun bottom do return y
296 end
297
298 redef class IPoint3d[N]
299 super Boxed3d[N]
300
301 redef fun front do return z
302 redef fun back do return z
303 end
304
305 redef class ILine[N]
306 super Boxed[N]
307
308 redef fun left do return point_left.x
309 redef fun right do return point_right.x
310 redef fun top do return point_left.y.min(point_right.y)
311 redef fun bottom do return point_left.y.max(point_right.y)
312 end
313
314 redef class ILine3d[N]
315 super Boxed3d[N]
316
317 redef fun front do return point_left.z.min(point_right.z)
318 redef fun back do return point_left.z.max(point_right.z)
319 end