Skip to content

Commit ce286e3

Browse files
JorjMcKiejamie-lemon
authored andcommitted
Supporting vector dot products
Adds support for vector dot products between two points.
1 parent 7211dae commit ce286e3

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

docs/algebra.rst

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ General Remarks
1919
-----------------
2020
1. Operators can be either **binary** (i.e. involving two objects) or **unary**.
2121

22-
2. The resulting type of **binary** operations is either a **new object of the left operand's class** or a bool.
22+
2. The resulting type of **binary** operations is either a **new object of the left operand's class,** a bool or (for dot products) a float.
2323

2424
3. The result of **unary** operations is either a **new object** of the same class, a bool or a float.
2525

26-
4. The binary operators *+, -, *, /* are defined for all classes. They *roughly* do what you would expect -- **except, that the second operand ...**
26+
4. The binary operators `+, -, *, /` are defined for all classes. They *roughly* do what you would expect -- **except, that the second operand ...**
2727

2828
- may always be a number which then performs the operation on every component of the first one,
2929
- may always be a numeric sequence of the same length (2, 4 or 6) -- we call such sequences :data:`point_like`, :data:`rect_like`, :data:`quad_like` or :data:`matrix_like`, respectively.
3030

31-
5. Rectangles support additional binary operations: **intersection** (operator *"&"*), **union** (operator *"|"*) and **containment** checking.
31+
5. Rectangles support **additional binary** operations: **intersection** (operator `"&"`), **union** (operator `"|"`) and **containment** checking.
3232

33-
6. Binary operators fully support in-place operations, so expressions like `a /= b` are valid if b is numeric or "a_like".
33+
6. Binary operators fully support in-place operations. So if "°" is a binary operator then the expression `a °= b` is always valid and the same as `a = a ° b`. Therefore, be careful and do **not** do `p1 *= p2` for two points, because thereafter "p1" is a **float**.
3434

3535

3636
Unary Operations
@@ -50,17 +50,21 @@ Oper. Result
5050

5151
Binary Operations
5252
------------------
53-
For every geometry object "a" and every number "b", the operations "a ° b" and "a °= b" are always defined for the operators *+, -, *, /*. The respective operation is simply executed for each component of "a". If the **second operand is not a number**, then the following is defined:
53+
These are expressions like `a ° b` where "°" is any of the operators `+, -, *, /`. Also binary operations are expressions of the form `a == b` and `b in a`.
5454

55-
========= =======================================================================
55+
If "b" is a number, then the respective operation is executed for each component of "a". Otherwise, if "b" is **not a number,** then the following happens:
56+
57+
58+
========= ===========================================================================
5659
Oper. Result
57-
========= =======================================================================
60+
========= ===========================================================================
5861
a+b, a-b component-wise execution, "b" must be "a-like".
59-
a*m, a/m "a" can be a point, rectangle or matrix, but "m" must be
62+
a*m, a/m "a" can be a point, rectangle or matrix and "m" is a
6063
:data:`matrix_like`. *"a/m"* is treated as *"a*~m"* (see note below
6164
for non-invertible matrices). If "a" is a **point** or a **rectangle**,
6265
then *"a.transform(m)"* is executed. If "a" is a matrix, then
6366
matrix concatenation takes place.
67+
a*b returns the **vector dot product** for a point "a" and point-like "b".
6468
a&b **intersection rectangle:** "a" must be a rectangle and
6569
"b" :data:`rect_like`. Delivers the **largest rectangle**
6670
contained in both operands.
@@ -71,7 +75,7 @@ b in a if "b" is a number, then `b in tuple(a)` is returned.
7175
If "b" is :data:`point_like`, :data:`rect_like` or :data:`quad_like`,
7276
then "a" must be a rectangle, and `a.contains(b)` is returned.
7377
a == b *True* if *bool(a-b)* is *False* ("b" may be "a-like").
74-
========= =======================================================================
78+
========= ===========================================================================
7579

7680

7781
.. note:: Please note an important difference to usual arithmetic:
@@ -118,6 +122,29 @@ The following will deliver the **middle point of a line** that connects two poin
118122
Point(2356.0, 1571.5)
119123
>>>
120124

125+
Compute the ** vector dot product** of two points. You can compute the **cosine of angles** and check orthogonality.
126+
127+
>>> p1 = pymupdf.Point(1, 0)
128+
>>> p2 = pymupdf.Point(1, 1)
129+
>>> dot = p1 * p2
130+
>>> dot
131+
1.0
132+
133+
>>> # compute the cosine of the angle between p1 and p2:
134+
>>> cosine = dot / (abs(p1) * abs(p2))
135+
>>> cosine # cosine of 45 degrees
136+
0.7071067811865475
137+
138+
>>> math.cos(mat.radians(45)) # verify:
139+
0.7071067811865476
140+
141+
>>> # check orhogonality
142+
>>> p3 = pymupdf.Point(0, 1)
143+
>>> # p1 and p3 are orthogonal so, as expected:
144+
>>> p1 * p3
145+
0.0
146+
147+
121148
Manipulation with "like" Objects
122149
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123150

src/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10765,6 +10765,9 @@ def __len__(self):
1076510765
def __mul__(self, m):
1076610766
if hasattr(m, "__float__"):
1076710767
return Point(self.x * m, self.y * m)
10768+
if hasattr(m, "__getitem__") and len(m) == 2:
10769+
# dot product
10770+
return self.x * m[0] + self.y * m[1]
1076810771
p = Point(self)
1076910772
return p.transform(m)
1077010773

0 commit comments

Comments
 (0)