# Tkinter Tricks: Using Complex Numbers to Rotate Canvas Items

Python’s complex number (dead link) type can be used to represent coordinates in a 2-dimensional graphics system. Simply store the X coordinate as the real part, and the Y coordinate as the imaginary part.

Complex numbers provide a compact way of storing 2D coordinates, but they also make it really easy to manipulate coordinate values. For example, to translate a coordinate, just add the offset (represented as complex number). And to rotate a coordinate, all you have to do is to multiply the coordinate with a complex number representing the angle.

First, you need a complex number that represents the angle. If you have the angle, you can use the cmath.exp function:

```import cmath, math
cangle = cmath.exp(angle*1j) # angle in radians```

Alternatively, if you have two deltas (dx, dy), you can calculate the complex angle directly from the deltas:

```cangle = complex(dx, dy)
cangle = cangle / abs(cangle)```

(the cangle complex value can be seen as a unit vector, with one end at (0, 0)).

To rotate a coordinate around (0, 0), convert the coordinate to a complex number, and multiply it with the complex angle:

```for x, y in coordinates:
v = cangle * complex(x, y)
print v.real, v.imag```

To rotate around an arbitrary point, create a complex number corresponding to that point, subtract that number before you multiply with the angle, and add it back afterwards:

```center = complex(xoffset, yoffset)
for x, y in coordinates:
v = cangle * (complex(x, y) - center) + center
print v.real, v.imag```

The following Tkinter example allows the user to use the mouse to rotate an item around a given center point.

```from Tkinter import *

import math

c = Canvas(width=200, height=200)
c.pack()

# a square
xy = [(50, 50), (150, 50), (150, 150), (50, 150)]

polygon_item = c.create_polygon(xy)

center = 100, 100

def getangle(event):
dx = c.canvasx(event.x) - center
dy = c.canvasy(event.y) - center
try:
return complex(dx, dy) / abs(complex(dx, dy))
except ZeroDivisionError:
return 0.0 # cannot determine angle

def press(event):
# calculate angle at start point
global start
start = getangle(event)

def motion(event):
# calculate current angle relative to initial angle
global start
angle = getangle(event) / start
offset = complex(center, center)
newxy = []
for x, y in xy:
v = angle * (complex(x, y) - offset) + offset
newxy.append(v.real)
newxy.append(v.imag)
c.coords(polygon_item, *newxy)

c.bind("<Button-1>", press)
c.bind("<B1-Motion>", motion)

mainloop()```

Note that for the Tkinter canvas, this only works properly for lines and polygons (all other items are always aligned with the canvas coordinate system). To rotate a rectangle, for example, you must first convert it to a polygon. rendered by a django application. hosted by webfaction.