#if !defined(QUATERNION) #define QUATERNION #include "quaternion.h" #endif // ---------------------------------------------------- // --------- quaternion(void) -------------- quaternion::quaternion(void) { // by default we set an identity rotation around the vector e1 theta=0.0; alpha=kpi/2.0; beta=0.0; } // ---------------------------------------------------- // --------- quaternion(v, theta) -------------- quaternion::quaternion(vector3d v, double t) { double dpi=2.0*kpi; try { theta=modulo(t,kpi); if(v.norm()1.0) cp1=1.0; if(cp1<-1.0) cp1=-1.0; beta=acos(cp1); if(fabs(u[2]-sin(alpha)*sin(dpi-beta))3)) throw "quaternion::operator[], (C) index out of range."; switch(i) { case 1: return theta; break; case 2: return alpha; break; case 3: return beta; break; } } catch(const char* message){cerr << message << "\n";} return dummy; } // ---------------------------------------------------- // --------- vect() ---------- vector3d quaternion::vect(void) { double sina=sin(alpha); //cerr << "q.vect():" << alpha << ", " << beta << endl; return vector3d(sina*cos(beta), sina*sin(beta), cos(alpha)); } // ---------------------------------------------------- // --------- operator* ---------- quaternion operator*(const quaternion& a, const quaternion& b) { double a0,a1,a2,a3,b0,b1,b2,b3,p0,p1,p2,p3; // a and b coordinates double beta1, beta2; double sinat=sin(a.theta); double sinbt=sin(b.theta); double sinaa=sin(a.alpha); double sinba=sin(b.alpha); quaternion tmp; double dpi=2.0*kpi; try { // compute a and b cartesian coord. from the angles a0=cos(a.theta); a1=sinat*sinaa*cos(a.beta); a2=sinat*sinaa*sin(a.beta); a3=sinat*cos(a.alpha); b0=cos(b.theta); b1=sinbt*sinba*cos(b.beta); b2=sinbt*sinba*sin(b.beta); b3=sinbt*cos(b.alpha); // compute the product coordinates p0=a0*b0-(a1*b1+a2*b2+a3*b3); p1=a0*b1+a1*b0+a2*b3-a3*b2; p2=a0*b2+a2*b0-a1*b3+a3*b1; p3=a0*b3+a3*b0+a1*b2-a2*b1; // and now; compute the angle back // There is a short problem because a rotation of theta around the vector U can not // be separate from a rotation of 2pi-theta around -U. These two rotations are represented // by the same quaternion. An it is true that they are equivalent. In the way we determine // theta in this part, we have theta between 0 and pi. A rotation of more than pi around a // a given direction U will // therefore become a rotation of 2pi-theta around -U. Physically speaking, they can not be distinguish // because they will give the same image of vector. double p=sqrt(p0*p0+p1*p1+p2*p2+p3*p3); if (p1.0) cp1=1.0; if(cp1<-1.0) cp1=-1.0; tmp.theta=acos(cp1); //cerr << "theta " << tmp.theta << endl; if((tmp.theta1.0) cp3=1.0; if(cp3<-1.0) cp3=-1.0; tmp.alpha=acos(cp3); //cerr << "alpha " << tmp.alpha << endl; if((tmp.alpha1.0) cp1=1.0; if(cp1<-1.0) cp1=-1.0; tmp.beta=acos(cp1); //cerr << "beta " << tmp.beta << endl; // here we check because theta is between 0 and 2*pi if(fabs(p2-sint*sin(tmp.alpha)*sin(dpi-tmp.beta))> ---------- istream& operator>>(istream& in, quaternion &q) { double tmp[4]; double qn; double dpi=2.0*kpi; try { for(int i=0;i<=3;i++) in >> tmp[i]; q.theta=modulo(tmp[0],kpi); qn=sqrt(sqr(tmp[1])+sqr(tmp[2])+sqr(tmp[3])); if(qn>, (C) null quaternion is not a unit quaternion"; q.alpha=acos(tmp[3]/qn); if((q.alpha>, (I) vector along e3\n"; q.beta=0.0; } else { double cp1=tmp[1]/(qn*sin(q.alpha)); if(cp1>1.0) cp1=1.0; if(cp1<-1.0) cp1=-1.0; q.beta=acos(cp1); if(fabs(tmp[2]-sin(q.alpha)*sin(dpi-q.beta))=0.0) if((kpi-alpha)<=da) // check if alpha+da will acceed pi { alpha = alpha + da -kpi; beta = modulo(beta+kpi,dpi); // beta has also to change } else alpha+=da; else { da=-da; // take the absolute value of da if(alpha