轴的旋转

Rotation of Axis

我正在使用 rotation of axis formula 如下:

假设 θ 是 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

所以问题是您已经知道椭圆 (x0,y0,rx,ry) 旋转 a0 并且想要获得椭圆上的点,该点将在椭圆中心和轴之间创建精确的角度 ma穿过它并与 x 平行。

  1. 你把减号弄错了,它应该在 sin(a) ...
  2. 之一之前
  3. 如果需要,这是 XY 平面或围绕 z 轴的旋转!!!
  4. 参数角度 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. 重新缩放,使椭圆变成圆形 只需将 xy(仅一个)乘以比率 ry/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,my 对应于真实角度 ma.

的点坐标

此处预览:

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

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