Python 坐标旋转随着迭代变小 基本三角函数翻译成代码

问题描述

当我的程序迭代坐标旋转算法时,我的坐标变得无限小,我遇到了一个问题。我在下面放了一个 gif,以较慢的帧速率展示了这一点;随着它继续下去,这条线最终会消失。

https://i.gyazo.com/368fbc65dbc5d3deaa282a4b72ec5d22.mp4

我认为问题在于 sin 和 cos 可能会截断数字,但我不确定

def run(root,canvas,line,x,y,width,height):
    # counter clockwise rotation of cartesian coordinates
    # X =  xcosθ + ysinθ
    # Y = -xsinθ + ycosθ

    theta = 1/8

    x,y = tk_to_cart(width/2,height/2,y)

    x =  x * cos(theta) + y * sin(theta)
    y = -x * sin(theta) + y * cos(theta)

    x,y = cart_to_tk(width/2,y)

    canvas.delete(line)
    line = canvas.create_line(width/2,y)

    root.after(20,lambda: run(root,height))

tk_to_cart 和 cart_to_tk 只是画布上的简单翻译,因为 tkinter 的坐标系在左上角有 0,0。

解决方法

可能会损失沿线某处的精度,特别是如果 tk_to_cart 和/或 cart_to_tk 舍入或截断为整数。

一些想法:

  • 让数据只在一个方向(从模型到屏幕)流动,而不是来回流动;如果这没有帮助,
  • 避免重复旋转,而是增加角度并始终从原来的 xy 旋转。

类似于:

def run(root,canvas,line,x_cart,y_cart,width,height,theta=0):
    # counter clockwise rotation of cartesian coordinates
    # X =  xcosθ + ysinθ
    # Y = -xsinθ + ycosθ

    theta += 1/8

    x_rot =  x_cart * cos(theta) + y_cart * sin(theta)
    y_rot = -x_cart * sin(theta) + y_cart * cos(theta)

    x_tk,y_tl = cart_to_tk(width/2,height/2,x_rot,y_rot)

    canvas.delete(line)
    line = canvas.create_line(width/2,x_tk,y_tk)

    root.after(20,lambda: run(root,theta))
,

我想提出这个解决方案,使线绕一个点转。

基本三角函数

参考下图

trigonometric diagram

您将某个 length 的片段从点 x_o,y_o 转到点 x_p,y_p。其中 x_o,y_o 是片段的旋转中心,以及相对于 x',y' 参考系 canva 的平移参考系 x,y 的原点。>

现在,x_o,y_olength 是输入数据,不会随时间变化(除非您决定)。

鉴于此,x',y' 中有一些三角函数:

x_p = length * cos(theta)
y_p = length * sin(theta)

由于您的参考系被翻译,上述公式变为:

x_p = length * cos(theta) + x_o
y_p = length * sin(theta) + y_o

如您所见,您正在计算 x_p,y_p,因此此处的长度不会改变。


翻译成代码

让我们将 theta 表示为在循环中更新的 math.pi 的倍数。

方法变成:

def draw_line(root,length,x_o=0,y_o=0,theta=0.1,rotation='cw',line=None):
    if line is not None:
        canvas.delete(line)
    
    x_p = length * math.cos(math.pi * theta) + x_o
    y_p = length * math.sin(math.pi * theta) + y_o

    k = {'ccw': -1,'cw': 1}[rotation]
    theta = theta + k * 0.05 # or any non linear function to change the motion

    line = canvas.create_line(x_o,y_o,x_p,y_p)
    root.after(100,lambda: draw_line(root,x_o,theta,rotation,line))

所以,运行测试:

import tkinter
import math

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack()

length = 100
x_o = 100
y_o = 100
draw_line(root,rotation='ccw')

使用这种基本的三角方法可以更容易地控制运动。

您可以更改旋转方向 cwccw。您可以使用非线性函数计算 theta 以随时间改变角速度。您可以添加速度参数作为参数。您可以随着时间的推移更改 x_o,y_o 以使线条移动。等

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...