- renamed all l,t,r,b tuff to xMin, yMin, xMax, yMax

- added ome more doc strings
- added some minimal test code


git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@441 4cde692c-a291-49d1-8350-778aa11640f8
This commit is contained in:
jvr 2003-08-29 19:29:46 +00:00
parent 6628513fe4
commit fc3879e463

View File

@ -1,20 +1,19 @@
# #
# Various array and rectangle tools # Various array and rectangle tools, but mostly rectangles, hence the
# name of this module (not).
# #
import Numeric
def calcBounds(array): def calcBounds(array):
"""Calculate the bounding rectangle of a 2D array. """Return the bounding rectangle of a 2D points array as a tuple:
Returns a 4-tuple: (xMin, yMin, xMax, yMax)
smallest x, smallest y, largest x, largest y.
""" """
import Numeric
if len(array) == 0: if len(array) == 0:
return 0, 0, 0, 0 return 0, 0, 0, 0
xmin, ymin = Numeric.minimum.reduce(array) xMin, yMin = Numeric.minimum.reduce(array)
xmax, ymax = Numeric.maximum.reduce(array) xMax, yMax = Numeric.maximum.reduce(array)
return xmin, ymin, xmax, ymax return xMin, yMin, xMax, yMax
def updateBounds(bounds, (x, y), min=min, max=max): def updateBounds(bounds, (x, y), min=min, max=max):
"""Return the bounding recangle of rectangle bounds and point (x, y).""" """Return the bounding recangle of rectangle bounds and point (x, y)."""
@ -30,52 +29,106 @@ def pointsInRect(array, rect):
"""Find out which points or array are inside rect. """Find out which points or array are inside rect.
Returns an array with a boolean for each point. Returns an array with a boolean for each point.
""" """
import Numeric
if len(array) < 1: if len(array) < 1:
return [] return []
lefttop = rect[:2] lefttop = rect[:2]
rightbottom = rect[2:] rightbottom = rect[2:]
condition = Numeric.logical_and( condition = Numeric.logical_and(
Numeric.greater(array, lefttop), Numeric.greater_equal(array, lefttop),
Numeric.less(array, rightbottom)) Numeric.less_equal(array, rightbottom))
return Numeric.logical_and.reduce(condition, -1) return Numeric.logical_and.reduce(condition, -1)
def vectorLength(vector): def vectorLength(vector):
"""Return the length of the given vector."""
import Numeric
return Numeric.sqrt(vector[0]**2 + vector[1]**2) return Numeric.sqrt(vector[0]**2 + vector[1]**2)
def asInt16(array): def asInt16(array):
"Round and cast to 16 bit integer." """Round and cast to 16 bit integer."""
import Numeric
return Numeric.floor(array + 0.5).astype(Numeric.Int16) return Numeric.floor(array + 0.5).astype(Numeric.Int16)
def normRect((l, t, r, b)): def normRect((xMin, yMin, xMax, yMax)):
"""XXX doc""" """Normalize the rectangle so that the following holds:
return min(l, r), min(t, b), max(l, r), max(t, b) xMin <= xMax and yMin <= yMax
"""
return min(xMin, xMax), min(yMin, yMax), max(xMin, xMax), max(yMin, yMax)
def scaleRect((l, t, r, b), x, y): def scaleRect((xMin, yMin, xMax, yMax), x, y):
return l * x, t * y, r * x, b * y """Scale the rectangle by x, y."""
return xMin * x, yMin * y, xMax * x, yMax * y
def offsetRect((l, t, r, b), dx, dy): def offsetRect((xMin, yMin, xMax, yMax), dx, dy):
return l+dx, t+dy, r+dx, b+dy """Offset the rectangle by dx, dy."""
return xMin+dx, yMin+dy, xMax+dx, yMax+dy
def insetRect((l, t, r, b), dx, dy): def insetRect((xMin, yMin, xMax, yMax), dx, dy):
return l+dx, t+dy, r-dx, b-dy """Inset the rectangle by dx, dy on all sides."""
return xMin+dx, yMin+dy, xMax-dx, yMax-dy
def sectRect((l1, t1, r1, b1), (l2, t2, r2, b2)): def sectRect((xMin1, yMin1, xMax1, yMax1), (xMin2, yMin2, xMax2, yMax2)):
l, t, r, b = max(l1, l2), max(t1, t2), min(r1, r2), min(b1, b2) """Return a boolean and a rectangle. If the input rectangles intersect, return
if l >= r or t >= b: True and the intersecting rectangle. Return False and (0, 0, 0, 0) if the input
rectangles don't intersect.
"""
xMin, yMin, xMax, yMax = (max(xMin1, xMin2), max(yMin1, yMin2),
min(xMax1, xMax2), min(yMax1, yMax2))
if xMin >= xMax or yMin >= yMax:
return 0, (0, 0, 0, 0) return 0, (0, 0, 0, 0)
return 1, (l, t, r, b) return 1, (xMin, yMin, xMax, yMax)
def unionRect((l1, t1, r1, b1), (l2, t2, r2, b2)): def unionRect((xMin1, yMin1, xMax1, yMax1), (xMin2, yMin2, xMax2, yMax2)):
l, t, r, b = min(l1, l2), min(t1, t2), max(r1, r2), max(b1, b2) """Return the smallest rectangle in which both input rectangles are fully
return (l, t, r, b) enclosed. In other words, return the total bounding rectangle of both input
rectangles.
"""
xMin, yMin, xMax, yMax = (min(xMin1, xMin2), min(yMin1, yMin2),
max(xMax1, xMax2), max(yMax1, yMax2))
return (xMin, yMin, xMax, yMax)
def rectCenter((l, t, r, b)): def rectCenter((xMin, yMin, xMax, yMax)):
return (l+r)/2, (t+b)/2 """Return the center of the rectangle as an (x, y) coordinate."""
return (xMin+xMax)/2, (yMin+yMax)/2
def intRect(rect): def intRect((xMin, yMin, xMax, yMax)):
rect = Numeric.array(rect) """Return the rectangle, rounded off to integer values, but guaranteeing that
l, t = Numeric.floor(rect[:2]) the resulting rectangle is NOT smaller than the original.
r, b = Numeric.ceil(rect[2:]) """
return tuple(Numeric.array((l, t, r, b)).astype(Numeric.Int)) import math
xMin = int(math.floor(xMin))
yMin = int(math.floor(yMin))
xMax = int(math.ceil(xMax))
yMax = int(math.ceil(yMax))
return (xMin, yMin, xMax, yMax)
if __name__ == "__main__":
import Numeric, math
assert calcBounds([(0, 40), (0, 100), (50, 50), (80, 10)]) == (0, 10, 80, 100)
assert updateBounds((0, 0, 0, 0), (100, 100)) == (0, 0, 100, 100)
assert pointInRect((50, 50), (0, 0, 100, 100))
assert pointInRect((0, 0), (0, 0, 100, 100))
assert pointInRect((100, 100), (0, 0, 100, 100))
assert not pointInRect((101, 100), (0, 0, 100, 100))
assert list(pointsInRect([(50, 50), (0, 0), (100, 100), (101, 100)],
(0, 0, 100, 100))) == [1, 1, 1, 0]
assert vectorLength((3, 4)) == 5
assert vectorLength((1, 1)) == math.sqrt(2)
assert list(asInt16(Numeric.array([0, 0.1, 0.5, 0.9]))) == [0, 0, 1, 1]
assert normRect((0, 10, 100, 200)) == (0, 10, 100, 200)
assert normRect((100, 200, 0, 10)) == (0, 10, 100, 200)
assert scaleRect((10, 20, 50, 150), 1.5, 2) == (15, 40, 75, 300)
assert offsetRect((10, 20, 30, 40), 5, 6) == ((15, 26, 35, 46))
assert insetRect((10, 20, 50, 60), 5, 10) == (15, 30, 45, 50)
assert insetRect((10, 20, 50, 60), -5, -10) == (5, 10, 55, 70)
intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50))
assert not intersects
intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50))
assert intersects
assert rect == (5, 20, 20, 30)
assert unionRect((0, 10, 20, 30), (0, 40, 20, 50)) == (0, 10, 20, 50)
assert rectCenter((0, 0, 100, 200)) == (50, 100)
assert rectCenter((0, 0, 100, 199.0)) == (50, 99.5)
assert intRect((0.9, 2.9, 3.1, 4.1)) == (0, 2, 4, 5)