0

I had been doing some image rotation using Pillow (PIL) in an application I am developing. Unfortunately I am not going to be able to get the performance I want rotating images. I am going back to the drawing board and going to attempt to just draw lines and rotate them instead. Last night I put this together based off of some code from the book Python 2.5 Graphics Cookbook. I am hoping someone can show me how to rotate this line not at it end point but at a designated point in the line. In this case the center of the circle Here is my code.

# rotate_line_1.py
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
from Tkinter import *
import math

class RotateLine(object):
    def __init__(self, master):

        self.cw = 430
        self.ch = 480

        self.chart_1 = Canvas(root, width=self.cw, height=self.ch, background='white' )
        self.chart_1.grid(row=0, column=0)

        self.counter = StringVar()
        self.counter.set('0')

        self.linewidth = 10

        self.o1 = self.chart_1.create_oval(1, 1, 430, 430, width=2, fill='#555555')
        self.o2 = self.chart_1.create_oval(15, 15, 420, 420, width=2, fill='black')
        self.a = self.chart_1.create_line(215, 20, 215, 215, width=self.linewidth, fill='red')


        self.p1_x = 214.9 # the pivot point
        self.p1_y = 20.0 # the pivot point,
        self.p2_x = 215.0 # the specific point to be rotated
        self.p2_y = 215.0 # the specific point to be rotated.

        self.a_radian = math.atan((self.p2_y - self.p1_y)/(self.p2_x - self.p1_x))
        self.a_length = math.sqrt((self.p2_y - self.p1_y)*(self.p2_y - self.p1_y) + (self.p2_x - self.p1_x)*(self.p2_x - self.p1_x))

        self.cycle_period = 0 # pause duration (milliseconds).
        self.x = 0

        self.buttonFw = Button(root, text="1 >>", command=lambda: self.rotate_line(1, 1))
        self.buttonBk = Button(root, text="<< 1", command=lambda: self.rotate_line(-1, 1))
        self.button45B = Button(root, text="<< 45", command=lambda: self.rotate_line(-1, 45))
        self.button45F = Button(root, text="45 >>", command=lambda: self.rotate_line(1, 45))
        self.button0 = Button(root, text="0", command=lambda: self.rotate_line(-1, 0))


        self.buttonBk.place(x=10, y=440)
        self.button45B.place(x=75, y=440)
        self.button45F.place(x=290, y=440)
        self.buttonFw.place(x=363, y=440)

        self.button0.place(x=198, y=440)

        self.clicks = 0
        print self.a_radian

    def rotate_line(self, direction, degree):
        self.chart_1.delete(self.a)
        if degree == 0:
            print 'Hello zero'
            self.chart_1.delete(self.a)
            self.a = self.chart_1.create_line(215, 20, 215, 215, width=self.linewidth, fill='red')
            self.a_radian = 1.57028350633
        else:
            self.a_radian += (.01747 * degree) * direction # incremental rotation with direction
            print self.a_radian
            self.p1_x = self.p2_x - self.a_length * math.cos(self.a_radian)
            self.p1_y = self.p2_y - self.a_length * math.sin(self.a_radian)
            self.i = self.chart_1.create_line(self.p1_x, self.p1_y, self.p2_x, self.p2_y, width=self.linewidth, fill='red')
            self.chart_1.update()
            self.chart_1.after(self.cycle_period)
            self.chart_1.delete(self.i)
            self.a = self.chart_1.create_line(self.p1_x, self.p1_y, self.p2_x, self.p2_y, width=self.linewidth, fill='red')

root = Tk()
root.title("Rotating line")
app = RotateLine(root)
root.mainloop()

If you run this you will get a line on a couple of circle backgrounds. Press the buttons to move the line around the center of the circles.

What I want to do it make the line longer but still rotate it at the circle center. Update the line cordinates in both of these lines in the code to 325.

self.a = self.chart_1.create_line(215, 20, 215, 325, width=self.linewidth,
                                  fill='red')

Once the line is longer how can I keep the rotation point still at the center of the circle and redraw the line accordingly?

Thanks in advance and yes my trig skills stink.

martineau
  • 119,623
  • 25
  • 170
  • 301
Husar
  • 413
  • 1
  • 6
  • 17
  • 1
    Translate, rotate, translate. – Ignacio Vazquez-Abrams Mar 14 '15 at 18:29
  • If the [book](http://www.amazon.com/Python-Graphics-Cookbook-Mike-Ohlson/dp/1849513848) you're using doesn't describe how to do this, I'd look another one. – martineau Mar 14 '15 at 19:01
  • @martineau Is there another one that you recommend? – nbro Mar 14 '15 at 19:04
  • @Rinzler: I'd recommend getting something specifically about Computer Graphics. The first one I ever read was the 1st edition of the classic [_Principles Of Interactive Computer Graphics_](http://www.amazon.com/Principles-Interactive-Computer-Graphics-McGraw-Hill/dp/0070463387/ref=sr_1_1?s=books&ie=UTF8&qid=1426364355&sr=1-1&keywords=principles+of+interactive+Computer+Graphics) by Neuman and Sproull — but surely something more up-to-date has been published by now. On the other hand, the basic math involved in doing basic two-dimensional transformations hasn't changed AFAIK. – martineau Mar 14 '15 at 20:27
  • I don't want to rotate at the center of the line. @martineau you seem to have a good understanding of how to do the rotation at a particular point. In my case it could even be hardcore. would you've so kind as to show me using my example above? – Husar Mar 15 '15 at 02:13
  • In your code it looks like you're trying to rotate a line that initially starts out vertical, running from (215, 20) to (215, 215), about that point (215, 0), which is approximately the center of circle (and initially lies directly below the line). Just keep rotating the line's current endpoints about that point using the formulas for calculating new rotated x & y values that's given in the duplicate question's accepted answer. – martineau Mar 15 '15 at 13:16
  • @mantineau You are not reading the entire post. I clearly say to update the line to 215, 20, 215, 325 and then rotate it at the center of the circle. – Husar Mar 15 '15 at 16:38

0 Answers0