Ruboid 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +7 -0
- data/README +46 -0
- data/lib/ruboid.rb +2 -0
- data/lib/ruboid/ruboid.rb +220 -0
- data/lib/ruboid/vector.rb +98 -0
- data/rakefile.rb +48 -0
- data/test/test_vector.rb +71 -0
- metadata +52 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2006 Guilhem Vellut <guilhem.vellut+georuby@gmail.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
=GeoRuby
|
2
|
+
Ruboid is a ruby implementation of Craig Reynolds' Boid alogrithm (http://www.red3d.com/cwr/boids/), which realistically simulates the behaviour of a flock of creatures with a small set of simple rules. See Conrad Parker's page at http://www.vergenet.net/~conrad/boids/pseudocode.html for a more detailed explanation of how the simulation is performed.
|
3
|
+
|
4
|
+
===Operations
|
5
|
+
==== Basic operations
|
6
|
+
Currently, the library implements the 3 rules descibed by Reynolds. You could create a Flock and give it a few boids like this:
|
7
|
+
flock = Flock.new
|
8
|
+
1.upto(10) do |i|
|
9
|
+
flock << Boid.new(Vector.new([rand(300),rand(300)]),
|
10
|
+
Vector.new([rand(10)-5,rand(10)-5]))
|
11
|
+
end
|
12
|
+
Here I created a flock composed of 10 boids with a random starting position and an initial velocity between -5 and 5. The velocity can be understood as the distance the boid moves per time step.
|
13
|
+
|
14
|
+
To move the flock, you must call the method +update_and_move+ on the flock:
|
15
|
+
1.upto(100) do |i|
|
16
|
+
flock.update_and_move
|
17
|
+
end
|
18
|
+
The flock has just moved of 100 steps. You should perform some actions (like drawing the flock) between each update.
|
19
|
+
|
20
|
+
==== More operations
|
21
|
+
On top of these basic rules, some addition ones have been implemented:
|
22
|
+
- +scatter+: Scatters the flock, not as a reaction to a particular obstacle, but for example, as a reaction to a loud noise. It will break the cohesion. To reverse it, you should use +regroup+.
|
23
|
+
- +go_to+: Gives a goal to reach to the boids. Boids will have a tendency to go in the direction of this goal. Use +forget_goal+ to reverse it.
|
24
|
+
- +bound+: Encourages the boids to stay in a certain area (for example the drawing area). Use +move_freely+ to reverse it.
|
25
|
+
- +rebel+: Adds an element of chance to the movement of boids. Use +calm_down+ to reverse it.
|
26
|
+
|
27
|
+
==== Examples
|
28
|
+
I have included 2 examples in the distribution. One is stand-alone, the other necessitates RMagick and draws an animated GIF.
|
29
|
+
|
30
|
+
==== Vector class
|
31
|
+
To ease the computations, I have created a Vector class, which can be of any dimension. All the positions and velocities of the boids are in this format. You can create a vector from an array of value like this:
|
32
|
+
v = Vector.new(array)
|
33
|
+
And access it like that :
|
34
|
+
v[0]
|
35
|
+
v.each ...
|
36
|
+
|
37
|
+
|
38
|
+
===Installation
|
39
|
+
To install the latest version, just type :
|
40
|
+
gem install Ruboid
|
41
|
+
|
42
|
+
===License
|
43
|
+
Ruboid is released under the MIT license.
|
44
|
+
|
45
|
+
===Support
|
46
|
+
Any questions, enhancement proposals, bug notifications or corrections can be sent to mailto:guilhem.vellut+georuby@gmail.com.
|
data/lib/ruboid.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
module Ruboid
|
2
|
+
|
3
|
+
#Represents a flock of boids, which move together according to Reynolds' rules
|
4
|
+
class Flock
|
5
|
+
attr_accessor :boids, :velocity_limit, :safety_distance, :rebellion
|
6
|
+
attr_accessor :separation_factor, :cohesion_factor, :alignment_factor, :goal_factor
|
7
|
+
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def initialize(velocity_limit = 10,
|
11
|
+
safety_distance = 30,
|
12
|
+
separation_factor = 1.0,
|
13
|
+
cohesion_factor = 0.01,
|
14
|
+
alignment_factor = 0.125)
|
15
|
+
|
16
|
+
@boids = []
|
17
|
+
|
18
|
+
@velocity_limit = velocity_limit
|
19
|
+
@safety_distance = safety_distance
|
20
|
+
@separation_factor = separation_factor
|
21
|
+
@cohesion_factor = cohesion_factor
|
22
|
+
@alignment_factor = alignment_factor
|
23
|
+
@goal_factor = goal_factor
|
24
|
+
@rebellion = rebellion
|
25
|
+
|
26
|
+
#indicates if the flock must scatter or be grouped
|
27
|
+
@flock = 1
|
28
|
+
|
29
|
+
@goal=nil
|
30
|
+
@goal_factor = 0
|
31
|
+
|
32
|
+
@bound_corner1=nil
|
33
|
+
@bound_corner2=nil
|
34
|
+
@bound_encouragement = nil
|
35
|
+
|
36
|
+
@free_will=false
|
37
|
+
@rebellion = 0
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
#Adds a boid to the flock
|
42
|
+
def <<(boid)
|
43
|
+
@boids << boid
|
44
|
+
end
|
45
|
+
|
46
|
+
def each
|
47
|
+
boids.each {|b| yield b}
|
48
|
+
end
|
49
|
+
|
50
|
+
#Scatters the flock, not as a reaction to a particular obstacle, but for example, as a reaction to a loud noise. It will break the cohesion.
|
51
|
+
def scatter
|
52
|
+
@flock = -1
|
53
|
+
end
|
54
|
+
|
55
|
+
#Regroups the flock
|
56
|
+
def regroup
|
57
|
+
@flock = 1
|
58
|
+
end
|
59
|
+
|
60
|
+
#set a goal for the flock
|
61
|
+
def go_to(goal,goal_factor = 0.05)
|
62
|
+
@goal = goal
|
63
|
+
@goal_factor = goal_factor
|
64
|
+
end
|
65
|
+
|
66
|
+
#go back to meaningless wandering
|
67
|
+
def forget_goal
|
68
|
+
@goal = nil
|
69
|
+
end
|
70
|
+
|
71
|
+
#bound the boids
|
72
|
+
def bound(corner1,corner2,bound_encouragement = 10)
|
73
|
+
@bound_corner1 = corner1
|
74
|
+
@bound_corner2 = corner2
|
75
|
+
@bound_encouragement = bound_encouragement
|
76
|
+
end
|
77
|
+
|
78
|
+
def move_freely
|
79
|
+
@bound_corner1 = nil
|
80
|
+
@bound_corner2 = nil
|
81
|
+
@bound_encouragement = nil
|
82
|
+
end
|
83
|
+
|
84
|
+
#degree of
|
85
|
+
def rebel(rebellion = 5)
|
86
|
+
@free_will = true
|
87
|
+
@rebellion = rebellion
|
88
|
+
end
|
89
|
+
|
90
|
+
def calm_down
|
91
|
+
@free_will = false
|
92
|
+
end
|
93
|
+
|
94
|
+
#Main method of the class : calculates a variation of the velocity of each boid according to the position and velocity of the other boids. Finally update the velocity and the position of each boid.
|
95
|
+
def update_and_move
|
96
|
+
#calculate the new velocity : keep in a temp variable so all the boids get updated at the same time
|
97
|
+
velocity_update = Array.new
|
98
|
+
|
99
|
+
#calculate the variation of velocity of the boids
|
100
|
+
@boids.each do |boid|
|
101
|
+
d_vc = boid.cohesion(@boids).mul(@cohesion_factor * @flock)
|
102
|
+
d_vs = boid.separation(@boids,@safety_distance).mul(@separation_factor)
|
103
|
+
d_va = boid.alignment(@boids).mul(@alignment_factor)
|
104
|
+
|
105
|
+
d_v = d_vc.add(d_vs).add(d_va)
|
106
|
+
|
107
|
+
if @goal
|
108
|
+
d_vg = boid.go_to(@goal).mul(@goal_factor)
|
109
|
+
d_v.add(d_vg)
|
110
|
+
end
|
111
|
+
|
112
|
+
if @bound_corner1
|
113
|
+
d_vb = boid.bound(@bound_corner1,@bound_corner2,@bound_encouragement)
|
114
|
+
d_v.add(d_vb)
|
115
|
+
end
|
116
|
+
|
117
|
+
if @free_will
|
118
|
+
d_vf = Vector.new([rand(@rebellion),rand(@rebellion)])
|
119
|
+
d_v.add(d_vf)
|
120
|
+
end
|
121
|
+
|
122
|
+
velocity_update << d_v
|
123
|
+
end
|
124
|
+
|
125
|
+
#calculate a new velocity, limit the speed and update the position of the boids
|
126
|
+
@boids.each_with_index do |boid,index|
|
127
|
+
boid.velocity.add(velocity_update[index])
|
128
|
+
boid.limit(@velocity_limit)
|
129
|
+
boid.move
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#Represents a boid : You can think of it as a fish or a bird
|
136
|
+
class Boid
|
137
|
+
#position of the boid
|
138
|
+
attr_accessor :position
|
139
|
+
#distance done by the boid by unit of time chosen by the application using the lib
|
140
|
+
attr_accessor :velocity
|
141
|
+
|
142
|
+
#the initial parameters of the boid are the responsibility of the calling application
|
143
|
+
def initialize(position,velocity)
|
144
|
+
@position = position
|
145
|
+
@velocity = velocity
|
146
|
+
end
|
147
|
+
|
148
|
+
def dimension
|
149
|
+
@position.dimension
|
150
|
+
end
|
151
|
+
|
152
|
+
#Move a boid of one step
|
153
|
+
def move
|
154
|
+
@position.add(@velocity)
|
155
|
+
end
|
156
|
+
|
157
|
+
#Limits the velocity of the boid so it doesn't go supersonic.
|
158
|
+
def limit(velocity_limit)
|
159
|
+
velocity_norm = @velocity.norm
|
160
|
+
if velocity_norm > velocity_limit
|
161
|
+
@velocity.mul(velocity_limit / velocity_norm)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def go_to(goal)
|
166
|
+
goal.clone.sub(@position)
|
167
|
+
end
|
168
|
+
|
169
|
+
def bound(bound_corner1,bound_corner2,bound_encouragement)
|
170
|
+
v = Vector.zero(dimension)
|
171
|
+
v.each_index do |i|
|
172
|
+
if @position[i] < bound_corner1[i]
|
173
|
+
v[i] = bound_encouragement[i]
|
174
|
+
elsif @position[i] > bound_corner2[i]
|
175
|
+
v[i] = -bound_encouragement[i]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
v
|
179
|
+
end
|
180
|
+
|
181
|
+
#Moves the boid to the center of mass : Rule 1 of Conrad Parker's pseudo code
|
182
|
+
def cohesion(boids)
|
183
|
+
perceived_center = Vector.zero(dimension)
|
184
|
+
boids.each do |b|
|
185
|
+
if b != self
|
186
|
+
perceived_center.add(b.position)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
perceived_center.div(boids.length - 1).sub(@position)
|
190
|
+
end
|
191
|
+
|
192
|
+
#Moves the boid away from the other boids which are too close to it : Rule 2 of Conrad Parker's pseudo code
|
193
|
+
def separation(boids,distance)
|
194
|
+
c = Vector.zero(dimension)
|
195
|
+
boids.each do |b|
|
196
|
+
if b != self
|
197
|
+
if b.position.distance_to(@position) < distance
|
198
|
+
c.add(@position).sub(b.position)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
c
|
203
|
+
end
|
204
|
+
|
205
|
+
#Modifies the velocity so the boids have the tendency to go in the same direction : Rule 3 of Conrad Parker's pseudo code
|
206
|
+
def alignment(boids)
|
207
|
+
perceived_velocity = Vector.zero(dimension)
|
208
|
+
boids.each do |b|
|
209
|
+
if b != self
|
210
|
+
perceived_velocity.add(b.velocity)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
perceived_velocity.div(boids.length - 1).sub(@velocity)
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Ruboid
|
2
|
+
|
3
|
+
#Pure Ruby simplistic vector arithmetic class with no checks at all
|
4
|
+
#For speed, the NArray library could be considered (but some part is in C)
|
5
|
+
#Vectors taking part in operations are assumed to be of the same dimension
|
6
|
+
class Vector
|
7
|
+
attr_accessor :coords
|
8
|
+
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
def initialize(array)
|
12
|
+
@coords = array
|
13
|
+
end
|
14
|
+
|
15
|
+
def clone
|
16
|
+
Vector.new(@coords.clone)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.zero(dimension)
|
20
|
+
Vector.new(Array.new(dimension,0.0))
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
@coords.join(",")
|
25
|
+
end
|
26
|
+
|
27
|
+
def each
|
28
|
+
@coords.each { |c| yield c}
|
29
|
+
end
|
30
|
+
|
31
|
+
def each_index
|
32
|
+
0.upto(dimension-1) { |i| yield i}
|
33
|
+
end
|
34
|
+
|
35
|
+
def dimension
|
36
|
+
@coords.length
|
37
|
+
end
|
38
|
+
|
39
|
+
def [](n)
|
40
|
+
@coords[n]
|
41
|
+
end
|
42
|
+
|
43
|
+
def []=(n,value)
|
44
|
+
@coords[n]=value
|
45
|
+
end
|
46
|
+
|
47
|
+
#Calculates the euclidian distance between 2 vectors
|
48
|
+
def distance_to(vector)
|
49
|
+
diff = self.clone.sub(vector)
|
50
|
+
distance = diff.inject(0) do |distance_acc,value|
|
51
|
+
distance_acc + value**2
|
52
|
+
end
|
53
|
+
Math.sqrt(distance)
|
54
|
+
end
|
55
|
+
|
56
|
+
#Calculates the euclidian norm of the vector
|
57
|
+
def norm
|
58
|
+
distance_to(Vector.zero(dimension))
|
59
|
+
end
|
60
|
+
|
61
|
+
def add(vector)
|
62
|
+
@coords.each_index do |i|
|
63
|
+
@coords[i] += vector[i]
|
64
|
+
end
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def sub(vector)
|
69
|
+
@coords.each_index do |i|
|
70
|
+
@coords[i] -= vector[i]
|
71
|
+
end
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
def div(scalar)
|
76
|
+
@coords.each_index do |i|
|
77
|
+
@coords[i] /= scalar
|
78
|
+
end
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def mul(scalar)
|
83
|
+
@coords.each_index do |i|
|
84
|
+
@coords[i] *= scalar
|
85
|
+
end
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
#Tests for the equality of vectors
|
90
|
+
def ==(vector)
|
91
|
+
@coords.each_index do |i|
|
92
|
+
return false if @coords[i] != vector[i]
|
93
|
+
end
|
94
|
+
true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
data/rakefile.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc "Run the tests"
|
9
|
+
Rake::TestTask::new do |t|
|
10
|
+
t.test_files = FileList['test/test*.rb']
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Generate the documentation"
|
15
|
+
Rake::RDocTask::new do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'ruboid-doc/'
|
17
|
+
rdoc.title = "Ruboid Documentation"
|
18
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
19
|
+
rdoc.rdoc_files.include('README')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
spec = Gem::Specification::new do |s|
|
24
|
+
s.platform = Gem::Platform::RUBY
|
25
|
+
|
26
|
+
s.name = 'Ruboid'
|
27
|
+
s.version = "0.0.1"
|
28
|
+
s.summary = "Ruby Boid Library"
|
29
|
+
s.description ="Ruboid is a ruby implementation of Craig Reynolds' Boid alogrithm (http://www.red3d.com/cwr/boids/), which realistically simulates the behaviour of a flock of creatures with a small set of simple rules."
|
30
|
+
s.author = 'Guilhem Vellut'
|
31
|
+
s.email = 'guilhem.vellut+georuby@gmail.com'
|
32
|
+
s.homepage = "http://thepochisuperstarmegashow.com"
|
33
|
+
|
34
|
+
s.requirements << 'none'
|
35
|
+
s.require_path = 'lib'
|
36
|
+
s.files = FileList["lib/**/*.rb", "test/**/*.rb", "README","MIT-LICENSE","rakefile.rb"]
|
37
|
+
s.test_files = FileList['test/test*.rb']
|
38
|
+
|
39
|
+
s.has_rdoc = true
|
40
|
+
s.extra_rdoc_files = ["README"]
|
41
|
+
s.rdoc_options.concat ['--main', 'README']
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Package the library as a gem"
|
45
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
46
|
+
pkg.need_zip = true
|
47
|
+
pkg.need_tar = true
|
48
|
+
end
|
data/test/test_vector.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'ruboid'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
include Ruboid
|
7
|
+
|
8
|
+
class TestVector < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_add
|
11
|
+
a = Vector.new([1,2])
|
12
|
+
b = Vector.new([3,4])
|
13
|
+
assert_equal([4,6],a.add(b).coords)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_sub
|
17
|
+
a = Vector.new([1.5,2.6])
|
18
|
+
b = Vector.new([3.1,4.7])
|
19
|
+
assert_equal([-1.6,-2.1],a.sub(b).coords)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_mul
|
23
|
+
a = Vector.new([1.5,2.6])
|
24
|
+
assert_equal([3.0,5.2],a.mul(2).coords)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_div
|
28
|
+
a = Vector.new([1.5,2.6])
|
29
|
+
assert_equal([0.75,1.3],a.div(2).coords)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_equal
|
33
|
+
a = Vector.new([1.5,2.6])
|
34
|
+
b = Vector.new([3.1,4.7])
|
35
|
+
assert(a != b)
|
36
|
+
|
37
|
+
c = Vector.new([1.5,2.6])
|
38
|
+
assert(a == c)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_dimension
|
42
|
+
assert_equal(2,Vector.new([1.5,2.6]).dimension)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_modification
|
46
|
+
a = Vector.new([1.5,2.6])
|
47
|
+
a[0] = 2
|
48
|
+
|
49
|
+
assert_equal([2,2.6],a.coords)
|
50
|
+
assert_equal(2,a[0])
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_zero
|
54
|
+
a = Vector.zero(2)
|
55
|
+
assert_equal(2,a.dimension)
|
56
|
+
assert_equal([0,0],a.coords)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_norm
|
60
|
+
a = Vector.new([3,4])
|
61
|
+
assert_equal(5,a.norm)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_distance_to
|
65
|
+
a = Vector.new([2,3])
|
66
|
+
b = Vector.new([2,9])
|
67
|
+
|
68
|
+
assert_equal(6,a.distance_to(b))
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: Ruboid
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2006-05-11 00:00:00 +05:00
|
8
|
+
summary: Ruby Boid Library
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: guilhem.vellut+georuby@gmail.com
|
12
|
+
homepage: http://thepochisuperstarmegashow.com
|
13
|
+
rubyforge_project:
|
14
|
+
description: Ruboid is a ruby implementation of Craig Reynolds' Boid alogrithm (http://www.red3d.com/cwr/boids/), which realistically simulates the behaviour of a flock of creatures with a small set of simple rules.
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Guilhem Vellut
|
30
|
+
files:
|
31
|
+
- lib/ruboid.rb
|
32
|
+
- lib/ruboid/ruboid.rb
|
33
|
+
- lib/ruboid/vector.rb
|
34
|
+
- test/test_vector.rb
|
35
|
+
- README
|
36
|
+
- MIT-LICENSE
|
37
|
+
- rakefile.rb
|
38
|
+
test_files:
|
39
|
+
- test/test_vector.rb
|
40
|
+
rdoc_options:
|
41
|
+
- --main
|
42
|
+
- README
|
43
|
+
extra_rdoc_files:
|
44
|
+
- README
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
requirements:
|
50
|
+
- none
|
51
|
+
dependencies: []
|
52
|
+
|