lib/mageo/vector3d.rb in mageo-0.0.0 vs lib/mageo/vector3d.rb in mageo-0.0.1

- old
+ new

@@ -7,240 +7,239 @@ require "mageo/polar3d.rb" require "mageo/axes.rb" require "mageo/vector.rb" require "rubygems" gem "malge" -#require "malge.rb" -require "malge/simultaneousequations.rb" +require "malge.rb" +#require "malge/simultaneousequations.rb" #require "simultaneousequations.rb" # Open class to add "to_v3d" method. class Array - # Convert Array to Vector3D - def to_v3d - Vector3D[*self] - #要素数チェックは Vector3D.[] 側でやっている。 - end + # Convert Array to Vector3D + def to_v3d + Vector3D[*self] + #要素数チェックは Vector3D.[] 側でやっている。 + end end class Vector - # Return a new instance converted to Vector3D class. - def to_v3d - Vector3D[*self] - #要素数チェックは Vector3D.[] 側でやっている。 - end + # Return a new instance converted to Vector3D class. + def to_v3d + Vector3D[*self] + #要素数チェックは Vector3D.[] 側でやっている。 + end end # Vector class specialized for vectors in a three-dimensional Cartesian space. # This class provide exterior_product method and others, which is not included # in native Vector class. # This class is constructed under the assumption in the Cartesian coordinate. # If you want to be in an internal coordinate, you can use Math/Vector3DInternal.rb . # # Memo: -# Vector3DInternal との対比として、Vector3DCartesian という名前にすることも考えたが、 -# 長くなるし、普通直交座標で考えるよね、と。 +# Vector3DInternal との対比として、Vector3DCartesian という名前にすることも考えたが、 +# 長くなるし、普通直交座標で考えるよね、と。 # -# インスタンス生成の時点で要素数をチェックし、要素の追加削除を禁止しているので -# 要素数は常に3であることが保証されている。 +# インスタンス生成の時点で要素数をチェックし、要素の追加削除を禁止しているので +# 要素数は常に3であることが保証されている。 # class Vector3D < Vector - class TypeError < Exception; end - class ZeroOperation < Exception; end - class RangeError < Exception; end + class TypeError < Exception; end + class ZeroOperation < Exception; end + class RangeError < Exception; end - # Class methods + # Class methods - def self.[](*args) - raise RangeError, "#{args}" unless args.size == 3 - super(*args) - end - - # Get the exterior product. - def self.exterior_product(vec0, vec1) - [vec0, vec1].each_with_index do |vec, index| - unless (vec.class == Vector3D) - raise TypeError, "Vector #{index}, #{vec.inspect}." - end - end + def self.[](*args) + raise RangeError, "#{args}" unless args.size == 3 + super(*args) + end + + # Get the exterior product. + def self.exterior_product(vec0, vec1) + [vec0, vec1].each_with_index do |vec, index| + unless (vec.class == Vector3D) + raise TypeError, "Vector #{index}, #{vec.inspect}." + end + end - bX = vec1[0]; - bY = vec1[1]; - bZ = vec1[2]; + bX = vec1[0]; + bY = vec1[1]; + bZ = vec1[2]; - cX = (vec0[1] * bZ - vec0[2] * bY); - cY = (vec0[2] * bX - vec0[0] * bZ); - cZ = (vec0[0] * bY - vec0[1] * bX); + cX = (vec0[1] * bZ - vec0[2] * bY); + cY = (vec0[2] * bX - vec0[0] * bZ); + cZ = (vec0[0] * bY - vec0[1] * bX); - self[cX, cY, cZ] - end - class << self - alias :cross_product :exterior_product - alias :vector_product :exterior_product - end + self[cX, cY, cZ] + end + class << self + alias :cross_product :exterior_product + alias :vector_product :exterior_product + end - # Get the scalar triple product. - def self.scalar_triple_product(vec0, vec1, vec2) - [vec0, vec1, vec2].each_with_index do |vec, index| - raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D) - end + # Get the scalar triple product. + def self.scalar_triple_product(vec0, vec1, vec2) + [vec0, vec1, vec2].each_with_index do |vec, index| + raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D) + end - vec0.inner_product(vec1.exterior_product(vec2)) - end + vec0.inner_product(vec1.exterior_product(vec2)) + end - # Get the angle with radian between self and other vectors. - def self.angle_radian(vec0, vec1) - [vec0, vec1].each_with_index do |vec, index| - raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D) - raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0) - end + # Get the angle with radian between self and other vectors. + def self.angle_radian(vec0, vec1) + [vec0, vec1].each_with_index do |vec, index| + raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D) + raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0) + end - Math::acos(vec0.inner_product(vec1) / (vec0.r * vec1.r)) - end + Math::acos(vec0.inner_product(vec1) / (vec0.r * vec1.r)) + end - # Get the angle with degree between self and other vectors. - def self.angle_degree(vec0, vec1) - [vec0, vec1].each_with_index do |vec, index| - raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D) - raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0) - end + # Get the angle with degree between self and other vectors. + def self.angle_degree(vec0, vec1) + [vec0, vec1].each_with_index do |vec, index| + raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D) + raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0) + end - self.angle_radian(vec0, vec1) * (180.0 / Math::PI) - end + self.angle_radian(vec0, vec1) * (180.0 / Math::PI) + end - # Instance methods + # Instance methods - def [](index) - raise RangeError, "index: #{index}." if (index < 0 || 2 < index) - super index - end - - def []=(index, val) - raise RangeError, "index: #{index}." if (index < 0 || 2 < index) - super index, val - end - - - # ベクトルが等しいかチェック。 - # other として Vector3D クラス以外のインスタンス渡すと Vector3D::TypeError。 - # 両者の差分ベクトルの長さが tolerance 以下という判定になる。 - def equal_in_delta?(other, tolerance = 0.0) - raise TypeError if (other.class != Vector3D) - return (other - self).r <= tolerance - end + def [](index) + raise RangeError, "index: #{index}." if (index < 0 || 2 < index) + super index + end + + def []=(index, val) + raise RangeError, "index: #{index}." if (index < 0 || 2 < index) + super index, val + end + + + # ベクトルが等しいかチェック。 + # other として Vector3D クラス以外のインスタンス渡すと Vector3D::TypeError。 + # 両者の差分ベクトルの長さが tolerance 以下という判定になる。 + def equal_in_delta?(other, tolerance = 0.0) + raise TypeError if (other.class != Vector3D) + return (other - self).r <= tolerance + end - # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 - # Vector3D クラスインスタンスを返すようにした + メソッド。 - def +(vec) - unless (vec.class == Vector3D) - raise TypeError, "#{vec.inspect}." - end - super(vec).to_v3d - end + # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 + # Vector3D クラスインスタンスを返すようにした + メソッド。 + def +(vec) + unless (vec.class == Vector3D) + raise TypeError, "#{vec.inspect}." + end + super(vec).to_v3d + end - # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 - # Vector3D クラスインスタンスを返すようにした - メソッド。 - def -(vec) - unless (vec.class == Vector3D) - raise TypeError, "#{vec.inspect}." - end - super(vec).to_v3d - end + # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 + # Vector3D クラスインスタンスを返すようにした - メソッド。 + def -(vec) + unless (vec.class == Vector3D) + raise TypeError, "#{vec.inspect}." + end + super(vec).to_v3d + end - # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 - # Vector3D クラスインスタンスを返すようにした * メソッド。 - # Argument 'val' must have :to_f method. - def *(val) - #raise TypeError if (val.class != Float) - raise TypeError unless val.methods.include?(:to_f) - super(val.to_f).to_v3d - end + # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 + # Vector3D クラスインスタンスを返すようにした * メソッド。 + # Argument 'val' must have :to_f method. + def *(val) + #raise TypeError if (val.class != Float) + raise TypeError unless val.methods.include?(:to_f) + super(val.to_f).to_v3d + end - # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 - # Vector3D クラスインスタンスを返すようにした clone メソッド。 - def clone - super().to_v3d - end + # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 + # Vector3D クラスインスタンスを返すようにした clone メソッド。 + def clone + super().to_v3d + end - # Convert to Vector3DInternal. Non-destructive. - def to_v3di(axes) - #pp axes.is_a?(Axes) - raise TypeError unless axes.is_a?(Axes) + # Convert to Vector3DInternal. Non-destructive. + def to_v3di(axes) + #pp axes.is_a?(Axes) + raise TypeError unless axes.is_a?(Axes) - axes = axes.to_a - Vector3DInternal[ *(SimultaneousEquations.cramer(axes.transpose, self)) ] - end + axes = axes.to_a + Vector3DInternal[ *(Malge::SimultaneousEquations.cramer(axes.transpose, self)) ] + end - #Return size, always 3. - def size - return 3 - end + #Return size, always 3. + def size + return 3 + end - # Get the exterior product. - def exterior_product(vec) - self.class.exterior_product(self, vec) - end - alias :cross_product :exterior_product - alias :vector_product :exterior_product + # Get the exterior product. + def exterior_product(vec) + self.class.exterior_product(self, vec) + end + alias :cross_product :exterior_product + alias :vector_product :exterior_product - def scalar_triple_product(vec0, vec1) - self.class.scalar_triple_product(self, vec0, vec1) - end + def scalar_triple_product(vec0, vec1) + self.class.scalar_triple_product(self, vec0, vec1) + end - def angle_radian(vec) - self.class.angle_radian(self, vec) - end + def angle_radian(vec) + self.class.angle_radian(self, vec) + end - def angle_degree(vec) - self.class.angle_degree(self, vec) - end + def angle_degree(vec) + self.class.angle_degree(self, vec) + end - #3次元極座標への変換した Polar3D インスタンスを返す。 - def to_p3d - r = self.r - if r == 0.0 - theta = 0.0 - phi = 0.0 - else - theta = Polar2D.minimum_radian(Math::acos(self[2] / r)) - phi = Vector[ self[0], self[1] ].to_p2d.theta - end - Polar3D.new(r, theta, phi) - end + #3次元極座標への変換した Polar3D インスタンスを返す。 + def to_p3d + r = self.r + if r == 0.0 + theta = 0.0 + phi = 0.0 + else + theta = Polar2D.minimum_radian(Math::acos(self[2] / r)) + phi = Vector[ self[0], self[1] ].to_p2d.theta + end + Polar3D.new(r, theta, phi) + end - #x, y, z 軸のいずれかで self を回転する。破壊的。 - #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。 - #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。 - #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。 - #e.g., y軸中心で回転し、z軸を x軸になるように変換。 - # self.rotate_axis!(1, 0.5*PI) - def rotate_axis!(axis, radian) - raise RangeError, "Axis id is #{axis}." if (axis < 0 || 2 < axis) - #axis1, axis2 はそれぞれ、 x軸から見て y軸, z軸。y に対する z, x。z に対する x, y。 - axis1 = (axis + 1) % 3 - axis2 = (axis + 2) % 3 + #x, y, z 軸のいずれかで self を回転する。破壊的。 + #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。 + #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。 + #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。 + #e.g., y軸中心で回転し、z軸を x軸になるように変換。 + # self.rotate_axis!(1, 0.5*PI) + def rotate_axis!(axis, radian) + raise RangeError, "Axis id is #{axis}." if (axis < 0 || 2 < axis) + #axis1, axis2 はそれぞれ、 x軸から見て y軸, z軸。y に対する z, x。z に対する x, y。 + axis1 = (axis + 1) % 3 + axis2 = (axis + 2) % 3 - tmp = Array.new(3) - tmp[ axis ] = self[ axis ] - tmp[ axis1 ] = Math::cos(radian) * self[ axis1 ] - Math::sin(radian) * self[ axis2 ] - tmp[ axis2 ] = Math::sin(radian) * self[ axis1 ] + Math::cos(radian) * self[ axis2 ] - tmp.to_v3d - self[0] = tmp[0] - self[1] = tmp[1] - self[2] = tmp[2] - end + tmp = Array.new(3) + tmp[ axis ] = self[ axis ] + tmp[ axis1 ] = Math::cos(radian) * self[ axis1 ] - Math::sin(radian) * self[ axis2 ] + tmp[ axis2 ] = Math::sin(radian) * self[ axis1 ] + Math::cos(radian) * self[ axis2 ] + tmp.to_v3d + self[0] = tmp[0] + self[1] = tmp[1] + self[2] = tmp[2] + end - #x, y, z 軸のいずれかで self を回転した座標を返す。非破壊的。 - #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。 - #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。 - #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。 - #e.g., y軸中心で回転し、z軸を x軸になるように変換。 - # self.rotate_axis(1, 0.5*PI) - def rotate_axis(axis, radian) - tmp = Marshal.load(Marshal.dump(self)) - tmp.rotate_axis!(axis, radian) - tmp - end - + #x, y, z 軸のいずれかで self を回転した座標を返す。非破壊的。 + #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。 + #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。 + #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。 + #e.g., y軸中心で回転し、z軸を x軸になるように変換。 + # self.rotate_axis(1, 0.5*PI) + def rotate_axis(axis, radian) + tmp = Marshal.load(Marshal.dump(self)) + tmp.rotate_axis!(axis, radian) + tmp + end end