netrate
netrate

Reputation: 443

Formula for rotating a 4 point (rectangle) polygon?

I am using Zelle graphics, but I suppose it is the same for any graphics program. From what I can tell, Zelle graphics does not have a "setheading" or "rotate" command for the rectangle (this is probably because the bounding box is created with two points). In turtle graphics it is easy with setheading(). So presently, I have a class that creates a polygon. I have a draw method and a rotate method. In the rotate method I am changing the Point(x1,y1) for each corner in a FOR LOOP. I broke out some graph paper to get the initial first few points to rotate, there is complex math I believe that would make this more palatable. Presently this is my init method with these attributes, but I am sure there is a better way:

    class create():
def __init__(self, p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y):
    self.p1x = p1x
    self.p2x = p2x
    self.p3x = p3x
    self.p4x = p4x
    self.p1y = p1y
    self.p2y = p2y
    self.p3y = p3y
    self.p4y = p4y

NOTE : this is not the entirety of my code. This is just the INIT method. I don't want anyone to think I have not tried this. I have with working code to rotate a polygon to the left about 5 points, but this is just using self.p1x=self.p1x+1 - I know this is not the correct way to rotate a rectangle. But at present I have a working model for rotating it slightly.

EDIT : Here is the new work I have tried. I am still trying to understand this :

Does this code look ok so far? I am going to assume a rotation angle of 10 degrees for this example.

import math
#assume a 10 x 10 rectangle top left corner 0,0
#top left coords
x=0
y=0
#midpoints
midx = 5
midy = 5

#degrees to radians???????
angle=math.radians(10)

#new top left x
newx1 = x - midx * math.cos(angle) - (y-midy)*math.sin(angle)+ midx
#new top left y
newy1 = y - midy * math.sin(angle) + (x-midx)*math.cos(angle)+ midy
print(newx1, newy1)
  

The output is : 0.9442021232736115 -0.7922796533956911

Upvotes: 0

Views: 869

Answers (1)

furas
furas

Reputation: 142681

This is version which works for me - it rotates Point around midx, midy with angle.

First it has to move middle to (0,0) and get current angle.

def rotate_point(point, angle, midx, midy):
    
    old_x = point.x
    old_y = point.y
    
    old_cx = old_x - midx  # move middle to (0,0)
    old_cy = old_y - midy  # move middle to (0,0)
    
    angle_radians = math.radians(angle)

    angle_sin = math.sin(angle_radians)
    angle_cos = math.cos(angle_radians)
         
    new_cx = old_cx * angle_cos - old_cy * angle_sin
    new_cy = old_cx * angle_sin + old_cy * angle_cos
    
    new_x =  new_cx + midx  # move back
    new_y =  new_cy + midy  # move back
    
    point = Point(new_x, new_y)
    
    return point

And next I can use it to rotate Polygon

def rotate_polygon(polygon, angle, midx, midy):
    
    new_points = []
    
    for p in polygon.getPoints():
        new_p = rotate_point(p, angle, midx, midy)
        new_points.append(new_p)
        
    return Polygon(*new_points)

Here full code which rotates

  • rectangle around middle point (angles: 30, 60),
  • triangle around one of corners (angles: 90, 180, 270).

enter image description here

import math
from graphics import *

def rotate_point(point, angle, midx, midy):
    
    old_x = point.x
    old_y = point.y
    
    old_cx = old_x - midx  # move middle to (0,0)
    old_cy = old_y - midy  # move middle to (0,0)
    
    angle_radians = math.radians(angle)

    angle_sin = math.sin(angle_radians)
    angle_cos = math.cos(angle_radians)
         
    new_cx = old_cx * angle_cos - old_cy * angle_sin
    new_cy = old_cx * angle_sin + old_cy * angle_cos
    
    new_x =  new_cx + midx  # move back
    new_y =  new_cy + midy  # move back
    
    point = Point(new_x, new_y)
    
    return point

def rotate_polygon(polygon, angle, midx, midy):
    
    new_points = []
    
    for p in polygon.getPoints():
        new_p = rotate_point(p, angle, midx, midy)
        new_points.append(new_p)
        
    return Polygon(*new_points)
    
# --- main ---


win = GraphWin()

# --- rectangle ---

x = 100
y = 100
w = 50
h = 50
midx = x + w//2  # rectangle middle
midy = y + h//2  # rectangle middle 

p1 = Polygon(Point(x, y), Point(x+w, y), Point(x+w, y+h), Point(x, y+h), Point(x, y))
p1.draw(win)

p2 = rotate_polygon(p1, 30, midx, midy)
p2.draw(win)

p3 = rotate_polygon(p1, 60, midx, midy)
p3.draw(win)

# --- triangle ---

x = 60
y = 60
w = 50
h = 50
midx = x #+5  # triangle corner
midy = y #+5  # triangle corner

t1 = Polygon(Point(x, y), Point(x+w, y), Point(x+w//2, y+h), Point(x, y))
t1.draw(win)

t2 = rotate_polygon(t1, 90, midx, midy)
t2.draw(win)

t3 = rotate_polygon(t1, 180, midx, midy)
t3.draw(win)

t4 = rotate_polygon(t1, 270, midx, midy)
t4.draw(win)

# ---

win.getMouse()
win.close()

Upvotes: 0

Related Questions