几何对象的运算符代数#
Point、IRect、Rect、Quad 和 Matrix 类实例统称为“几何”对象。
它们都是 Python 序列的特例,更多背景信息请参阅在 PyMuPDF 中使用 Python 序列作为参数。
我们为这些类定义了运算符,使其(几乎)可以像普通数字一样进行加、减、乘、除等运算。
本章概述了可能的操作。
一般说明#
运算符可以是二元的(即涉及两个对象)或一元的。
二元运算的结果类型是左操作数类的一个新对象,或者是一个布尔值,或者(对于点积)一个浮点数。
一元运算的结果是同类的一个新对象,或者是一个布尔值,或者一个浮点数。
二元运算符
+, -, *, /
为所有类定义。它们大致执行您期望的操作——但第二操作数除外,因为它…可能总是一个数字,该数字将对第一个操作数的每个分量执行运算,
可能总是一个相同长度(2、4 或 6)的数字序列——我们将此类序列分别称为
point_like
、rect_like
、quad_like
或matrix_like
。
矩形支持额外的二元运算:交集(运算符
"&"
)、并集(运算符"|"
)和包含检查。二元运算符完全支持原地操作。因此,如果“°”是二元运算符,则表达式
a °= b
始终有效,且与a = a ° b
相同。因此,请小心,不要对两个点执行p1 *= p2
,因为此后“p1”将是一个浮点数。
一元运算#
运算符 |
结果 |
---|---|
|
当且仅当 OBJ 的所有分量均为零时为假 |
|
矩形面积——对于其他类型等于 |
|
分量平方和的平方根(欧几里得范数) |
|
OBJ 的新副本 |
|
分量取反的 OBJ 新副本 |
|
矩阵“m”的逆矩阵,如果不可逆则为零矩阵 |
二元运算#
这些是像 a ° b
这样的表达式,其中“°”可以是运算符 +, -, *, /
中的任意一个。a == b
和 b in a
形式的表达式也是二元运算。
如果“b”是一个数字,则对“a”的每个分量执行相应的运算。否则,如果“b”不是一个数字,则发生以下情况
运算符 |
结果 |
---|---|
|
按分量执行,“b”必须是“a-like”。 |
|
“a”可以是点、矩形或矩阵,“m”是 |
|
返回点“a”与 point-like “b”的向量点积。 |
|
交集矩形:“a”必须是一个矩形,“b”是 |
|
并集矩形:“a”必须是一个矩形,“b”可以是 |
|
如果“b”是一个数字,则返回 |
|
如果 * |
注意
请注意与通常算术的一个重要区别
矩阵乘法不满足交换律,即通常对于两个矩阵 m 和 n,有 m*n != n*m
。此外,存在没有逆的非零矩阵,例如 m = Matrix(1, 0, 1, 0, 1, 0)
。如果您尝试除以这些矩阵中的任何一个,使用运算符“/”时将收到 ZeroDivisionError
异常,例如对于表达式 pymupdf.Identity / m
。但如果您写成 pymupdf.Identity * ~m
,结果将是 pymupdf.Matrix()
(零矩阵)。
诚然,这代表了一个不一致之处,我们正在考虑移除它。目前,您可以选择通过检查 ~m 是否为零矩阵来避免异常,或者通过使用 pymupdf.Identity / m
接受潜在的 ZeroDivisionError。
注意
遵循这些约定,所有通常的代数规则均适用。例如,可以任意使用括号(在同类对象之间!):如果 r1, r2 是矩形,m1, m2 是矩阵,您可以执行
(r1 + r2) * m1 * m2
。对于所有同类对象,
a + b + c == (a + b) + c == a + (b + c)
为真。此外,对于矩阵,以下为真:
(m1 + m2) * m3 == m1 * m3 + m2 * m3
(分配律)。- 但是应用矩阵的顺序很重要:如果 r 是一个矩形,m1 和 m2 是矩阵,那么——注意!:
r * m1 * m2 == (r * m1) * m2 != r * (m1 * m2)
一些示例#
数字操作#
对于通常的算术运算,数字始终允许作为第二个操作数。此外,您可以写成 "x in OBJ"
,其中 x 是一个数字。它的实现是 "x in tuple(OBJ)"
>>> pymupdf.Rect(1, 2, 3, 4) + 5
pymupdf.Rect(6.0, 7.0, 8.0, 9.0)
>>> 3 in pymupdf.Rect(1, 2, 3, 4)
True
>>>
以下代码将创建一个文档页面矩形的左上角四分之一
>>> page.rect
Rect(0.0, 0.0, 595.0, 842.0)
>>> page.rect / 2
Rect(0.0, 0.0, 297.5, 421.0)
>>>
以下代码将返回连接两个点 p1 和 p2 的线段中点
>>> p1 = pymupdf.Point(1, 2)
>>> p2 = pymupdf.Point(4711, 3141)
>>> mp = (p1 + p2) / 2
>>> mp
Point(2356.0, 1571.5)
>>>
计算两个点的向量点积。您可以计算夹角的余弦并检查正交性。
>>> p1 = pymupdf.Point(1, 0)
>>> p2 = pymupdf.Point(1, 1)
>>> dot = p1 * p2
>>> dot
1.0
>>> # compute the cosine of the angle between p1 and p2:
>>> cosine = dot / (abs(p1) * abs(p2))
>>> cosine # cosine of 45 degrees
0.7071067811865475
>>> math.cos(mat.radians(45)) # verify:
0.7071067811865476
>>> # check orhogonality
>>> p3 = pymupdf.Point(0, 1)
>>> # p1 and p3 are orthogonal so, as expected:
>>> p1 * p3
0.0
“Like”对象操作#
二元运算的第二个操作数始终可以是左操作数的“like”类型。“Like”在此语境下表示“相同长度的数字序列”。结合以上示例
>>> p1 + p2
Point(4712.0, 3143.0)
>>> p1 + (4711, 3141)
Point(4712.0, 3143.0)
>>> p1 += (4711, 3141)
>>> p1
Point(4712.0, 3143.0)
>>>
要将矩形向右移动 5 个像素,请执行此操作
>>> pymupdf.Rect(100, 100, 200, 200) + (5, 0, 5, 0) # add 5 to the x coordinates
Rect(105.0, 100.0, 205.0, 200.0)
>>>
点、矩形和矩阵可以被矩阵变换。在 PyMuPDF 中,我们将其视为一种“乘法”(或相应的“除法”),其中第二个操作数可以是 matrix 的“like”类型。此处的除法表示“乘以逆矩阵”
>>> m = pymupdf.Matrix(1, 2, 3, 4, 5, 6)
>>> n = pymupdf.Matrix(6, 5, 4, 3, 2, 1)
>>> p = pymupdf.Point(1, 2)
>>> p * m
Point(12.0, 16.0)
>>> p * (1, 2, 3, 4, 5, 6)
Point(12.0, 16.0)
>>> p / m
Point(2.0, -2.0)
>>> p / (1, 2, 3, 4, 5, 6)
Point(2.0, -2.0)
>>>
>>> m * n # matrix multiplication
Matrix(14.0, 11.0, 34.0, 27.0, 56.0, 44.0)
>>> m / n # matrix division
Matrix(2.5, -3.5, 3.5, -4.5, 5.5, -7.5)
>>>
>>> m / m # result is equal to the Identity matrix
Matrix(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
>>>
>>> # look at this non-invertible matrix:
>>> m = pymupdf.Matrix(1, 0, 1, 0, 1, 0)
>>> ~m
Matrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
>>> # we try dividing by it in two ways:
>>> p = pymupdf.Point(1, 2)
>>> p * ~m # this delivers point (0, 0):
Point(0.0, 0.0)
>>> p / m # but this is an exception:
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
p / m
File "... /site-packages/fitz/pymupdf.py", line 869, in __truediv__
raise ZeroDivisionError("matrix not invertible")
ZeroDivisionError: matrix not invertible
>>>
作为一项特色,矩形支持额外的二元运算
交集 – rectangle-likes 的共同区域,运算符 “&”
包含 – 扩大以包含 point-like 或 rect-like,运算符 “|”
包含检查 – point-like 或 rect-like 是否在内部
以下是创建包含给定点的最小矩形的示例
>>> # first define some point-likes
>>> points = []
>>> for i in range(10):
for j in range(10):
points.append((i, j))
>>>
>>> # now create a rectangle containing all these 100 points
>>> # start with an empty rectangle
>>> r = pymupdf.Rect(points[0], points[0])
>>> for p in points[1:]: # and include remaining points one by one
r |= p
>>> r # here is the to be expected result:
Rect(0.0, 0.0, 9.0, 9.0)
>>> (4, 5) in r # this point-like lies inside the rectangle
True
>>> # and this rect-like is also inside
>>> (4, 4, 5, 5) in r
True
>>>