三維空間任意一點繞任意軸線旋轉


三維空間任意一點繞任意軸線旋轉

參考鏈接三維空間任意一點繞任意軸線旋轉_Marc Pony-CSDN博客_三維坐標旋轉公式繞任意軸

對三維空間任意一點 \(P(p_x,p_y,p_z)\),求繞任意軸線旋轉角度 \(\alpha\) 得到新的點 \(P^{'}(p^{'}_{x},p^{'}_{y},p^{'}_{z})\)

設軸線的方程為

\(\left\{\matrix{x=x_0+n_xt\\y=y_0+n_yt\\z=z_0+n_zt}\right.\)

\(PP^{'}\)所在平面在坐標系 \(XYZ\) 下的平面方程為:

\(n_x(x-p_x)+n_y(y-p_y)+n_z(z-p_z)=0\)

結合兩式可以求得

\(t_0=n_x(x-p_x)+n_y(y-p_y)+n_z(z-p_z)\)

平面與軸線相交的圓心坐標為

\(\left\{\matrix{x_c=x_0+n_xt_0\\y_c=y_0+n_yt_0\\z_c=z_0+n_zt_0}\right.\)

圓半徑

\(r=\sqrt{(p_x-x_c)^2+(p_y-y_c)^2+(p_z-z_c)^2}\)

向量OP

\(\textbf{OP}=[p_x-x_c\ p_y-y_c\ p_z-z_c]^T/r\)

沿軸線建立新坐標系,根據右手法則

\(\textbf{y}^{'}=[n_x\ n_y\ n_z]^{T}\times\textbf{OP}\)

新的坐標系與舊坐標系之間的旋轉變換矩陣為

\(R_{3\times3}=[\textbf{OP}\ \textbf{y}^{'}\ \hat{n}]\)

\(P^{'}\) 在新坐標系下的坐標為

\(\left\{\matrix{x_{temp}=rcos(\alpha)\\y_{temp}=rsin(\alpha)\\z_{temp}=0}\right.\)

利用齊次變換,將點 \(P^{'}\) 在新坐標系變回原坐標系

\(\left[\matrix{p^{'}_x\\p^{'}_y\\p^{'}_z\\1}\right]=\left[\matrix{R_{11}&R_{12}&R_{13}&x_c\\R_{21}&R_{22}&R_{23}&y_c\\R_{31}&R_{32}&R_{33}&z_c\\0&0&0&1}\right]\left[\matrix{x_{temp}\\y_{temp}\\z_{temp}\\1}\right]\)

\(\left[\matrix{p^{'}_x\\p^{'}_y\\p^{'}_z\\1}\right]=T_{4\times4}\left[\matrix{p_x\\p_y\\p_z\\1}\right]\)

\(T_{4\times4}=\left[\matrix{{n^2_x}K+cos(\alpha)&n_xn_yK-n_zsin(\alpha)&n_xn_zK+n_ysin(\alpha)&(x_0-n_zM)K+(n_zy_0-n_yz_0)sin(\alpha)\\n_xn_yK+n_zsin(\alpha)&n_y^2K+cos(\alpha)&n_yn_zK-n_xsin(\alpha)&(y_0-n_yM)K+(n_xz_0-n_zx_0)sin(\alpha)\\n_xn_zK-n_ysin(\alpha)&n_yn_zK+n_xsin(\alpha)&n_z^2K+cos(\alpha)&(z_0-n_zM)K+(n_yx_0-n_xy_0)sin(\alpha)\\0&0&0&1}\right]\)

其中 \(K=1-cos(\alpha),M=n_xx_0+n_yy_0+n_zz_0\)

代碼

經場上測試,軸過原點時適用

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
struct tnode{
    double x,y,z;
};
tnode xz(tnode l,tnode r,tnode from,double dp)
{
    tnode to;
    tnode n;
    n.x=r.x-l.x;
    n.y=r.y-l.y;
    n.z=r.z-l.z;
    double cosa=cos(pi*dp/180);
    double sina=sin(pi*dp/180);
    double K=1-cosa;
    double M=0;
    double p=sqrt(n.x*n.x+n.y*n.y+n.z*n.z);
    n.x/=p;n.y/=p;n.z/=p;
    double t00=n.x*n.x*K+cosa;
    double t01=n.x*n.y*K-n.z*sina;
    double t02=n.x*n.z*K+n.y*sina;
    double t03=0;
    double t10=n.x*n.y*K+n.z*sina;
    double t11=n.y*n.y*K+cosa;
    double t12=n.y*n.z*K-n.x*sina;
    double t13=0;
    double t20=n.z*n.x*K-n.y*sina;
    double t21=n.y*n.z*K+n.x*sina;
    double t22=n.z*n.z*K+cosa;
    double t23=0;
    to.x=from.x*t00+from.y*t01+from.z*t02;
    to.y=from.x*t10+from.y*t11+from.z*t12;
    to.z=from.x*t20+from.y*t21+from.z*t22;
    return to;
}
int main()
{
    tnode l;tnode r;double dq;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf%lf%lf%lf%lf%lf",&l.x,&l.y,&l.z,&r.x,&r.y,&r.z,&dq);
        tnode o;
        o.x=0;o.y=0;o.z=0;
        tnode pl=xz(o,l,r,-dq);
        tnode pr=xz(o,l,r,dq);
        if(pr.z>pl.z)
        {
            printf("%.9lf %.9lf %.9lf\n",pr.x,pr.y,pr.z);
        }
        else
        {
            printf("%.9lf %.9lf %.9lf\n",pl.x,pl.y,pl.z);
        }
    }
    return 0;
}

未經測試,理論上沒錯

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
struct tnode{
    double x,y,z;
};
tnode xz(tnode l,tnode r,tnode from,double dp)
{
	//l為起始點,r為中止點,from為目標點,dp為旋轉角度 
    tnode to;
    tnode n;
    n.x=r.x-l.x;
    n.y=r.y-l.y;
    n.z=r.z-l.z;
    double x0=l.x,y0=l.y,z0=l.z; 
    double cosa=cos(pi*dp/180);
    double sina=sin(pi*dp/180);
    double K=1-cosa;
    double M=n.x*x0+n.y*y0+n.z*z0;
    double p=sqrt(n.x*n.x+n.y*n.y+n.z*n.z);
    n.x/=p;n.y/=p;n.z/=p;
    double t00=n.x*n.x*K+cosa;
    double t01=n.x*n.y*K-n.z*sina;
    double t02=n.x*n.z*K+n.y*sina;
    double t03=(x0-n.x*M)*K+(n.z*y0-n.y*z0)*sina;
    double t10=n.x*n.y*K+n.z*sina;
    double t11=n.y*n.y*K+cosa;
    double t12=n.y*n.z*K-n.x*sina;
    double t13=(y0-n.y*M)*K+(n.x*z0-n.z*x0)*sina;
    double t20=n.z*n.x*K-n.y*sina;
    double t21=n.y*n.z*K+n.x*sina;
    double t22=n.z*n.z*K+cosa;
    double t23=(z0-n.z*M)*K+(n.y*x0-n.x*y0)*sina;;
    to.x=from.x*t00+from.y*t01+from.z*t02+t03;
    to.y=from.x*t10+from.y*t11+from.z*t12+t13;
    to.z=from.x*t20+from.y*t21+from.z*t22+t23;
    return to;
}
int main()
{
    tnode l;tnode r;double dq;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf%lf%lf%lf%lf%lf",&l.x,&l.y,&l.z,&r.x,&r.y,&r.z,&dq);
        tnode o;
        o.x=0;o.y=0;o.z=0;
        tnode pl=xz(o,l,r,-dq);
        tnode pr=xz(o,l,r,dq);
        if(pr.z>pl.z)
        {
            printf("%.9lf %.9lf %.9lf\n",pr.x,pr.y,pr.z);
        }
        else
        {
            printf("%.9lf %.9lf %.9lf\n",pl.x,pl.y,pl.z);
        }
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM