interpolate 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/CHANGELOG.md +26 -16
- data/Gemfile +5 -0
- data/LICENSE +1 -1
- data/README.md +139 -126
- data/Rakefile +12 -26
- data/TODO +14 -0
- data/examples/arrays.rb +2 -2
- data/examples/buckets.rb +11 -8
- data/examples/colors.rb +16 -14
- data/examples/nested.rb +1 -1
- data/interpolate.gemspec +22 -57
- data/lib/interpolate.rb +14 -1
- data/lib/interpolate/add/core/array.rb +9 -11
- data/lib/interpolate/add/core/numeric.rb +5 -4
- data/lib/interpolate/base.rb +179 -0
- data/lib/interpolate/version.rb +6 -0
- data/test/test_all.rb +118 -44
- metadata +33 -56
- data/Manifest.txt +0 -16
- data/VERSION +0 -1
- data/lib/interpolate/interpolation.rb +0 -117
data/.gitignore
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,36 +1,46 @@
|
|
1
|
-
|
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
|
-
|
14
|
+
## 0.2.2 (2008.2.4)
|
6
15
|
|
7
|
-
* Single source file has been split into
|
8
|
-
* Tests now use
|
9
|
-
* Better edge case testing in the Array and Numeric
|
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
|
-
|
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
|
-
|
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
|
32
|
+
* Added `Array#interpolate` that covers uniform arrays and nested arrays
|
23
33
|
* Added more tests, documentation, and examples
|
24
34
|
|
25
|
-
|
35
|
+
## 0.1.0 (2008.1.22)
|
26
36
|
|
27
|
-
|
37
|
+
2 Major Changes:
|
28
38
|
|
29
|
-
*
|
30
|
-
* Checks added for respond_to?
|
31
|
-
* Added
|
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
|
-
|
43
|
+
## 0.0.1 (2008.1.20)
|
34
44
|
|
35
45
|
* Initial coding
|
36
46
|
* N-sized arbitrary floating point gradients
|
data/Gemfile
ADDED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -7,126 +7,96 @@ Adam Collins [adam@m104.us]
|
|
7
7
|
|
8
8
|
## Description
|
9
9
|
|
10
|
-
|
11
|
-
linear motion between
|
12
|
-
gradients, piecewise functions, or even just
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
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
|
-
|
138
|
-
|
139
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
141
|
+
require 'rubygems'
|
142
|
+
require 'interpolate'
|
143
|
+
require 'color'
|
154
144
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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-
|
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
|
-
|
2
|
-
require '
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
require 'interpolate'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
desc 'Build the gem'
|
5
|
+
task :build do
|
6
|
+
system 'gem build interpolate.gemspec'
|
7
|
+
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
28
|
-
|
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
|
+
|