-
Notifications
You must be signed in to change notification settings - Fork 653
Algebra with Matrices, Rectangles and Points
For the Matrix, Rect, IRect and Point classes algebraic operations are possible to some extent. Following we will describe what they are and how they can be used. For binary operations, the type of the second operand does not need to equal that of the left operand. Adjustments take place where necessary. Usually, numeric values are also allowed, as well as lists or tuples of numbers instead of points, rectangles or matrices. In such cases, we talk of "like" objects, e.g. (2, 4) is called a point-like object.
All binary operations are also fully supported in-place.
Matrix objects m, m1, m2 can be added, subtracted, negated, inverted, multiplied or divided. The result of these operations always is a new matrix. In addition, the "absolute value" of a matrix can be calculated - its Euclidean norm - which is a non-negative floating point number.
-
m1 + m2is defined as the matrix[m1.a + m2.a, m1.b + m2.b, ..., m1.f + m2.f].m2can as well be number, which is then added component-wise. Analogous is also true for the following binary operations. -
m1 - m2analogous to addition. -
m1 * m2is defined bym1.concat(m2), ifm2is a matrix-like object. If it is a number, component-wise multiplication takes place. -
m1 / m2is defined bym1 * ~m2. -
-mis defined by[-m.a, -m.b, ..., -m.f]. -
+mis just a copy ofm. -
~mis defined byinvert(m). This means thatm * ~m = ~m * m = fitz.Identity. Because we are dealing with floats here, this equality often is only almost true because of rounding effects etc. Ifmis not invertible (degenerate), then~m = [0, 0, 0, 0, 0, 0]. -
abs(m)is defined bymath.sqrt(m.a**2 + m.b**2 + ... + m.f**2). -
bool(m)isFalseifm = fitz.Matrix(0, 0, 0, 0, 0, 0), elseTrue. - Comparisons are based on components, not object identities:
m1 == m2isTrueif all components are equal. Note however, that floating point values are compared here: therefore a false inequality may result from e.g. rounding effects. - In-place operators are fully supperted:
m1 /= (1, 2, 3, 4, 5, 6)for example calculates the inverse offitz.Matrix(1,2,3,4,5,6)and multiplies the result intom1.
Following are some examples to illustrate the above.
- check if a matrix is invertible:
if not bool(~m): print("m is not invertible") - check whether two matrices are (almost) equal:
if abs(m1 - m2) < epsilon: print("m1 (almost) equals m2") - do a complex matrix calculation:
m = m1*(m2 + ~m3)*m4 - divide components by 2:
m /= 2.
Rect and IRect objects can be added and subtracted to / from other rectangle-like obects or numbers, they can be negated and multiplied with matrix-like objects or numbers. In addition, inclusion | and intersection & of rectangles with other objects are supported as binary operations. The result of these operations always is a new rectangle with the same type (Rect or IRect) as the left operand.
As with matrices, in-place operators are fully supported.
-
r1 + r2andr1 - r2are defined component-wise as with matrices. Any of the two operands can be aRector anIRect. In addition,r2can also be a number or rectangle-like. -
-ris defined component-wise (RectorIRect). -
+ris a copy ofr. -
r * mis a new rectangle resulting fromrtransformed with matrix-likem. Ifmis a number, it is multiplied with the coordinates. -
r / mis analogous to multiplication. Ifmis matrix-like, then its inverse is multiplied withr. -
r1 | r2(inclusion) is the smallest rectangle containing both,r1(rectangle) andr2(rectangle-like or point-like). -
r1 & r2(intersection) is the largest rectangle that is contained in both,r1(rectangle) andr2(rectangle-like). -
bool(r)isFalseif all components ofrare zero, elseTrue.
Example ("rectangle hull"):
If plist = [p0, p1, ..., pn] is a list of Point objects then r computed by
r = fitz.Rect(p0, p0)
for p in plist:
r = r | p
is the smallest rectangle containing all points in the list. Note: if you want an IRect perform a r.round() afterwards.
Example ("finite rectangle"):
MuPDF defines rectangles as infinite, if the bottom right corner is not south-eastern to the top left one. This may be awkward sometimes. So, here is a recipe to create a finite rectangle covering the same area:
r = fitz.Rect(...) # potentially infinite rectangle
s = fitz.Rect(r.top_left, r.top_left) # rect containing just a point
s = s | r.bottom_right # s now is a finite rectangle
A simpler method is r.normalize(). This converts the rectangle to its finite version. To leave it intact, create a finite copy like this:
s = (+r).normalize()
Point objects can be added, subtracted and negated just like rectangles, yielding new point objects.
-
p1 + p2,p1 - p2,-p,+pare defined component-wise like the rectangle operations.p2can be point-like or a number. -
abs(p)is the Eucldean normmath.sqrt(p.x**2 + p.y**2)as with matrices. -
p * mis a new point resulting fromptransformed with a matrix-likemor a number. Instead ofp * ~myou can also writep / mifmis matrix-like. - In-place operators are also fully supported: if
p = fitz.Point(100, 100), thenp /= (1, 2, 3, 4, 5, 6)deliversfitz.Point(-49.0, 48.0), andp /= 2isfitz.Point(50.0, 50.0).
HOWTO Button annots with JavaScript
HOWTO work with PDF embedded files
HOWTO extract text from inside rectangles
HOWTO extract text in natural reading order
HOWTO create or extract graphics
HOWTO create your own PDF Drawing
Rectangle inclusion & intersection
Metadata & bookmark maintenance