interpolate 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ == 0.2.0
2
+
3
+ * Changed the library name to "interpolate"
4
+ * Added Array#interpolate that covers uniform arrays and nested arrays
5
+ * Added more tests, documentation, and examples
6
+
7
+ == 0.1.0
8
+
9
+ * Gadient calls :interpolate on values for OOP goodness
10
+ * Checks added for respond_to? :interpolate on values
11
+ * Added Numeric#interpolate
12
+
13
+ == 0.0.1
14
+
15
+ * Initial coding
16
+ * N-sized arbitrary floating point gradients
17
+
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Adam Collins [adam.w.collins@gmail.com]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ CHANGELOG
2
+ MIT-LICENSE
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ examples/arrays.rb
7
+ examples/colors.rb
8
+ examples/nested.rb
9
+ examples/zones.rb
10
+ lib/interpolate.rb
11
+ test/test_all.rb
@@ -0,0 +1,11 @@
1
+ == Interpolate
2
+
3
+ Library for generic interpolation objects. Useful for such things as generating
4
+ linear motion between points (or arrays of points), multi-channel color
5
+ gradients, piecewise functions, or even just placing values within intervals.
6
+
7
+ == Author
8
+
9
+ Adam Collins
10
+ adam.w.collins@gmail.com
11
+
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ $:.unshift(File.dirname(__FILE__) + "/lib")
4
+ require 'interpolate'
5
+
6
+ Hoe.new('Interpolate', Interpolation::VERSION) do |p|
7
+ p.name = "interpolate"
8
+ p.author = "Adam Collins"
9
+ p.description = "Library for creating generic interpolations objects."
10
+ p.email = 'adam.w.collins@gmail.com'
11
+ p.summary = "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."
12
+ p.url = "http://interpolate.rubyforge.org"
13
+ #p.clean_globs = [''] # Remove this directory on "rake clean"
14
+ p.remote_rdoc_dir = '' # Release to root
15
+ p.changes = p.paragraphs_of('CHANGELOG', 0..1).join("\n\n")
16
+ # * extra_deps - An array of rubygem dependencies.
17
+ end
18
+
19
+ desc "Release and publish documentation"
20
+ task :repubdoc => [:release, :publish_docs]
21
+
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'interpolate'
3
+ require 'pp'
4
+
5
+
6
+ # a non-linear set of multi-dimensional points;
7
+ # perhaps the location of some actor in relation to time
8
+ time_frames = {
9
+ 0 => [0, 0, 0],
10
+ 1 => [1, 0, 0],
11
+ 2 => [0, 1, 0],
12
+ 3 => [0, 0, 2],
13
+ 4 => [3, 0, 1],
14
+ 5 => [1, 2, 3],
15
+ 6 => [0, 0, 0]
16
+ }
17
+
18
+ path = Interpolation.new(time_frames)
19
+
20
+ # play the actors positions in time increments of 0.25
21
+ (0).step(6, 0.25) do |time|
22
+ position = path.at(time)
23
+ puts ">> At #{time}s, actor is at:"
24
+ p position
25
+ end
26
+
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'interpolate'
3
+ require 'color'
4
+
5
+
6
+ # we need to implement :interpolate for Color::RGB
7
+ # in order for Interpolation to work
8
+ class Color::RGB
9
+ def interpolate(other, balance)
10
+ mix_with(other, balance * 100.0)
11
+ end
12
+ end
13
+
14
+ # a nice weathermap-style color gradient
15
+ points = {
16
+ 0 => Color::RGB::White,
17
+ 1 => Color::RGB::Lime,
18
+ # 2 => ? (something between Lime and Yellow)
19
+ 3 => Color::RGB::Yellow,
20
+ 4 => Color::RGB::Orange,
21
+ 5 => Color::RGB::Red,
22
+ 6 => Color::RGB::Magenta,
23
+ 7 => Color::RGB::DarkGray
24
+ }
25
+
26
+
27
+ gradient = Interpolation.new(points)
28
+
29
+ # what are the colors of the gradient from 0 to 7
30
+ # in increments of 0.2?
31
+ (0).step(7, 0.2) do |value|
32
+ color = gradient.at(value)
33
+ puts "A value of #{value} means #{color.html}"
34
+ end
35
+
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'interpolate'
3
+ require 'pp'
4
+
5
+
6
+ # a non-linear set of 2D vertexes;
7
+ # the shape changes at each frame
8
+ time_frames = {
9
+ 0 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line
10
+ 1 => [[0, 0], [1, 0], [3, 0], [0, 4], [0, 0]], # a triangle
11
+ 2 => [[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]], # a square
12
+ 3 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line, again
13
+ 4 => [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]] # a vertical line
14
+ }
15
+
16
+
17
+ paths = Interpolation.new(time_frames)
18
+
19
+ # show the vertex positions in time increments of 0.25
20
+ (0).step(4, 0.25) do |time|
21
+ points = paths.at(time)
22
+ puts ">> At #{time}s, points are:"
23
+ p points
24
+ end
25
+
26
+
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,304 @@
1
+ =begin rdoc
2
+
3
+ Library for generic interpolation objects. Useful for such things as generating
4
+ linear motion between points (or arrays of points), multi-channel color
5
+ gradients, piecewise functions, or even just placing values within intervals.
6
+
7
+ The only requirement is that each interpolation point value must be able to
8
+ figure out how to interpolate itself to its neighbor value(s). Numeric
9
+ objects and uniformly sized arrays are automatically endowed with this
10
+ ability by this gem, but other classes will require an implementation
11
+ of #interpolate. See the second example below for a brief demonstration
12
+ using Color objects.
13
+
14
+ Interpolation objects are constructed with a Hash object, wherein each key
15
+ is a real number value and each value is can respond to #interpolate and
16
+ determine the resulting value based on its neighbor value and the balance
17
+ ratio between the two points.
18
+
19
+ At or below the lower bounds of the interpolation, the result will be equal to
20
+ the value of the lower bounds interpolation point. At or above the upper
21
+ bounds of the graient, the result will be equal to the value of the upper
22
+ bounds interpolation point.
23
+
24
+
25
+ ==Author
26
+
27
+ {Adam Collins}[mailto:adam.w.collins@gmail.com]
28
+
29
+
30
+ ==General Usage
31
+
32
+ Specify the interpolation as a Hash, where keys represent numeric points
33
+ along the gradient and values represent the known values along that gradient.
34
+
35
+ Here's an example for determining which of 7 zones a set of values fall into:
36
+
37
+ require 'rubygems'
38
+ require 'interpolate'
39
+
40
+ points = {
41
+ 0.000 => 0,
42
+ 0.427 => 1,
43
+ 1.200 => 2,
44
+ 3.420 => 3,
45
+ 27.50 => 4,
46
+ 45.20 => 5,
47
+ 124.4 => 6,
48
+ }
49
+
50
+ zones = Interpolation.new(points)
51
+
52
+ values = [
53
+ -20.2,
54
+ 0.234,
55
+ 65.24,
56
+ 9.234,
57
+ 398.4,
58
+ 4000
59
+ ]
60
+
61
+ values.each do |value|
62
+ zone = zones.at(value).floor
63
+ puts "A value of #{value} falls into zone #{zone}"
64
+ end
65
+
66
+
67
+ ==Non-Numeric Gradients
68
+
69
+ For non-Numeric gradient value objects, you'll need to implement :interpolate
70
+ for the class in question. Here's an example using an RGB color gradient with
71
+ the help of the 'color' gem:
72
+
73
+ require 'rubygems'
74
+ require 'interpolate'
75
+ require 'color'
76
+
77
+ # we need to implement :interpolate for Color::RGB
78
+ # in order for Interpolation to work
79
+ class Color::RGB
80
+ def interpolate(other, balance)
81
+ mix_with(other, balance * 100.0)
82
+ end
83
+ end
84
+
85
+ # a nice weathermap-style color gradient
86
+ points = {
87
+ 0 => Color::RGB::White,
88
+ 1 => Color::RGB::Lime,
89
+ # 2 => ? (something between Lime and Yellow)
90
+ 3 => Color::RGB::Yellow,
91
+ 4 => Color::RGB::Orange,
92
+ 5 => Color::RGB::Red,
93
+ 6 => Color::RGB::Magenta,
94
+ 7 => Color::RGB::DarkGray
95
+ }
96
+
97
+
98
+ gradient = Interpolation.new(points)
99
+
100
+ # what are the colors of the gradient from 0 to 7
101
+ # in increments of 0.2?
102
+ (0).step(7, 0.2) do |value|
103
+ color = gradient.at(value)
104
+ puts "A value of #{value} means #{color.html}"
105
+ end
106
+
107
+
108
+ ==Array-based Interpolations
109
+
110
+ Aside from single value gradient points, you can interpolate over uniformly sized
111
+ arrays. Between two interpolation points, let's say +a+ and +b+, the final
112
+ result will be +c+ where +c[0]+ is the interpolation of +a[0]+ and +b[0]+ and
113
+ +c[1]+ is interpolated between +a[1]+ and +b[1]+ and so on up to +c[n]+.
114
+
115
+ Here is an example:
116
+
117
+ require 'rubygems'
118
+ require 'interpolate'
119
+ require 'pp'
120
+
121
+ # a non-linear set of multi-dimensional points;
122
+ # perhaps the location of some actor in relation to time
123
+ time_frames = {
124
+ 0 => [0, 0, 0],
125
+ 1 => [1, 0, 0],
126
+ 2 => [0, 1, 0],
127
+ 3 => [0, 0, 2],
128
+ 4 => [3, 0, 1],
129
+ 5 => [1, 2, 3],
130
+ 6 => [0, 0, 0]
131
+ }
132
+
133
+ path = Interpolation.new(time_frames)
134
+
135
+ # play the actors positions in time increments of 0.25
136
+ (0).step(6, 0.25) do |time|
137
+ position = path.at(time)
138
+ puts ">> At #{time}s, actor is at:"
139
+ p position
140
+ end
141
+
142
+
143
+ ==Nested Array Interpolations
144
+
145
+ As long as each top level array is uniformly sized in the first dimension
146
+ and each nested array is uniformly sized in the second dimension (and so
147
+ on...), multidimensional interpolation point values will just work.
148
+
149
+ Here's an example of a set of 2D points being morphed:
150
+
151
+ require 'rubygems'
152
+ require 'interpolate'
153
+ require 'pp'
154
+
155
+
156
+ # a non-linear set of 2D vertexes;
157
+ # the shape changes at each frame
158
+ time_frames = {
159
+ 0 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line
160
+ 1 => [[0, 0], [1, 0], [3, 0], [0, 4], [0, 0]], # a triangle
161
+ 2 => [[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]], # a square
162
+ 3 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line, again
163
+ 4 => [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]] # a vertical line
164
+ }
165
+
166
+
167
+ paths = Interpolation.new(time_frames)
168
+
169
+ # show the vertex positions in time increments of 0.25
170
+ (0).step(4, 0.25) do |time|
171
+ points = paths.at(time)
172
+ puts ">> At #{time}s, points are:"
173
+ p points
174
+ end
175
+
176
+
177
+ ==License
178
+
179
+ Licensed under the MIT license.
180
+
181
+ =end
182
+
183
+
184
+ # all numeric objects should be supported out of the box
185
+ class Numeric
186
+ def interpolate(other, balance)
187
+ left = self.to_f
188
+ right = other.to_f
189
+ delta = (right - left).to_f
190
+ return left + (delta * balance)
191
+ end
192
+ end
193
+
194
+
195
+ # a little more complicated, but there's no reason why we can't
196
+ # interpolate between two equal length arrays as long as each element
197
+ # responds to :interpolate
198
+ class Array
199
+ def interpolate(other, balance)
200
+ if (self.length < 1) then
201
+ raise ArgumentError, "cannot interpolate array with no values"
202
+ end
203
+
204
+ if (self.length != other.length) then
205
+ raise ArgumentError, "cannot interpolate between arrays of different length"
206
+ end
207
+
208
+ final = Array.new
209
+
210
+ self.each_with_index do |left, index|
211
+ unless (left.respond_to? :interpolate) then
212
+ raise "array element does not respond to :interpolate"
213
+ end
214
+
215
+ right = other[index]
216
+
217
+ final[index] = left.interpolate(right, balance)
218
+ end
219
+
220
+ return final
221
+ end
222
+ end
223
+
224
+
225
+ class Interpolation
226
+ VERSION = '0.2.0'
227
+
228
+ def initialize(points = {})
229
+ @points = {}
230
+ add!(points)
231
+ end
232
+
233
+ def add(points = {})
234
+ Interpolation.new(points.merge(@points))
235
+ end
236
+
237
+ def add!(points = {})
238
+ @points.merge!(points)
239
+ normalize_data
240
+ end
241
+
242
+
243
+ def at(point)
244
+ # deal with the two out-of-bounds cases first
245
+ if (point <= @min_point)
246
+ return @data.first.last
247
+ elsif (point >= @max_point)
248
+ return @data.last.last
249
+ end
250
+
251
+ # go through the interpolation intervals, in order, to determine
252
+ # into which this point falls
253
+ 1.upto(@data.length - 1) do |zone|
254
+ left = @data.at(zone - 1)
255
+ right = @data.at(zone)
256
+ zone_range = left.first..right.first
257
+
258
+ if (zone_range.include?(point))
259
+ # what are the points in question?
260
+ left_point = left.first.to_f
261
+ right_point = right.first.to_f
262
+
263
+ # what are the values in question?
264
+ left_value = left.last
265
+ right_value = right.last
266
+
267
+ # span: difference between the left point and right point
268
+ # balance: ratio of right point to left point
269
+ span = right_point - left_point
270
+ balance = (point.to_f - left_point) / span
271
+
272
+ # catch the cases where the point in quesion is
273
+ # on one of the zone's endpoints
274
+ return left_value if (balance == 0.0)
275
+ return right_value if (balance == 1.0)
276
+
277
+ # otherwise, we need to interpolate
278
+ return left_value.interpolate(right_value, balance)
279
+ end
280
+ end
281
+
282
+ # we shouldn't get to this point
283
+ raise "couldn't come up with a value for some reason!"
284
+ end
285
+
286
+ private
287
+
288
+ def normalize_data
289
+ @data = @points.sort
290
+ @min_point = @data.first.first
291
+ @max_point = @data.last.first
292
+
293
+ # make sure that all values respond_to? :interpolate
294
+ @data.each do |point|
295
+ value = point.last
296
+ unless value.respond_to?(:interpolate)
297
+ raise ArgumentError, "found an interpolation point that doesn't respond to :interpolate"
298
+ end
299
+ end
300
+ end
301
+
302
+ end
303
+
304
+
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby1.8 -w
2
+
3
+ require 'test/unit'
4
+ require 'lib/interpolate'
5
+
6
+
7
+ class InterpolationTest < Test::Unit::TestCase
8
+
9
+ DELTA = 1e-7
10
+
11
+ def setup
12
+ decimal_points = {
13
+ 0 => 0,
14
+ 1 => 0.1,
15
+ 2 => 0.2,
16
+ 3 => 0.3,
17
+ 4 => 0.4,
18
+ 5 => 0.5,
19
+ 6 => 0.6,
20
+ 7 => 0.7,
21
+ 8 => 0.8,
22
+ 9 => 0.9,
23
+ 10 => 1
24
+ }
25
+
26
+ array_points = {
27
+ 100 => [1, 10, 100],
28
+ 200 => [5, 50, 500],
29
+ 500 => [10, 100, 1000]
30
+ }
31
+
32
+ @dec_gradient = Interpolation.new(decimal_points)
33
+ @array_gradient = Interpolation.new(array_points)
34
+ end
35
+
36
+
37
+ def test_bad_points
38
+ bad_points = {
39
+ 0 => 4.2,
40
+ 1 => "hello", # not allowed by default
41
+ 2 => 3.4,
42
+ 3 => 4.8
43
+ }
44
+
45
+ assert_raise ArgumentError do
46
+ gradient = Interpolation.new(bad_points)
47
+ end
48
+
49
+ end
50
+
51
+ def test_lower_bounds
52
+ assert_equal(@dec_gradient.at(0), 0)
53
+ assert_equal(@dec_gradient.at(-1), 0)
54
+ assert_equal(@dec_gradient.at(-10), 0)
55
+ assert_equal(@dec_gradient.at(-100), 0)
56
+ end
57
+
58
+ def test_upper_bounds
59
+ assert_equal(@dec_gradient.at(10), 1)
60
+ assert_equal(@dec_gradient.at(100), 1)
61
+ assert_equal(@dec_gradient.at(1000), 1)
62
+ end
63
+
64
+ def test_midpoints
65
+ assert_in_delta(@dec_gradient.at(1.5), 0.15, DELTA)
66
+ assert_in_delta(@dec_gradient.at(2.5), 0.25, DELTA)
67
+ assert_in_delta(@dec_gradient.at(3.5), 0.35, DELTA)
68
+ assert_in_delta(@dec_gradient.at(4.5), 0.45, DELTA)
69
+ assert_in_delta(@dec_gradient.at(5.5), 0.55, DELTA)
70
+ assert_in_delta(@dec_gradient.at(6.5), 0.65, DELTA)
71
+ assert_in_delta(@dec_gradient.at(7.5), 0.75, DELTA)
72
+ assert_in_delta(@dec_gradient.at(8.5), 0.85, DELTA)
73
+ assert_in_delta(@dec_gradient.at(9.5), 0.95, DELTA)
74
+ end
75
+
76
+ def test_precision
77
+ assert_in_delta(@dec_gradient.at(1.5555), 0.15555, DELTA)
78
+ assert_in_delta(@dec_gradient.at(2.5678), 0.25678, DELTA)
79
+ assert_in_delta(@dec_gradient.at(3.5701), 0.35701, DELTA)
80
+ end
81
+
82
+ def test_gradient_add
83
+ new_points = {
84
+ 11 => 1.1,
85
+ 12 => 1.2,
86
+ 13 => 1.3,
87
+ 14 => 1.4,
88
+ 15 => 1.5,
89
+ 16 => 1.6,
90
+ 17 => 1.7,
91
+ 18 => 1.8,
92
+ 19 => 1.9,
93
+ 20 => 2
94
+ }
95
+
96
+ original = @dec_gradient.dup
97
+ expanded = original.add(new_points)
98
+
99
+ assert_equal(original.at(5), 0.5)
100
+ assert_equal(expanded.at(5), 0.5)
101
+
102
+ assert_equal(original.at(15), 1)
103
+ assert_equal(expanded.at(15), 1.5)
104
+ end
105
+
106
+ def test_gradient_add!
107
+ new_points = {
108
+ 11 => 1.1,
109
+ 12 => 1.2,
110
+ 13 => 1.3,
111
+ 14 => 1.4,
112
+ 15 => 1.5,
113
+ 16 => 1.6,
114
+ 17 => 1.7,
115
+ 18 => 1.8,
116
+ 19 => 1.9,
117
+ 20 => 2
118
+ }
119
+
120
+ original = @dec_gradient.dup
121
+ expanded = original.dup
122
+ expanded.add!(new_points)
123
+
124
+ assert_equal(original.at(5), 0.5)
125
+ assert_equal(expanded.at(5), 0.5)
126
+
127
+ assert_equal(original.at(15), 1)
128
+ assert_equal(expanded.at(15), 1.5)
129
+ end
130
+
131
+ def test_array_values
132
+ assert_equal(@array_gradient.at(150), [3, 30, 300])
133
+ assert_equal(@array_gradient.at(200), [5, 50, 500])
134
+ assert_equal(@array_gradient.at(350), [7.5, 75, 750])
135
+ end
136
+
137
+ end
138
+
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: interpolate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Collins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-24 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.4.0
23
+ version:
24
+ description: Library for creating generic interpolations objects.
25
+ email: adam.w.collins@gmail.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - Manifest.txt
32
+ - README.txt
33
+ files:
34
+ - CHANGELOG
35
+ - MIT-LICENSE
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - examples/arrays.rb
40
+ - examples/colors.rb
41
+ - examples/nested.rb
42
+ - examples/zones.rb
43
+ - lib/interpolate.rb
44
+ - test/test_all.rb
45
+ has_rdoc: true
46
+ homepage: http://interpolate.rubyforge.org
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --main
50
+ - README.txt
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project: interpolate
68
+ rubygems_version: 1.0.1
69
+ signing_key:
70
+ specification_version: 2
71
+ summary: 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.
72
+ test_files:
73
+ - test/test_all.rb