Skip to content

Instantly share code, notes, and snippets.

@codejoust
Created January 27, 2012 20:50
Show Gist options
  • Save codejoust/1690854 to your computer and use it in GitHub Desktop.
Save codejoust/1690854 to your computer and use it in GitHub Desktop.
Some Basic Vector Classes and Functions
# encoding: utf-8
#require 'rubygems'
#require 'fraction'
class Base3D
attr_accessor :x, :y, :z
def initialize(x, y, z)
@x = x; @y = y; @z = z
end
def to_h; {:x => @x, :y => @y, :z => @z}; end
def to_a; [x, y, z]; end
def -(v2)
if v2.is_a? self.class
self.class.new(self.x - v2.x, self.y - v2.y, self.z - v2.z)
else
self.x -= v2; self.y -= v2; self.z -= v2
self
end
end
def +(v2)
if v2.is_a? self.class
self.class.new(self.x + v2.x, self.y + v2.y, self.z + v2.z)
else
self.x += v2; self.y += v2; self.z += v2
self
end
end
def *(v2)
if v2.is_a? self.class
self.class.new(self.x * v2.x, self.y * v2.y, self.z * v2.z)
else
self.x *= v2; self.y *= v2; self.z *= v2;
self
end
end
def /(v2)
if v2.is_a? self.class
self.class.new(Rational(self.x,v2), Rational(self.y,v2), Rational(self.z,v2))
else
self.x /= v2; self.y /= v2; self.z /= v2
self
end
end
end
class PrimesSqrt
## Get a Prime Factorization of a Sqrt
attr_accessor :num, :sqrt, :orig, :raw
def factorize_generate(n)
return [] if n == 1
factor = (2..n).find {|x| n % x == 0}
[factor] + factorize_generate(n / factor)
end
def initialize(root_base)
self.num = []; self.sqrt = []; self.orig = root_base
arr = factorize_generate(root_base)
arr.inject(Hash.new(0)){|h,v| h[v] += 1; h}.each do |k,v|
self.sqrt << k; v -= 1 if v % 2 == 1
self.num << k * (v / 2) if v > 1
end
def mult(ar); ar.inject(nil){|sum,x| sum ? sum*x : x}; end
self.num = mult(self.num); self.sqrt = mult(self.sqrt)
self
end
def to_s
"#{self.num} √#{self.sqrt}"
end
def to_f
Math.sqrt(self.orig)
end
def to_i
self.to_f.to_i
end
def exact_sqrt
root_base = self.orig
return false if root_base.is_a? Float
root_try = root_base
until root_try < 3 or (Math.sqrt(root_try).to_i == Math.sqrt(root_try) and root_try != 1)
root_try -= 1
end
out = {:sqrt => Math.sqrt(root_try).to_i, :off => root_base-root_try, :orig => root_base}
out[:text] = "#{out[:sqrt]} √#{out[:off]}"
out
end
def coerce(other)
return self.to_f, other
end
end
class Point < Base3D
def distance(*other)
if other.is_a? Array
other = Point.new(*other)
end
other - self
end
alias :dis :distance
def to_s
"(#@x, #@y, #@z)"
end
def midpoint(other)
Point.new(self.x + other.x, self.y + other.y, self.z + other.z) / 2
end
end
class Vector < Base3D
def length
num = self.x**2 + self.y**2 + self.z**2
PrimesSqrt.new(num.to_f)
end
def dot(v2)
(self.x * v2.x) + (self.y * v2.y) + (self.z * v2.z)
end
def to_s
"{#@x, #@y, #@z}"
end
end
def cross(v1, v2)
v1.split(' ').map{|p| p.to_i} if v1.is_a? String
v2.split(' ').map{|p| p.to_i} if v2.is_a? String
v1 = Vector.new(*v1) if v1.is_a? Array
v2 = Vector.new(*v2) if v2.is_a? Array
# ^ handle arguments.
fvector = Vector.new(v1.y * v2.z, v1.z * v2.x, v1.x * v2.y)
fvector - Vector.new(v1.z * v2.y, v1.x * v2.z, v1.y * v2.x)
end
def mkpt(*args)
Point.new(*args)
end
def mkvect(*args)
Vector.new(*args)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment