如何围绕原点旋转一条线?

时间:2018-06-15 09:09:56

标签: python-3.x pyqt5 qpainter

我想通过读取文本文件值来旋转和翻译关于原点的线,并且它正在工作,但是它给了我最后一个和最后一个输出。我无法将其视为动画。 self.update()可能存在一些问题。文件名是无人机飞行阅读的日志文件。

{{1}}

提前致谢。

2 个答案:

答案 0 :(得分:0)

我在tkinter中尝试了它并且它的工作正确。这是代码。

from tkinter import *  
from tkinter import ttk 
import xlrd 
import time
import math

def read_file(lineno):
    with open('d:\detect\log_file\Attitude_data_Manual_1232018_1215.txt','r',) as f :
        lines = f.readlines()[4:]
        for s in lines:
            a = s.split()
                #print (len(a))
            if(len(a)!=14):
                print("point reached")
                lineno += 1
                continue
            pitch.append(float(a[4]))
            roll.append(float(a[6]))
            lineno += 1        
       # print(lineno)
    return lineno


def counterrotate(origin,point1,roll):
    ox,oy = origin
    px,py = point1
    angle=math.radians(roll)
    #counterclockwise
    qx= ox+ math.cos(angle)*(px-ox)-math.sin(angle)*(py-oy)
    qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
    return qx,qy

def rotate(origin,point,roll):
    ox,oy = origin
    px,py = point
    angle=math.radians(roll)
    #clockwise
    qx= ox+ math.cos(angle)*(px-ox)+math.sin(angle)*(py-oy)
    qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
    return qx,qy




app=Tk()
app.title("Python GUI Application ")  
name=ttk.Label(app, text="Draw basic line")  
name.pack()  
canvas=Canvas()  
canvas.pack()  
canvas.config(width=480,height=360) 
filename = open('d:\detect\log_file\Attitude_data_Manual_1232018_1215.txt','r')
pitch,roll=[],[]
lineno = 0
lineno = read_file(lineno)
for m in range(0,lineno,1):
    x0=-400
    x1=880
    y0=180
    y1=180
    xc=240
    yc=180

    point1= (x1,y1)
    point= (x0,y0)
    origin= (xc,yc)
    x0,y0=rotate(origin,point,roll[m]*10)
    y0=y0-(pitch[m]*60)
    canvas.move(point,x0,y0)
    x1,y1=counterrotate(origin,point1,roll[m]*10)
    y1=y1-(pitch[m]*60)
    canvas.move(point,x1,y1)
    line1=canvas.create_line(x0,y0,x1,y1,fill='green',width=1)
    blue_point= [x0,y0,x1,y1,480,0,0,0]
    green_points=[x0,y0,x1,y1,480,360,0,360]
    blue_poly=canvas.create_polygon(blue_point,fill='sky blue',width=2)
    green_poly=canvas.create_polygon(green_points,fill='green',width=2)
    canvas.create_line(0,180,480,180,fill='black',width=1)
    canvas.update()
    time.sleep(0.1)
    canvas.delete(line1)
    canvas.delete(green_poly)
    canvas.delete(blue_poly)

app.mainloop()

答案 1 :(得分:0)

您必须避免在GUI中使用time.sleep(),因为它会阻止事件循环,因此会生成它无法正确更新。我没有花时间审查出了什么问题,但提出了正确的实施方案。

我的解决方案建议有一个通过信号每隔一定时间间隔提供数据的类,以生成我使用QTimer的时间间隔。

小部件获取数据并按您的意愿执行计算。

import sys

import math

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


def counterrotate(origin,point1,roll):
    ox,oy = origin
    px,py = point1
    angle=math.radians(roll)
    #counterclockwise
    qx= ox+ math.cos(angle)*(px-ox)-math.sin(angle)*(py-oy)
    qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
    return qx,qy

def rotate(origin,point,roll):
    ox,oy = origin
    px,py = point
    angle=math.radians(roll)
    #clockwise
    qx= ox+ math.cos(angle)*(px-ox)+math.sin(angle)*(py-oy)
    qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
    return qx,qy


class Manager(QObject):
    changedValue = pyqtSignal(tuple)
    def __init__(self):
        QObject.__init__(self)
        filename = "Attitude_data_Manual_1232018_1158.txt"
        res = self.read_content(filename)
        self.results = zip(*res)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_value)
        self.timer.start(100)

    @pyqtSlot()
    def update_value(self):
        try:
            self.changedValue.emit(next(self.results))
        except StopIteration:
            self.timer.stop()
            #QCoreApplication.instance().quit()

    def read_content(self, filename):
        pitch = []
        roll = []
        with open(filename,'r') as f :
            lines = f.readlines()[4:]
            for s in lines:
                a = s.split()
                if len(a) !=14:
                    print("point reached")
                    continue
                pitch.append(float(a[4]))
                roll.append(float(a[6]))
        return pitch, roll

class Widget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.v = None

    @pyqtSlot(tuple)
    def update_value(self, v):
        self.v = v
        self.update()

    def paintEvent(self, event):
        QWidget.paintEvent(self, event)
        painter = QPainter(self)
        r = self.rect()

        if self.v:
            x0, x1, y0, y1, xc, yc = -400, 880, 180, 180, 240, 180
            point1 = (x1,y1)
            point = (x0,y0)
            origin = (xc,yc)

            pitch, roll = self.v

            x0,y0 = rotate(origin, point, roll*10)
            y0 -= pitch*60
            x1, y1 = counterrotate(origin,point1, roll*10)
            y1 -= pitch*60

            posx0 = QPoint(x0, y0)
            posx1 = QPoint(x1, y1)

            upper_polygon = QPolygonF([r.topLeft(), posx0, posx1, r.topRight()])
            bottom_polygon = QPolygonF([posx0, posx1, r.bottomRight(), r.bottomLeft()])


            painter.setBrush(QColor("skyblue"))
            painter.drawPolygon(upper_polygon)

            painter.setBrush(QColor("green"))
            painter.drawPolygon(bottom_polygon)

        painter.drawLine(r.left(), r.center().y(), r.right(), r.center().y())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    manager = Manager()
    w = Widget()
    manager.changedValue.connect(w.update_value)
    w.show()
    sys.exit(app.exec_())