class Quaternion

Class for Quaternion calculation.

Public Class Methods

new(*vars) click to toggle source

Returns an instance of Quaternion. The following code instanciate a quaternion of q0 + q1 i + q2 j + q3 k, where q0 = 1, q1 = 2, q2 = 3 and q3 = 4.

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)         # => Quaternion(1.0; Vector[2.0, 3.0, 4.0])
q = Quaternion.new(1.0, [2.0, 3.0, 4.0])       # => Quaternion(1.0; Vector[2.0, 3.0, 4.0])
q = Quaternion.new(1.0, Vector[2.0, 3.0, 4.0]) # => Quaternion(1.0; Vector[2.0, 3.0, 4.0])
# File lib/quaternion.rb, line 35
def initialize *vars
  case vars.size
  when 2
    @w = vars[0]

    case vars[1]
    when Vector
      @v = vars[1].clone
    when Array
      @v = Vector.elements(vars[1], true)
    else
      raise ArgumentError, "Invalid type"
    end
  when 4
    @w = vars[0]
    @v = Vector.elements(vars[1..3], true)
  end
end
rotation(axis, theta) click to toggle source

Returns an instance of Quaternion for rotateion aroud axis with angle theta.

qrot = Quaternion.rotation([1.0, 1.0, 1.0], PI/2.0)
# File lib/quaternion.rb, line 14
def self.rotation axis, theta
  case axis
  when Array
    axis = Vector.elements(axis, true)
    axis = axis.normalize
  when Vector
    axis = axis.normalize
  else
    raise ArgumentError, "Invalid type"
  end

  return Quaternion.new(cos(theta/2.0), axis*sin(theta/2.0))
end

Public Instance Methods

*(other) click to toggle source

Returns product with other. other can be Quaternion or Numeric.

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q*2 # => Quarternion(2.0; Vector[4.0, 6.0, 8.0])

q1 = Quaternion.new(1.0, 4.0, 5.0, 6.0)
q*q1 # => Quaternion(-46.0, Vector[4.0, 12.0, 8.0])
# File lib/quaternion.rb, line 154
def * other
  case other
  when self.class
    w = @w*other[:w] - @v.inner_product(other[:v])
    v = @w*other[:v] + @v*other[:w] + @v.cross_product(other[:v])

    return self.class.new(w, v)
  when Numeric
    w = @w*other
    v = @v*other

    return self.class.new(w, v)
  else
    raise ArgumentError, "Invalide type"
  end
end
+(other) click to toggle source

Returns result of addition.

q1 = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q2 = Quaternion.new(5.0, 6.0, 7.0, 8.0)
q1 + q2 # => Quaternion(6.0; Vector[8.0, 10.0, 12.0])
# File lib/quaternion.rb, line 127
def + other
  w = @w + other[:w]
  v = @v + other[:v]

  return Quaternion.new(w, v)
end
-(other) click to toggle source

Returns result of subtraction

q1 = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q2 = Quaternion.new(5.0, 4.0, 3.0, 2.0)
q1 - q2 # => Quaternion(-4.0; Vector[-2.0, 0.0, 2.0])
# File lib/quaternion.rb, line 139
def - other
  w = @w - other[:w]
  v = @v - other[:v]

  return Quaternion.new(w, v)
end
/(other) click to toggle source

Devision by a scalar other. Returns Quaternion with each element is divided by other.

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q/2 # => Quaternion(0.5; Vector[1.0, 1.5, 2.0])
# File lib/quaternion.rb, line 176
def / other
  case other
  when Numeric
    w = @w/other
    v = @v/other

    return self.class.new(w, v)
  else
    raise ArgumentError, "Invalid type"
  end
end
==(other) click to toggle source

Compares with other Quaternion

# File lib/quaternion.rb, line 110
def == other
  if other.is_a?(self.class)
    if (@w == other[:w]) and (@v == other[:v])
      return true
    else
      return false
    end
  else
    return false
  end
end
[](i) click to toggle source

Returns element i.

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q[0]  # => 1.0
q[:w] # => 1.0
q[:x] # => 2.0
q[:y] # => 3.0
q[:z] # => 4.0
q[:v] # => Vector[2.0, 3.0, 4.0]
# File lib/quaternion.rb, line 63
def [] i
  case i
  when :w, 0
    return @w
  when :x, 1
    return @v[0]
  when :y, 2
    return @v[1]
  when :z, 3
    return @v[2]
  when :v
    return @v
  else
    raise ArgumentError, "Invalid index"
  end
end
[]=(i, var) click to toggle source

Sets var to element i

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q[0] = 0.0
q # => Quaternion(0.0; Vector[2.0, 3.0, 4.0])
# File lib/quaternion.rb, line 85
def []= i, var
  case i
  when :w, 0
    @w = var
  when :x, 1
    @v = Vector.elements([var, @v[1], @v[2]])
  when :y, 2
    @v = Vector.elements([@v[0], var, @v[2]])
  when :z, 3
    @v = Vector.elements([@v[0], @v[1], var])
  when :v
    if var.is_a?(Array)
      @v = Vector.elements(var, true)
    elsif var.is_a?(Vector)
      @v = var
    else
      raise ArgumentError, "Invalid type. Should be Array or Vector"
    end
  else
    raise ArgumentError, "Invalid index"
  end
end
coerce(n) click to toggle source

Inverts order of multiplication, so our math methods will be used for types that don't know how to deal Quaternions

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
2*q # => Quarternion(2.0; Vector[4.0, 6.0, 8.0])
# File lib/quaternion.rb, line 264
def coerce(n)
  [self, n]
end
conjugate() click to toggle source

Returns conjugate of self

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q.conjugate # => Quaternion(1.0; Vector[-2.0, -3.0, -4.0])
# File lib/quaternion.rb, line 192
def conjugate
  return self.class.new(@w, -@v)
end
inspect() click to toggle source

Returns string expression of self

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q.inspect # => "Quaternion(1.0; Vector[2.0, 3.0, 4.0])"
# File lib/quaternion.rb, line 236
def inspect
  return "Quaternion(#{@w}; #{@v})"
end
Also aliased as: to_s
inverse() click to toggle source

Returns inverse of self.

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q.inverse # => Quaternion(0.03333333333333333; Vector[-0.06666666666666667, -0.1, -0.13333333333333333])
# File lib/quaternion.rb, line 209
def inverse
  return (self.conjugate)/(self.norm**2)
end
magnitude()
Alias for: norm
norm() click to toggle source

Returns norm of self

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q.norm # => 5.477225575051661
# File lib/quaternion.rb, line 200
def norm
  return sqrt(@w**2 + @v.inner_product(@v))
end
Also aliased as: magnitude
normalize() click to toggle source

Returns normailzed Quaternion

q = Quaternion.new(1.0, 2.0, 3.0, 4.0)
q.normalize # => Quaternion(0.18257418583505536; Vector[0.3651483716701107, 0.5477225575051661, 0.7302967433402214])
# File lib/quaternion.rb, line 217
def normalize
  return self/self.magnitude
end
normalize!() click to toggle source

Destructive method of Quaternion#normalize

# File lib/quaternion.rb, line 223
def normalize!
  m = self.magnitude

  @w /= m
  @v /= m

  return self
end
rotate(v) click to toggle source

Rotates a point v. This method does not check if the quaternion's norm is 1 or not.

qrot = Quaternion.rotation([1.0, 1.0, 1.0], PI/2.0)
qrot.rotate([1.0, 0.0, 0.0]) # =>[0.3333333333333334, 0.9106836025229592, -0.24401693585629253]
# File lib/quaternion.rb, line 246
def rotate v
  q_v = Quaternion.new(0.0, v)

  res = self*q_v*(self.conjugate)

  case v
  when Array
    return res[:v].to_a
  when Vector
    return res[:v]
  end
end
to_s()
Alias for: inspect

Private Instance Methods

to_vector(v) click to toggle source
# File lib/quaternion.rb, line 269
def to_vector v
  case v
  when Array
    Vector.elements(v, true)
  when Vector
    v.clone
  else
    raise ArgumentError, "Fail to convert to Vector"
  end
end