python - python中的透视投影和旋转

标签 python rotation projection perspective

我尝试过搜索,但其他问题似乎都不像我的。我或多或少在 python 中尝试透视投影和旋转,但遇到了障碍。我确信我的投影方程以及旋转方程都是准确的;但是,当我运行它时,旋转开始正常,但开始向内旋转,直到矢量与 Z 轴(我旋转的轴)处于同一位置。

''' Imports '''
from tkinter import Tk, Canvas, TclError
from threading import Thread
from math import cos, sin, radians, ceil
from time import sleep

''' Points class '''
class pPoint:
    def __init__(self, fPoint, wWC, wHC):
        self.X = 0
        self.Y = 0
        self.Z = 0
        self.xP = 0
        self.yP = 0
        self.fPoint = fPoint
        self.wWC = wWC
        self.wHC = wHC

    def pProject(self):
        self.xP = (self.fPoint * (self.X + self.wWC)) / (self.fPoint + self.Z)
        self.yP = (self.fPoint * (self.Y + self.wHC)) / (self.fPoint + self.Z)

''' Main class '''
class Main:
    def __init__(self):
        ''' Declarations '''
        self.wWidth = 640
        self.wHeight = 480

        self.fPoint = 256

        ''' Generated declarations '''
        self.wWC = self.wWidth / 2
        self.wHC = self.wHeight / 2

        ''' Misc declarations '''
        self.gWin = Tk()

        self.vPoint = pPoint(self.fPoint, self.wWC, self.wHC)

        self.vPoint.X = 50
        self.vPoint.Y = 60
        self.vPoint.Z = -25
        self.vPoint.pProject()

        self.ang = 0

    def initWindow(self):
        self.gWin.minsize(self.wWidth, self.wHeight)
        self.gWin.maxsize(self.wWidth, self.wHeight)

        ''' Create canvas '''
        self.gCan = Canvas(self.gWin, width = self.wWidth, height = self.wHeight, background = "black")
        self.gCan.pack()

    def setAxis(self):
        ''' Create axis points '''
        self.pXax = pPoint(self.fPoint, self.wWC, self.wHC)
        self.pXbx = pPoint(self.fPoint, self.wWC, self.wHC)
        self.pYax = pPoint(self.fPoint, self.wWC, self.wHC)
        self.pYbx = pPoint(self.fPoint, self.wWC, self.wHC)
        self.pZax = pPoint(self.fPoint, self.wWC, self.wHC)
        self.pZbx = pPoint(self.fPoint, self.wWC, self.wHC)

        ''' Set axis points '''
        self.pXax.X = -(self.wWC)
        self.pXax.Y = 0
        self.pXax.Z = 1
        self.pXbx.X = self.wWC
        self.pXbx.Y = 0
        self.pXbx.Z = 1
        self.pYax.X = 0
        self.pYax.Y = -(self.wHC)
        self.pYax.Z = 1
        self.pYbx.X = 0
        self.pYbx.Y = self.wHC
        self.pYbx.Z = 1
        self.pZax.X = 0
        self.pZax.Y = 0
        self.pZax.Z = -(self.fPoint) / 2
        self.pZbx.X = 0
        self.pZbx.Y = 0
        self.pZbx.Z = (self.fPoint * self.wWC) - self.fPoint

    def projAxis(self):
        ''' Project the axis '''
        self.pXax.pProject()
        self.pXbx.pProject()
        self.pYax.pProject()
        self.pYbx.pProject()
        self.pZax.pProject()
        self.pZbx.pProject()

    def drawAxis(self):
        ''' Draw the axis '''
        self.gCan.create_line(self.pXax.xP, self.pXax.yP, self.pXbx.xP, self.pXbx.yP, fill = "white")
        self.gCan.create_line(self.pYax.xP, self.pYax.yP, self.pYbx.xP, self.pYbx.yP, fill = "white")
        self.gCan.create_line(self.pZax.xP, self.pZax.yP, self.pZbx.xP, self.pZbx.yP, fill = "white")

    def prePaint(self):
        self.vA = self.gCan.create_line(self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP, fill = "red")

    def paintCanvas(self):
        try:
            while True:
                self.ang += 1
                if self.ang >= 361:
                    self.ang = 0

                self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))) - (self.vPoint.Y * sin(radians(self.ang))) 
                self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))) + (self.vPoint.Y * cos(radians(self.ang)))
                self.vPoint.pProject()

                self.gCan.coords(self.vA, self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP)

                self.gWin.update_idletasks()
                self.gWin.update()

                sleep(0.1)
        except TclError:
            pass

mMain = Main()

mMain.initWindow()
mMain.setAxis()
mMain.projAxis()
mMain.drawAxis()
mMain.prePaint()
mMain.paintCanvas()

感谢您的任何意见:)

编辑:抱歉,我刚刚意识到我忘记提出问题。我只是想知道为什么它向内引力,而不只是“正常”旋转?

最佳答案

这部分是错误的:

self.ang += 1
if self.ang >= 361:
    self.ang = 0

self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))
               - self.vPoint.Y * sin(radians(self.ang))) 
self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))
               + self.vPoint.Y * cos(radians(self.ang)))
self.vPoint.pProject()

有两个原因:

  1. self.ang 将采用开放范围 [0 - 360] 内的整数,这意味着重复角度 360 (== 0)。
  2. 在每次迭代中,您都会将前一次迭代中的点旋转一定角度。因此,您的第一帧的角度为 1 度,第二帧的角度为 1+2 = 3,第三帧的角度为 1 + 2 + 3...您应该是:
    • 每次将上一次迭代中的点旋转恒定角度 (1°)。这遇到了我评论中提到的问题
    • 每次将初始点旋转当前旋转角度

关于python - python中的透视投影和旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13983162/

相关文章:

java - 如何使用 Jython 执行 if 语句

python - python 中的 Mechanizer - 选择没有名称的表单字段

安卓大图旋转

opengl - NDS 上的 gluProject?

c# - Linq 到实体。嵌套投影

python - SQLAlchemy 和多列不区分大小写的查询

python - python中字典列表的字典

javascript - 在 IE 中使轮子旋转

javascript - 如何旋转图像.onclick

java - 通过 Hibernate Projections on Entity with ManyToOne 关系在 SQL 查询中使用更少的列