/usr/lib/python2.7/dist-packages/FontTools/fontTools/misc/arrayTools.py is in fonttools 3.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | #
# Various array and rectangle tools, but mostly rectangles, hence the
# name of this module (not).
#
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
import math
def calcBounds(array):
"""Return the bounding rectangle of a 2D points array as a tuple:
(xMin, yMin, xMax, yMax)
"""
if len(array) == 0:
return 0, 0, 0, 0
xs = [x for x, y in array]
ys = [y for x, y in array]
return min(xs), min(ys), max(xs), max(ys)
def calcIntBounds(array):
"""Return the integer bounding rectangle of a 2D points array as a
tuple: (xMin, yMin, xMax, yMax)
"""
xMin, yMin, xMax, yMax = calcBounds(array)
xMin = int(math.floor(xMin))
xMax = int(math.ceil(xMax))
yMin = int(math.floor(yMin))
yMax = int(math.ceil(yMax))
return xMin, yMin, xMax, yMax
def updateBounds(bounds, p, min=min, max=max):
"""Return the bounding recangle of rectangle bounds and point (x, y)."""
(x, y) = p
xMin, yMin, xMax, yMax = bounds
return min(xMin, x), min(yMin, y), max(xMax, x), max(yMax, y)
def pointInRect(p, rect):
"""Return True when point (x, y) is inside rect."""
(x, y) = p
xMin, yMin, xMax, yMax = rect
return (xMin <= x <= xMax) and (yMin <= y <= yMax)
def pointsInRect(array, rect):
"""Find out which points or array are inside rect.
Returns an array with a boolean for each point.
"""
if len(array) < 1:
return []
xMin, yMin, xMax, yMax = rect
return [(xMin <= x <= xMax) and (yMin <= y <= yMax) for x, y in array]
def vectorLength(vector):
"""Return the length of the given vector."""
x, y = vector
return math.sqrt(x**2 + y**2)
def asInt16(array):
"""Round and cast to 16 bit integer."""
return [int(math.floor(i+0.5)) for i in array]
def normRect(rect):
"""Normalize the rectangle so that the following holds:
xMin <= xMax and yMin <= yMax
"""
(xMin, yMin, xMax, yMax) = rect
return min(xMin, xMax), min(yMin, yMax), max(xMin, xMax), max(yMin, yMax)
def scaleRect(rect, x, y):
"""Scale the rectangle by x, y."""
(xMin, yMin, xMax, yMax) = rect
return xMin * x, yMin * y, xMax * x, yMax * y
def offsetRect(rect, dx, dy):
"""Offset the rectangle by dx, dy."""
(xMin, yMin, xMax, yMax) = rect
return xMin+dx, yMin+dy, xMax+dx, yMax+dy
def insetRect(rect, dx, dy):
"""Inset the rectangle by dx, dy on all sides."""
(xMin, yMin, xMax, yMax) = rect
return xMin+dx, yMin+dy, xMax-dx, yMax-dy
def sectRect(rect1, rect2):
"""Return a boolean and a rectangle. If the input rectangles intersect, return
True and the intersecting rectangle. Return False and (0, 0, 0, 0) if the input
rectangles don't intersect.
"""
(xMin1, yMin1, xMax1, yMax1) = rect1
(xMin2, yMin2, xMax2, yMax2) = rect2
xMin, yMin, xMax, yMax = (max(xMin1, xMin2), max(yMin1, yMin2),
min(xMax1, xMax2), min(yMax1, yMax2))
if xMin >= xMax or yMin >= yMax:
return False, (0, 0, 0, 0)
return True, (xMin, yMin, xMax, yMax)
def unionRect(rect1, rect2):
"""Return the smallest rectangle in which both input rectangles are fully
enclosed. In other words, return the total bounding rectangle of both input
rectangles.
"""
(xMin1, yMin1, xMax1, yMax1) = rect1
(xMin2, yMin2, xMax2, yMax2) = rect2
xMin, yMin, xMax, yMax = (min(xMin1, xMin2), min(yMin1, yMin2),
max(xMax1, xMax2), max(yMax1, yMax2))
return (xMin, yMin, xMax, yMax)
def rectCenter(rect0):
"""Return the center of the rectangle as an (x, y) coordinate."""
(xMin, yMin, xMax, yMax) = rect0
return (xMin+xMax)/2, (yMin+yMax)/2
def intRect(rect1):
"""Return the rectangle, rounded off to integer values, but guaranteeing that
the resulting rectangle is NOT smaller than the original.
"""
(xMin, yMin, xMax, yMax) = rect1
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)
def _test():
"""
>>> import math
>>> calcBounds([])
(0, 0, 0, 0)
>>> calcBounds([(0, 40), (0, 100), (50, 50), (80, 10)])
(0, 10, 80, 100)
>>> updateBounds((0, 0, 0, 0), (100, 100))
(0, 0, 100, 100)
>>> pointInRect((50, 50), (0, 0, 100, 100))
True
>>> pointInRect((0, 0), (0, 0, 100, 100))
True
>>> pointInRect((100, 100), (0, 0, 100, 100))
True
>>> not pointInRect((101, 100), (0, 0, 100, 100))
True
>>> list(pointsInRect([(50, 50), (0, 0), (100, 100), (101, 100)], (0, 0, 100, 100)))
[True, True, True, False]
>>> vectorLength((3, 4))
5.0
>>> vectorLength((1, 1)) == math.sqrt(2)
True
>>> list(asInt16([0, 0.1, 0.5, 0.9]))
[0, 0, 1, 1]
>>> normRect((0, 10, 100, 200))
(0, 10, 100, 200)
>>> normRect((100, 200, 0, 10))
(0, 10, 100, 200)
>>> scaleRect((10, 20, 50, 150), 1.5, 2)
(15.0, 40, 75.0, 300)
>>> offsetRect((10, 20, 30, 40), 5, 6)
(15, 26, 35, 46)
>>> insetRect((10, 20, 50, 60), 5, 10)
(15, 30, 45, 50)
>>> insetRect((10, 20, 50, 60), -5, -10)
(5, 10, 55, 70)
>>> intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50))
>>> not intersects
True
>>> intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50))
>>> intersects
1
>>> rect
(5, 20, 20, 30)
>>> unionRect((0, 10, 20, 30), (0, 40, 20, 50))
(0, 10, 20, 50)
>>> rectCenter((0, 0, 100, 200))
(50.0, 100.0)
>>> rectCenter((0, 0, 100, 199.0))
(50.0, 99.5)
>>> intRect((0.9, 2.9, 3.1, 4.1))
(0, 2, 4, 5)
"""
if __name__ == "__main__":
import sys
import doctest
sys.exit(doctest.testmod().failed)
|