Updated FloatCanvas code from Chris
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@45725 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
170
wxPython/wx/lib/floatcanvas/Utilities/BBox.py
Normal file
170
wxPython/wx/lib/floatcanvas/Utilities/BBox.py
Normal file
@@ -0,0 +1,170 @@
|
||||
"""
|
||||
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__(BBox, 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 ( (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 Merge(self, BB):
|
||||
"""
|
||||
Joins this bounding box with the one passed in, maybe making this one bigger
|
||||
|
||||
"""
|
||||
|
||||
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]
|
||||
|
||||
### 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
|
||||
|
||||
"""
|
||||
return N.all(self.Array__eq__(BB))
|
||||
|
||||
|
||||
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
|
||||
|
||||
"""
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user