interpolate 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,19 +1,18 @@
1
- == 0.2.3 (2009.10.27)
1
+ == 0.2.4 (2011.4.10)
2
2
 
3
- * Support for passing a block to new Interpolation objects
3
+ * Project cleanup: minor updates to the lib/ file structure and documentation
4
4
 
5
5
  == 0.2.2 (2008.2.4)
6
6
 
7
7
  * Single source file has been split into Class files
8
- * Tests now use +freeze
8
+ * Tests now use +freeze+
9
9
  * Better edge case testing in the Array and Numeric +interpolate+ methods
10
10
 
11
11
  == 0.2.1 (2008.1.27)
12
12
 
13
- * First public release
14
-
15
- * Project Cleanup:
13
+ First public release
16
14
 
15
+ Project Cleanup:
17
16
  * Documentation enhancements and updates.
18
17
  * +add+ is now +merge+
19
18
 
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2009 Adam Collins [adam.w.collins@gmail.com]
1
+ Copyright (c) 2008-2011 Adam Collins [adam@m104.us]
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/Manifest.txt CHANGED
@@ -1,14 +1,16 @@
1
- History.txt
2
- LICENSE.txt
1
+ CHANGELOG.md
2
+ LICENSE
3
3
  Manifest.txt
4
- README.txt
5
4
  Rakefile
5
+ README.md
6
+ VERSION
6
7
  examples/arrays.rb
8
+ examples/buckets.rb
7
9
  examples/colors.rb
8
10
  examples/nested.rb
9
- examples/zones.rb
10
11
  lib/interpolate.rb
11
- lib/interpolate/add/array.rb
12
+ lib/interpolate/interpolation.rb
12
13
  lib/interpolate/add/core.rb
13
- lib/interpolate/add/numeric.rb
14
+ lib/interpolate/add/core/array.rb
15
+ lib/interpolate/add/core/numeric.rb
14
16
  test/test_all.rb
@@ -1,39 +1,40 @@
1
- = Interpolate
1
+ # Interpolate
2
2
 
3
- == Author
3
+ ## Author
4
4
 
5
- Adam Collins [adam.w.collins@gmail.com]
5
+ Adam Collins [adam@m104.us]
6
6
 
7
7
 
8
- == Description
8
+ ## Description
9
9
 
10
10
  Library for generic Interpolation objects. Useful for such things as generating
11
11
  linear motion between points (or arrays of points), multi-channel color
12
12
  gradients, piecewise functions, or even just placing values within intervals.
13
13
 
14
14
 
15
- == General Usage
15
+ ## General Usage
16
16
 
17
17
  Specify the interpolation as a Hash, where keys represent numeric points
18
- along the gradient and values represent the known values along that gradient.
18
+ along the gradient and values represent the known (key) values along that
19
+ gradient.
19
20
 
20
- Here's an example for determining where, in a range of seven zones, each value
21
- of a set falls into:
21
+ Here's an example for placing values within one of seven buckets:
22
22
 
23
23
  require 'rubygems'
24
24
  require 'interpolate'
25
25
 
26
- points = {
27
- 0.000 => 0,
28
- 0.427 => 1,
29
- 1.200 => 2,
30
- 3.420 => 3,
31
- 27.50 => 4,
32
- 45.20 => 5,
33
- 124.4 => 6,
26
+ # min_value => bucket
27
+ buckets = {
28
+ 0.000 => 1,
29
+ 0.427 => 2,
30
+ 1.200 => 3,
31
+ 3.420 => 4,
32
+ 27.50 => 5,
33
+ 45.20 => 6,
34
+ 124.4 => 7,
34
35
  }
35
36
 
36
- zones = Interpolation.new(points)
37
+ bucketizer = Interpolation.new(buckets)
37
38
 
38
39
  values = [
39
40
  -20.2,
@@ -45,47 +46,51 @@ of a set falls into:
45
46
  ]
46
47
 
47
48
  values.each do |value|
48
- zone = zones.at(value).floor
49
- puts "A value of #{value} falls into zone #{zone}"
49
+ bucket = bucketizer.at(value).floor
50
+ puts "A value of #{value} falls into bucket #{bucket}"
50
51
  end
51
52
 
52
53
 
53
- == Non-Numeric Gradients
54
+ ## Non-Numeric Gradients
54
55
 
55
56
  For non-Numeric gradient value objects, you'll need to implement +interpolate+
56
- for the class in question or provide a block to the new Interpolation object.
57
- Here's an example using an RGB color gradient with the help of the 'color' gem:
57
+ for the class in question. Here's an example using an RGB color gradient with
58
+ the help of the 'color' gem:
58
59
 
59
60
  require 'rubygems'
60
61
  require 'interpolate'
61
62
  require 'color'
62
63
 
64
+ # we need to implement +interpolate+ for Color::RGB
65
+ # in order for Interpolation to work
66
+ class Color::RGB
67
+ def interpolate(other, balance)
68
+ mix_with(other, balance * 100.0)
69
+ end
70
+ end
71
+
63
72
  # a nice weathermap-style color gradient
64
73
  points = {
65
- 0 => Color::RGB::White,
66
- 1 => Color::RGB::Lime,
67
- # 2 => ? (something between Lime and Yellow)
68
- 3 => Color::RGB::Yellow,
69
- 4 => Color::RGB::Orange,
70
- 5 => Color::RGB::Red,
71
- 6 => Color::RGB::Magenta,
72
- 7 => Color::RGB::DarkGray
74
+ 1 => Color::RGB::White,
75
+ 2 => Color::RGB::Lime,
76
+ # 3 => ? (between Lime and Yellow; Interpolate will figure it out)
77
+ 4 => Color::RGB::Yellow,
78
+ 5 => Color::RGB::Orange,
79
+ 6 => Color::RGB::Red,
80
+ 7 => Color::RGB::Magenta
73
81
  }
74
82
 
75
- gradient = Interpolation.new(points) do |left, right, balance|
76
- left.mix_with(right, balance * 100.0)
77
- end
83
+ gradient = Interpolation.new(points)
78
84
 
79
- # what are the colors of the gradient from 0 to 7
85
+ # what are the colors of the gradient from 1 to 7
80
86
  # in increments of 0.2?
81
- (0).step(7, 0.2) do |value|
87
+ (1).step(7, 0.2) do |value|
82
88
  color = gradient.at(value)
83
89
  puts "A value of #{value} means #{color.html}"
84
90
  end
85
91
 
86
92
 
87
-
88
- == Array-based Interpolations
93
+ ## Array-based Interpolations
89
94
 
90
95
  Aside from single value gradient points, you can interpolate over uniformly sized
91
96
  arrays. Between two interpolation points, let's say +a+ and +b+, the final result
@@ -100,28 +105,28 @@ Here is an example:
100
105
  require 'pp'
101
106
 
102
107
  # a non-linear set of multi-dimensional points;
103
- # perhaps the location of some actor in relation to time
108
+ # perhaps the location of an actor in relation to time
104
109
  time_frames = {
105
- 0 => [0, 0, 0],
106
- 1 => [1, 0, 0],
107
- 2 => [0, 1, 0],
108
- 3 => [0, 0, 2],
109
- 4 => [3, 0, 1],
110
- 5 => [1, 2, 3],
111
- 6 => [0, 0, 0]
110
+ 1 => [0, 0, 0],
111
+ 2 => [1, 0, 0],
112
+ 3 => [0, 1, 0],
113
+ 4 => [0, 0, 2],
114
+ 5 => [3, 0, 1],
115
+ 6 => [1, 2, 3],
116
+ 7 => [0, 0, 0]
112
117
  }
113
118
 
114
119
  path = Interpolation.new(time_frames)
115
120
 
116
- # play the actors positions in time increments of 0.25
117
- (0).step(6, 0.25) do |time|
121
+ # play the actor's positions in time increments of 0.25
122
+ (1).step(7, 0.25) do |time|
118
123
  position = path.at(time)
119
124
  puts ">> At #{time}s, actor is at:"
120
125
  p position
121
126
  end
122
127
 
123
128
 
124
- == Nested Array Interpolations
129
+ ## Nested Array Interpolations
125
130
 
126
131
  As long as each top level array is uniformly sized in the first dimension
127
132
  and each nested array is uniformly sized in the second dimension (and so
@@ -134,8 +139,8 @@ Here's an example of a set of 2D points being morphed:
134
139
  require 'pp'
135
140
 
136
141
 
137
- # a non-linear set of 2D vertexes;
138
- # the shape changes at each frame
142
+ # a number of sets 2D vertices, each set corresponding to a particular
143
+ # shape on the grid
139
144
  time_frames = {
140
145
  0 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line
141
146
  1 => [[0, 0], [1, 0], [3, 0], [0, 4], [0, 0]], # a triangle
@@ -155,11 +160,11 @@ Here's an example of a set of 2D points being morphed:
155
160
  end
156
161
 
157
162
 
158
- == License
163
+ ## License
159
164
 
160
165
  (The MIT License)
161
166
 
162
- Copyright (c) 2008-2009 Adam Collins [adam.w.collins@gmail.com]
167
+ Copyright (c) 2008-2011 Adam Collins [adam@m104.us]
163
168
 
164
169
  Permission is hereby granted, free of charge, to any person obtaining
165
170
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,19 +1,35 @@
1
- require 'rubygems'
2
- require 'hoe'
3
- $:.unshift(File.dirname(__FILE__) + "/lib")
4
- require 'interpolate'
1
+ require 'jeweler'
2
+ require 'rake'
5
3
 
6
- Hoe.new('Interpolate', Interpolation::VERSION) do |p|
7
- p.name = "interpolate"
8
- p.author = "Adam Collins"
9
- p.email = 'adam.w.collins@gmail.com'
10
- p.url = "http://interpolate.rubyforge.org"
11
- p.description = File.read('README.txt').delete("\r").split(/^== /)[2].chomp.chomp
12
- p.summary = p.description
13
- p.changes = File.read('History.txt').delete("\r").split(/^== /)[1].chomp
14
- p.remote_rdoc_dir = '' # Release to root
4
+ require './lib/interpolate/interpolation'
5
+
6
+ Jeweler::Tasks.new do |g|
7
+ doc_sections = File.read('README.md').delete("\r").split(/^## /)
8
+
9
+ g.name = 'interpolate'
10
+ g.summary = 'Create linear interpolations from key points and values'
11
+ g.description = doc_sections[2].chomp.chomp # mmmm... tasty!
12
+ g.email = 'adam@m104.us'
13
+ g.homepage = "http://github.com/m104/interpolate"
14
+ g.authors = ["Adam Collins"]
15
+ g.version = Interpolation::VERSION
16
+ end
17
+
18
+ require 'rake/testtask'
19
+ Rake::TestTask.new(:test) do |test|
20
+ test.test_files = FileList.new('test/test_*.rb') do |list|
21
+ list.exclude 'test/test_helper.rb'
22
+ end
23
+ test.libs << 'test'
24
+ test.verbose = true
25
+ end
26
+
27
+ require 'rake/rdoctask'
28
+ Rake::RDocTask.new do |rdoc|
29
+ rdoc.rdoc_dir = 'rdoc'
30
+ rdoc.title = 'interpolate'
31
+ rdoc.rdoc_files.include('README.markdown')
32
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
33
  end
16
34
 
17
- desc "Release and publish documentation"
18
- task :repubdoc => [:release, :publish_docs]
19
35
 
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.4
data/examples/arrays.rb CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'interpolate'
3
3
  require 'pp'
4
4
 
5
+
5
6
  # a non-linear set of multi-dimensional points;
6
7
  # perhaps the location of some actor in relation to time
7
8
  time_frames = {
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'interpolate'
3
+
4
+ # min_value => bucket
5
+ buckets = {
6
+ 0.000 => 1,
7
+ 0.427 => 2,
8
+ 1.200 => 3,
9
+ 3.420 => 4,
10
+ 27.50 => 5,
11
+ 45.20 => 6,
12
+ 124.4 => 7,
13
+ }
14
+
15
+ bucketizer = Interpolation.new(buckets)
16
+
17
+ values = [
18
+ -20.2,
19
+ 0.234,
20
+ 65.24,
21
+ 9.234,
22
+ 398.4,
23
+ 4000
24
+ ]
25
+
26
+ values.each do |value|
27
+ bucket = bucketizer.at(value).floor
28
+ puts "A value of #{value} falls into bucket #{bucket}"
29
+ end
30
+
31
+
32
+
data/examples/colors.rb CHANGED
@@ -1,30 +1,33 @@
1
1
  require 'rubygems'
2
- require 'interpolate'
3
2
  require 'color'
3
+ require 'interpolate'
4
+
5
+ # we need to implement +interpolate+ for Color::RGB
6
+ # in order for Interpolation to work
7
+ class Color::RGB
8
+ def interpolate(other, balance)
9
+ mix_with(other, balance * 100.0)
10
+ end
11
+ end
4
12
 
5
13
  # a nice weathermap-style color gradient
6
14
  points = {
7
- 0 => Color::RGB::White,
8
- 1 => Color::RGB::Lime,
9
- # 2 => ? (something between Lime and Yellow)
10
- 3 => Color::RGB::Yellow,
11
- 4 => Color::RGB::Orange,
12
- 5 => Color::RGB::Red,
13
- 6 => Color::RGB::Magenta,
14
- 7 => Color::RGB::DarkGray
15
+ 1 => Color::RGB::White,
16
+ 2 => Color::RGB::Lime,
17
+ # 3 => ? (between Lime and Yellow; Interpolate will figure it out)
18
+ 4 => Color::RGB::Yellow,
19
+ 5 => Color::RGB::Orange,
20
+ 6 => Color::RGB::Red,
21
+ 7 => Color::RGB::Magenta
15
22
  }
16
23
 
17
- # Color objects can't interpolate themselves right out of the box,
18
- # so rather than monkey patch the :interpolate method, you can pass
19
- # a block with the instantiation of a new Interpolation object
20
- gradient = Interpolation.new(points) do |left, right, balance|
21
- left.mix_with(right, balance * 100.0)
22
- end
24
+ gradient = Interpolation.new(points)
23
25
 
24
- # what are the colors of the gradient from 0 to 7
26
+ # what are the colors of the gradient from 1 to 7
25
27
  # in increments of 0.2?
26
- (0).step(7, 0.2) do |value|
28
+ (1).step(7, 0.2) do |value|
27
29
  color = gradient.at(value)
28
30
  puts "A value of #{value} means #{color.html}"
29
31
  end
30
32
 
33
+
data/examples/nested.rb CHANGED
@@ -3,8 +3,8 @@ require 'interpolate'
3
3
  require 'pp'
4
4
 
5
5
 
6
- # a non-linear set of 2D vertexes;
7
- # the shape changes at each frame
6
+ # a number of sets 2D vertices, each set corresponding to a particular
7
+ # shape on the grid
8
8
  time_frames = {
9
9
  0 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line
10
10
  1 => [[0, 0], [1, 0], [3, 0], [0, 4], [0, 0]], # a triangle
@@ -0,0 +1,65 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{interpolate}
8
+ s.version = "0.2.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Adam Collins"]
12
+ s.date = %q{2011-04-10}
13
+ s.description = %q{Description
14
+
15
+ Library for generic Interpolation objects. Useful for such things as generating
16
+ linear motion between points (or arrays of points), multi-channel color
17
+ gradients, piecewise functions, or even just placing values within intervals.
18
+ }
19
+ s.email = %q{adam@m104.us}
20
+ s.extra_rdoc_files = [
21
+ "LICENSE",
22
+ "README.md"
23
+ ]
24
+ s.files = [
25
+ "CHANGELOG.md",
26
+ "LICENSE",
27
+ "Manifest.txt",
28
+ "README.md",
29
+ "Rakefile",
30
+ "VERSION",
31
+ "examples/arrays.rb",
32
+ "examples/buckets.rb",
33
+ "examples/colors.rb",
34
+ "examples/nested.rb",
35
+ "interpolate.gemspec",
36
+ "lib/interpolate.rb",
37
+ "lib/interpolate/add/core.rb",
38
+ "lib/interpolate/add/core/array.rb",
39
+ "lib/interpolate/add/core/numeric.rb",
40
+ "lib/interpolate/interpolation.rb",
41
+ "test/test_all.rb"
42
+ ]
43
+ s.homepage = %q{http://github.com/m104/interpolate}
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.7}
46
+ s.summary = %q{Create linear interpolations from key points and values}
47
+ s.test_files = [
48
+ "examples/arrays.rb",
49
+ "examples/buckets.rb",
50
+ "examples/colors.rb",
51
+ "examples/nested.rb",
52
+ "test/test_all.rb"
53
+ ]
54
+
55
+ if s.respond_to? :specification_version then
56
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
57
+ s.specification_version = 3
58
+
59
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
60
+ else
61
+ end
62
+ else
63
+ end
64
+ end
65
+
data/lib/interpolate.rb CHANGED
@@ -1,3 +1,2 @@
1
+ require 'interpolate/interpolation'
1
2
  require 'interpolate/add/core'
2
- require 'interpolate/add/array'
3
- require 'interpolate/add/numeric'
@@ -1,123 +1,2 @@
1
- # Library for generic interpolation objects. Useful for such things as generating
2
- # linear motion between points (or arrays of points), multi-channel color
3
- # gradients, piecewise functions, or even just placing values within intervals.
4
- #
5
- # Interpolation objects are constructed with a Hash object, wherein each key
6
- # is a real number value and each value can respond to +interpolate+ to
7
- # determine the resulting value based on its neighbor value and the balance
8
- # ratio between the two points.
9
- #
10
- # For objects which can't respond to +interpolate+ (or to override the default
11
- # behaviour), a block can be passed to +new+ which will be called whenever two
12
- # values need to be interpolated.
13
- #
14
- # At or below the lower bounds of the interpolation, the result will be equal to
15
- # the value of the lower bounds interpolation point. At or above the upper
16
- # bounds of the graient, the result will be equal to the value of the upper
17
- # bounds interpolation point.
18
- #
19
- #
20
- # ==Author
21
- #
22
- # {Adam Collins}[mailto:adam.w.collins@gmail.com]
23
- #
24
- #
25
- # ==License
26
- #
27
- # Licensed under the MIT license.
28
- #
29
-
30
- class Interpolation
31
- VERSION = '0.2.3'
32
-
33
- # creates an Interpolation object with Hash object that specifies
34
- # each point location (Numeric) and value (up to you)
35
- #
36
- # the optional+block+ can be used to interpolate objects that can't
37
- # respond to +interpolate+ on their own
38
- #
39
- # +block+ will receive the following arguments: "left" (lower) side
40
- # value, "right" (higher) side value, and the balance ratio from 0.0
41
- # to 1.0
42
- def initialize(points = {}, &block)
43
- @points = {}
44
- @block = block
45
- merge!(points)
46
- end
47
-
48
- # creates an Interpolation object from the receiver object,
49
- # merged with the interpolated points you specify
50
- def merge(points = {})
51
- Interpolation.new(points.merge(@points))
52
- end
53
-
54
- # merges the interpolation points with the receiver object
55
- def merge!(points = {})
56
- @points.merge!(points)
57
- normalize_data
58
- end
59
-
60
- # returns the interpolated value of the receiver object at the point specified
61
- def at(point)
62
- # deal with the two out-of-bounds cases first
63
- if (point <= @min_point)
64
- return @data.first.last
65
- elsif (point >= @max_point)
66
- return @data.last.last
67
- end
68
-
69
- # go through the interpolation intervals, in order, to determine
70
- # into which this point falls
71
- 1.upto(@data.length - 1) do |zone|
72
- left = @data.at(zone - 1)
73
- right = @data.at(zone)
74
- zone_range = left.first..right.first
75
-
76
- if (zone_range.include?(point))
77
- # what are the points in question?
78
- left_point = left.first.to_f
79
- right_point = right.first.to_f
80
-
81
- # what are the values in question?
82
- left_value = left.last
83
- right_value = right.last
84
-
85
- # span: difference between the left point and right point
86
- # balance: ratio of right point to left point
87
- span = right_point - left_point
88
- balance = (point.to_f - left_point) / span
89
-
90
- # catch the cases where the point in quesion is
91
- # on one of the zone's endpoints
92
- return left_value if (balance == 0.0)
93
- return right_value if (balance == 1.0)
94
-
95
- # given block should be called
96
- return @block.call(left_value, right_value, balance) if @block
97
-
98
- # otherwise, we need to interpolate
99
- return left_value.interpolate(right_value, balance) if left_value.respond_to?(:interpolate)
100
-
101
- raise ArgumentError, "no block given and interpolation point doesn't respond to :interpolate"
102
- end
103
- end
104
-
105
- # we shouldn't get to this point
106
- raise "couldn't come up with a value for some reason!"
107
- end
108
-
109
- private
110
-
111
- def normalize_data # :nodoc:
112
- @data = @points.sort
113
- @min_point = @data.first.first
114
- @max_point = @data.last.first
115
-
116
- # make sure that all values respond_to? :interpolate
117
- @data.each do |point|
118
- value = point.last
119
- end
120
- end
121
-
122
- end
123
-
1
+ require 'interpolate/add/core/numeric'
2
+ require 'interpolate/add/core/array'
File without changes
File without changes
@@ -0,0 +1,117 @@
1
+ # Library for generic interpolation objects. Useful for such things as generating
2
+ # linear motion between points (or arrays of points), multi-channel color
3
+ # gradients, piecewise functions, or even just placing values within intervals.
4
+ #
5
+ # The only requirement is that each interpolation point value must be able to
6
+ # figure out how to interpolate itself to its neighbor value(s). Numeric
7
+ # objects and uniformly sized arrays are automatically endowed with this
8
+ # ability by this gem, but other classes will require an implementation
9
+ # of +interpolate+. See the example color.rb in the examples directory for
10
+ # a brief demonstration using Color objects provided by the 'color' gem.
11
+ #
12
+ # Interpolation objects are constructed with a Hash object, wherein each key
13
+ # is a real number value and each value is can respond to +interpolate+ and
14
+ # determine the resulting value based on its neighbor value and the balance
15
+ # ratio between the two points.
16
+ #
17
+ # At or below the lower bounds of the interpolation, the result will be equal to
18
+ # the value of the lower bounds interpolation point. At or above the upper
19
+ # bounds of the graient, the result will be equal to the value of the upper
20
+ # bounds interpolation point.
21
+ #
22
+ #
23
+ # ==Author
24
+ #
25
+ # {Adam Collins}[mailto:adam@m104.us]
26
+ #
27
+ #
28
+ # ==License
29
+ #
30
+ # Licensed under the MIT license.
31
+ #
32
+
33
+ class Interpolation
34
+ VERSION = '0.2.4'
35
+
36
+ # creates an Interpolation object with Hash object that specifies
37
+ # each point location (Numeric) and value (up to you)
38
+ def initialize(points = {})
39
+ @points = {}
40
+ merge!(points)
41
+ end
42
+
43
+ # creates an Interpolation object from the receiver object,
44
+ # merged with the interpolated points you specify
45
+ def merge(points = {})
46
+ Interpolation.new(points.merge(@points))
47
+ end
48
+
49
+ # merges the interpolation points with the receiver object
50
+ def merge!(points = {})
51
+ @points.merge!(points)
52
+ normalize_data
53
+ end
54
+
55
+ # returns the interpolated value of the receiver object at the point specified
56
+ def at(point)
57
+ # deal with the two out-of-bounds cases first
58
+ if (point <= @min_point)
59
+ return @data.first.last
60
+ elsif (point >= @max_point)
61
+ return @data.last.last
62
+ end
63
+
64
+ # go through the interpolation intervals, in order, to determine
65
+ # into which this point falls
66
+ 1.upto(@data.length - 1) do |interval|
67
+ left = @data.at(interval - 1)
68
+ right = @data.at(interval)
69
+ interval_range = left.first..right.first
70
+
71
+ if (interval_range.include?(point))
72
+ # what are the points in question?
73
+ left_point = left.first.to_f
74
+ right_point = right.first.to_f
75
+
76
+ # what are the values in question?
77
+ left_value = left.last
78
+ right_value = right.last
79
+
80
+ # span: difference between the left point and right point
81
+ # balance: ratio of right point to left point
82
+ span = right_point - left_point
83
+ balance = (point.to_f - left_point) / span
84
+
85
+ # catch the cases where the point in quesion is
86
+ # on one of the interval's endpoints
87
+ return left_value if (balance == 0.0)
88
+ return right_value if (balance == 1.0)
89
+
90
+ # otherwise, we need to interpolate
91
+ return left_value.interpolate(right_value, balance)
92
+ end
93
+ end
94
+
95
+ # we shouldn't get to this point
96
+ raise "couldn't come up with a value for some reason!"
97
+ end
98
+
99
+ private
100
+
101
+ def normalize_data # :nodoc:
102
+ @data = @points.sort
103
+ @min_point = @data.first.first
104
+ @max_point = @data.last.first
105
+
106
+ # make sure that all values respond_to? :interpolate
107
+ @data.each do |point|
108
+ value = point.last
109
+ unless value.respond_to?(:interpolate)
110
+ raise ArgumentError, "found an interpolation point that doesn't respond to :interpolate"
111
+ end
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+
data/test/test_all.rb CHANGED
@@ -1,15 +1,15 @@
1
- #!/usr/bin/env ruby1.8 -w
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  require 'test/unit'
4
- require 'lib/interpolate'
4
+ require 'interpolate'
5
5
 
6
6
 
7
7
  class InterpolationTest < Test::Unit::TestCase
8
-
8
+ # acceptable delta; floating point values won't be exact
9
9
  DELTA = 1e-7
10
10
 
11
11
  def setup
12
- @decimal_points = {
12
+ decimal_points = {
13
13
  0 => 0,
14
14
  1 => 0.1,
15
15
  2 => 0.2,
@@ -23,28 +23,29 @@ class InterpolationTest < Test::Unit::TestCase
23
23
  10 => 1
24
24
  }.freeze
25
25
 
26
- @array_points = {
26
+ array_points = {
27
27
  100 => [1, 10, 100],
28
28
  200 => [5, 50, 500],
29
29
  500 => [10, 100, 1000]
30
30
  }.freeze
31
31
 
32
- @dec_gradient = Interpolation.new(@decimal_points).freeze
33
- @array_gradient = Interpolation.new(@array_points).freeze
32
+ @dec_gradient = Interpolation.new(decimal_points).freeze
33
+ @array_gradient = Interpolation.new(array_points).freeze
34
34
  end
35
35
 
36
- def test_bad_point
36
+
37
+ def test_bad_points
37
38
  bad_points = {
38
39
  0 => 4.2,
39
40
  1 => "hello", # not allowed by default
40
41
  2 => 3.4,
41
42
  3 => 4.8
42
43
  }
43
- gradient = Interpolation.new(bad_points)
44
44
 
45
45
  assert_raise ArgumentError do
46
- gradient.at(1.5)
46
+ gradient = Interpolation.new(bad_points)
47
47
  end
48
+
48
49
  end
49
50
 
50
51
  def test_lower_bounds
@@ -133,30 +134,6 @@ class InterpolationTest < Test::Unit::TestCase
133
134
  assert_equal(@array_gradient.at(350), [7.5, 75, 750])
134
135
  end
135
136
 
136
- def test_given_block_left
137
- gradient = Interpolation.new(@decimal_points) {|l, r, bal| l}
138
- assert_in_delta(gradient.at(1.5), 0.1, DELTA)
139
- assert_in_delta(gradient.at(2.5), 0.2, DELTA)
140
- assert_in_delta(gradient.at(3.5), 0.3, DELTA)
141
- end
142
-
143
- def test_given_block_right
144
- gradient = Interpolation.new(@decimal_points) {|l, r, bal| r}
145
- assert_in_delta(gradient.at(1.5), 0.2, DELTA)
146
- assert_in_delta(gradient.at(2.5), 0.3, DELTA)
147
- assert_in_delta(gradient.at(3.5), 0.4, DELTA)
148
- end
149
-
150
- def test_given_block_mean_squared
151
- # squared balance, not linear
152
- gradient = Interpolation.new(@decimal_points) do |l, r, bal|
153
- l + ((r - l).to_f * bal * bal)
154
- end
155
- assert_in_delta(gradient.at(1.5), 0.12500, DELTA)
156
- assert_in_delta(gradient.at(2.75), 0.25625, DELTA)
157
- assert_in_delta(gradient.at(3.99), 0.39801, DELTA)
158
- end
159
-
160
137
  def test_frozen_points
161
138
  a = @array_gradient.at(200)
162
139
  assert_nothing_raised RuntimeError do
metadata CHANGED
@@ -1,48 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interpolate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 4
9
+ version: 0.2.4
5
10
  platform: ruby
6
11
  authors:
7
12
  - Adam Collins
8
13
  autorequire:
9
14
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDPjCCAiagAwIBAgIBADANBgkqhkiG9w0BAQUFADBFMRcwFQYDVQQDDA5hZGFt
14
- LncuY29sbGluczEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQB
15
- GRYDY29tMB4XDTA4MDEyNDA4NTEyOFoXDTA5MDEyMzA4NTEyOFowRTEXMBUGA1UE
16
- AwwOYWRhbS53LmNvbGxpbnMxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmS
17
- JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMP8
18
- 3Nz8g1K+Z4p59/keyov5ihFgzJuhlnvbRLr0y2jtDybeyc0TSMnY7sjhx+T0yVI5
19
- 9tEtUMo3d2m0woaHw7kc3VAo68GQKGAN02bdaPc4ODcObL9DAr8Y3CCwml5CiLtX
20
- L5Lz8zO9EU6jv6bTecRW5DsY9nPjc/TLqXjYxDgSL8dppBmHs2k82bJCaCaTFj9M
21
- ORRZpdkdTBdecI7p8DKt2WAX12deT/XUan7mpiBChKJsNVpcAe6CUqVfb6hMGA95
22
- KtW+GxvK6F6UgkcFG8ljrXks8Dfm4jMYVkpmw1YUGYU9Wj9R8X94ecAi9By/ngJ7
23
- svhO6ouvVk9J9hgpWukCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
24
- HQYDVR0OBBYEFIpBCufIdqpuVqh/Mt46Gq9FKa0pMA0GCSqGSIb3DQEBBQUAA4IB
25
- AQBbwpirH1tNzkESxQIBZd10xK3Dca141G9+lHl7OK3UCk1ZF6TiXxgl7Qnug4A5
26
- 3mEn/catvIdMYcA1GLNWL7qlW2Fpk2w0qgVbx1agK724BrZm5Op6lain+vi6BXd3
27
- QM32MqZAL96e40i6UCutsNIdZeRDfR7hRcmqPTkoSUEu/3X6qegnvJHpVw36dsG6
28
- trlR7ps6/GSlnZNkD5TayaybO3TiA+KGA19/zQhO6DMPds+swW0Jz7xv2VBzIWg5
29
- RAnseWJ5nOAftsE9D1NGp3TEH+ceNKO3IP0OtDl9L2F0a/9XbPJdmsaQR+FPX30Z
30
- xJc09X9KG2jBdxa4tp+uy7KZ
31
- -----END CERTIFICATE-----
15
+ cert_chain: []
32
16
 
33
- date: 2009-10-27 00:00:00 -07:00
17
+ date: 2011-04-10 00:00:00 -07:00
34
18
  default_executable:
35
- dependencies:
36
- - !ruby/object:Gem::Dependency
37
- name: hoe
38
- type: :development
39
- version_requirement:
40
- version_requirements: !ruby/object:Gem::Requirement
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- version: 2.3.3
45
- version:
19
+ dependencies: []
20
+
46
21
  description: |
47
22
  Description
48
23
 
@@ -50,59 +25,67 @@ description: |
50
25
  linear motion between points (or arrays of points), multi-channel color
51
26
  gradients, piecewise functions, or even just placing values within intervals.
52
27
 
53
- email: adam.w.collins@gmail.com
28
+ email: adam@m104.us
54
29
  executables: []
55
30
 
56
31
  extensions: []
57
32
 
58
33
  extra_rdoc_files:
59
- - History.txt
60
- - LICENSE.txt
61
- - Manifest.txt
62
- - README.txt
34
+ - LICENSE
35
+ - README.md
63
36
  files:
64
- - History.txt
65
- - LICENSE.txt
37
+ - CHANGELOG.md
38
+ - LICENSE
66
39
  - Manifest.txt
67
- - README.txt
40
+ - README.md
68
41
  - Rakefile
42
+ - VERSION
69
43
  - examples/arrays.rb
44
+ - examples/buckets.rb
70
45
  - examples/colors.rb
71
46
  - examples/nested.rb
72
- - examples/zones.rb
47
+ - interpolate.gemspec
73
48
  - lib/interpolate.rb
74
- - lib/interpolate/add/array.rb
75
49
  - lib/interpolate/add/core.rb
76
- - lib/interpolate/add/numeric.rb
50
+ - lib/interpolate/add/core/array.rb
51
+ - lib/interpolate/add/core/numeric.rb
52
+ - lib/interpolate/interpolation.rb
77
53
  - test/test_all.rb
78
54
  has_rdoc: true
79
- homepage: http://interpolate.rubyforge.org
55
+ homepage: http://github.com/m104/interpolate
80
56
  licenses: []
81
57
 
82
58
  post_install_message:
83
- rdoc_options:
84
- - --main
85
- - README.txt
59
+ rdoc_options: []
60
+
86
61
  require_paths:
87
62
  - lib
88
63
  required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
89
65
  requirements:
90
66
  - - ">="
91
67
  - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
92
70
  version: "0"
93
- version:
94
71
  required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
95
73
  requirements:
96
74
  - - ">="
97
75
  - !ruby/object:Gem::Version
76
+ segments:
77
+ - 0
98
78
  version: "0"
99
- version:
100
79
  requirements: []
101
80
 
102
- rubyforge_project: interpolate
103
- rubygems_version: 1.3.5
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.7
104
83
  signing_key:
105
84
  specification_version: 3
106
- summary: Description 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.
85
+ summary: Create linear interpolations from key points and values
107
86
  test_files:
87
+ - examples/arrays.rb
88
+ - examples/buckets.rb
89
+ - examples/colors.rb
90
+ - examples/nested.rb
108
91
  - test/test_all.rb
data.tar.gz.sig DELETED
Binary file
data/examples/zones.rb DELETED
@@ -1,28 +0,0 @@
1
- require 'rubygems'
2
- require 'interpolate'
3
-
4
- points = {
5
- 0.000 => 0,
6
- 0.427 => 1,
7
- 1.200 => 2,
8
- 3.420 => 3,
9
- 27.50 => 4,
10
- 45.20 => 5,
11
- 124.4 => 6,
12
- }
13
-
14
- zones = Interpolation.new(points)
15
-
16
- values = [
17
- -20.2,
18
- 0.234,
19
- 65.24,
20
- 9.234,
21
- 398.4,
22
- 4000
23
- ]
24
-
25
- values.each do |value|
26
- zone = zones.at(value).floor
27
- puts "A value of #{value} falls into zone #{zone}"
28
- end
metadata.gz.sig DELETED
Binary file