1 module des.math.linear.quaterni; 2 3 import std.exception : enforce; 4 import std.math; 5 6 import des.ts; 7 import des.stdx.traits; 8 9 import des.math.linear.vector; 10 import des.math.linear.matrix; 11 12 import des.math.util; 13 14 /// 15 struct Quaterni(T) if( isFloatingPoint!T ) 16 { 17 /// 18 alias vectype = Vector!(4,T); 19 /// 20 vectype data; 21 /// 22 alias data this; 23 /// 24 alias selftype = Quaterni!T; 25 26 pure: 27 /// 28 this(E...)( in E vals ) 29 if( is( typeof( vectype(vals) ) ) ) 30 { data = vectype(vals); } 31 32 /// 33 this( in Quaterni!T q ) pure { data = q.data; } 34 35 mixin accessByString!(4,T,"data.data","i j k a"); 36 mixin( BasicMathOp!"data" ); 37 38 /// 39 static selftype fromAngle(size_t K,E)( T alpha, auto ref const(Vector!(K,E)) axis ) 40 if( (K==0||K==3) && isFloatingPoint!E ) 41 { 42 static if( K==0 ) enforce( axis.length == 3, "wrong length" ); 43 T a = alpha / cast(T)(2.0); 44 auto vv = axis * sin(a); 45 return selftype( vv[0], vv[1], vv[2], cos(a) ); 46 } 47 48 /// 49 auto opMul(E)( auto ref const(Quaterni!E) b ) const 50 { 51 alias this a; 52 auto aijk = a.ijk; 53 auto bijk = b.ijk; 54 auto vv = cross( aijk, bijk ) + aijk * b.a + bijk * a.a; 55 return Quaterni!T( vv[0], vv[1], vv[2], a.a * b.a - dot(aijk, bijk) ); 56 } 57 58 /// 59 auto rot(size_t K,E)( auto ref const(Vector!(K,E)) b ) const 60 if( (K==0||K==3) && is( CommonType!(T,E) : T ) ) 61 { 62 static if( K==0 ) enforce( b.length == 3, "wrong length" ); 63 auto res = this * selftype(b,0) * inv; 64 return Vector!(K,T)( res.ijk ); 65 } 66 67 const @property 68 { 69 /// 70 T norm() { return dot( this, this ); } 71 /// 72 T mag() { return sqrt( norm ); } 73 /// 74 auto con() { return selftype( -this.ijk, this.a ); } 75 /// 76 auto inv() { return selftype( con / norm ); } 77 78 auto len2() { return data.len2; } 79 } 80 } 81 82 /// 83 alias Quaterni!float quat; 84 /// 85 alias Quaterni!double dquat; 86 /// 87 alias Quaterni!real rquat; 88 89 /// 90 unittest 91 { 92 auto q = quat.fromAngle( PI_2, vec3(0,0,1) ); 93 auto v = vec3(1,0,0); 94 auto e = vec3(0,1,0); 95 auto r = q.rot(v); 96 assertEq( r, e ); 97 }