Skip to content

Commit 4f77faa

Browse files
committed
Add Transform.inverted() method #292
1 parent 786a629 commit 4f77faa

File tree

4 files changed

+33
-29
lines changed

4 files changed

+33
-29
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
Changelog
33
=========
44

5+
.. NEXT
6+
- Added Tranform.inverted() to get the inverse transform.
7+
58
Pymunk 7.1.0 (2025-06-29)
69
-------------------------
710

TODO.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ v6.x
4040
- Update benchmark
4141
- Make benchmark that compares different pymunk and python versions easily
4242
- Update get_vertices doc to use body.local_to_world shorthand to conv.
43-
- Package pymunk for Pyodide
4443
- Add Canvas util module (after pyodide)
4544
- Use https://diataxis.fr/ method of organizing docs (tutorials, how-to, explanation, reference)
4645
- Make sure cffi extensions included in wheel and zip!

pymunk/tests/test_transform.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,6 @@
55

66

77
class UnitTestTransform(unittest.TestCase):
8-
def testInit(self) -> None:
9-
10-
t = p.Transform(1, 2, 3, 4, 5, 6)
11-
self.assertEqual(t.a, 1)
12-
self.assertEqual(t.b, 2)
13-
self.assertEqual(t.c, 3)
14-
self.assertEqual(t.d, 4)
15-
self.assertEqual(t.tx, 5)
16-
self.assertEqual(t.ty, 6)
17-
self.assertEqual(str(t), "Transform(a=1, b=2, c=3, d=4, tx=5, ty=6)")
18-
19-
t = p.Transform(b=4, ty=2)
20-
self.assertEqual(t.a, 1)
21-
self.assertEqual(t.b, 4)
22-
self.assertEqual(t.c, 0)
23-
self.assertEqual(t.d, 1)
24-
self.assertEqual(t.tx, 0)
25-
self.assertEqual(t.ty, 2)
26-
27-
def testIdentity(self) -> None:
28-
t = p.Transform.identity()
29-
self.assertEqual(t.a, 1)
30-
self.assertEqual(t.b, 0)
31-
self.assertEqual(t.c, 0)
32-
self.assertEqual(t.d, 1)
33-
self.assertEqual(t.tx, 0)
34-
self.assertEqual(t.ty, 0)
35-
368
def testPickle(self) -> None:
379
x = p.Transform.identity()
3810
s = pickle.dumps(x, 2)

pymunk/transform.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,36 @@ def rotated(self, t: float) -> "Transform":
164164
"""
165165
return self @ Transform.rotation(t)
166166

167+
def inverted(self):
168+
"""Invert this Transform and return the result
169+
170+
>>> t = Transform.translation(3,4).scaled(2)
171+
>>> v1 = Vec2d(5, 6)
172+
>>> v2 = (t @ v1)
173+
>>> t.inverted() @ v2 == v1
174+
True
175+
176+
>>> t = Transform(1,2,3,4,5,6)
177+
>>> t @ t.inverted()
178+
Transform(a=1.0, b=0.0, c=0.0, d=1.0, tx=0.0, ty=0.0)
179+
180+
>>> i = Transform.identity()
181+
>>> i == i.inverted()
182+
True
183+
"""
184+
det = self.a * self.d - self.b * self.c
185+
if det == 0:
186+
raise ValueError("Singular transform cannot be inverted")
187+
188+
inv_a = self.d / det
189+
inv_b = -self.b / det
190+
inv_c = -self.c / det
191+
inv_d = self.a / det
192+
inv_tx = (self.c * self.ty - self.d * self.tx) / det
193+
inv_ty = (self.b * self.tx - self.a * self.ty) / det
194+
195+
return Transform(inv_a, inv_b, inv_c, inv_d, inv_tx, inv_ty)
196+
167197
@staticmethod
168198
def translation(x: float, y: float) -> "Transform":
169199
"""A translation transform

0 commit comments

Comments
 (0)