⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rotate.c

📁 c源码
💻 C
字号:
/* Matrix and rotation subroutines */#include "kep.h"#include <stdio.h>#if __STDC__double zatan2(double, double);double fabs(double);double sqrt(double);double sin(double);double cos(double);double atan2(double, double);void midentity (double M[]);void mmpy3 (double A[], double B[], double C[]);void mrotate (int from, int to, double M[], double theta);void EtoM (double e[], double M[]);void epmat (double JD, double P[]);#elsedouble zatan2(), fabs(), sqrt(), sin(), cos(), atan2();void midentity();void mmpy3();void mrotate();void EtoM();void epmat();#endif#define N 3/* Construct the matrix that represents the composite of * successive rotations by the three Euler angles: *   first by an angle phi about the z axis, *   second by an angle theta about the new x axis, *   third by an angle psi about the final z axis. * The input array e[] contains the three angles in the order * phi, theta, psi.  The 3x3 output matrix M[][] is the  * composite transformation of the three rotations in * Cartesian coordinates. *   The matrix elements have been written out directly * in trigonometric form so that the derivation of the * inverse function MtoE() will be clear. */voidEtoM( e, M )double e[];double M[];{double a, b;double sinpsi, cospsi, sinth, costh, sinphi, cosphi;sinpsi = sin(e[2]);cospsi = cos(e[2]);sinth = sin(e[1]);costh = cos(e[1]);sinphi = sin(e[0]);cosphi = cos(e[0]);a = costh*sinphi;b = costh*cosphi;M[0] = cospsi*cosphi - a*sinpsi;  /* M[0][0] */M[1] = cospsi*sinphi + b*sinpsi;  /* M[0][1] */M[2] = sinpsi*sinth;M[3] = -sinpsi*cosphi - a*cospsi;  /* M[1][0] */M[4] = -sinpsi*sinphi + b*cospsi;M[5] = cospsi*sinth;M[6] = sinth*sinphi;  /* M[2][0] */M[7] = -sinth*cosphi;M[8] = costh;  /* M[2][2] */}/* Deduce the three Euler angles e[] * from the input coordinate rotation matrix M[][]. * This is done by trigonometry from the elements of M. * * Since *   M[2][1] = -sin(theta) * cos(phi) *   M[2][0] =  sin(theta) * sin(phi), * then phi = arctan( M[2][0]/M[2][1]. * * Similarly, *  M[0][2] = sin(psi) * sin(theta) *  M[1][2] = cos(psi) * sin(theta), * so psi = arctan( M[0][2]/M[1][2] ). * * Finally, *   M[2][2] = cos(theta) *   M[1][2]/cos(psi) = sin(theta), * which gives the arctangent of theta. */voidMtoE( M, e )double M[], e[];{double a, b, phi, theta, psi;/* phi = zatan2( -M[2][1], M[2][0] ); */phi = atan2(  M[2*3+0], -M[2*3+1]);a = M[0*3+2];b = M[1*3+2];/* psi = zatan2( b, a ); */psi = atan2( a, b );if( fabs(a) > fabs(b) )	a = a/sin(psi);else	a = b/cos(psi);/* theta = zatan2( M[2][2], a ); */theta = atan2( a, M[2*3+2]);e[0] = phi;e[1] = theta;e[2] = psi;}/* Display elements of the NxN matrix M. */voidprtmat( M )double M[];{int r, c;for( r=0; r<N; r++ )	{	for( c=0; c<N; c++ )		printf( "%18.9f ", M[N*r+c] );	printf( "\n" );	}printf( "\n" );}voidprtvec( v )double v[];{int i;for( i=0; i<N; i++ )	printf( "%18.9f ", v[i] );printf( "\n\n" );}/* Fill the array M with an NxN identity matrix. */voidmidentity( M )double M[];{double *p;int i;p = &M[0];for( i=0; i<(N*N); i++ )	*p++ = 0.0;for( i=0; i<N; i++ )	M[i*(N+1)] = 1.0;}/* Matrix transpose. * B, the output, can occupy the same storage locations as * A, the input. */voidmtransp( A, B )double A[], B[];{double x, y;int r, c, rc, cr;for( r=0; r<N; r++ )	{	for( c=0; c<=r; c++ )		{		rc = N*r+c;		cr = N*c+r;		x = A[rc];		y = A[cr];		B[rc] = y;		B[cr] = x;		}	}}/* 3x3 matrix multiply * C = A * B * A is on the left. * C may occupy the same storage as either A or B. */voidmmpy3( A, B, C )double A[], B[], C[];{double ans[9];double s;int i, r, c;for( r=0; r<3; r++ )	{	for( c=0; c<3; c++ )		{		s = 0.0;		for ( i=0; i<3; i++ )			s += A[3*r+i] * B[3*i+c];		ans[3*r+c] = s;		}	}for( i=0; i<9; i++ )	{	C[i] = ans[i];	}}/* Modify matrix M to include a rotation of theta radians * in the from-to plane.  The sense of the rotation is * from the "from" axis (labeled 0, 1, or 2) to the "to" axis. */voidmrotate( from, to, M, theta )int from, to;double M[];double theta;{double c;double R[N*N];if( from == to )	{	printf( "mrotate: from and to must be different\n" );	return;	}midentity( R );c = cos(theta);R[N*from+from] = c;R[N*to+to] = c;c = sin(theta);R[N*from+to] = c;R[N*to+from] = -c;mmpy3( R, M, M );}/* Modify the input matrix M to include a rotation * of theta radians about the x axis. */voidmrotx( M, theta )double M[];double theta;{mrotate( 1, 2, M, theta );}/* Modify the input matrix M to include a rotation * of theta radians about the y axis. */voidmroty( M, theta )double M[];double theta;{mrotate( 2, 0, M, theta );}/* Modify the input matrix M to include a rotation * of theta radians about the z axis. */voidmrotz( M, theta )double M[];double theta;{mrotate( 0, 1, M, theta );}/* Transform the input vector v by rotating the coordinate system * theta radians about the x axis. */voidrotx( v, theta )double v[];double theta;{double y, sinth, costh;sinth = sin(theta);costh = cos(theta);y = costh*v[1] + sinth*v[2];v[2] = -sinth*v[1] + costh*v[2];v[1] = y;}/* Transform the input vector v by rotating the coordinate system * theta radians about the y axis. */voidroty( v, theta )double v[];double theta;{double x, sinth, costh;sinth = sin(theta);costh = cos(theta);x = costh*v[0] - sinth*v[2];v[2] = sinth*v[0] + costh*v[2];v[0] = x;}/* Transform the input vector v by rotating the coordinate system * theta radians about the z axis. */voidrotz( v, theta )double v[];double theta;{double x, sinth, costh;sinth = sin(theta);costh = cos(theta);x = costh*v[0] + sinth*v[1];v[1] = -sinth*v[0] + costh*v[1];v[0] = x;}/* Return the largest element-by-element difference between * two NxN arrays A and B. */double l1diff( A, B )double *A, *B;{double x, max;int i;max = 0;for( i=0; i<N*N; i++ )	{	x = fabs( *A++ - *B++ );	if( x > max )		max = x;	}return( max );}/* The following subprogram, epmat( JD, P ), * constructs the precession matrix in ecliptic coordinates * to go from the epoch J2000.0 to the date JD.  Output P is the * 3x3 rotation matrix.  To go in the opposite direction, * from JD to J2000.0, the required matrix is just the transpose of P. * Note that the obliquity of Earth's equator is not required here * since the coordinates are ecliptic, not equatorial. */#if (DE403 | DE404 | LIB403 | DE405 | DE406 | DE406CD)/* James G. Williams, "Contributions to the Earth's obliquity rate,   precession, and nutation,"  Astron. J. 108, 711-72s4 (1994).   The values used here are slightly different, for DE403.  */  /* 0.000000   5028.791959   1.105414   0.000076  -0.000024 */static double pAcof[] = { -8.66e-10, -4.759e-8, 2.424e-7, 1.3095e-5, 1.7451e-4, -1.8055e-3, -0.235316, 0.076, 110.5414, 50287.91959};/* Pi from Williams' 1994 paper, in radians.  No change in DE403.  *//* 629543.967373   -867.919986   0.153382   0.000026  -0.000004 */static double nodecof[] = {6.6402e-16, -2.69151e-15, -1.547021e-12, 7.521313e-12, 1.9e-10, -3.54e-9, -1.8103e-7,  1.26e-7,  7.436169e-5,-0.04207794833,  3.052115282424};/* pi from Williams' 1994 paper, in radians.  No change in DE403.  *//* 0.000000     46.997570  -0.033506  -0.000124   0.000000 */static double inclcof[] = {1.2147e-16, 7.3759e-17, -8.26287e-14, 2.503410e-13, 2.4650839e-11, -5.4000441e-11, 1.32115526e-9, -6.012e-7, -1.62442e-5, 0.00227850649, 0.0 };#else /* not DE403 *//* Accumulated precession in longitude.  Coefficients are from: * J. Laskar, "Secular terms of classical planetary theories * using the results of general theory," Astronomy and Astrophysics * 157, 59070 (1986). */static double pAcof[] = { -8.66e-10, -4.759e-8, 2.424e-7, 1.3095e-5, 1.7451e-4, -1.8055e-3, -0.235316, 0.07732, 111.1971, 50290.966 };/* Node and inclination of the earth's orbit computed from * Laskar's data as explained in the following paper: * P. Bretagnon and G. Francou, "Planetary theories in rectangular * and spherical variables. VSOP87 solutions," Astronomy and * Astrophysics 202, 309-315 (1988). */static double nodecof[] = {6.6402e-16, -2.69151e-15, -1.547021e-12, 7.521313e-12, 6.3190131e-10, -3.48388152e-9, -1.813065896e-7, 2.75036225e-8, 7.4394531426e-5,-0.042078604317, 3.052112654975 };static double inclcof[] = {1.2147e-16, 7.3759e-17, -8.26287e-14, 2.503410e-13, 2.4650839e-11, -5.4000441e-11, 1.32115526e-9, -5.998737027e-7, -1.6242797091e-5, 0.002278495537, 0.0 };#endif /* not DE403 *//* radians per arc second */#define STR 4.8481368110953599359e-6voidepmat( JD, P )double JD;double P[];{double T, pA, i, Omega;double e[3];double *p;int j;/* Thousands of years from J2000.0.  */T = (JD - 2451545.0)/365250.0;/* Accumulated precession in longitude.  */p = pAcof;pA = *p++;for( j=0; j<9; j++ )	pA = pA * T + *p++;pA *= STR * T;/* Node of the moving ecliptic on the J2000 ecliptic.  */p = nodecof;Omega = *p++;for( j=0; j<10; j++ )	Omega = Omega * T + *p++;/* Inclination of the moving ecliptic to the J2000 ecliptic.  */p = inclcof;i = *p++;for( j=0; j<10; j++ )	i = i * T + *p++;/* Set up the Euler angles. */e[0] = Omega;e[1] = i;e[2] = -(Omega + pA );/* Construct the rotation matrix  to go from J2000 to JD  */EtoM( e, P );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -