MeesterTeem - 3 months ago 13

Python Question

I'm working on a program to manipulate GIS data, but for this precise problem, I'm trying to rotate a rectangle of 4 points around the bottom left corner. I've got 1 tuple describing the bottom left corner:

`x, y=40000,40000`

I've also got a length x, and a length y,

`x_displacement`

`y_displacement`

`theta`

http://i.imgur.com/pp3hFyA.jpg

`x_displacement=100`

y_displacement=100

x = 40000

y = 40000

x1 = x

y1 = y + a.y_displacement

x2 = x + a.x_displacement

y2 = y + a.y_displacement

x3 = x + a.x_displacement

y3 = y

#describes the other 4 corners of the rectangle

Coord is a class that holds an x and a y value.

`coords`

`c = Coord(x, y)`

coords.append(c)

c = Coord(x1, y1)

coords.append(c)

c = Coord(x2, y2)

coords.append(c)

c = Coord(x3, y3)

coords.append(c)

#Adds each corner to the list of coordinates

theta = math.radians(a.angle)

newcoords = []

for c in coords:

newcoords.append(Coord((c.x * math.cos(theta) - c.y * math.sin(theta)),

(c.x * math.sin(theta) + c.y * math.cos(theta))))

coords=newcoords

I suspect that there's something relatively trivial that I'm doing wrong, but I've been stuck on this problem for quite some time.

This code produces a new rectangle that is either misshapen, or has negative corners, rather than slightly left-rotated corners as wanted.

I've seen many posts on here about rotating rectangles, but none seem to be a direct duplicate, because they do not handle negative angles. I'd appreciate any pointers!

Answer

As a few commenters mentioned, you are rotating around the (0, 0) point, rather than the lower left point. As we are constructing the coordinates we can:

- First construct the shape at the (0, 0) point
- Rotate it
- Translate it out to where it needs to be

The below gives an example using plain lists rather than your Coord object, but I'm sure it makes the point.

```
import math
def rotate(xy, theta):
# https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions
cos_theta, sin_theta = math.cos(theta), math.sin(theta)
return (
xy[0] * cos_theta - xy[1] * sin_theta,
xy[0] * sin_theta + xy[1] * cos_theta
)
def translate(xy, offset):
return xy[0] + offset[0], xy[1] + offset[1]
if __name__ == '__main__':
# Create the square relative to (0, 0)
w, h = 100, 100
points = [
(0, 0),
(0, h),
(w, h),
(w, 0)
]
offset = (40000, 50000)
degrees = 90
theta = math.radians(degrees)
# Apply rotation, then translation to each point
print [translate(rotate(xy, theta), offset) for xy in points]
```

As a bonus, this should work with any set of points defined relative to (0, 0), regardless of whether they form any sensible polygon.