轴旋转

Rotation of Axis

提问人:metron 提问时间:11/26/2020 最后编辑:metron 更新时间:11/27/2020 访问量:492

问:

我使用轴的旋转公式如下:

enter image description here

假设 θ 是 30 度,所以为了回到未旋转的状态,我只是使用 (360-30) 表示α(全部以弧度为单位)。但是,我没有回到 0 度。我已经在 python 中添加了代码进行验证,所以一切似乎都很好(为 α 添加 90 度或 π/2)给了我正确的偏移量,但是,添加偏移量以返回“未旋转”状态是一个问题。

可能是什么问题?

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Ellipse
import numpy.random as rnd


angle=2 * np.pi * rnd.random(size=1)
print("angle",np.degrees(angle))
x_circle90 = np.cos(np.pi / 2)
y_circle90 = np.sin(np.pi / 2)
x_90 = (x_circle90 * (40 * 0.5))
y_90 = (y_circle90 * (50 * 0.5))
xx90 = x_90 * np.cos(angle) - y_90 * np.sin(angle) + 108
yy90 = x_90 * np.sin(angle) + y_90 * np.cos(angle) + 60


x_circle0 = np.cos(0)
y_circle0 = np.sin(0)
x_0 = (x_circle0 * (40 * 0.5))
y_0 = (y_circle0 * (50 * 0.5))
xx0 = x_0 * np.cos(angle) - y_0 * np.sin(angle) + 108
yy0 = x_0 * np.sin(angle) + y_0 * np.cos(angle) + 60

negation=(2*np.pi-angle)
x_circlen = np.cos(negation)
y_circlen = np.sin(negation)
x_n = (x_circlen * (40 * 0.5))
y_n = (y_circlen * (50 * 0.5))
xxn = x_n * np.cos(angle) - y_n * np.sin(angle) + 108
yyn = x_n * np.sin(angle) + y_n * np.cos(angle) + 60


fig = plt.figure()
ax = fig.add_subplot(111)
ax.add_patch(
    Ellipse(xy=[108,60],
            width=40,
            height=50,
            angle=np.degrees(angle),
            fill=False, color='k', linewidth=1))

ax.plot(xx0, yy0, 'rp', color='blue', markersize=2)
ax.plot(xx90, yy90, 'rp', color='green', markersize=2)
ax.plot(xxn, yyn, 'rp', color='black', markersize=2)
ax.plot(108,60,'rp', color='red', markersize=2)
ax.set_xlim(xmin=0, xmax=200)
ax.set_ylim(0, 200)
ax.set_aspect('equal', adjustable='box')
plt.show()
plt.pause()
plt.close

enter image description here

python numpy 几何 与语言无关

评论


答:

1赞 Spektre 11/26/2020 #1

所以问题是你已经知道椭圆()旋转了,并希望获得椭圆上的点,该点将在椭圆中心和穿过它并平行于x的轴之间产生精确的角度。x0,y0,rx,rya0ma

  1. 你弄错了减号,它应该在其中一个之前......sin(a)
  2. 如果需要,这是 XY 平面或绕轴旋转!!z
  3. 参数角是非线性的,因此简单的减法是行不通的b

旋转公式本身为:

x' =  x*cos(a) - y*sin(a)
y' =  x*sin(a) + y*cos(a)

或:

x' =  x*cos(a) + y*sin(a)
y' = -x*sin(a) + y*cos(a)

对于相反的方向......现在参数椭圆为:

x = rx*cos(b)
y = ry*sin(b)

所以当放在一起时(第二次旋转公式):

x' =  rx*cos(b)*cos(a) + ry*sin(b)*sin(a)
y' = -rx*cos(b)*sin(a) + ry*sin(b)*cos(a)

现在我们有了可以从参数角度获得点的公式,我们想从真实角度计算点。这可以通过更多方式完成。我选择:

  1. 计算具有实际角度的方向向量ma
  2. 取消旋转a0
  3. 重新缩放它,使椭圆变为圆形 只需乘以或(仅 1)乘以比率或xyry/rxrx/ry
  4. 旋转方式a0
  5. 使用 ATAN2 获取参数角度

下面是 C++/VCL 示例:

//---------------------------------------------------------------------------
const double pi2=6.283185307179586476925286766559;
const double deg=6.283185307179586476925286766559/360.0;
double x0=125,y0=75,rx=100,ry=50.0,a0=15.0*deg; // ellipse center,radiuses,rotation
//---------------------------------------------------------------------------
void ellipse_draw(TCanvas *can) // render ellipse
    {
    int e;
    double b=0.0,db=0.01*pi2,x,y;
    x =  rx*cos(b)*cos(a0) + ry*sin(b)*sin(a0) +x0;
    y = -rx*cos(b)*sin(a0) + ry*sin(b)*cos(a0) +y0;
    can->MoveTo(x,y);
    for (e=1;e;b+=db)
        {
        if (b>=pi2) { b=pi2; e=0; }
        x =  rx*cos(b)*cos(a0) + ry*sin(b)*sin(a0) +x0;
        y = -rx*cos(b)*sin(a0) + ry*sin(b)*cos(a0) +y0;
        can->LineTo(x,y);
        }
    }
//---------------------------------------------------------------------------
void ellipse_getpnt(double &mx,double &my,double ma) // (mx,my) = point at global angle ma from (x0,y0)
    {
    int e;
    double b,x,y;
    // direction vector with global angle ma in ellipse local coordinates
    b=ma+a0;
    x =cos(b);
    y =sin(b);
    // rescale to circle
    y*=rx/ry;
    // convert (x,y) to unrotated coordinates
    mx =  x*cos(a0) + y*sin(a0);
    my = -x*sin(a0) + y*cos(a0);

    // b = atan2(my,mx)
    e=1;
    if (fabs(mx)<1e-3){ e=0; b=+90.0*deg; if (my<0) b= -90.0*deg; }
    if (fabs(my)<1e-3){ e=0; b=+ 0.0*deg; if (mx<0) b=+180.0*deg; }
    if (fabs(mx)+fabs(my)<1e-3){ e=0;  ma=0.0*deg; }
    if (e) b=atan2(my,mx);

    b+=a0;

    // point on ellipse with new angle
    mx =  rx*cos(b)*cos(a0) + ry*sin(b)*sin(a0) +x0;
    my = -rx*cos(b)*sin(a0) + ry*sin(b)*cos(a0) +y0;
    }
//---------------------------------------------------------------------------

第一个函数只是按线条渲染椭圆(这样你就可以匹配你的渲染和坐标系)。第二个是您需要的计算。它计算与实际角度相对应的点坐标。mx,myma

这里预览:

preview

蓝色是椭圆,灰色是实际角度的方向(我使用了鼠标位置),Aqua 是椭圆中心和实际角度计算点之间的线。正如你所看到的,它完全重叠,所以它工作。它沿着整个圆周工作。

为简单起见,我使用了常见的功能,但至少在我的环境中,我必须处理一些边缘情况......atan2

评论

0赞 metron 11/26/2020
我没有完全理解这一点,我使用的是维基百科方程式中显示的正常公式。因此,在“变换后的坐标”中说进入“未旋转”状态,我的意思是从未变换坐标的角度回到“0度”,x轴为水平,y轴为垂直。因此,为此,我只需将角度差代入 $\alpha$ 中,因此差值为 360-(旋转),因此,如果坐标旋转 30 度,则插入方程的角度差值为 $\alpha$ 为 330,$\theta$ 为 30,以旋转坐标为 0 度得到 (x',y')。
0赞 metron 11/26/2020
我正在使用极坐标,因为我使用的应用程序的坐标已经倾斜到 $\theta$,所以我必须计算与旋转坐标相对应的未旋转/未转换坐标的角度,我认为这应该很容易,因为说一切都被 $\theta$ 移动/旋转,所以我可以先减去 $\theta$,然后添加与未旋转坐标中的角度相对应的角度,它将反映相应的值 (x,y) 的旋转椭圆。
1赞 Spektre 11/26/2020
@metron极坐标的旋转只是角度变化,不涉及......从极地到笛卡尔的转换只有单一的罪恶和 cos 没有减号......你提到了椭圆???也许你应该编辑你的问题,并添加所有关于你到底想做什么的信息......你有什么作为输入,你想要什么输出,你遇到的问题是什么。因为如果我把你的问题和你的评论中的所有东西放在一起,对我来说没有任何意义。如果您不知道如何用文字表达它,也许草图/图像会更好。sin,cosrelevant details
1赞 Spektre 11/26/2020
@metron 如果你想成为实际的角度,那么计算要复杂得多......就像非线性一样(你知道,如果你以 10 度采样,椭圆切片将没有 10 度角(有些会更大,有些会更小......bbb
1赞 Spektre 11/26/2020
@metron,所以你得到了具有已知旋转角度的旋转椭圆,并且想在椭圆上获得恰好从屏幕的 x 轴测量的某个角度的点?rx,rya