1 """
2 Bounding regions and bounding boxes.
3
4 $Id: boundingregion.py 10672 2009-10-28 01:00:50Z ceball $
5 """
6
7 __version__='$Revision: 10672 $'
8
9 from numpy import inf
10
11
12
13
14
15 import param
16 from param.parameterized import get_all_slots
17
19 """
20 Abstract bounding region class, for any portion of a 2D plane.
21
22 Only subclasses can be instantiated directly.
23 """
24 __abstract = True
25
26 __slots__ = ['_aarect']
27
29 raise NotImplementedError
31 raise NotImplementedError
36 raise NotImplementedError
38 raise NotImplementedError
40 """
41 Return the coordinates of the center of this BoundingBox
42 """
43 return self.aarect().centroid()
44
45 - def set(self,points):
47
48
56
60
61
63 """
64 A rectangular bounding box defined either by two points forming
65 an axis-aligned rectangle (or simply a radius for a square).
66 """
67 __slots__ = []
68
70 """
71 Return BoundingBox(points=((left,bottom),(right,top)))
72
73 Reimplemented here so that 'print' for a BoundingBox
74 will display the bounds.
75 """
76 l,b,r,t = self._aarect.lbrt()
77 if r == -l and t == -b and r == t:
78 return 'BoundingBox(radius=%s)'%(r)
79 else:
80 return 'BoundingBox(points=((%s,%s),(%s,%s)))'%(l,b,r,t)
81
84
86
87 cls = self.__class__.__name__
88 mod = self.__module__
89 imports.append("from %s import %s" % (mod,cls))
90 return self.__str__()
91
93 """
94 Create a BoundingBox.
95
96 Either 'radius' or 'points' can be specified for the
97 AARectangle.
98
99 If radius is passed in, the BoundingBox will use min_radius
100 (which defaults to 0.0) if it's larger than radius - so by
101 passing min_radius=1.25/density, a BoundingBox of at least 3x3
102 matrix units can be guaranteed.
103
104 If neither radius nor points is passed in, create a default
105 AARectangle defined by (-0.5,-0.5),(0.5,0.5).
106 """
107
108
109
110 if 'radius' in args:
111 radius = args['radius']
112 del args['radius']
113
114 if 'min_radius' in args:
115 min_radius = args['min_radius']
116 del args['min_radius']
117 else:
118 min_radius = 0.0
119
120 r=max(radius,min_radius)
121 self._aarect=AARectangle((-r,-r),(r,r))
122
123 elif 'points' in args:
124 self._aarect = AARectangle(*args['points'])
125 del args['points']
126 else:
127 self._aarect = AARectangle((-0.5,-0.5),(0.5,0.5))
128
129 super(BoundingBox,self).__init__(**args)
130
131
133 """
134 Returns true if the given point is contained within the
135 bounding box, where all boundaries of the box are
136 considered to be inclusive.
137 """
138 left,bottom,right,top = self.aarect().lbrt()
139 return (left <= x <= right) and (bottom <= y <= top)
140
150
151
153 """
154 Returns true if the given BoundingBox x is contained within the
155 bounding box, where at least one of the boundaries of the box has
156 to be exclusive.
157 """
158 left,bottom,right,top = self.aarect().lbrt()
159 leftx,bottomx,rightx,topx = x.aarect().lbrt()
160 return (left <= leftx) and (bottom <= bottomx) and (right >= rightx) and (top >= topx) and (not ((left == leftx) and (bottom == bottomx) and (right == rightx) and (top == topx)))
161
163 """
164 Returns true if the given BoundingBox x is contained within the
165 bounding box, including cases of exact match.
166 """
167 left,bottom,right,top = self.aarect().lbrt()
168 leftx,bottomx,rightx,topx = x.aarect().lbrt()
169 return (left <= leftx) and (bottom <= bottomx) and (right >= rightx) and (top >= topx)
170
172 """
173 Returns true if the given point is contained within the
174 bounding box, where the right and upper boundaries
175 are exclusive, and the left and lower boundaries are
176 inclusive. Useful for tiling a plane into non-overlapping
177 regions.
178 """
179 left,bottom,right,top = self.aarect().lbrt()
180 return (left <= x < right) and (bottom <= y < top)
181
184
186 """
187 return left,bottom,right,top values for the BoundingBox.
188 """
189 return self._aarect.lbrt()
190
191
192
194 """
195 Parameter whose value represents a point in a 2D Cartesian plane.
196 """
197
199 try:
200 (x,y) = val
201 super(Cartesian2DPoint,self).__set__(obj,val)
202 except:
203 raise ValueError("Parameter must be a 2D point (an x,y tuple).")
204
205
207 """
208 Similar to BoundingBox, but the region is the ellipse
209 inscribed within the rectangle.
210 """
211 __slots__ = []
212
224
226 """
227 A circular BoundingRegion.
228
229 Takes parameters center (a single 2D point (x,y)) and radius (a
230 scalar radius).
231 """
232
233 __slots__ = ['radius','center']
234
235
236
237
238 - def __init__(self,center=(0.0,0.0),radius=0.5,**args):
242
244 xc,yc = self.center
245 xd = x-xc
246 yd = y-yc
247 return xd*xd + yd*yd <= self.radius*self.radius
248
253
254
268
269
270
271
272
273
274
275
276
277
278
280 """A BoundingBox initialized as the intersection of the supplied list of BoundingBoxes."""
281
283 """
284 Given a list of BoundingBoxes, computes a new BoundingBox that is
285 the intersection of all of the supplied boxes.
286 """
287 super(BoundingBoxIntersection,self).__init__(**params)
288
289 bounds = [r.aarect().lbrt() for r in boxes]
290 left = max([l for (l,b,r,t) in bounds])
291 bottom = max([b for (l,b,r,t) in bounds])
292 right = min([r for (l,b,r,t) in bounds])
293 top = min([t for (l,b,r,t) in bounds])
294
295
296
297
298 self.__aarect = AARectangle((left,bottom),(right,top))
299
302
303
304
305
306
308 """
309 Axis-aligned rectangle class.
310
311 Defines the smallest axis-aligned rectangle that encloses a set of
312 points.
313
314 Usage: aar = AARectangle( (x1,y1),(x2,y2), ... , (xN,yN) )
315 """
316 __slots__ = ['_left','_bottom','_right','_top']
318 self._top = max([y for x,y in points])
319 self._bottom = min([y for x,y in points])
320 self._left = min([x for x,y in points])
321 self._right = max([x for x,y in points])
322
323
324
325
331
335
337 """
338 Return the y-coordinate of the top of the rectangle.
339 """
340 return self._top
342 """
343 Return the y-coordinate of the bottom of the rectangle.
344 """
345 return self._bottom
347 """
348 Return the x-coordinate of the left side of the rectangle.
349 """
350 return self._left
352 """
353 Return the x-coordinate of the right side of the rectangle.
354 """
355 return self._right
357 """
358 Return (left,bottom,right,top) as a tuple
359 """
360 return (self._left,
361 self._bottom,
362 self._right,
363 self._top)
364
365
372
373
375
376 l1,b1,r1,t1 = self.lbrt()
377 l2,b2,r2,t2 = other.lbrt()
378
379 l = max(l1,l2)
380 b = max(b1,b2)
381 r = min(r1,r2)
382 t = min(t1,t2)
383
384 return AARectangle(points=((l,b),(r,t)))
385
390
394
395
396
397
398
399
400
402 """
403 Parameter whose value can be any BoundingRegion instance, enclosing a region in a 2D plane.
404 """
407
413