lib/vector3.rb in gmath3D-0.2.4 vs lib/vector3.rb in gmath3D-0.2.5
- old
+ new
@@ -1,227 +1,227 @@
-# -*- coding: cp932 -*-
-require 'gmath3D'
-
-module GMath3D
- #
- # Vector3 represents a point or a vector on 3D space.
- #
- class Vector3 < Geom
- attr_accessor :x
- attr_accessor :y
- attr_accessor :z
-
- # [Input]
- # _x_, _y_, _z_ should be Numeric.
- # [Output]
- # return new instance as Vector3.
- def initialize(x=0.0,y=0.0,z=0.0)
- Util3D.check_arg_type(Numeric, x)
- Util3D.check_arg_type(Numeric, y)
- Util3D.check_arg_type(Numeric, z)
- super()
- @x = x
- @y = y
- @z = z
- end
-
- def to_element_s
- "[#{@x}, #{@y}, #{@z}]"
- end
-
- def to_s
- "Vector3" + to_element_s
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return true if rhs equals myself.
- def ==(rhs)
- return false if( !rhs.kind_of?(Vector3) )
- equals_inner(rhs)
- end
-
- # For using Vector3 as hash key
- def hash
- [@x.to_f, @y.to_f, @z.to_f].hash
- end
- def eql?(rhs)
- equals_inner(rhs)
- end
-
- # [Output]
- # return axially aligned bounding box as Box.
- def box
- return Box.new(self, self)
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return added result as Vector3.
- def +(rhs)
- add(rhs)
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return subtracted result as Vector3.
- def -(rhs)
- subtract(rhs)
- end
-
- # [Input]
- # _rsh_ should be Numeric.
- # [Output]
- # return multiplyed result as Vector3.
- def *(rhs)
- multiply(rhs)
- end
-
- # [Input]
- # _rhs_ should be Numeric.
- # [Output]
- # return divided result as Vector3.
- def /(rhs)
- divide(rhs)
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return inner product as Numeric
- def dot(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- self.x*rhs.x + self.y*rhs.y + self.z*rhs.z
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return cross product as Vector3.
- def cross(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- Vector3.new(
- self.y*rhs.z - self.z*rhs.y,
- self.z*rhs.x - self.x*rhs.z,
- self.x*rhs.y - self.y*rhs.x)
- end
-
- # [Output]
- # return orthogonal vector as Vector3.
- def arbitrary_orthogonal
- return Vector3.new() if(self.length < self.tolerance)
-
- if(!self.parallel?( Vector3.new(0.0, 1.0, 0.0) ))
- un_parallel_vec = Vector3.new(0.0,1.0,0.0)
- elsif(!self.parallel?( Vector3.new(0.0,0.0,1.0) ))
- un_parallel_vec = Vector3.new(0.0,0.0,1.0)
- else
- un_parallel_vec = Vector3.new(1.0,0.0,0.0)
- end
-
- orthogonal = self.cross(un_parallel_vec)
- return orthogonal.normalize
- end
-
- # [Output]
- # return vector length as Numeric
- def length
- Math::sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return distance between two points as Numeric.
- def distance(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- Math::sqrt((self.x - rhs.x)*(self.x - rhs.x) + (self.y - rhs.y)*(self.y - rhs.y) + (self.z - rhs.z)*(self.z - rhs.z))
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return two vectors angle as Numeric (rad).
- def angle(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- vec1Length = self.length ;
- vec2Length = rhs.length ;
- return 0.0 if(vec1Length*vec2Length < self.tolerance )
- v = self.dot(rhs)/(vec1Length*vec2Length)
- Math::acos( v )
- end
-
- # [Output]
- # return normalized vector as Vector3
- def normalize()
- self / self.length.to_f
- end
-
- # [Input]
- # _rhs_ should be Vector3
- # [Output]
- # return true if myself and rhs is parallel as boolean
- def parallel?(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- return false if(self.length < self.tolerance or rhs.length < rhs.tolerance)
- return false if(self.cross(rhs).length > self.tolerance)
- return true
- end
-
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return true if myself and rhs have same direction as boolean.
- def same_direction?(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- return false if(!parallel?(rhs))
- return false if(self.dot(rhs) < self.tolerance)
- return true
- end
-
- # This function projects self vector to rhs vector.
- # [Input]
- # _rhs_ should be Vector3.
- # [Output]
- # return projected result as Vector3.
- def project_to(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- return Vector3.new, 0.0 if( rhs.length < rhs.tolerance )
- parameter = self.dot( rhs ) / ( rhs.x * rhs.x + rhs.y * rhs.y + rhs.z * rhs.z ).to_f
- return rhs*parameter, parameter
- end
-
- # [Output]
- # return column vector as Matrix
- def to_column_vector
- return Matrix.column_vector([x,y,z])
- end
-
- private
- def equals_inner(rhs)
- return false if((self.x - rhs.x).abs > @tolerance)
- return false if((self.y - rhs.y).abs > @tolerance)
- return false if((self.z - rhs.z).abs > @tolerance)
- true
- end
- def add(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- Vector3.new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
- end
- def subtract(rhs)
- Util3D.check_arg_type(Vector3, rhs)
- Vector3.new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
- end
- def multiply(rhs)
- Util3D.check_arg_type(::Numeric, rhs)
- Vector3.new(self.x * rhs, self.y * rhs, self.z * rhs)
- end
- def divide(rhs)
- Util3D.check_arg_type(::Numeric, rhs)
- Vector3.new(self.x.to_f / rhs, self.y / rhs.to_f, self.z / rhs.to_f)
- end
- end
-end
-
+# -*- coding: cp932 -*-
+require 'gmath3D'
+
+module GMath3D
+ #
+ # Vector3 represents a point or a vector on 3D space.
+ #
+ class Vector3 < Geom
+ attr_accessor :x
+ attr_accessor :y
+ attr_accessor :z
+
+ # [Input]
+ # _x_, _y_, _z_ should be Numeric.
+ # [Output]
+ # return new instance as Vector3.
+ def initialize(x=0.0,y=0.0,z=0.0)
+ Util3D.check_arg_type(Numeric, x)
+ Util3D.check_arg_type(Numeric, y)
+ Util3D.check_arg_type(Numeric, z)
+ super()
+ @x = x
+ @y = y
+ @z = z
+ end
+
+ def to_element_s
+ "[#{@x}, #{@y}, #{@z}]"
+ end
+
+ def to_s
+ "Vector3" + to_element_s
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return true if rhs equals myself.
+ def ==(rhs)
+ return false if( !rhs.kind_of?(Vector3) )
+ equals_inner(rhs)
+ end
+
+ # For using Vector3 as hash key
+ def hash
+ [@x.to_f, @y.to_f, @z.to_f].hash
+ end
+ def eql?(rhs)
+ equals_inner(rhs)
+ end
+
+ # [Output]
+ # return axially aligned bounding box as Box.
+ def box
+ return Box.new(self, self)
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return added result as Vector3.
+ def +(rhs)
+ add(rhs)
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return subtracted result as Vector3.
+ def -(rhs)
+ subtract(rhs)
+ end
+
+ # [Input]
+ # _rsh_ should be Numeric.
+ # [Output]
+ # return multiplyed result as Vector3.
+ def *(rhs)
+ multiply(rhs)
+ end
+
+ # [Input]
+ # _rhs_ should be Numeric.
+ # [Output]
+ # return divided result as Vector3.
+ def /(rhs)
+ divide(rhs)
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return inner product as Numeric
+ def dot(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ self.x*rhs.x + self.y*rhs.y + self.z*rhs.z
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return cross product as Vector3.
+ def cross(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ Vector3.new(
+ self.y*rhs.z - self.z*rhs.y,
+ self.z*rhs.x - self.x*rhs.z,
+ self.x*rhs.y - self.y*rhs.x)
+ end
+
+ # [Output]
+ # return orthogonal vector as Vector3.
+ def arbitrary_orthogonal
+ return Vector3.new() if(self.length < self.tolerance)
+
+ if(!self.parallel?( Vector3.new(0.0, 1.0, 0.0) ))
+ un_parallel_vec = Vector3.new(0.0,1.0,0.0)
+ elsif(!self.parallel?( Vector3.new(0.0,0.0,1.0) ))
+ un_parallel_vec = Vector3.new(0.0,0.0,1.0)
+ else
+ un_parallel_vec = Vector3.new(1.0,0.0,0.0)
+ end
+
+ orthogonal = self.cross(un_parallel_vec)
+ return orthogonal.normalize
+ end
+
+ # [Output]
+ # return vector length as Numeric
+ def length
+ Math::sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return distance between two points as Numeric.
+ def distance(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ Math::sqrt((self.x - rhs.x)*(self.x - rhs.x) + (self.y - rhs.y)*(self.y - rhs.y) + (self.z - rhs.z)*(self.z - rhs.z))
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return two vectors angle as Numeric (rad).
+ def angle(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ vec1Length = self.length ;
+ vec2Length = rhs.length ;
+ return 0.0 if(vec1Length*vec2Length < self.tolerance )
+ v = self.dot(rhs)/(vec1Length*vec2Length)
+ Math::acos( v )
+ end
+
+ # [Output]
+ # return normalized vector as Vector3
+ def normalize()
+ self / self.length.to_f
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3
+ # [Output]
+ # return true if myself and rhs is parallel as boolean
+ def parallel?(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ return false if(self.length < self.tolerance or rhs.length < rhs.tolerance)
+ return false if(self.cross(rhs).length > self.tolerance)
+ return true
+ end
+
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return true if myself and rhs have same direction as boolean.
+ def same_direction?(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ return false if(!parallel?(rhs))
+ return false if(self.dot(rhs) < self.tolerance)
+ return true
+ end
+
+ # This function projects self vector to rhs vector.
+ # [Input]
+ # _rhs_ should be Vector3.
+ # [Output]
+ # return projected result as Vector3.
+ def project_to(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ return Vector3.new, 0.0 if( rhs.length < rhs.tolerance )
+ parameter = self.dot( rhs ) / ( rhs.x * rhs.x + rhs.y * rhs.y + rhs.z * rhs.z ).to_f
+ return rhs*parameter, parameter
+ end
+
+ # [Output]
+ # return column vector as Matrix
+ def to_column_vector
+ return Matrix.column_vector([x,y,z])
+ end
+
+ private
+ def equals_inner(rhs)
+ return false if((self.x - rhs.x).abs > @tolerance)
+ return false if((self.y - rhs.y).abs > @tolerance)
+ return false if((self.z - rhs.z).abs > @tolerance)
+ true
+ end
+ def add(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ Vector3.new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
+ end
+ def subtract(rhs)
+ Util3D.check_arg_type(Vector3, rhs)
+ Vector3.new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
+ end
+ def multiply(rhs)
+ Util3D.check_arg_type(::Numeric, rhs)
+ Vector3.new(self.x * rhs, self.y * rhs, self.z * rhs)
+ end
+ def divide(rhs)
+ Util3D.check_arg_type(::Numeric, rhs)
+ Vector3.new(self.x.to_f / rhs, self.y / rhs.to_f, self.z / rhs.to_f)
+ end
+ end
+end
+