vector2d 1.1.1 → 1.1.2
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/Rakefile +6 -0
- data/lib/vector2d/version.rb +1 -1
- data/lib/vector2d.rb +13 -6
- data/spec/lib/vector2d_spec.rb +323 -0
- data/spec/spec_helper.rb +1 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 682557f0f29ae91579f654ea0d158b294f34842a
|
4
|
+
data.tar.gz: 3c06461f5a55f84d40c2d9a6ccaeb2c588180b5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be219090e10f35d43eee02aafb26008dac0763cc206d748e51169eff6f5d208a8afbb058e489f150584828ee2b58abb665595514bec5562d12fbe2f5ae69ed6a
|
7
|
+
data.tar.gz: 46aba4ea456801fe4cf7403a431ef3a754424623004faec67b7c9290042af806dbd8195c6c67bcd70d9f01560228793a8938a5e9474e1c292eb35dd99946551f
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
data/lib/vector2d/version.rb
CHANGED
data/lib/vector2d.rb
CHANGED
@@ -29,10 +29,16 @@ class Vector2d
|
|
29
29
|
elsif args[0].kind_of?(Vector2d)
|
30
30
|
args = [args[0].x, args[0].y]
|
31
31
|
elsif args[0].kind_of?(Hash)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
if args[0].has_key?(:y)
|
33
|
+
args[1] = args[0][:y]
|
34
|
+
elsif args[0].has_key?("y")
|
35
|
+
args[1] = args[0]["y"]
|
36
|
+
end
|
37
|
+
if args[0].has_key?(:x)
|
38
|
+
args[0] = args[0][:x]
|
39
|
+
elsif args[0].has_key?("x")
|
40
|
+
args[0] = args[0]["x"]
|
41
|
+
end
|
36
42
|
else
|
37
43
|
args = [args[0], args[0]]
|
38
44
|
end
|
@@ -81,6 +87,7 @@ class Vector2d
|
|
81
87
|
end
|
82
88
|
|
83
89
|
def normalized?
|
90
|
+
self.length == 1.0
|
84
91
|
end
|
85
92
|
|
86
93
|
# Rounds coordinates to nearest integer.
|
@@ -150,7 +157,7 @@ class Vector2d
|
|
150
157
|
# sets the length under the given value. Nothing is done if
|
151
158
|
# the vector is already shorter.
|
152
159
|
def truncate(max)
|
153
|
-
length =
|
160
|
+
self.length = [max, self.length].min
|
154
161
|
self
|
155
162
|
end
|
156
163
|
|
@@ -178,7 +185,7 @@ class Vector2d
|
|
178
185
|
|
179
186
|
# cross product of two vectors
|
180
187
|
def self.cross_product(vector1, vector2)
|
181
|
-
|
188
|
+
vector1.x * vector2.y - vector1.y * vector2.x
|
182
189
|
end
|
183
190
|
|
184
191
|
# dot product of two vectors
|
@@ -0,0 +1,323 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vector2d do
|
4
|
+
subject(:vector) { Vector2d.new(2, 3) }
|
5
|
+
|
6
|
+
shared_examples "a vector constructor" do |x, y|
|
7
|
+
it "receives the x and y properties" do
|
8
|
+
expect(subject.x).to eq(x)
|
9
|
+
expect(subject.y).to eq(y)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "new" do
|
14
|
+
context "with two arguments, fixnum" do
|
15
|
+
subject(:vector) { Vector2d.new(1, 2) }
|
16
|
+
it_behaves_like "a vector constructor", [1, 2]
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with two arguments, float" do
|
20
|
+
subject(:vector) { Vector2d.new(1.0, 2.0) }
|
21
|
+
it_behaves_like "a vector constructor", [1.0, 2.0]
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with string argument, fixnum" do
|
25
|
+
subject(:vector) { Vector2d.new("1x2") }
|
26
|
+
it_behaves_like "a vector constructor", [1, 2]
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with string argument, float" do
|
30
|
+
subject(:vector) { Vector2d.new("1.0x2.0") }
|
31
|
+
it_behaves_like "a vector constructor", [1.0, 2.0]
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with array argument" do
|
35
|
+
subject(:vector) { Vector2d.new([1, 2]) }
|
36
|
+
it_behaves_like "a vector constructor", [1, 2]
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with hash argument, symbol keys" do
|
40
|
+
subject(:vector) { Vector2d.new({:x => 1, :y => 2}) }
|
41
|
+
it_behaves_like "a vector constructor", [1, 2]
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with hash argument, string keys" do
|
45
|
+
subject(:vector) { Vector2d.new({'x' => 1, 'y' => 2}) }
|
46
|
+
it_behaves_like "a vector constructor", [1, 2]
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with vector argument" do
|
50
|
+
subject(:vector) { Vector2d.new(Vector2d.new(1, 2)) }
|
51
|
+
it_behaves_like "a vector constructor", [1, 2]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe ".cross_product" do
|
56
|
+
let(:v1) { Vector2d.new(2, 3) }
|
57
|
+
let(:v2) { Vector2d.new(4, 5) }
|
58
|
+
it "calculates the cross product between two vectors" do
|
59
|
+
expect(Vector2d.cross_product(v1, v2)).to be_within(0.0001).of(-2.0)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe ".dot_product" do
|
64
|
+
let(:v1) { Vector2d.new(2, 3) }
|
65
|
+
let(:v2) { Vector2d.new(4, 5) }
|
66
|
+
it "calculates the dot product between two vectors" do
|
67
|
+
expect(Vector2d.dot_product(v1, v2)).to be_within(0.0001).of(23.0)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe ".angle_between" do
|
72
|
+
let(:v1) { Vector2d.new(2, 3) }
|
73
|
+
let(:v2) { Vector2d.new(4, 5) }
|
74
|
+
it "calculates the angle between two vectors" do
|
75
|
+
expect(Vector2d.angle_between(v1, v2)).to be_within(0.0001).of(0.0867)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#==" do
|
80
|
+
subject { vector == comp }
|
81
|
+
|
82
|
+
context "with both arguments equal" do
|
83
|
+
let(:comp) { Vector2d.new(2, 3) }
|
84
|
+
it { should be_true }
|
85
|
+
end
|
86
|
+
|
87
|
+
context "with x differing" do
|
88
|
+
let(:comp) { Vector2d.new(3, 3) }
|
89
|
+
it { should be_false }
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with y differing" do
|
93
|
+
let(:comp) { Vector2d.new(2, 4) }
|
94
|
+
it { should be_false }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#to_s" do
|
99
|
+
it "renders a string" do
|
100
|
+
expect(vector.to_s).to eq('2.0x3.0')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#length" do
|
105
|
+
it "calculates the length" do
|
106
|
+
expect(vector.length).to be_within(0.0001).of(3.6055)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#length_squared" do
|
111
|
+
it "calculates the squared length" do
|
112
|
+
expect(vector.length_squared).to be_within(0.0001).of(13.0)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#length=" do
|
117
|
+
it "modifies the vector length" do
|
118
|
+
vector.length = 2.0
|
119
|
+
expect(vector.length).to be_within(0.0001).of(2.0)
|
120
|
+
expect(vector.x).to be_within(0.0001).of(1.1094)
|
121
|
+
expect(vector.y).to be_within(0.0001).of(1.6641)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "#normalize" do
|
126
|
+
it "normalizes the vector" do
|
127
|
+
expect(vector.normalize.x).to be_within(0.0001).of(0.5547)
|
128
|
+
expect(vector.normalize.y).to be_within(0.0001).of(0.8320)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#normalize!" do
|
133
|
+
it "normalizes the vector in place" do
|
134
|
+
vector.normalize!
|
135
|
+
expect(vector).to eq(vector.normalize)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#round" do
|
140
|
+
subject(:vector) { Vector2d.new(2.3, 3.6) }
|
141
|
+
it "rounds the vector" do
|
142
|
+
expect(vector.round).to eq(Vector2d.new(2, 4))
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#round!" do
|
147
|
+
subject(:vector) { Vector2d.new(2.3, 3.6) }
|
148
|
+
it "rounds the vector in place" do
|
149
|
+
vector.round!
|
150
|
+
expect(vector).to eq(Vector2d.new(2, 4))
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "*" do
|
155
|
+
context "with vector" do
|
156
|
+
subject(:vector) { Vector2d.new(2, 3) * Vector2d.new(3, 4) }
|
157
|
+
it "multiplies the vectors" do
|
158
|
+
expect(vector).to eq(Vector2d.new(6, 12))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
context "with number" do
|
162
|
+
subject(:vector) { Vector2d.new(2, 3) * 3 }
|
163
|
+
it "multiplies both members" do
|
164
|
+
expect(vector).to eq(Vector2d.new(6, 9))
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "/" do
|
170
|
+
context "with vector" do
|
171
|
+
subject(:vector) { Vector2d.new(6, 12) / Vector2d.new(2, 3) }
|
172
|
+
it "divides the vectors" do
|
173
|
+
expect(vector).to eq(Vector2d.new(3, 4))
|
174
|
+
end
|
175
|
+
end
|
176
|
+
context "with number" do
|
177
|
+
subject(:vector) { Vector2d.new(6, 12) / 3 }
|
178
|
+
it "divides both members" do
|
179
|
+
expect(vector).to eq(Vector2d.new(2, 4))
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "+" do
|
185
|
+
context "with vector" do
|
186
|
+
subject(:vector) { Vector2d.new(2, 3) + Vector2d.new(3, 4) }
|
187
|
+
it "adds the vectors" do
|
188
|
+
expect(vector).to eq(Vector2d.new(5, 7))
|
189
|
+
end
|
190
|
+
end
|
191
|
+
context "with number" do
|
192
|
+
subject(:vector) { Vector2d.new(2, 3) + 2 }
|
193
|
+
it "adds to both members" do
|
194
|
+
expect(vector).to eq(Vector2d.new(4, 5))
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "-" do
|
200
|
+
context "with vector" do
|
201
|
+
subject(:vector) { Vector2d.new(3, 5) - Vector2d.new(1, 2) }
|
202
|
+
it "subtracts the vectors" do
|
203
|
+
expect(vector).to eq(Vector2d.new(2, 3))
|
204
|
+
end
|
205
|
+
end
|
206
|
+
context "with number" do
|
207
|
+
subject(:vector) { Vector2d.new(2, 3) - 2 }
|
208
|
+
it "subtracts from both members" do
|
209
|
+
expect(vector).to eq(Vector2d.new(0, 1))
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "#perpendicular" do
|
215
|
+
it "returns a perpendicular vector" do
|
216
|
+
expect(vector.perpendicular).to eq(Vector2d.new(-3, 2))
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "#distance" do
|
221
|
+
let(:comp) { Vector2d.new(3, 4) }
|
222
|
+
it "returns the distance between two vectors" do
|
223
|
+
expect(vector.distance(comp)).to be_within(0.0001).of(1.4142)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
describe "#distance_sq" do
|
228
|
+
let(:comp) { Vector2d.new(5, 6) }
|
229
|
+
it "returns the squared distance between two vectors" do
|
230
|
+
expect(vector.distance_sq(comp)).to be_within(0.0001).of(18.0)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "#angle" do
|
235
|
+
it "returns the angle" do
|
236
|
+
expect(vector.angle).to be_within(0.0001).of(0.9827)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "#truncate" do
|
241
|
+
context "when argument is longer than length" do
|
242
|
+
let(:arg) { 5.0 }
|
243
|
+
it "does not change the length" do
|
244
|
+
expect(vector.truncate(arg).length).to be_within(0.0001).of(3.6055)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
context "when argument is shorter than length" do
|
248
|
+
let(:arg) { 2.5 }
|
249
|
+
it "changes the length" do
|
250
|
+
expect(vector.truncate(arg).length).to be_within(0.0001).of(arg)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "#reverse" do
|
256
|
+
it "reverses the vector" do
|
257
|
+
expect(vector.reverse).to eq(Vector2d.new(-2, -3))
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
describe "#cross_product" do
|
262
|
+
let(:comp) { Vector2d.new(3, 4) }
|
263
|
+
it "calulates the cross product" do
|
264
|
+
expect(vector.cross_product(comp)).to eq(Vector2d.cross_product(vector, comp))
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
describe "#dot_product" do
|
269
|
+
let(:comp) { Vector2d.new(3, 4) }
|
270
|
+
it "calulates the dot product" do
|
271
|
+
expect(vector.dot_product(comp)).to eq(Vector2d.dot_product(vector, comp))
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe "#angle_between" do
|
276
|
+
let(:comp) { Vector2d.new(3, 4) }
|
277
|
+
it "calculates the angle between vectors" do
|
278
|
+
expect(vector.angle_between(comp)).to eq(Vector2d.angle_between(vector, comp))
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "#contrain_both" do
|
283
|
+
let(:original) { Vector2d.new(300, 300) }
|
284
|
+
subject(:vector) { original.constrain_both(comp) }
|
285
|
+
|
286
|
+
context "when scaling by height" do
|
287
|
+
let(:comp) { Vector2d.new(200, 150) }
|
288
|
+
it "should fit within the other vector" do
|
289
|
+
expect(vector.x).to be_within(0.0001).of(150)
|
290
|
+
expect(vector.y).to be_within(0.0001).of(150)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context "when scaling by width" do
|
295
|
+
let(:comp) { Vector2d.new(150, 200) }
|
296
|
+
it "should fit within the other vector" do
|
297
|
+
expect(vector.x).to be_within(0.0001).of(150)
|
298
|
+
expect(vector.y).to be_within(0.0001).of(150)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
describe "#contrain_one" do
|
304
|
+
let(:original) { Vector2d.new(300, 300) }
|
305
|
+
subject(:vector) { original.constrain_one(comp) }
|
306
|
+
|
307
|
+
context "when width is largest" do
|
308
|
+
let(:comp) { Vector2d.new(200, 150) }
|
309
|
+
it "should be the same width" do
|
310
|
+
expect(vector.x).to be_within(0.0001).of(200)
|
311
|
+
expect(vector.y).to be_within(0.0001).of(200)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "when height is largest" do
|
316
|
+
let(:comp) { Vector2d.new(150, 200) }
|
317
|
+
it "should be the same height" do
|
318
|
+
expect(vector.x).to be_within(0.0001).of(200)
|
319
|
+
expect(vector.y).to be_within(0.0001).of(200)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'vector2d'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vector2d
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Inge Jørgensen
|
@@ -55,6 +55,8 @@ files:
|
|
55
55
|
- VERSION
|
56
56
|
- lib/vector2d.rb
|
57
57
|
- lib/vector2d/version.rb
|
58
|
+
- spec/lib/vector2d_spec.rb
|
59
|
+
- spec/spec_helper.rb
|
58
60
|
- vector2d.gemspec
|
59
61
|
homepage: http://github.com/elektronaut/vector2d
|
60
62
|
licenses:
|
@@ -80,4 +82,6 @@ rubygems_version: 2.2.0
|
|
80
82
|
signing_key:
|
81
83
|
specification_version: 4
|
82
84
|
summary: Library for handling two-dimensional vectors
|
83
|
-
test_files:
|
85
|
+
test_files:
|
86
|
+
- spec/lib/vector2d_spec.rb
|
87
|
+
- spec/spec_helper.rb
|