マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

クォータニオンクラスを作ってみた

まだ途中だけどクォータニオンクラスを作ってみた。正しいかどうかは知らない。掛け算を間違えてました。

class Quaternion
    attr_reader :values
    
    #各要素のindex
    @@X = 0
    @@Y = 1
    @@Z = 2
    @@W = 3

    #クォータニオンの初期化を行う
    def initialize(x = 0, y = 0, z = 0, w = 0)
        @values = Array.new()
        set(x, y, z, w)
    end
    
    #引数のx, y, z, wをこのクォータニオンに格納する
    def set(x, y, z, w)
        @values[@@X] = x.to_f()
        @values[@@Y] = y.to_f()
        @values[@@Z] = z.to_f()
        @values[@@W] = w.to_f()
    end
    
    #引数のクォータニオンもしくは配列の値をこのクォータニオンに格納する
    def set_array(other)
        4.times do |index|
            @values[index] = other[index].to_f()
        end
    end
    
    #このクォータニオンと引数の足し算を行い結果を格納する
    def add(other)
        4.times do |index|
            @values[index] += other[index]
        end
    end
    
    #このクォータニオンと引数のクォータニオンの掛け算を行い結果を格納する
    def mul(other)
        a = self
        b = other
        r = Array.new()
        
        r[@@X] = a[@@W] * b[@@X] + a[@@X] * b[@@W] + a[@@Y] * b[@@Z] - a[@@Z] * b[@@Y]
        r[@@Y] = a[@@W] * b[@@Y] - a[@@X] * b[@@Z] + a[@@Y] * b[@@W] + a[@@Z] * b[@@X]
        r[@@Z] = a[@@W] * b[@@Z] + a[@@X] * b[@@Y] - a[@@Y] * b[@@X] + a[@@Z] * b[@@W]
        r[@@W] = a[@@W] * b[@@W] - a[@@X] * b[@@X] - a[@@Y] * b[@@Y] - a[@@Z] * b[@@Z]
        
        4.times do |index|
            @values[index] = r[index]
        end
    end
    
    #このクォータニオンのwを計算する
    def cal_w()
        x = @values[@@X]
        y = @values[@@Y]
        z = @values[@@Z]
        
        @values[@@W] = -Math::sqrt((1.0 - x * x - y * y - z * z).abs())
    end
    
    #index番目の要素を返す
    def [](index)
        return @values[index]
    end
    
    #index番目の要素にvalueを入れる
    def []=(index, value)
        @values[index] = value
    end
    
    #このクォータニオンのノルムの二乗を返す
    def norm2()
        ret = 0
        
        4.times do |index|
            ret += @values[index] * @values[index]
        end
        
        return ret
    end
    
    #このクォータニオンのノルムを返す
    def norm
        Math.sqrt(norm2())
    end
    
    #引数のクォータニオンの逆クォータニオンを返す
    def Quaternion.inverse(quat)
        n = quat.norm2()
        
        return Quaternion.new(-quat[@@X] / n, -quat[@@Y] / n, -quat[@@Z] / n, quat[@@W] / n)
    end
    
    #引数のクォータニオンの共役クォータニオンを返す
    def Quaternion.conj(quat)
        return Quaternion.new(-quat[@@X], -quat[@@Y], -quat[@@Z], quat[@@W])
    end
end

quat1 = Quaternion.new(1, 2, 3, 4)
quat2 = Quaternion.new(2, 3, 4, 5)

quat1.mul(quat2)
p quat1