~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#!/usr/bin/env python

"""
A Bounding Box object and assorted utilities , subclassed from a numpy array

"""

import numpy as N

class BBox(N.ndarray):
    """
    A Bounding Box object:
    
    Takes Data as an array. Data is any python sequence that can be turned into a 
    2x2 numpy array of floats:

    [[MinX, MinY ],
     [MaxX, MaxY ]]

    It is a subclass of numpy.ndarray, so for the most part it can be used as 
    an array, and arrays that fit the above description can be used in its place.
    
    Usually created by the factory functions:
    
        asBBox
        
        and 
        
        fromPoints
    
    """
    def __new__(subtype, data):
        """
        Takes Data as an array. Data is any python sequence that can be turned into a 
        2x2 numpy array of floats:

        [[MinX, MinY ],
        [MaxX, MaxY ]]

        You don't usually call this directly. BBox objects are created with the factory functions:
        
        asBBox
        
        and 
        
        fromPoints

        """
        arr = N.array(data, N.float)
        arr.shape = (2,2)
        if arr[0,0] > arr[1,0] or arr[0,1] > arr[1,1]:
            # note: zero sized BB OK.
            raise ValueError("BBox values not aligned: \n minimum values must be less that maximum values")
        return N.ndarray.__new__(subtype, shape=arr.shape, dtype=arr.dtype, buffer=arr)

    def Overlaps(self, BB):
        """
        Overlap(BB):

        Tests if the given Bounding Box overlaps with this one.
        Returns True is the Bounding boxes overlap, False otherwise
        If they are just touching, returns True
        """

        if N.isinf(self).all() or N.isinf(BB).all():
            return True
        if ( (self[1,0] >= BB[0,0]) and (self[0,0] <= BB[1,0]) and
             (self[1,1] >= BB[0,1]) and (self[0,1] <= BB[1,1]) ):
            return True
        else:
            return False

    def Inside(self, BB):
        """
        Inside(BB):

        Tests if the given Bounding Box is entirely inside this one.

        Returns True if it is entirely inside, or touching the
        border.

        Returns False otherwise
        """
        if ( (BB[0,0] >= self[0,0]) and (BB[1,0] <= self[1,0]) and
             (BB[0,1] >= self[0,1]) and (BB[1,1] <= self[1,1]) ):
            return True
        else:
            return False
    
    def PointInside(self, Point):
        """
        Inside(BB):

        Tests if the given Point is entirely inside this one.

        Returns True if it is entirely inside, or touching the
        border.

        Returns False otherwise
        
        Point is any length-2 sequence (tuple, list, array) or two numbers
        """
        if Point[0] >= self[0,0] and \
               Point[0] <= self[1,0] and \
               Point[1] <= self[1,1] and \
               Point[1] >= self[0,1]:
            return True
        else:
            return False
    
    def Merge(self, BB):
        """
        Joins this bounding box with the one passed in, maybe making this one bigger

        """ 
        if self.IsNull():
            self[:] = BB
        elif N.isnan(BB).all(): ## BB may be a regular array, so I can't use IsNull
            pass
        else:
            if BB[0,0] < self[0,0]: self[0,0] = BB[0,0]
            if BB[0,1] < self[0,1]: self[0,1] = BB[0,1]
            if BB[1,0] > self[1,0]: self[1,0] = BB[1,0]
            if BB[1,1] > self[1,1]: self[1,1] = BB[1,1]
        
        return None
    
    def IsNull(self):
        return N.isnan(self).all()

    ## fixme: it would be nice to add setter, too.
    def _getLeft(self):
        return self[0,0]
    Left = property(_getLeft)
    def _getRight(self):
        return self[1,0]
    Right = property(_getRight)
    def _getBottom(self):
        return self[0,1]
    Bottom = property(_getBottom)
    def _getTop(self):
        return self[1,1]
    Top = property(_getTop)

    def _getWidth(self):
        return self[1,0] - self[0,0]
    Width = property(_getWidth)

    def _getHeight(self):
        return self[1,1] - self[0,1]
    Height = property(_getHeight)
    
    def _getCenter(self):
        return self.sum(0) / 2.0
    Center = property(_getCenter)
    ### This could be used for a make BB from a bunch of BBs

    #~ def _getboundingbox(bboxarray): # lrk: added this
        #~ # returns the bounding box of a bunch of bounding boxes
        #~ upperleft = N.minimum.reduce(bboxarray[:,0])
        #~ lowerright = N.maximum.reduce(bboxarray[:,1])
        #~ return N.array((upperleft, lowerright), N.float)
    #~ _getboundingbox = staticmethod(_getboundingbox)


    ## Save the ndarray __eq__ for internal use.
    Array__eq__ = N.ndarray.__eq__
    def __eq__(self, BB):
        """
        __eq__(BB) The equality operator

        A == B if and only if all the entries are the same

        """
        if self.IsNull() and N.isnan(BB).all(): ## BB may be a regular array, so I can't use IsNull
            return True
        else:
            return self.Array__eq__(BB).all()
        
   
def asBBox(data):
    """
    returns a BBox object.

    If object is a BBox, it is returned unaltered

    If object is a numpy array, a BBox object is returned that shares a
    view of the data with that array. The numpy array should be of the correct
    format: a 2x2 numpy array of floats:

    [[MinX, MinY ],
     [MaxX, MaxY ]]
    
    """

    if isinstance(data, BBox):
        return data
    arr = N.asarray(data, N.float)
    return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)

def fromPoints(Points):
    """
    fromPoints (Points).

    reruns the bounding box of the set of points in Points. Points can
    be any python object that can be turned into a numpy NX2 array of Floats.

    If a single point is passed in, a zero-size Bounding Box is returned.
    
    """
    Points = N.asarray(Points, N.float).reshape(-1,2)

    arr = N.vstack( (Points.min(0), Points.max(0)) )
    return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)

def fromBBArray(BBarray):
   """
   Builds a BBox object from an array of Bounding Boxes. 
   The resulting Bounding Box encompases all the included BBs.
   
   The BBarray is in the shape: (Nx2x2) where BBarray[n] is a 2x2 array that represents a BBox
   """
   
   #upperleft = N.minimum.reduce(BBarray[:,0])
   #lowerright = N.maximum.reduce(BBarray[:,1])

#   BBarray = N.asarray(BBarray, N.float).reshape(-1,2)
#   arr = N.vstack( (BBarray.min(0), BBarray.max(0)) )
   BBarray = N.asarray(BBarray, N.float).reshape(-1,2,2)
   arr = N.vstack( (BBarray[:,0,:].min(0), BBarray[:,1,:].max(0)) )
   return asBBox(arr)
   #return asBBox( (upperleft, lowerright) ) * 2
   
def NullBBox():
    """
    Returns a BBox object with all NaN entries.
    
    This represents a Null BB box;
    
    BB merged with it will return BB.
    
    Nothing is inside it.

    """

    arr = N.array(((N.nan, N.nan),(N.nan, N.nan)), N.float)
    return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)

def InfBBox():
    """
    Returns a BBox object with all -inf and inf entries

    """

    arr = N.array(((-N.inf, -N.inf),(N.inf, N.inf)), N.float)
    return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)

class RectBBox(BBox):
    """
    subclass of a BBox that can be used for a rotated Rectangle
    
    contributed by MArco Oster (marco.oster@bioquant.uni-heidelberg.de)

    """
    
    def __new__(self, data, edges=None):
        return BBox.__new__(self, data)

    def __init__(self, data, edges=None):
        ''' assume edgepoints are ordered such you can walk along all edges with left rotation sense
            This may be:
            left-top
            left-bottom
            right-bottom
            right-top

            or any rotation.
        '''
        BBox.BBox(data)
        self.edges = np.asarray(edges)

        print "new rectbbox created"


    def ac_leftOf_ab(self, a, b, c):
        ab = np.array(b) - np.array(a)
        ac = np.array(c) - np.array(a)

        return (ac[0]*ab[1] - ac[1]*ab[0]) <= 0

    def PointInside(self, point):
        print "point inside called"

        for edge in xrange(4):
            if self.ac_leftOf_ab(self.edges[edge],
                                 self.edges[(edge+1)%4],
                                 point):
                continue
            else:
                return False
        return True