213 lines
4.4 KiB
Ruby
Executable File
213 lines
4.4 KiB
Ruby
Executable File
#
|
|
# File:: vector.rb
|
|
# Description:: Vector classes (2, 3 and 4 component).
|
|
#
|
|
# Author:: David Muir <david.muir@rockstarnorth.com>
|
|
# Date:: 28 February 2008
|
|
#
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Uses
|
|
#----------------------------------------------------------------------------
|
|
require 'pipeline/math/angles'
|
|
require 'pipeline/util/float'
|
|
require 'mathn'
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Implementation
|
|
#----------------------------------------------------------------------------
|
|
module Pipeline
|
|
module Math
|
|
|
|
#
|
|
# == Description
|
|
# 2D vector class.
|
|
#
|
|
class Vector2
|
|
attr_accessor :x
|
|
attr_accessor :y
|
|
|
|
#
|
|
# == Description
|
|
# Vector class constructor, taking two optional arguments. All
|
|
# vector components must be of the same class otherwise an
|
|
# ArgumentError exception is raised.
|
|
#
|
|
def initialize( x = 0.0, y = 0.0 )
|
|
throw ArgumentError.new( 'Not all vector components are same type' ) \
|
|
unless ( x.class == y.class )
|
|
@x = x
|
|
@y = y
|
|
end
|
|
|
|
#
|
|
# Addition with another vector object or scalar.
|
|
#
|
|
def +( v )
|
|
if ( v.is_a?( Vector ) )
|
|
Vector.new( @x + v.x, @y + v.y )
|
|
elsif ( v.is_a?( Numeric ) )
|
|
Vector.new( @x + v, @y + v )
|
|
else
|
|
throw ArgumentError.new( "Addition of Vector2 and #{v.class} not supported." )
|
|
end
|
|
end
|
|
|
|
#
|
|
# Subtraction of another vector object or scalar.
|
|
#
|
|
def -( v )
|
|
if ( v.is_a?( Vector ) )
|
|
Vector.new( @x - v.x, @y - v.y )
|
|
elsif ( v.is_a?( Numeric ) )
|
|
Vector.new( @x - v, @y - v )
|
|
else
|
|
throw ArgumentError.new( "Subtraction of #{v.class} from Vector2 not supported." )
|
|
end
|
|
end
|
|
|
|
#
|
|
# Multiplication by a scalar.
|
|
#
|
|
def *( s )
|
|
if ( v.is_a?( Numeric ) )
|
|
Vector.new( @x * s, @y * s )
|
|
else
|
|
throw ArgumentError.new( "Multiplication by #{v.class} is not supported." )
|
|
end
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Return magnitude of vector.
|
|
#
|
|
def magnitude
|
|
::Math::sqrt( @x*@x + @y*@y )
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Alias for vector magnitude.
|
|
#
|
|
alias length magnitude
|
|
|
|
#
|
|
# == Description
|
|
# Return the inverse magnitude of this vector.
|
|
#
|
|
def inverse_magnitude
|
|
::Math::rsqrt( dot( self ) )
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Normalise this vector.
|
|
#
|
|
def normalise!
|
|
scale!( inverse_magnitude )
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Return this vector normalised
|
|
#
|
|
def normalise
|
|
scale( inverse_magnitude )
|
|
end
|
|
|
|
alias normalize! normalise!
|
|
alias normalize normalise
|
|
|
|
#
|
|
# == Description
|
|
# Scale this vector.
|
|
#
|
|
def scale!( f )
|
|
@x *= f
|
|
@y *= f
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Return this vector scaled by multiplier f.
|
|
#
|
|
def scale( f )
|
|
Vector.new( @x * f, @y * f )
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Return this vector scaled by inverse of f.
|
|
#
|
|
def inverse_scale( f )
|
|
inv_f = 1.0 / f
|
|
scale( inf_f )
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Scale this vector by the inverse of a value.
|
|
def inverse_scale!( f )
|
|
inv_f = 1.0 / f
|
|
scale!( inv_f )
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# Find and return dot product of this vector and v2.
|
|
#
|
|
def dot( v2 )
|
|
( (@x * v2.x) + (@y * v2.y) )
|
|
end
|
|
|
|
#---------------------------------------------------------------------
|
|
# Operators
|
|
#---------------------------------------------------------------------
|
|
|
|
#
|
|
# == Description
|
|
# [] operator for readonly access to components
|
|
#
|
|
def [](index)
|
|
case index
|
|
when 0
|
|
return @x
|
|
when 1
|
|
return @y
|
|
else
|
|
raise ArgumentError.new( "0 <= index <= 1 for xy vector" )
|
|
end
|
|
end
|
|
|
|
#---------------------------------------------------------------------
|
|
# Overloaded Methods
|
|
#---------------------------------------------------------------------
|
|
|
|
#
|
|
# Return Vector2 as an Array object.
|
|
#
|
|
def to_a( )
|
|
[ @x, @y ]
|
|
end
|
|
|
|
#
|
|
# == Description
|
|
# String conversion function for vectors. Optional precision flag
|
|
# can be used if x, y and z components are all Float.
|
|
#
|
|
def to_s( prec = nil )
|
|
all_float = ( Float == @x.class and Float == @y.class )
|
|
|
|
if ( all_float and !prec.nil? )
|
|
return "[ #{@x.to_s(prec)}, #{@y.to_s(prec)} ]"
|
|
else
|
|
return "[ #{@x}, #{@y} ]"
|
|
end
|
|
end
|
|
end
|
|
|
|
end # Math module
|
|
end # Pipeline module
|
|
|
|
# End of vector.rb
|