幾何学オブジェクトのためのオペレーター代数#

クラス Point (ポイント)IRectRect (矩形)Quad (クアッド) 、および Matrix (マトリックス) のインスタンスは、集合的に「幾何学オブジェクト」とも呼ばれます。

これらはすべてPythonシーケンスの特殊なケースであり、詳細については、PyMuPDFでのPythonシーケンスを引数として使用するを参照してください。

これらのクラスには、加算、減算、乗算、除算など、通常の数値とほぼ同じように取り扱うための演算子が定義されています。

この章では、可能な操作の要約を説明します。

一般的な注意事項#

  1. 演算子は2つのオブジェクトを含むバイナリ演算子または単項演算子になります。

  2. バイナリ演算の結果の型は、左オペランドのクラスの新しいオブジェクトまたはbool型です。

  3. 単項演算の結果は、同じクラスの新しいオブジェクト、bool型、またはfloat型のいずれかです。

  4. バイナリ演算子 +-*/ はすべてのクラスで定義されています。これらはおおよその期待通りの動作をしますが、2番目のオペランドは...(省略されました)。

    • 第2のオペランドは常に数値であり、それにより最初のオペランドのすべての要素に対して操作を行います。

    • 第2のオペランドは常に同じ長さの数値のシーケンスであることができます(2つ、4つ、または6つ) - それぞれ point_likerect_likequad_like 、または matrix_like と呼びます。

  5. 矩形は追加のバイナリ演算をサポートしています:交差(演算子“&”)、結合(演算子“|”)、および包含チェック。

  6. バイナリ演算子は、すべての場所で完全にサポートされているため、b が数値または「a_like」の場合、 a /= b のような式が有効です

単項演算#

演算

結果

bool(OBJ)

OBJのすべての成分がゼロの場合にのみfalse

abs(OBJ)

他のタイプに対してnorm(OBJ)と等しい長方形の面積

norm(OBJ)

成分の二乗の平方根(ユークリッドノルム)

+OBJ

OBJの新しいコピー

-OBJ

成分が反転されたOBJの新しいコピー

~m

行列 "m" の逆行列、または逆行列が存在しない場合は零行列

二項演算#

あらゆるジオメトリオブジェクト"a"とあらゆる数値 "b" に対して、演算子 +, - , * , / については常に "a ° b" と "a °= b" の操作が定義されています。それぞれの操作は、"a" の各成分に対して単純に実行されます。もし第二オペランドが数値でない場合、次のように定義されます:

演算

結果

a+b, a-b

成分ごとの実行。"b" は "a" と同様の要素数である必要があります。

a*m, a/m

"a" はポイント、矩形、または行列になりますが、"m" は matrix_like でなければなりません。"a/m" は "a*〜m" として処理されます(非逆行列の場合は以下の注記を参照)。"a" がポイントまたは矩形の場合、"a.transform(m)" が実行されます。"a" が行列の場合、行列の連結が行われます。

a&b

共通の長方形: "a" は長方形であり、"b" は rect_like 形式である必要があります。両方のオペランドに含まれる最大の長方形を返します。

a|b

合併した長方形: "a" は長方形であり、"b" は 点のような point_like rect_like 形式である必要があります。両方のオペランドを含む最小の長方形を返します。

b in a

もし "b" が数値である場合、 b in tuple(a) が返されます。もし "b" が point_like 形式、 rect_like 形式、または quad_like 形式である場合、"a" は長方形である必要があり、a.contains(b) が返されます。

a == b

bool(a-b) が False であれば True を返します("b"は"a-like"である可能性があります)。

注釈

以下は通常の算術との重要な違いに注意してください:

行列の乗算は可換ではありません。つまり、一般に2つの行列に対して m*n != n*m が成り立ちます。また、逆行列を持たないゼロでない行列も存在します。例えば、m = Matrix(1, 0, 1, 0, 1, 0) のような行列があります。これらの行列で除算しようとすると、演算子 "/" を使用して pymupdf.Identity / m のような式で ZeroDivisionError 例外が発生します。しかし、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)
>>>

「Like」オブジェクトを用いた操作#

2項演算の第2オペランドは常に左オペランドと「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では、これを「乗算」(または「除算」とも)として扱います。ここで、第2オペランドは行列と「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
>>>

特に、長方形は追加の2項演算をサポートしています:

  • 交差 -- 長方形や類似の長方形の共通領域を示す演算子 "&"

  • 含有 -- 点状または長方形状を含むように拡大する演算子 "|"

  • 含有確認 点状または長方形状が内部にあるかどうかを確認します

以下は、与えられた点を囲む最小の長方形を作成する例です:

>>> # 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
>>>

This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of that license. Refer to licensing information at artifex.com or contact Artifex Software Inc., 39 Mesa Street, Suite 108A, San Francisco CA 94129, United States for further information.

Discord logo