2016-04-14 109 views
2

我已經接近了,但有兩個問題。一個是旋轉正方形的最終位置(不再居中)。第二個是我的原始頂點列表發生了變化,儘管我使用list(..)進行了複製。在Tkinter帆布上旋轉方塊

任何幫助像往常一樣受到重視。

from Tkinter import * 
import math 


WIDTH = 400 
HEIGHT = 400 
CANVAS_MID_X = WIDTH/2 
CANVAS_MID_Y = HEIGHT/2 
SIDE = WIDTH/4 

root = Tk() 
canvas = Canvas(root, bg="black", height=HEIGHT, width=WIDTH) 
canvas.pack() 

vertices = [ 
        [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y - SIDE/2], 
        [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y - SIDE/2], 
        [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y + SIDE/2], 
        [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y + SIDE/2]] 

def rotate(points, angle): 
    new_points = list(points) 
    rad = angle * (math.pi/180) 
    cos_val = math.cos(rad) 
    sin_val = math.sin(rad) 
    for coords in new_points: 
     x_val = coords[0] 
     y_val = coords[1] 
     coords[0] = x_val * cos_val - y_val * sin_val 
     coords[1] = x_val * sin_val + y_val * cos_val 
    return new_points 

def draw_square(points): 
    canvas.create_polygon(points, fill="red") 

def test(): 
    print "vertices: ", vertices, "should be: ", "[[150, 150], [250, 150], [250, 250], [150, 250]]" 


new_square = rotate(vertices, 30) 
draw_square(new_square) 
test() 
mainloop() 
+0

感謝您清楚解釋您的問題併發布[mcve]! –

回答

2

您的第一個問題是您使用的公式圍繞原點旋轉。我假設你想圍繞它的中心旋轉正方形。要做到這一點,你只需翻譯廣場,使其中心位於原點,旋轉它,然後將其翻譯回來。

第二個問題是,這樣做list(points)確實創建一個新的外單,但對內部points列表創建新的列表。有許多方法可以爲這些內部列表創建新列表的深層副本,但您並不需要在此處這樣做。只需從旋轉的頂點創建一個新的列表。

我的代碼版本以藍色繪製原始正方形,以便我們可以看到旋轉後的正方形結束於正確的位置。

from Tkinter import * 
import math 

WIDTH = 400 
HEIGHT = 400 
CANVAS_MID_X = WIDTH/2 
CANVAS_MID_Y = HEIGHT/2 
SIDE = WIDTH/4 

root = Tk() 
canvas = Canvas(root, bg="black", height=HEIGHT, width=WIDTH) 
canvas.pack() 

vertices = [ 
    [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y - SIDE/2], 
    [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y - SIDE/2], 
    [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y + SIDE/2], 
    [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y + SIDE/2], 
] 

def rotate(points, angle, center): 
    angle = math.radians(angle) 
    cos_val = math.cos(angle) 
    sin_val = math.sin(angle) 
    cx, cy = center 
    new_points = [] 
    for x_old, y_old in points: 
     x_old -= cx 
     y_old -= cy 
     x_new = x_old * cos_val - y_old * sin_val 
     y_new = x_old * sin_val + y_old * cos_val 
     new_points.append([x_new + cx, y_new + cy]) 
    return new_points 

def draw_square(points, color="red"): 
    canvas.create_polygon(points, fill=color) 

def test(): 
    old_vertices = [[150, 150], [250, 150], [250, 250], [150, 250]] 
    print "vertices: ", vertices, "should be: ", old_vertices 
    print vertices == old_vertices 

draw_square(vertices, "blue") 

center = (CANVAS_MID_X, CANVAS_MID_Y) 
new_square = rotate(vertices, 30, center) 
test() 
draw_square(new_square) 

mainloop() 

我也對你的代碼做了一些其他的小改動。

順便說一句,你應該做的

from __future__ import division 
你等進口前

。這告訴Python使用真正的劃分。沒有它,SIDE/2做整數除法。這在那裏可行,但如果SIDE是奇數,它將不正確。


你應該想辦法去幹什麼

from Tkinter import * 

相反的習慣,做

import Tkinter as tk 

,然後調用Tkinter的功能是這樣的:

canvas = tk.Canvas(root, bg="black", height=HEIGHT, width=WIDTH) 

這是稍微打字,但它使代碼更易於閱讀和維護,並且可以防止在代碼意外使用Tkinter定義的名稱之一時發生的錯誤。 FWIW,from Tkinter import *將170多個名稱導入您的名稱空間。你不需要那麼混亂!

+0

喜歡它!謝謝。在我學習的這個階段,這種「超越基礎」的答案確實非常有用。 – Robin