Dart Documentationvector_mathquat

quat class

class quat {
 double x;
 double y;
 double z;
 double w;

 /// Constructs a quaternion using the raw values [x], [y], [z], and [w]
 quat.raw(this.x, this.y, this.z, this.w);
 /**
  *  Constructs a new quaternion. Behaviour depends on the types of arguments:
  *
  *  +  *([double] x,[double] y,[double] z,[double] w)* Raw values
  *  +  *([vec3] axis,[double] angle)* Rotation of [angle] degrees around [axis]
  *  +  *([quat] other)* Copy of other
  *  +  *([mat3])* Convert rotation matrix into quaternion
  *
  *
  */
 quat([dynamic a, dynamic b, dynamic c, dynamic d]) {
   x = 0.0;
   y = 0.0;
   z = 0.0;
   w = 1.0;

   if (a is num && b is num && c is num && d is num) {
     x = a.toDouble();
     y = b.toDouble();
     z = c.toDouble();
     w = d.toDouble();
     return;
   }

   if (a is vec3 && b is num) {
     setAxisAngle(a, b);
     return;
   }

   if (a is vec3) {
     x = a.x;
     y = a.y;
     z = a.z;
     w = 0.0;
     return;
   }

   if (a is quat) {
     x = a.x;
     y = a.y;
     z = a.z;
     w = a.w;
     return;
   }

   if (a is mat3) {
     double trace = a.trace();
     if (trace > 0.0) {
       double s = Math.sqrt(trace + 1.0);
       w = s * 0.5;
       s = 0.5 / s;
       x = (a.col1.z - a.col2.y) * s;
       y = (a.col2.x - a.col0.z) * s;
       z = (a.col0.y - a.col1.x) * s;
     } else {
       int i = a.col0.x < a.col1.y ? (a.col1.y < a.col2.z ? 2 : 1) :
           (a.col0.x < a.col2.z ? 2 : 0);
       int j = (i + 1) % 3;
       int k = (i + 2) % 3;
       double s = Math.sqrt(a[i][i] - a[j][j] - a[k][k] + 1.0);
       this[i] = s * 0.5;
       s = 0.5 / s;
       this[3] = (a[j][k] - a[k][j]) * s;
       this[j] = (a[i][j] + a[j][i]) * s;
       this[k] = (a[i][k] + a[k][i]) * s;
     }
   }
 }

 /// Constructs a new quaternion representing a rotation of [angle] around [axis]
 quat.axisAngle(vec3 axis, num angle) {
   setAxisAngle(axis, angle);
 }

 /// Constructs a new quaternion which is a copy of [original]
 quat.copy(quat original) {
   x = original.x;
   y = original.y;
   z = original.z;
   w = original.w;
 }

 /** Constructs a random rotation */
 quat.random(Math.Random rn) {
 // From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III,
 //       pg. 124-132
   double x0 = rn.nextDouble();
   double r1 = Math.sqrt(1.0 - x0);
   double r2 = Math.sqrt(x0);
   double t1 = Math.PI*2.0 * rn.nextDouble();
   double t2 = Math.PI*2.0 * rn.nextDouble();
   double c1 = Math.cos(t1);
   double s1 = Math.sin(t1);
   double c2 = Math.cos(t2);
   double s2 = Math.sin(t2);
   x = s1 * r1;
   y = c1 * r1;
   z = s2 * r2;
   w = c2 * r2;
 }

 /// Constructs the identity quaternion
 quat.identity() {
   x = 0.0;
   y = 0.0;
   z = 0.0;
   w = 1.0;
 }

 /** Constructs the time derivative of [q] with angular velocity [omega] */
 quat.dq(quat q, vec3 omega) {
   x = omega.x * q.w + omega.y * q.z - omega.z * q.y;
   y = omega.y * q.w + omega.z * q.x - omega.x * q.z;
   z = omega.z * q.w + omega.x * q.y - omega.y * q.x;
   w = -omega.x * q.x - omega.y * q.y - omega.z * q.z;
   x *= 0.5;
   y *= 0.5;
   z *= 0.5;
   w *= 0.5;
 }

 /// Returns a new copy of this
 quat clone() {
   return new quat.copy(this);
 }

 /// Copy [source] into [this]
 void copyFrom(quat source) {
   x = source.x;
   y = source.y;
   z = source.z;
   w = source.w;
 }

 /// Copy [this] into [target].
 void copyTo(quat target) {
   target.x = x;
   target.y = y;
   target.z = z;
   target.w = w;
 }

 /// Set quaternion with rotation of [radians] around [axis].
 void setAxisAngle(vec3 axis, num radians) {
   radians = radians.toDouble();
   double len = axis.length;
   if (len == 0.0) {
     return;
   }
   double halfSin = sin(radians * 0.5) / len;
   x = axis.x * halfSin;
   y = axis.y * halfSin;
   z = axis.z * halfSin;
   w = cos(radians * 0.5);
 }

 /** Set quaternion with rotation of [yaw], [pitch] and [roll] */
 void setEuler(num yaw, num pitch, num roll) {
   yaw = yaw.toDouble();
   pitch = pitch.toDouble();
   roll = roll.toDouble();
   double halfYaw = yaw * 0.5;
   double halfPitch = pitch * 0.5;
   double halfRoll = roll * 0.5;
   double cosYaw = Math.cos(halfYaw);
   double sinYaw = Math.sin(halfYaw);
   double cosPitch = Math.cos(halfPitch);
   double sinPitch = Math.sin(halfPitch);
   double cosRoll = Math.cos(halfRoll);
   double sinRoll = Math.sin(halfRoll);
   x = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
   y = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
   z = sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw;
   w = cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw;
 }

 /** Normalize [this] */
 quat normalize() {
   double l = length;
   if (l == 0.0) {
     return this;
   }
   x /= l;
   y /= l;
   z /= l;
   w /= l;
   return this;
 }

 /** Conjugate [this] */
 quat conjugate() {
   x = -x;
   y = -y;
   z = -z;
   w = w;
   return this;
 }

 /** Invert [this]  */
 quat inverse() {
   double l = 1.0 / length2;
   x = -x * l;
   y = -y * l;
   z = -z * l;
   w = w * l;
   return this;
 }

 /** Normalized copy of [this]. Optionally stored in [out]*/
 quat normalized([quat out=null]) {
   if (out == null) {
     out = new quat.copy(this);
   }
   return out.normalize();
 }

 /** Conjugated copy of [this]. Optionally stored in [out] */
 quat conjugated([quat out=null]) {
   if (out == null) {
     out = new quat.copy(this);
   }
   return out.conjugate();
 }

 /** Inverted copy of [this]. Optionally stored in [out] */
 quat inverted([quat out=null]) {
   if (out == null) {
     out = new quat.copy(this);
   }
   return out.inverse();
 }

 /** Radians of rotation */
 double get radians {
   return 2.0 * acos(w);
 }

 /** Axis of rotation */
 vec3 get axis {
     double divisor = 1.0 - (w*w);
     return new vec3(x / divisor, y / divisor, z / divisor);
 }

 /** Squared length */
 double get length2 {
   return (x*x) + (y*y) + (z*z) + (w*w);
 }

 /** Length */
 double get length {
   return Math.sqrt(length2);
 }

 /** Returns a copy of [v] rotated by quaternion. Copy optionally stored in [out] */
 vec3 rotated(vec3 v, [vec3 out=null]) {
   if (out == null) {
     out = new vec3.copy(v);
   } else {
     out.copyFrom(v);
   }
   return rotate(out);
 }

 /** Rotates [v] by [this]. Returns [v]. */
 vec3 rotate(vec3 v) {
   // conjugate(this) * [v,0] * this
   double tix = -x;
   double tiy = -y;
   double tiz = -z;
   double tiw = w;
   double tx = tiw * v.x + tix * 0.0 + tiy * v.z - tiz * v.y;
   double ty = tiw * v.y + tiy * 0.0 + tiz * v.x - tix * v.z;
   double tz = tiw * v.z + tiz * 0.0 + tix * v.y - tiy * v.x;
   double tw = tiw * 0.0 - tix * v.x - tiy * v.y - tiz * v.z;
   double result_x = tw * x + tx * w + ty * z - tz * y;
   double result_y = tw * y + ty * w + tz * x - tx * z;
   double result_z = tw * z + tz * w + tx * y - ty * x;
   v.x = result_x;
   v.y = result_y;
   v.z = result_z;
   return v;
 }

 /** Return a copy of [this] divided by [scale] */
 quat operator/(num scale) {
   scale = scale.toDouble();
   return new quat(x / scale, y / scale, z / scale, w / scale);
 }

 /**  Returns copy of [this] multiplied by [scale]
   *  Returns copy of [this] rotated by [otherQuat]
   */
 quat operator*(dynamic other) {
   if (other is num) {
     other = other.toDouble();
     return new quat(x * other, y * other, z * other, w * other);
   }
   if (other is quat) {
     return new quat(w * other.x + x * other.w + y * other.z - z * other.y,
                     w * other.y + y * other.w + z * other.x - x * other.z,
                     w * other.z + z * other.w + x * other.y - y * other.x,
                     w * other.w - x * other.x - y * other.y - z * other.z);
   }
 }

 /** Returns copy of [this] - [other] */
 quat operator+(quat other) {
   return new quat(x + other.x, y + other.y, z + other.z, w + other.w);
 }

 /** Returns copy of [this] + [other] */
 quat operator-(quat other) {
   return new quat(x - other.x, y - other.y, z - other.z, w - other.w);
 }

 /** Returns negated copy of [this] */
 quat operator-() {
   return new quat(-x, -y, -z, -w);
 }

 /** Treats [this] as an array and returns [x],[y],[z], or [w] */
 double operator[](int i) {
   assert(i >= 0 && i < 4);
   switch (i) {
   case 0: return x;
   case 1: return y;
   case 2: return z;
   case 3: return w;
   }
   return 0.0;
 }

 /** Treats [this] as an array and assigns [x],[y],[z], or [w] the value of [arg]*/
 void operator[]=(int i, double arg) {
   assert(i >= 0 && i < 4);
   switch (i) {
   case 0: x = arg; break;
   case 1: y = arg; break;
   case 2: z = arg; break;
   case 3: w = arg; break;
   }
 }

 /** Returns a rotation matrix containing the same rotation as [this] */
 mat3 asRotationMatrix() {
   double d = length2;
   assert(d != 0.0);
   double s = 2.0 / d;

   double xs = x * s;
   double ys = y * s;
   double zs = z * s;

   double wx = w * xs;
   double wy = w * ys;
   double wz = w * zs;

   double xx = x * xs;
   double xy = x * ys;
   double xz = x * zs;

   double yy = y * ys;
   double yz = y * zs;
   double zz = z * zs;

   return new mat3.raw(1.0 - (yy + zz), xy + wz, xz - wy, // column 0
     xy - wz, 1.0 - (xx + zz), yz + wx, // column 1
     xz + wy, yz - wx, 1.0 - (xx + yy) // column 2
     );
 }

 /** Returns a printable string */
 String toString() {
   return '$x, $y, $z @ $w';
 }

 /** Returns relative error between [this]  and [correct] */
 double relativeError(quat correct) {
   quat diff = correct - this;
   double norm_diff = diff.length;
   double correct_norm = correct.length;
   return norm_diff/correct_norm;
 }

 /** Returns absolute error between [this] and [correct] */
 double absoluteError(quat correct) {
   double this_norm = length;
   double correct_norm = correct.length;
   double norm_diff = (this_norm - correct_norm).abs();
   return norm_diff;
 }
}

Constructors

new quat([a, b, c, d]) #

Constructs a new quaternion. Behaviour depends on the types of arguments:

  • (double x,double y,double z,double w) Raw values
  • (vec3 axis,double angle) Rotation of angle degrees around axis
  • (quat other) Copy of other
  • (mat3) Convert rotation matrix into quaternion
quat([dynamic a, dynamic b, dynamic c, dynamic d]) {
 x = 0.0;
 y = 0.0;
 z = 0.0;
 w = 1.0;

 if (a is num && b is num && c is num && d is num) {
   x = a.toDouble();
   y = b.toDouble();
   z = c.toDouble();
   w = d.toDouble();
   return;
 }

 if (a is vec3 && b is num) {
   setAxisAngle(a, b);
   return;
 }

 if (a is vec3) {
   x = a.x;
   y = a.y;
   z = a.z;
   w = 0.0;
   return;
 }

 if (a is quat) {
   x = a.x;
   y = a.y;
   z = a.z;
   w = a.w;
   return;
 }

 if (a is mat3) {
   double trace = a.trace();
   if (trace > 0.0) {
     double s = Math.sqrt(trace + 1.0);
     w = s * 0.5;
     s = 0.5 / s;
     x = (a.col1.z - a.col2.y) * s;
     y = (a.col2.x - a.col0.z) * s;
     z = (a.col0.y - a.col1.x) * s;
   } else {
     int i = a.col0.x < a.col1.y ? (a.col1.y < a.col2.z ? 2 : 1) :
         (a.col0.x < a.col2.z ? 2 : 0);
     int j = (i + 1) % 3;
     int k = (i + 2) % 3;
     double s = Math.sqrt(a[i][i] - a[j][j] - a[k][k] + 1.0);
     this[i] = s * 0.5;
     s = 0.5 / s;
     this[3] = (a[j][k] - a[k][j]) * s;
     this[j] = (a[i][j] + a[j][i]) * s;
     this[k] = (a[i][k] + a[k][i]) * s;
   }
 }
}

new quat.axisAngle(vec3 axis, num angle) #

Constructs a new quaternion representing a rotation of angle around axis

quat.axisAngle(vec3 axis, num angle) {
 setAxisAngle(axis, angle);
}

new quat.copy(quat original) #

Constructs a new quaternion which is a copy of original

quat.copy(quat original) {
 x = original.x;
 y = original.y;
 z = original.z;
 w = original.w;
}

new quat.dq(quat q, vec3 omega) #

Constructs the time derivative of q with angular velocity omega

quat.dq(quat q, vec3 omega) {
 x = omega.x * q.w + omega.y * q.z - omega.z * q.y;
 y = omega.y * q.w + omega.z * q.x - omega.x * q.z;
 z = omega.z * q.w + omega.x * q.y - omega.y * q.x;
 w = -omega.x * q.x - omega.y * q.y - omega.z * q.z;
 x *= 0.5;
 y *= 0.5;
 z *= 0.5;
 w *= 0.5;
}

new quat.identity() #

Constructs the identity quaternion

quat.identity() {
 x = 0.0;
 y = 0.0;
 z = 0.0;
 w = 1.0;
}

new quat.random(Random rn) #

Constructs a random rotation

quat.random(Math.Random rn) {
// From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III,
//       pg. 124-132
 double x0 = rn.nextDouble();
 double r1 = Math.sqrt(1.0 - x0);
 double r2 = Math.sqrt(x0);
 double t1 = Math.PI*2.0 * rn.nextDouble();
 double t2 = Math.PI*2.0 * rn.nextDouble();
 double c1 = Math.cos(t1);
 double s1 = Math.sin(t1);
 double c2 = Math.cos(t2);
 double s2 = Math.sin(t2);
 x = s1 * r1;
 y = c1 * r1;
 z = s2 * r2;
 w = c2 * r2;
}

new quat.raw(double x, double y, double z, double w) #

Constructs a quaternion using the raw values x, y, z, and w

quat.raw(this.x, this.y, this.z, this.w);

Properties

final vec3 axis #

Axis of rotation

vec3 get axis {
   double divisor = 1.0 - (w*w);
   return new vec3(x / divisor, y / divisor, z / divisor);
}

final double length #

Length

double get length {
 return Math.sqrt(length2);
}

final double length2 #

Squared length

double get length2 {
 return (x*x) + (y*y) + (z*z) + (w*w);
}

final double radians #

Radians of rotation

double get radians {
 return 2.0 * acos(w);
}

double w #

double w

double x #

double x

double y #

double y

double z #

double z

Operators

double operator [](int i) #

Treats this as an array and returns x,y,z, or w

double operator[](int i) {
 assert(i >= 0 && i < 4);
 switch (i) {
 case 0: return x;
 case 1: return y;
 case 2: return z;
 case 3: return w;
 }
 return 0.0;
}

void operator []=(int i, double arg) #

Treats this as an array and assigns x,y,z, or w the value of arg

void operator[]=(int i, double arg) {
 assert(i >= 0 && i < 4);
 switch (i) {
 case 0: x = arg; break;
 case 1: y = arg; break;
 case 2: z = arg; break;
 case 3: w = arg; break;
 }
}

quat operator +(quat other) #

Returns copy of this - other

quat operator+(quat other) {
 return new quat(x + other.x, y + other.y, z + other.z, w + other.w);
}

quat operator -() #

Returns negated copy of this

quat operator-() {
 return new quat(-x, -y, -z, -w);
}

quat operator -(quat other) #

Returns copy of this + other

quat operator-(quat other) {
 return new quat(x - other.x, y - other.y, z - other.z, w - other.w);
}

quat operator *(other) #

Returns copy of this multiplied by scale Returns copy of this rotated by otherQuat

quat operator*(dynamic other) {
 if (other is num) {
   other = other.toDouble();
   return new quat(x * other, y * other, z * other, w * other);
 }
 if (other is quat) {
   return new quat(w * other.x + x * other.w + y * other.z - z * other.y,
                   w * other.y + y * other.w + z * other.x - x * other.z,
                   w * other.z + z * other.w + x * other.y - y * other.x,
                   w * other.w - x * other.x - y * other.y - z * other.z);
 }
}

quat operator /(num scale) #

Return a copy of this divided by scale

quat operator/(num scale) {
 scale = scale.toDouble();
 return new quat(x / scale, y / scale, z / scale, w / scale);
}

Methods

double absoluteError(quat correct) #

Returns absolute error between this and correct

double absoluteError(quat correct) {
 double this_norm = length;
 double correct_norm = correct.length;
 double norm_diff = (this_norm - correct_norm).abs();
 return norm_diff;
}

mat3 asRotationMatrix() #

Returns a rotation matrix containing the same rotation as this

mat3 asRotationMatrix() {
 double d = length2;
 assert(d != 0.0);
 double s = 2.0 / d;

 double xs = x * s;
 double ys = y * s;
 double zs = z * s;

 double wx = w * xs;
 double wy = w * ys;
 double wz = w * zs;

 double xx = x * xs;
 double xy = x * ys;
 double xz = x * zs;

 double yy = y * ys;
 double yz = y * zs;
 double zz = z * zs;

 return new mat3.raw(1.0 - (yy + zz), xy + wz, xz - wy, // column 0
   xy - wz, 1.0 - (xx + zz), yz + wx, // column 1
   xz + wy, yz - wx, 1.0 - (xx + yy) // column 2
   );
}

quat clone() #

Returns a new copy of this

quat clone() {
 return new quat.copy(this);
}

quat conjugate() #

Conjugate this

quat conjugate() {
 x = -x;
 y = -y;
 z = -z;
 w = w;
 return this;
}

quat conjugated([quat out = null]) #

Conjugated copy of this. Optionally stored in out

quat conjugated([quat out=null]) {
 if (out == null) {
   out = new quat.copy(this);
 }
 return out.conjugate();
}

void copyFrom(quat source) #

Copy source into this

void copyFrom(quat source) {
 x = source.x;
 y = source.y;
 z = source.z;
 w = source.w;
}

void copyTo(quat target) #

Copy this into target.

void copyTo(quat target) {
 target.x = x;
 target.y = y;
 target.z = z;
 target.w = w;
}

quat inverse() #

Invert this

quat inverse() {
 double l = 1.0 / length2;
 x = -x * l;
 y = -y * l;
 z = -z * l;
 w = w * l;
 return this;
}

quat inverted([quat out = null]) #

Inverted copy of this. Optionally stored in out

quat inverted([quat out=null]) {
 if (out == null) {
   out = new quat.copy(this);
 }
 return out.inverse();
}

quat normalize() #

Normalize this

quat normalize() {
 double l = length;
 if (l == 0.0) {
   return this;
 }
 x /= l;
 y /= l;
 z /= l;
 w /= l;
 return this;
}

quat normalized([quat out = null]) #

Normalized copy of this. Optionally stored in out

quat normalized([quat out=null]) {
 if (out == null) {
   out = new quat.copy(this);
 }
 return out.normalize();
}

double relativeError(quat correct) #

Returns relative error between this and correct

double relativeError(quat correct) {
 quat diff = correct - this;
 double norm_diff = diff.length;
 double correct_norm = correct.length;
 return norm_diff/correct_norm;
}

vec3 rotate(vec3 v) #

Rotates v by this. Returns v.

vec3 rotate(vec3 v) {
 // conjugate(this) * [v,0] * this
 double tix = -x;
 double tiy = -y;
 double tiz = -z;
 double tiw = w;
 double tx = tiw * v.x + tix * 0.0 + tiy * v.z - tiz * v.y;
 double ty = tiw * v.y + tiy * 0.0 + tiz * v.x - tix * v.z;
 double tz = tiw * v.z + tiz * 0.0 + tix * v.y - tiy * v.x;
 double tw = tiw * 0.0 - tix * v.x - tiy * v.y - tiz * v.z;
 double result_x = tw * x + tx * w + ty * z - tz * y;
 double result_y = tw * y + ty * w + tz * x - tx * z;
 double result_z = tw * z + tz * w + tx * y - ty * x;
 v.x = result_x;
 v.y = result_y;
 v.z = result_z;
 return v;
}

vec3 rotated(vec3 v, [vec3 out = null]) #

Returns a copy of v rotated by quaternion. Copy optionally stored in out

vec3 rotated(vec3 v, [vec3 out=null]) {
 if (out == null) {
   out = new vec3.copy(v);
 } else {
   out.copyFrom(v);
 }
 return rotate(out);
}

void setAxisAngle(vec3 axis, num radians) #

Set quaternion with rotation of radians around axis.

void setAxisAngle(vec3 axis, num radians) {
 radians = radians.toDouble();
 double len = axis.length;
 if (len == 0.0) {
   return;
 }
 double halfSin = sin(radians * 0.5) / len;
 x = axis.x * halfSin;
 y = axis.y * halfSin;
 z = axis.z * halfSin;
 w = cos(radians * 0.5);
}

void setEuler(num yaw, num pitch, num roll) #

Set quaternion with rotation of yaw, pitch and roll

void setEuler(num yaw, num pitch, num roll) {
 yaw = yaw.toDouble();
 pitch = pitch.toDouble();
 roll = roll.toDouble();
 double halfYaw = yaw * 0.5;
 double halfPitch = pitch * 0.5;
 double halfRoll = roll * 0.5;
 double cosYaw = Math.cos(halfYaw);
 double sinYaw = Math.sin(halfYaw);
 double cosPitch = Math.cos(halfPitch);
 double sinPitch = Math.sin(halfPitch);
 double cosRoll = Math.cos(halfRoll);
 double sinRoll = Math.sin(halfRoll);
 x = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
 y = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
 z = sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw;
 w = cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw;
}

String toString() #

Returns a printable string

String toString() {
 return '$x, $y, $z @ $w';
}