interpolate 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ module Interpolate
2
+ VERSION_MAJOR = 0
3
+ VERSION_MINOR = 3
4
+ VERSION_BUILD = 0
5
+ VERSION = [VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD].join('.')
6
+ end
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ $LOAD_PATH.unshift File.expand_path('../lib')
4
+
3
5
  require 'test/unit'
4
6
  require 'interpolate'
5
7
 
6
8
 
7
9
  class InterpolationTest < Test::Unit::TestCase
8
10
  # acceptable delta; floating point values won't be exact
9
- DELTA = 1e-7
11
+ DELTA = (1.0 - (1.2 - 0.1 - 0.1)) * 100.0
10
12
 
11
13
  def setup
14
+ # NOTE changing these stock points will alter later tests!
12
15
  decimal_points = {
13
16
  0 => 0,
14
17
  1 => 0.1,
@@ -29,56 +32,91 @@ class InterpolationTest < Test::Unit::TestCase
29
32
  500 => [10, 100, 1000]
30
33
  }.freeze
31
34
 
32
- @dec_gradient = Interpolation.new(decimal_points).freeze
33
- @array_gradient = Interpolation.new(array_points).freeze
35
+ @dec_gradient = Interpolate::Points.new(decimal_points).freeze
36
+ @array_gradient = Interpolate::Points.new(array_points).freeze
37
+
38
+ @floor_func = Proc.new{|low, high, bal| low }
39
+ @ceil_func = Proc.new{|low, high, bal| high }
40
+ end
41
+
42
+
43
+ def test_point_counts
44
+ assert_equal(11, @dec_gradient.points.size)
45
+ assert_equal(3, @array_gradient.points.size)
34
46
  end
35
47
 
36
48
 
37
- def test_bad_points
49
+ def test_overlapping_points
50
+ gradient = @dec_gradient.dup
51
+
52
+ # one point added, non-overlapping
53
+ gradient.merge!(11 => 1.1)
54
+ assert_equal(12, gradient.points.size)
55
+
56
+ # one point added, overlapping
57
+ gradient.merge!(8 => 1.2)
58
+ assert_equal(12, gradient.points.size)
59
+
60
+ # verify overlapping point change
61
+ assert_in_delta(1.2, gradient.at(8), DELTA)
62
+ end
63
+
64
+
65
+ def test_bad_point
38
66
  bad_points = {
39
- 0 => 4.2,
40
- 1 => "hello", # not allowed by default
41
- 2 => 3.4,
42
- 3 => 4.8
67
+ 0 => 0,
68
+ 'h' => 3, # non-Numeric key point not allowed
69
+ 2 => 5,
70
+ 3 => 10
43
71
  }
44
72
 
45
73
  assert_raise ArgumentError do
46
- gradient = Interpolation.new(bad_points)
74
+ gradient = Interpolate::Points.new(bad_points)
47
75
  end
48
76
 
77
+ assert_raise ArgumentError do
78
+ gradient = Interpolate::Points.new
79
+ gradient.merge(bad_points)
80
+ end
49
81
  end
50
82
 
83
+
51
84
  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)
85
+ assert_equal(0, @dec_gradient.at(0))
86
+ assert_equal(0, @dec_gradient.at(-1))
87
+ assert_equal(0, @dec_gradient.at(-10))
88
+ assert_equal(0, @dec_gradient.at(-100))
56
89
  end
57
90
 
91
+
58
92
  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)
93
+ assert_equal(1, @dec_gradient.at(10))
94
+ assert_equal(1, @dec_gradient.at(50))
95
+ assert_equal(1, @dec_gradient.at(100))
96
+ assert_equal(1, @dec_gradient.at(500))
62
97
  end
63
98
 
99
+
64
100
  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)
101
+ 1.5.step(9.5, 1.0) do |point|
102
+ assert_in_delta(point / 10.0, @dec_gradient.at(point), DELTA)
103
+ end
74
104
  end
75
105
 
106
+
76
107
  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)
108
+ [
109
+ 0.12343232,
110
+ 0.35583519,
111
+ 0.54363462,
112
+ 0.67658245,
113
+ 0.89234124
114
+ ].each do |point|
115
+ assert_in_delta(point / 10.0, @dec_gradient.at(point), DELTA)
116
+ end
80
117
  end
81
118
 
119
+
82
120
  def test_gradient_merge
83
121
  new_points = {
84
122
  11 => 1.1,
@@ -93,16 +131,17 @@ class InterpolationTest < Test::Unit::TestCase
93
131
  20 => 2
94
132
  }
95
133
 
96
- original = @dec_gradient.dup
97
- expanded = original.merge(new_points)
134
+ base = @dec_gradient.dup
135
+ expanded = base.merge(new_points)
98
136
 
99
- assert_equal(original.at(5), 0.5)
100
- assert_equal(expanded.at(5), 0.5)
137
+ assert_equal(0.5, base.at(5))
138
+ assert_equal(0.5, expanded.at(5))
101
139
 
102
- assert_equal(original.at(15), 1)
103
- assert_equal(expanded.at(15), 1.5)
140
+ assert_equal(1.0, base.at(15))
141
+ assert_equal(1.5, expanded.at(15))
104
142
  end
105
143
 
144
+
106
145
  def test_gradient_merge!
107
146
  new_points = {
108
147
  11 => 1.1,
@@ -117,23 +156,26 @@ class InterpolationTest < Test::Unit::TestCase
117
156
  20 => 2
118
157
  }
119
158
 
120
- original = @dec_gradient.dup
121
- expanded = original.dup
122
- expanded.merge!(new_points)
159
+ base = @dec_gradient.dup
160
+ expanded = base.merge(new_points)
123
161
 
124
- assert_equal(original.at(5), 0.5)
125
- assert_equal(expanded.at(5), 0.5)
162
+ # should match (original range)
163
+ assert_equal(0.5, base.at(5))
164
+ assert_equal(0.5, expanded.at(5))
126
165
 
127
- assert_equal(original.at(15), 1)
128
- assert_equal(expanded.at(15), 1.5)
166
+ # should be different (expanded range)
167
+ assert_equal(1.0, base.at(15))
168
+ assert_equal(1.5, expanded.at(15))
129
169
  end
130
170
 
171
+
131
172
  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])
173
+ assert_equal([3, 30, 300], @array_gradient.at(150))
174
+ assert_equal([5, 50, 500], @array_gradient.at(200))
175
+ assert_equal([7.5, 75, 750], @array_gradient.at(350))
135
176
  end
136
177
 
178
+
137
179
  def test_frozen_points
138
180
  a = @array_gradient.at(200)
139
181
  assert_nothing_raised RuntimeError do
@@ -143,5 +185,37 @@ class InterpolationTest < Test::Unit::TestCase
143
185
  end
144
186
  end
145
187
 
188
+
189
+ def test_stored_blend_function
190
+ gradient = @dec_gradient.dup
191
+
192
+ # floor function
193
+ gradient.blend_with(&@floor_func)
194
+ 0.5.step(9.5, 1.0) do |point|
195
+ assert_in_delta((point - 0.5) / 10.0, gradient.at(point), DELTA)
196
+ end
197
+
198
+ # ceiling
199
+ gradient.blend_with(&@ceil_func)
200
+ 0.5.step(9.5, 1.0) do |point|
201
+ assert_in_delta((point + 0.5) / 10.0, gradient.at(point), DELTA)
202
+ end
203
+ end
204
+
205
+
206
+ def test_given_blend_function
207
+ gradient = @dec_gradient.dup
208
+
209
+ # floor
210
+ 0.5.step(9.5, 1.0) do |point|
211
+ assert_in_delta((point - 0.5) / 10.0, gradient.at(point, &@floor_func), DELTA)
212
+ end
213
+
214
+ # ceiling
215
+ 0.5.step(9.5, 1.0) do |point|
216
+ assert_in_delta((point + 0.5) / 10.0, gradient.at(point, &@ceil_func), DELTA)
217
+ end
218
+ end
219
+
146
220
  end
147
221
 
metadata CHANGED
@@ -1,45 +1,33 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: interpolate
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- - 4
9
- version: 0.2.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Adam Collins
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-04-10 00:00:00 -07:00
18
- default_executable:
12
+ date: 2012-09-05 00:00:00.000000000 Z
19
13
  dependencies: []
20
-
21
- description: |
22
- Description
23
-
24
- Library for generic Interpolation objects. Useful for such things as generating
25
- linear motion between points (or arrays of points), multi-channel color
26
- gradients, piecewise functions, or even just placing values within intervals.
27
-
28
- email: adam@m104.us
14
+ description: Interpolate is a library for generic linear interpolation objects. Useful
15
+ for such things as calculating linear motion between locations (or arrays of locations),
16
+ multi-channel color gradients, piecewise functions, or even just placing values
17
+ within intervals.
18
+ email:
19
+ - adam@m104.us
29
20
  executables: []
30
-
31
21
  extensions: []
32
-
33
- extra_rdoc_files:
34
- - LICENSE
35
- - README.md
36
- files:
22
+ extra_rdoc_files: []
23
+ files:
24
+ - .gitignore
37
25
  - CHANGELOG.md
26
+ - Gemfile
38
27
  - LICENSE
39
- - Manifest.txt
40
28
  - README.md
41
29
  - Rakefile
42
- - VERSION
30
+ - TODO
43
31
  - examples/arrays.rb
44
32
  - examples/buckets.rb
45
33
  - examples/colors.rb
@@ -49,43 +37,32 @@ files:
49
37
  - lib/interpolate/add/core.rb
50
38
  - lib/interpolate/add/core/array.rb
51
39
  - lib/interpolate/add/core/numeric.rb
52
- - lib/interpolate/interpolation.rb
40
+ - lib/interpolate/base.rb
41
+ - lib/interpolate/version.rb
53
42
  - test/test_all.rb
54
- has_rdoc: true
55
43
  homepage: http://github.com/m104/interpolate
56
44
  licenses: []
57
-
58
45
  post_install_message:
59
46
  rdoc_options: []
60
-
61
- require_paths:
47
+ require_paths:
62
48
  - lib
63
- required_ruby_version: !ruby/object:Gem::Requirement
49
+ required_ruby_version: !ruby/object:Gem::Requirement
64
50
  none: false
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- segments:
69
- - 0
70
- version: "0"
71
- required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
56
  none: false
73
- requirements:
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- segments:
77
- - 0
78
- version: "0"
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: 1.3.6
79
61
  requirements: []
80
-
81
62
  rubyforge_project:
82
- rubygems_version: 1.3.7
63
+ rubygems_version: 1.8.24
83
64
  signing_key:
84
65
  specification_version: 3
85
- summary: Create linear interpolations from key points and values
86
- test_files:
87
- - examples/arrays.rb
88
- - examples/buckets.rb
89
- - examples/colors.rb
90
- - examples/nested.rb
66
+ summary: Create arbitrary interpolations from key points and values
67
+ test_files:
91
68
  - test/test_all.rb
@@ -1,16 +0,0 @@
1
- CHANGELOG.md
2
- LICENSE
3
- Manifest.txt
4
- Rakefile
5
- README.md
6
- VERSION
7
- examples/arrays.rb
8
- examples/buckets.rb
9
- examples/colors.rb
10
- examples/nested.rb
11
- lib/interpolate.rb
12
- lib/interpolate/interpolation.rb
13
- lib/interpolate/add/core.rb
14
- lib/interpolate/add/core/array.rb
15
- lib/interpolate/add/core/numeric.rb
16
- test/test_all.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.2.4
@@ -1,117 +0,0 @@
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
-