Created
January 27, 2012 20:50
-
-
Save codejoust/1690854 to your computer and use it in GitHub Desktop.
Some Basic Vector Classes and Functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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