2

我试过搜索,但其他问题似乎都不像我的。我或多或少地在 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()

感谢您的任何输入:)

编辑:对不起,我刚刚意识到我忘了提出我的问题。我只想知道为什么它向内吸引,而不仅仅是“正常”旋转?

4

2 回答 2

1

实际上与您的问题无关,但我强烈建议您使用 Numpy 执行几何变换,特别是如果它涉及 3D 点。

下面,我发布一个示例片段,希望对您有所帮助:

import numpy
from math import radians, cos, sin

## suppose you have a Nx3 cloudpoint (it might even be a single row of x,y,z coordinates)
cloudpoint = give_me_a_cloudpoint()

## this will be a rotation around Y azis:
yrot = radians(some_angle_in_degrees)

## let's create a rotation matrix using a numpy array
yrotmatrix = numpy.array([[cos(yrot), 0, -sin(yrot)],
                          [0,         1,          0],
                          [sin(yrot), 0,  cos(yrot)]], dtype=float)


## apply the rotation via dot multiplication
rotatedcloud = numpy.dot(yrotmatrix, pointcloud.T).T   # .T means transposition
于 2012-12-21T22:06:58.823 回答
1

这一段是错的:

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°)。这受到我评论中提到的问题的影响
    • 每次将初始点旋转当前的旋转角度
于 2012-12-21T21:51:07.310 回答