lib/rubysketch/processing.rb in rubysketch-0.3.2 vs lib/rubysketch/processing.rb in rubysketch-0.3.3

- old
+ new

@@ -4,45 +4,599 @@ # Processing compatible API # module Processing + # Vector class. + # + class Vector + + include Comparable + + # Initialize vector object. + # + # @overload new() + # @overload new(x) + # @overload new(x, y) + # @overload new(x, y, z) + # @overload new(v) + # @overload new(a) + # + # @param x [Numeric] x of vector + # @param y [Numeric] y of vector + # @param z [Numeric] z of vector + # @param v [Vector] vector object to copy + # @param a [Array] array like [x, y, z] + # + def initialize (x = 0, y = 0, z = 0, context: context) + @point = case x + when Rays::Point then x.dup + when Vector then x.getInternal__.dup + when Array then Rays::Point.new x[0] || 0, x[1] || 0, x[2] || 0 + else Rays::Point.new x || 0, y || 0, z || 0 + end + @context = context + end + + # Initializer for dup or clone + # + def initialize_copy (o) + @point = o.getInternal__.dup + end + + # Copy vector object + # + # @return [Vector] duplicated vector object + # + alias copy dup + + # Sets x, y and z. + # + # @overload set(x) + # @overload set(x, y) + # @overload set(x, y, z) + # @overload set(v) + # @overload set(a) + # + # @param x [Numeric] x of vector + # @param y [Numeric] y of vector + # @param z [Numeric] z of vector + # @param v [Vector] vector object to copy + # @param a [Array] array with x, y, z + # + # @return [nil] nil + # + def set (*args) + initialize *args + self + end + + # Gets x value. + # + # @return [Numeric] x value of vector + # + def x () + @point.x + end + + # Gets y value. + # + # @return [Numeric] y value of vector + # + def y () + @point.y + end + + # Gets z value. + # + # @return [Numeric] z value of vector + # + def z () + @point.z + end + + # Sets x value. + # + # @return [Numeric] x value of vector + # + def x= (x) + @point.x = x + end + + # Sets y value. + # + # @return [Numeric] y value of vector + # + def y= (y) + @point.y = y + end + + # Sets z value. + # + # @return [Numeric] z value of vector + # + def z= (z) + @point.z = z + end + + # Returns the interpolated vector between 2 vectors. + # + # @overload lerp(v, amount) + # @overload lerp(x, y, amount) + # @overload lerp(x, y, z, amount) + # + # @param v [Vector] vector to interpolate + # @param x [Numeric] x of vector to interpolate + # @param y [Numeric] y of vector to interpolate + # @param z [Numeric] z of vector to interpolate + # @param amount [Numeric] amount to interpolate + # + # @return [Vector] interporated vector + # + def lerp (*args, amount) + v = toVector__ *args + self.x = x + (v.x - x) * amount + self.y = y + (v.y - y) * amount + self.z = z + (v.z - z) * amount + self + end + + # Returns the interpolated vector between 2 vectors. + # + # @param v1 [Vector] vector to interpolate + # @param v2 [Vector] vector to interpolate + # @param amount [Numeric] amount to interpolate + # + # @return [Vector] interporated vector + # + def self.lerp (v1, v2, amount) + v1.dup.lerp v2, amount + end + + # Returns x, y, z as an array + # + # @return [Array] array of x, y, z + # + def array () + @point.to_a 3 + end + + # Adds a vector. + # + # @overload add(v) + # @overload add(x, y) + # @overload add(x, y, z) + # + # @param v [Vector] vector to add + # @param x [Vector] x of vector to add + # @param y [Vector] y of vector to add + # @param z [Vector] z of vector to add + # + # @return [Vector] added vector + # + def add (*args) + @point += toVector__(*args).getInternal__ + self + end + + # Subtracts a vector. + # + # @overload sub(v) + # @overload sub(x, y) + # @overload sub(x, y, z) + # + # @param v [Vector] vector to subtract + # @param x [Vector] x of vector to subtract + # @param y [Vector] y of vector to subtract + # @param z [Vector] z of vector to subtract + # + # @return [Vector] subtracted vector + # + def sub (*args) + @point -= toVector__(*args).getInternal__ + self + end + + # Multiplies a vector by scalar. + # + # @param num [Numeric] number to multiply the vector + # + # @return [Vector] multiplied vector + # + def mult (num) + @point *= num + self + end + + # Divides a vector by scalar. + # + # @param num [Numeric] number to divide the vector + # + # @return [Vector] divided vector + # + def div (num) + @point /= num + self + end + + # Adds a vector. + # + # @param v [Vector] vector to add + # + # @return [Vector] added vector + # + def + (v) + dup.add v + end + + # Subtracts a vector. + # + # @param v [Vector] vector to subtract + # + # @return [Vector] subtracted vector + # + def - (v) + dup.sub v + end + + # Multiplies a vector by scalar. + # + # @param num [Numeric] number to multiply the vector + # + # @return [Vector] multiplied vector + # + def * (num) + dup.mult num + end + + # Divides a vector by scalar. + # + # @param num [Numeric] number to divide the vector + # + # @return [Vector] divided vector + # + def / (num) + dup.div num + end + + # Adds 2 vectors. + # + # @overload add(v1, v2) + # @overload add(v1, v2, target) + # + # @param v1 [Vector] a vector + # @param v2 [Vector] another vector + # @param target [Vector] vector to store added vector + # + # @return [Vector] added vector + # + def self.add (v1, v2, target = nil) + v = v1 + v2 + target.set v if self === target + v + end + + # Subtracts 2 vectors. + # + # @overload sub(v1, v2) + # @overload sub(v1, v2, target) + # + # @param v1 [Vector] a vector + # @param v2 [Vector] another vector + # @param target [Vector] vector to store subtracted vector + # + # @return [Vector] subtracted vector + # + def self.sub (v1, v2, target = nil) + v = v1 - v2 + target.set v if self === target + v + end + + # Multiplies a vector by scalar. + # + # @overload mult(v, num) + # @overload mult(v, num, target) + # + # @param v [Vector] a vector + # @param num [Numeric] number to multiply the vector + # @param target [Vector] vector to store multiplied vector + # + # @return [Vector] multiplied vector + # + def self.mult (v1, num, target = nil) + v = v1 * num + target.set v if self === target + v + end + + # Divides a vector by scalar. + # + # @overload div(v, num) + # @overload div(v, num, target) + # + # @param v [Vector] a vector + # @param num [Numeric] number to divide the vector + # @param target [Vector] vector to store divided vector + # + # @return [Vector] divided vector + # + def self.div (v1, num, target = nil) + v = v1 / num + target.set v if self === target + v + end + + # Returns the length of the vector. + # + # @return [Numeric] length + # + def mag () + @point.length + end + + # Returns squared length of the vector. + # + # @return [Numeric] squared length + # + def magSq () + Rays::Point::dot(@point, @point) + end + + # Changes the length of the vector. + # + # @overload setMag(len) + # @overload setMag(target, len) + # + # @param len [Numeric] length of new vector + # @param target [Vector] vector to store new vector + # + # @return [Vector] vector with new length + # + def setMag (target = nil, len) + (target || self).set @point.normal * len + end + + # Changes the length of the vector to 1.0. + # + # @param target [Vector] vector to store the normalized vector + # + # @return [Vector] normalized vector + # + def normalize (target = nil) + (target || self).set @point.normal + end + + # Changes the length of the vector if it's length is greater than the max value. + # + # @param max [Numeric] max length + # + # @return [Vector] new vector + # + def limit (max) + setMag max if magSq > max ** 2 + self + end + + # Returns the distance of 2 vectors. + # + # @param v [Vector] a vector + # + # @return [Numeric] the distance + # + def dist (v) + (self - v).mag + end + + # Returns the distance of 2 vectors. + # + # @param v1 [Vector] a vector + # @param v2 [Vector] another vector + # + # @return [Numeric] the distance + # + def self.dist (v1, v2) + v1.dist v2 + end + + # Calculates the dot product of 2 vectors. + # + # @overload dot(v) + # @overload dot(x, y) + # @overload dot(x, y, z) + # + # @param v [Vector] a vector + # @param x [Numeric] x of vector + # @param y [Numeric] y of vector + # @param z [Numeric] z of vector + # + # @return [Numeric] result of dot product + # + def dot (*args) + Rays::Point::dot getInternal__, toVector__(*args).getInternal__ + end + + # Calculates the dot product of 2 vectors. + # + # @param v1 [Vector] a vector + # @param v2 [Vector] another vector + # + # @return [Numeric] result of dot product + # + def self.dot (v1, v2) + v1.dot v2 + end + + # Calculates the cross product of 2 vectors. + # + # @overload cross(v) + # @overload cross(x, y) + # @overload cross(x, y, z) + # + # @param v [Vector] a vector + # @param x [Numeric] x of vector + # @param y [Numeric] y of vector + # @param z [Numeric] z of vector + # + # @return [Numeric] result of cross product + # + def cross (a, *rest) + target = self.class === rest.last ? rest.pop : nil + v = self.class.new Rays::Point::cross getInternal__, toVector__(a, *rest).getInternal__ + target.set v if self.class === target + v + end + + # Calculates the cross product of 2 vectors. + # + # @param v1 [Vector] a vector + # @param v2 [Vector] another vector + # + # @return [Numeric] result of cross product + # + def self.cross (v1, v2, target = nil) + v1.cross v2, target + end + + # Rotate the vector. + # + # @param angle [Numeric] the angle of rotation + # + # @return [Vector] rotated this object + # + def rotate (angle) + angle = @context ? @context.toAngle__(angle) : angle * Utility::RAD2DEG__ + @point.rotate! angle + self + end + + # Returns the angle of rotation for this vector. + # + # @return [Numeric] the angle in radians + # + def heading () + Math.atan2 y, x + end + + # Returns rotated new vector. + # + # @param angle [Numeric] the angle of rotation + # @param target [Vector] vector to store new vector + # + # @return [Vector] rotated vector + # + def self.fromAngle (angle, target = nil) + v = self.new(1, 0, 0).rotate(angle) + target.set v if target + v + end + + # Returns angle between 2 vectors. + # + # @param v1 [Vector] a vector + # @param v2 [Vector] another vector + # + # @return [Numeric] angle in radians + # + def self.angleBetween (v1, v2) + x1, y1, z1 = v1.array + x2, y2, z2 = v2.array + return 0 if (x1 == 0 && y1 == 0 && z1 == 0) || (x2 == 0 && y2 == 0 && z2 == 0) + + x = dot(v1, v2) / (v1.mag * v2.mag) + return Math::PI if x <= -1 + return 0 if x >= 1 + return Math.acos x + end + + # Returns a new 2D unit vector with a random direction. + # + # @param target [Vector] a vector to store the new vector + # + # @return [Vector] a random vector + # + def self.random2D (target = nil) + v = self.fromAngle rand 0.0...(Math::PI * 2) + target.set v if target + v + end + + # Returns a new 3D unit vector with a random direction. + # + # @param target [Vector] a vector to store the new vector + # + # @return [Vector] a random vector + # + def self.random3D (target = nil) + angle = rand 0.0...(Math::PI * 2) + z = rand -1.0..1.0 + z2 = z ** 2 + x = Math.sqrt(1.0 - z2) * Math.cos(angle) + y = Math.sqrt(1.0 - z2) * Math.sin(angle) + v = self.new x, y, z + target.set v if target + v + end + + # @private + def inspect () + "<##{self.class.name} #{x}, #{y}, #{z}>" + end + + # @private + def <=> (o) + @point <=> o.getInternal__ + end + + # @private + protected def getInternal__ () + @point + end + + # @private + private def toVector__ (*args) + self.class === args.first ? args.first : self.class.new(*args) + end + + end# Vector + + # Image object. # class Image # @private def initialize (image) - @image__ = image + @image = image end # Gets width of image. # # @return [Numeric] width of image # def width () - @image__.width + @image.width end # Gets height of image. # # @return [Numeric] height of image # def height () - @image__.height + @image.height end # Resizes image. # # @param width [Numeric] width for resized image # @param height [Numeric] height for resized image # # @return [nil] nil # def resize (width, height) - @image__ = Rays::Image.new(width, height).paint do |painter| - painter.image @image__, 0, 0, width, height + @image = Rays::Image.new(width, height).paint do |painter| + painter.image @image, 0, 0, width, height end nil end # Copies image. @@ -62,26 +616,26 @@ # # @return [nil] nil # def copy (img = nil, sx, sy, sw, sh, dx, dy, dw, dh) img ||= self - @image__.paint do |painter| + @image.paint do |painter| painter.image img.getInternal__, sx, sy, sw, sh, dx, dy, dw, dh end end # Saves image to file. # # @param filename [String] file name to save image # def save (filename) - @image__.save filename + @image.save filename end # @private def getInternal__ () - @image__ + @image end end# Image @@ -367,11 +921,11 @@ end nil end # @private - private def toAngle__ (angle) + protected def toAngle__ (angle) angle * @angleScale__ end # Sets rect mode. Default is CORNER. # @@ -1023,15 +1577,15 @@ popMatrix popStyle end # @private - def getInternal__ () + private def getInternal__ () @image__ end # @private - def assertDrawing__ () + private def assertDrawing__ () raise "call beginDraw() before drawing" unless @drawing end end# GraphicsContext