2016-04-14 47 views
2

私は近づいていますが、2つの問題があります。 1つは回転した正方形の最終位置です(もう中心にはありません)。 2番目は私の元の頂点リストの変更ですが、私はリスト(..)でコピーしています。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は整数除算を行います。ここでOKですが、SIDEが奇数の場合は正しくありません。


あなたが代わりに

from Tkinter import * 

行うための習慣から抜け出すために試してみてくださいは、

import Tkinter as tk 

を行い、その後、このようTkinterの関数を呼び出す:

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

これはややタイピングですが、コードを読みやすく保守しやすくし、Tkinterが定義した名前の1つをコードが誤って使用したときに発生するエラーを防止します。 FWIWは、from Tkinter import *を実行して170個以上の名前をネームスペースにインポートします。あなたはその混乱を必要としません!

+0

それを愛する!ありがとう。私の学習のこの段階では、この種の「基礎を超えた」答えは確かに非常に便利です。 – Robin

関連する問題