source: trunk/anuga_core/source/anuga/geometry/aabb.py @ 7753

Last change on this file since 7753 was 7751, checked in by hudson, 14 years ago

Refactorings from May ANUGA meeting.

File size: 3.3 KB
Line 
1"""
2    Axially aligned bounding box.
3    Contains a class describing a bounding box. It contains methods
4    to split itself and return child boxes.
5"""
6
7# Allow children to be slightly bigger than their parents to prevent
8# straddling of a boundary
9SPLIT_BORDER_RATIO    = 0.55
10
11class AABB:
12    """Axially-aligned bounding box class.
13       Defines a box which can check for intersections with other boxes,
14       or if a point lies within it.
15    """
16   
17    def __init__(self, xmin, xmax, ymin, ymax):
18        """ Define axially-algned bounding box.
19            xmin is minimum x
20            xmax is maximum x (absolute coord, ie, not size)
21            ymin is minimum y
22            ymax is maximum y (absolute coord, ie, not size)
23        """
24        self.xmin = xmin   
25        self.xmax = xmax
26        self.ymin = ymin   
27        self.ymax = ymax
28
29
30    def __repr__(self):
31        return 'AABB(xmin:%f, xmax:%f, ymin:%f, ymax:%f)' \
32               % (round(self.xmin,1), round(self.xmax,1), \
33                  round(self.ymin,1), round(self.ymax, 1)) 
34
35
36    def grow(self, amount):
37        """ Expand region by given amount.
38            amount is a multiplier, ie 1.1 will expand border by 10%.
39        """
40        self.ymax += (self.ymax-self.ymin)*amount
41        self.xmax += (self.xmax-self.xmin)*amount
42        self.ymin -= (self.ymax-self.ymin)*amount
43        self.xmin -= (self.xmax-self.xmin)*amount   
44
45       
46    def size(self):
47        """return size as (w,h)"""
48        return self.xmax - self.xmin, self.ymax - self.ymin
49
50       
51    def split(self, border=SPLIT_BORDER_RATIO):
52        """Split box along shorter axis.
53           return 2 subdivided AABBs. This is useful for recursive
54           algorithms.
55           
56           border is the overlap between the 2 regions - if set to 0.5
57                  it will subdivide them exactly, > 0.5 will create a
58                  shared overlapping area.
59        """
60       
61        width, height = self.size()
62        assert width >= 0 and height >= 0
63       
64        if (width > height):
65            # split vertically
66            split1 = self.xmin+width*border
67            split2 = self.xmax-width*border
68            return AABB(self.xmin, split1, self.ymin, self.ymax), \
69                   AABB(split2, self.xmax, self.ymin, self.ymax)
70        else:
71            # split horizontally       
72            split1 = self.ymin+height*border
73            split2 = self.ymax-height*border
74            return AABB(self.xmin, self.xmax, self.ymin, split1), \
75                   AABB(self.xmin, self.xmax, split2, self.ymax)   
76
77   
78    def is_trivial_in(self, test):
79        """ Is trivial in.
80            test a box to test against the bounding box
81            return True if the test box falls fully within the
82                   bounding box without intersecting it.
83        """
84        if (test.xmin < self.xmin) or (test.xmax > self.xmax):
85            return False       
86        if (test.ymin < self.ymin) or (test.ymax > self.ymax):
87            return False       
88        return True
89 
90    def contains(self, point):
91        """ is point within box
92            point is a test point
93            return True if the point is contained within the box.
94        """
95        return (self.xmin <= point[0] <= self.xmax) \
96                and (self.ymin <= point[1] <= self.ymax)
97       
Note: See TracBrowser for help on using the repository browser.