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,7 @@
1
+ .DS_Store
2
+ *.swp
3
+ Gemfile.lock
4
+ .bundle/
5
+ rdoc/
6
+ pkg/
7
+ *.gem
@@ -1,36 +1,46 @@
1
- == 0.2.4 (2011.4.10)
1
+ ## 0.3.0 (2012.9.01)
2
+
3
+ Major gem revisions:
4
+
5
+ * Interpolation class moved to Interpolate::Points
6
+ * Binary search to find the correct interpolation interval
7
+ * Optional blending function block can be passed to Interpolate::Points
8
+ * gemspec file completely rebuilt, sans Jeweler
9
+
10
+ ## 0.2.4 (2011.4.10)
2
11
 
3
12
  * Project cleanup: minor updates to the lib/ file structure and documentation
4
13
 
5
- == 0.2.2 (2008.2.4)
14
+ ## 0.2.2 (2008.2.4)
6
15
 
7
- * Single source file has been split into Class files
8
- * Tests now use +freeze+
9
- * Better edge case testing in the Array and Numeric +interpolate+ methods
16
+ * Single source file has been split into class files
17
+ * Tests now use `freeze`
18
+ * Better edge case testing in the `Array` and `Numeric` `interpolate` methods
10
19
 
11
- == 0.2.1 (2008.1.27)
20
+ ## 0.2.1 (2008.1.27)
12
21
 
13
22
  First public release
14
23
 
15
24
  Project Cleanup:
16
- * Documentation enhancements and updates.
17
- * +add+ is now +merge+
18
25
 
19
- == 0.2.0 (2008.1.24)
26
+ * Documentation enhancements and updates.
27
+ * `add` is now `merge`
28
+
29
+ ## 0.2.0 (2008.1.24)
20
30
 
21
31
  * Changed the library name to "interpolate"
22
- * Added +interpolate+ (+Array+) that covers uniform arrays and nested arrays
32
+ * Added `Array#interpolate` that covers uniform arrays and nested arrays
23
33
  * Added more tests, documentation, and examples
24
34
 
25
- == 0.1.0 (2008.1.22)
35
+ ## 0.1.0 (2008.1.22)
26
36
 
27
- * 2 Major Changes:
37
+ 2 Major Changes:
28
38
 
29
- * Gadient calls +interpolate+ on values for OOP goodness
30
- * Checks added for respond_to? +interpolate+ on values
31
- * Added +interpolate+ (+Numeric+)
39
+ * Gradient calls `interpolate` on values for OOP goodness
40
+ * Checks added for `respond_to?(:interpolate)` on values
41
+ * Added `Numeric#interpolate`
32
42
 
33
- == 0.0.1 (2008.1.20)
43
+ ## 0.0.1 (2008.1.20)
34
44
 
35
45
  * Initial coding
36
46
  * N-sized arbitrary floating point gradients
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rake'
4
+
5
+ gemspec
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2011 Adam Collins [adam@m104.us]
1
+ Copyright (c) 2008-2012 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/README.md CHANGED
@@ -7,126 +7,96 @@ Adam Collins [adam@m104.us]
7
7
 
8
8
  ## Description
9
9
 
10
- Library for generic Interpolation objects. Useful for such things as generating
11
- linear motion between points (or arrays of points), multi-channel color
12
- gradients, piecewise functions, or even just placing values within intervals.
10
+ Interpolate is a library for generic linear interpolation objects. Useful for
11
+ such things as calculating linear motion between locations (or arrays of
12
+ locations), multi-channel color gradients, piecewise functions, or even just
13
+ placing values within intervals.
13
14
 
14
15
 
15
16
  ## General Usage
16
17
 
17
- Specify the interpolation as a Hash, where keys represent numeric points
18
- along the gradient and values represent the known (key) values along that
19
- gradient.
20
-
21
- Here's an example for placing values within one of seven buckets:
22
-
23
- require 'rubygems'
24
- require 'interpolate'
25
-
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,
35
- }
36
-
37
- bucketizer = Interpolation.new(buckets)
38
-
39
- values = [
40
- -20.2,
41
- 0.234,
42
- 65.24,
43
- 9.234,
44
- 398.4,
45
- 4000
46
- ]
47
-
48
- values.each do |value|
49
- bucket = bucketizer.at(value).floor
50
- puts "A value of #{value} falls into bucket #{bucket}"
51
- end
52
-
53
-
54
- ## Non-Numeric Gradients
55
-
56
- For non-Numeric gradient value objects, you'll need to implement +interpolate+
57
- for the class in question. Here's an example using an RGB color gradient with
58
- the help of the 'color' gem:
59
-
60
- require 'rubygems'
61
- require 'interpolate'
62
- require 'color'
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)
18
+ Interpolation generators can be created with the Interpolate::Points class,
19
+ given a Hash of "key points" and associated key values.
20
+
21
+ By default, the key values should be able to calculate their own blending
22
+ function (by defining an +interpolate+ instance method). Alternatively, the
23
+ Interpolate::Points object can be passed a block that takes three arguments: the
24
+ lower value, the higher value, and the balance ratio between the two.
25
+
26
+ Here's an example for placing values within one of seven buckets, accomplished
27
+ with the help of a `floor` blending function:
28
+
29
+ require 'rubygems'
30
+ require 'interpolate'
31
+
32
+ # min_value => bucket
33
+ buckets = {
34
+ 0.000 => 1,
35
+ 0.500 => 2,
36
+ 1.250 => 3,
37
+ 7.725 => 4,
38
+ 28.85 => 5,
39
+ 50.00 => 6,
40
+ 127.5 => 7
41
+ }
42
+
43
+ values = [
44
+ -20.2,
45
+ 0.234,
46
+ 65.24,
47
+ 9.234,
48
+ 398.4,
49
+ 4000
50
+ ]
51
+
52
+ # using Interpolate::Points to place values within discrete intervals
53
+ bucketizer = Interpolate::Points.new(buckets)
54
+ # the blending function will mimic the mathematical floor function
55
+ bucketizer.blend_with {|low, high, balance| low }
56
+
57
+ values.each do |value|
58
+ bucket = bucketizer.at(value).floor
59
+ puts "A value of #{value} falls into bucket #{bucket}"
69
60
  end
70
- end
71
61
 
72
- # a nice weathermap-style color gradient
73
- points = {
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
81
- }
82
62
 
83
- gradient = Interpolation.new(points)
84
63
 
85
- # what are the colors of the gradient from 1 to 7
86
- # in increments of 0.2?
87
- (1).step(7, 0.2) do |value|
88
- color = gradient.at(value)
89
- puts "A value of #{value} means #{color.html}"
90
- end
64
+ ## Array-based Interpolate::Points
91
65
 
92
-
93
- ## Array-based Interpolations
94
-
95
- Aside from single value gradient points, you can interpolate over uniformly sized
96
- arrays. Between two interpolation points, let's say +a+ and +b+, the final result
97
- will be +c+ where <tt>c[0]</tt> is the interpolation of <tt>a[0]</tt> and
98
- <tt>b[0]</tt> and <tt>c[1]</tt> is interpolated between <tt>a[1]</tt> and
99
- <tt>b[1]</tt> and so on up to <tt>c[n]</tt>.
66
+ Aside from single value gradient points, you can interpolate over uniformly
67
+ sized arrays. Between two interpolation points, let's say _a_ and _b_, the
68
+ final result will be _c_ where _c[0]_ is the interpolation of _a[0]_ and _b[0]_
69
+ and _c[1]_ is interpolated between _a[1]_ and _b[1]_ and so on up to _c[n]_.
100
70
 
101
71
  Here is an example:
102
72
 
103
- require 'rubygems'
104
- require 'interpolate'
105
- require 'pp'
106
-
107
- # a non-linear set of multi-dimensional points;
108
- # perhaps the location of an actor in relation to time
109
- time_frames = {
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]
117
- }
118
-
119
- path = Interpolation.new(time_frames)
120
-
121
- # play the actor's positions in time increments of 0.25
122
- (1).step(7, 0.25) do |time|
123
- position = path.at(time)
124
- puts ">> At #{time}s, actor is at:"
125
- p position
126
- end
73
+ require 'rubygems'
74
+ require 'interpolate'
75
+ require 'pp'
76
+
77
+ # a non-linear set of multi-dimensional points;
78
+ # perhaps the location of some actor in relation to time
79
+ time_frames = {
80
+ 0 => [0, 0, 0],
81
+ 1 => [1, 0, 0],
82
+ 2 => [0, 1, 0],
83
+ 3 => [0, 0, 2],
84
+ 4 => [3, 0, 1],
85
+ 5 => [1, 2, 3],
86
+ 6 => [0, 0, 0]
87
+ }
88
+
89
+ path = Interpolate::Points.new(time_frames)
90
+
91
+ # play the actor's positions in time increments of 0.25
92
+ (0).step(6, 0.25) do |time|
93
+ position = path.at(time)
94
+ puts ">> At #{time}s, actor is at:"
95
+ p position
96
+ end
127
97
 
128
98
 
129
- ## Nested Array Interpolations
99
+ ## Nested Array Interpolate::Points
130
100
 
131
101
  As long as each top level array is uniformly sized in the first dimension
132
102
  and each nested array is uniformly sized in the second dimension (and so
@@ -134,37 +104,80 @@ on...), multidimensional interpolation point values will just work.
134
104
 
135
105
  Here's an example of a set of 2D points being morphed:
136
106
 
137
- require 'rubygems'
138
- require 'interpolate'
139
- require 'pp'
107
+ require 'rubygems'
108
+ require 'interpolate'
109
+ require 'pp'
110
+
111
+
112
+ # a number of sets 2D vertices, each set corresponding to a particular
113
+ # shape on the grid
114
+ time_frames = {
115
+ 0 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line
116
+ 1 => [[0, 0], [1, 0], [3, 0], [0, 4], [0, 0]], # a triangle
117
+ 2 => [[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]], # a square
118
+ 3 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line, again
119
+ 4 => [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]] # a vertical line
120
+ }
121
+
140
122
 
123
+ paths = Interpolate::Points.new(time_frames)
141
124
 
142
- # a number of sets 2D vertices, each set corresponding to a particular
143
- # shape on the grid
144
- time_frames = {
145
- 0 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line
146
- 1 => [[0, 0], [1, 0], [3, 0], [0, 4], [0, 0]], # a triangle
147
- 2 => [[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]], # a square
148
- 3 => [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], # a horizontal line, again
149
- 4 => [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]] # a vertical line
150
- }
125
+ # show the vertex positions in time increments of 0.25
126
+ (0).step(4, 0.25) do |time|
127
+ points = paths.at(time)
128
+ puts ">> At #{time}s, points are:"
129
+ p points
130
+ end
131
+
132
+
133
+
134
+ ## Other Interpolations
135
+
136
+ For other classes of value objects, you'll need to implement a blending
137
+ function. Here's an example using an RGB color gradient with the help of the
138
+ 'color' gem:
151
139
 
152
140
 
153
- paths = Interpolation.new(time_frames)
141
+ require 'rubygems'
142
+ require 'interpolate'
143
+ require 'color'
154
144
 
155
- # show the vertex positions in time increments of 0.25
156
- (0).step(4, 0.25) do |time|
157
- points = paths.at(time)
158
- puts ">> At #{time}s, points are:"
159
- p points
160
- end
145
+ # a nice weathermap-style color gradient
146
+ points = {
147
+ 1 => Color::RGB::Cyan,
148
+ 2 => Color::RGB::Lime,
149
+ # 3 => ? (between Lime and Yellow; Interpolate will figure it out)
150
+ 4 => Color::RGB::Yellow,
151
+ 5 => Color::RGB::Orange,
152
+ 6 => Color::RGB::Red,
153
+ 7 => Color::RGB::Magenta,
154
+ 8 => Color::RGB::White,
155
+ }
156
+
157
+ # we need to implement a blending function in order for Interpolate::Points to
158
+ # work properly
159
+ #
160
+ # fortunately, Color::RGB includes +mix_with+, which is almost functionally
161
+ # identical to what we need
162
+
163
+ gradient = Interpolate::Points.new(points)
164
+ gradient.blend_with {|color, other, balance|
165
+ color.mix_with(other, balance * 100.0)
166
+ }
167
+
168
+ # what are the colors of the gradient from 1 to 8
169
+ # in increments of 0.2?
170
+ (1).step(7, 0.2) do |value|
171
+ color = gradient.at(value)
172
+ puts "A value of #{value.round(3)} means #{color.html}"
173
+ end
161
174
 
162
175
 
163
176
  ## License
164
177
 
165
178
  (The MIT License)
166
179
 
167
- Copyright (c) 2008-2011 Adam Collins [adam@m104.us]
180
+ Copyright (c) 2008-2012 Adam Collins [adam@m104.us]
168
181
 
169
182
  Permission is hereby granted, free of charge, to any person obtaining
170
183
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,35 +1,21 @@
1
- require 'jeweler'
2
- require 'rake'
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ require 'interpolate'
3
3
 
4
- require './lib/interpolate/interpolation'
5
-
6
- Jeweler::Tasks.new do |g|
7
- doc_sections = File.read('README.md').delete("\r").split(/^## /)
4
+ desc 'Build the gem'
5
+ task :build do
6
+ system 'gem build interpolate.gemspec'
7
+ end
8
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
9
+ desc 'Release the gem'
10
+ task :release => :build do
11
+ system "gem push interpolate-#{Interpolation::VERSION}"
16
12
  end
17
13
 
18
14
  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
15
 
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')
16
+ Rake::TestTask.new do |t|
17
+ t.libs << 'test'
33
18
  end
34
19
 
20
+ task :default => :test
35
21
 
data/TODO ADDED
@@ -0,0 +1,14 @@
1
+ Interpolate::Points
2
+ - out of bounds behavior options
3
+ - more than one stock blending function
4
+ - allow symbol in place of blend_with Proc
5
+
6
+ Add/Core
7
+ - Complex type :interpolate method
8
+
9
+ Testing
10
+ - more coverage of blending function behavior
11
+ - split test_all.rb into case category files
12
+ - minitest
13
+ - contexts (?)
14
+