lib/interpolate/add/core.rb in interpolate-0.2.3 vs lib/interpolate/add/core.rb in interpolate-0.2.4
- old
+ new
@@ -1,123 +1,2 @@
-# Library for generic interpolation objects. Useful for such things as generating
-# linear motion between points (or arrays of points), multi-channel color
-# gradients, piecewise functions, or even just placing values within intervals.
-#
-# Interpolation objects are constructed with a Hash object, wherein each key
-# is a real number value and each value can respond to +interpolate+ to
-# determine the resulting value based on its neighbor value and the balance
-# ratio between the two points.
-#
-# For objects which can't respond to +interpolate+ (or to override the default
-# behaviour), a block can be passed to +new+ which will be called whenever two
-# values need to be interpolated.
-#
-# At or below the lower bounds of the interpolation, the result will be equal to
-# the value of the lower bounds interpolation point. At or above the upper
-# bounds of the graient, the result will be equal to the value of the upper
-# bounds interpolation point.
-#
-#
-# ==Author
-#
-# {Adam Collins}[mailto:adam.w.collins@gmail.com]
-#
-#
-# ==License
-#
-# Licensed under the MIT license.
-#
-
-class Interpolation
- VERSION = '0.2.3'
-
- # creates an Interpolation object with Hash object that specifies
- # each point location (Numeric) and value (up to you)
- #
- # the optional+block+ can be used to interpolate objects that can't
- # respond to +interpolate+ on their own
- #
- # +block+ will receive the following arguments: "left" (lower) side
- # value, "right" (higher) side value, and the balance ratio from 0.0
- # to 1.0
- def initialize(points = {}, &block)
- @points = {}
- @block = block
- merge!(points)
- end
-
- # creates an Interpolation object from the receiver object,
- # merged with the interpolated points you specify
- def merge(points = {})
- Interpolation.new(points.merge(@points))
- end
-
- # merges the interpolation points with the receiver object
- def merge!(points = {})
- @points.merge!(points)
- normalize_data
- end
-
- # returns the interpolated value of the receiver object at the point specified
- def at(point)
- # deal with the two out-of-bounds cases first
- if (point <= @min_point)
- return @data.first.last
- elsif (point >= @max_point)
- return @data.last.last
- end
-
- # go through the interpolation intervals, in order, to determine
- # into which this point falls
- 1.upto(@data.length - 1) do |zone|
- left = @data.at(zone - 1)
- right = @data.at(zone)
- zone_range = left.first..right.first
-
- if (zone_range.include?(point))
- # what are the points in question?
- left_point = left.first.to_f
- right_point = right.first.to_f
-
- # what are the values in question?
- left_value = left.last
- right_value = right.last
-
- # span: difference between the left point and right point
- # balance: ratio of right point to left point
- span = right_point - left_point
- balance = (point.to_f - left_point) / span
-
- # catch the cases where the point in quesion is
- # on one of the zone's endpoints
- return left_value if (balance == 0.0)
- return right_value if (balance == 1.0)
-
- # given block should be called
- return @block.call(left_value, right_value, balance) if @block
-
- # otherwise, we need to interpolate
- return left_value.interpolate(right_value, balance) if left_value.respond_to?(:interpolate)
-
- raise ArgumentError, "no block given and interpolation point doesn't respond to :interpolate"
- end
- end
-
- # we shouldn't get to this point
- raise "couldn't come up with a value for some reason!"
- end
-
- private
-
- def normalize_data # :nodoc:
- @data = @points.sort
- @min_point = @data.first.first
- @max_point = @data.last.first
-
- # make sure that all values respond_to? :interpolate
- @data.each do |point|
- value = point.last
- end
- end
-
-end
-
+require 'interpolate/add/core/numeric'
+require 'interpolate/add/core/array'