vector2d 2.2.3 → 2.2.4
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 +5 -5
- data/.github/workflows/build.yml +41 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +26 -0
- data/.travis.yml +6 -7
- data/Gemfile +12 -4
- data/Gemfile.lock +62 -28
- data/README.md +9 -4
- data/Rakefile +6 -2
- data/lib/vector2d/calculations.rb +10 -26
- data/lib/vector2d/coercions.rb +1 -10
- data/lib/vector2d/fitting.rb +22 -18
- data/lib/vector2d/properties.rb +4 -11
- data/lib/vector2d/transformations.rb +6 -17
- data/lib/vector2d/version.rb +2 -2
- data/lib/vector2d.rb +25 -51
- data/spec/lib/vector2d/calculations_spec.rb +29 -5
- data/spec/lib/vector2d/coercions_spec.rb +19 -15
- data/spec/lib/vector2d/fitting_spec.rb +26 -32
- data/spec/lib/vector2d/properties_spec.rb +8 -4
- data/spec/lib/vector2d/transformations_spec.rb +56 -18
- data/spec/lib/vector2d_spec.rb +39 -22
- data/spec/spec_helper.rb +5 -4
- data/vector2d.gemspec +12 -17
- metadata +14 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fc16e15dbb07e3fe138a13fdc3cc8edd6c1369e53bf337a47b8034359b826fa2
|
4
|
+
data.tar.gz: b4077e6730cd248749960253a22b78a89a9f876ebfd5ca4a097d42c44c246aa7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a93da54adf875ed88cc5f2fc7ab31a8f919d8352ddf2ee7259290ac2ed0a160b8edbf178f40788fd0e1f57c1c125877a20b6f3bbc3f8320d3929efb64da6862c
|
7
|
+
data.tar.gz: d1ed6fab76e6c0cd4c74104ed997927fb377dad0fd75790f576777392fc73d235b5e828a73b2d7c3bc2b00c54246c21a48fc36539f00870eb23c07767a80b477
|
@@ -0,0 +1,41 @@
|
|
1
|
+
---
|
2
|
+
name: Build
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- main
|
7
|
+
- develop
|
8
|
+
pull_request:
|
9
|
+
jobs:
|
10
|
+
rubocop-test:
|
11
|
+
name: Rubocop
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v1
|
15
|
+
- uses: ruby/setup-ruby@v1
|
16
|
+
with:
|
17
|
+
ruby-version: 3.2
|
18
|
+
bundler-cache: true
|
19
|
+
- name: Check code
|
20
|
+
run: bundle exec rubocop
|
21
|
+
|
22
|
+
rspec-test:
|
23
|
+
name: RSpec
|
24
|
+
runs-on: ubuntu-latest
|
25
|
+
strategy:
|
26
|
+
matrix:
|
27
|
+
ruby: ['2.7', '3.0', '3.1', '3.2']
|
28
|
+
steps:
|
29
|
+
- uses: actions/checkout@v1
|
30
|
+
- uses: ruby/setup-ruby@v1
|
31
|
+
with:
|
32
|
+
ruby-version: ${{ matrix.ruby }}
|
33
|
+
bundler-cache: true
|
34
|
+
- name: Run tests
|
35
|
+
run: bundle exec rspec
|
36
|
+
- name: Send results to Code Climate
|
37
|
+
uses: paambaati/codeclimate-action@v3.2.0
|
38
|
+
env:
|
39
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
40
|
+
with:
|
41
|
+
coverageCommand: ls
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rake
|
3
|
+
- rubocop-rspec
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
NewCops: enable
|
7
|
+
TargetRubyVersion: 2.7
|
8
|
+
|
9
|
+
Style/StringLiterals:
|
10
|
+
EnforcedStyle: double_quotes
|
11
|
+
|
12
|
+
Style/Documentation:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
Metrics/BlockLength:
|
16
|
+
Exclude:
|
17
|
+
- "*.gemspec"
|
18
|
+
- "**/*_spec.rb"
|
19
|
+
|
20
|
+
Naming/MethodName:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Naming/MethodParameterName:
|
24
|
+
AllowedNames:
|
25
|
+
- "x"
|
26
|
+
- "y"
|
data/.travis.yml
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
addons:
|
2
|
-
code_climate:
|
3
|
-
repo_token: bf65d5faaf8dc80d0d58f2e7c663323734237c0a3e91cba16b1c556a98b0971e
|
4
1
|
language: ruby
|
2
|
+
sudo: false
|
3
|
+
cache: bundler
|
4
|
+
dist: bionic
|
5
5
|
rvm:
|
6
|
-
-
|
7
|
-
- 2.
|
8
|
-
- 2.1
|
9
|
-
- 2.2.2
|
6
|
+
- 2.4.5
|
7
|
+
- 2.6.3
|
8
|
+
- 2.7.1
|
10
9
|
script:
|
11
10
|
- bundle exec rspec spec
|
data/Gemfile
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
5
|
-
group :test do
|
6
|
-
gem "
|
7
|
-
|
7
|
+
group :development, :test do
|
8
|
+
gem "rake"
|
9
|
+
gem "rspec", "~> 3.8"
|
10
|
+
gem "rspec-its", "~> 1.3"
|
11
|
+
gem "rubocop", require: false
|
12
|
+
gem "rubocop-rake", require: false
|
13
|
+
gem "rubocop-rspec", require: false
|
14
|
+
gem "simplecov", "~> 0.17.1"
|
15
|
+
end
|
data/Gemfile.lock
CHANGED
@@ -1,43 +1,77 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
vector2d (2.2.
|
5
|
-
contracts (~> 0.9.0)
|
4
|
+
vector2d (2.2.4)
|
6
5
|
|
7
6
|
GEM
|
8
|
-
remote:
|
7
|
+
remote: https://rubygems.org/
|
9
8
|
specs:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
rspec
|
22
|
-
rspec-
|
23
|
-
|
9
|
+
ast (2.4.2)
|
10
|
+
diff-lcs (1.5.0)
|
11
|
+
docile (1.4.0)
|
12
|
+
json (2.6.3)
|
13
|
+
parallel (1.22.1)
|
14
|
+
parser (3.2.0.0)
|
15
|
+
ast (~> 2.4.1)
|
16
|
+
rainbow (3.1.1)
|
17
|
+
rake (13.0.6)
|
18
|
+
regexp_parser (2.6.2)
|
19
|
+
rexml (3.2.5)
|
20
|
+
rspec (3.12.0)
|
21
|
+
rspec-core (~> 3.12.0)
|
22
|
+
rspec-expectations (~> 3.12.0)
|
23
|
+
rspec-mocks (~> 3.12.0)
|
24
|
+
rspec-core (3.12.1)
|
25
|
+
rspec-support (~> 3.12.0)
|
26
|
+
rspec-expectations (3.12.2)
|
24
27
|
diff-lcs (>= 1.2.0, < 2.0)
|
25
|
-
rspec-support (~> 3.
|
26
|
-
rspec-
|
28
|
+
rspec-support (~> 3.12.0)
|
29
|
+
rspec-its (1.3.0)
|
30
|
+
rspec-core (>= 3.0.0)
|
31
|
+
rspec-expectations (>= 3.0.0)
|
32
|
+
rspec-mocks (3.12.3)
|
27
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
-
rspec-support (~> 3.
|
29
|
-
rspec-support (3.
|
30
|
-
|
31
|
-
|
32
|
-
|
34
|
+
rspec-support (~> 3.12.0)
|
35
|
+
rspec-support (3.12.0)
|
36
|
+
rubocop (1.44.1)
|
37
|
+
json (~> 2.3)
|
38
|
+
parallel (~> 1.10)
|
39
|
+
parser (>= 3.2.0.0)
|
40
|
+
rainbow (>= 2.2.2, < 4.0)
|
41
|
+
regexp_parser (>= 1.8, < 3.0)
|
42
|
+
rexml (>= 3.2.5, < 4.0)
|
43
|
+
rubocop-ast (>= 1.24.1, < 2.0)
|
44
|
+
ruby-progressbar (~> 1.7)
|
45
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
46
|
+
rubocop-ast (1.24.1)
|
47
|
+
parser (>= 3.1.1.0)
|
48
|
+
rubocop-capybara (2.17.0)
|
49
|
+
rubocop (~> 1.41)
|
50
|
+
rubocop-rake (0.6.0)
|
51
|
+
rubocop (~> 1.0)
|
52
|
+
rubocop-rspec (2.18.1)
|
53
|
+
rubocop (~> 1.33)
|
54
|
+
rubocop-capybara (~> 2.17)
|
55
|
+
ruby-progressbar (1.11.0)
|
56
|
+
simplecov (0.17.1)
|
57
|
+
docile (~> 1.1)
|
58
|
+
json (>= 1.8, < 3)
|
33
59
|
simplecov-html (~> 0.10.0)
|
34
|
-
simplecov-html (0.10.
|
60
|
+
simplecov-html (0.10.2)
|
61
|
+
unicode-display_width (2.4.2)
|
35
62
|
|
36
63
|
PLATFORMS
|
37
64
|
ruby
|
38
65
|
|
39
66
|
DEPENDENCIES
|
40
|
-
|
41
|
-
|
42
|
-
rspec (~> 3
|
67
|
+
rake
|
68
|
+
rspec (~> 3.8)
|
69
|
+
rspec-its (~> 1.3)
|
70
|
+
rubocop
|
71
|
+
rubocop-rake
|
72
|
+
rubocop-rspec
|
73
|
+
simplecov (~> 0.17.1)
|
43
74
|
vector2d!
|
75
|
+
|
76
|
+
BUNDLED WITH
|
77
|
+
2.2.3
|
data/README.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
[](https://rubygems.org/gems/vector2d)
|
2
|
+

|
3
|
+
[](https://codeclimate.com/github/elektronaut/vector2d)
|
4
|
+
[](https://codeclimate.com/github/elektronaut/vector2d)
|
5
|
+
|
6
|
+
# Vector2d
|
2
7
|
|
3
8
|
Vector2d handles two-dimensional coordinates and vectors.
|
4
9
|
Vectors are immutable, meaning this is a purely functional library.
|
@@ -24,10 +29,10 @@ Vector2d.parse("50x70") # => Vector2d(50,70)
|
|
24
29
|
|
25
30
|
## Documentation
|
26
31
|
|
27
|
-
[API documentation](
|
32
|
+
[API documentation](https://rdoc.info/github/elektronaut/vector2d/main)
|
28
33
|
|
29
34
|
## License
|
30
35
|
|
31
|
-
Copyright (c) 2006-
|
36
|
+
Copyright (c) 2006-2019 Inge Jørgensen
|
32
37
|
|
33
|
-
Vector2d is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
38
|
+
Vector2d is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,21 +1,16 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Vector2d
|
4
4
|
module Calculations
|
5
|
-
include Contracts
|
6
|
-
|
7
5
|
module ClassMethods
|
8
|
-
include Contracts
|
9
|
-
|
10
6
|
# Calculates cross product of two vectors.
|
11
7
|
#
|
12
8
|
# v1 = Vector2d(2, 1)
|
13
9
|
# v2 = Vector2d(2, 3)
|
14
10
|
# Vector2d.cross_product(v1, v2) # => 4
|
15
11
|
#
|
16
|
-
Contract Vector2d, Vector2d => Num
|
17
12
|
def cross_product(vector1, vector2)
|
18
|
-
vector1.x * vector2.y - vector1.y * vector2.x
|
13
|
+
(vector1.x * vector2.y) - (vector1.y * vector2.x)
|
19
14
|
end
|
20
15
|
|
21
16
|
# Calculates dot product of two vectors.
|
@@ -24,9 +19,8 @@ class Vector2d
|
|
24
19
|
# v2 = Vector2d(2, 3)
|
25
20
|
# Vector2d.dot_product(v1, v2) # => 10
|
26
21
|
#
|
27
|
-
Contract Vector2d, Vector2d => Num
|
28
22
|
def dot_product(vector1, vector2)
|
29
|
-
vector1.x * vector2.x + vector1.y * vector2.y
|
23
|
+
(vector1.x * vector2.x) + (vector1.y * vector2.y)
|
30
24
|
end
|
31
25
|
|
32
26
|
# Calculates angle between two vectors in radians.
|
@@ -35,11 +29,10 @@ class Vector2d
|
|
35
29
|
# v2 = Vector2d(4, 5)
|
36
30
|
# Vector2d.angle_between(v1, v2) # => 0.0867..
|
37
31
|
#
|
38
|
-
Contract Vector2d, Vector2d => Num
|
39
32
|
def angle_between(vector1, vector2)
|
40
33
|
one = vector1.normalized? ? vector1 : vector1.normalize
|
41
34
|
two = vector2.normalized? ? vector2 : vector2.normalize
|
42
|
-
Math.acos(
|
35
|
+
Math.acos(dot_product(one, two))
|
43
36
|
end
|
44
37
|
end
|
45
38
|
|
@@ -48,7 +41,6 @@ class Vector2d
|
|
48
41
|
# Vector2d(1, 2) * Vector2d(2, 3) # => Vector2d(2, 6)
|
49
42
|
# Vector2d(1, 2) * 2 # => Vector2d(2, 4)
|
50
43
|
#
|
51
|
-
Contract VectorLike => Vector2d
|
52
44
|
def *(other)
|
53
45
|
calculate_each(:*, other)
|
54
46
|
end
|
@@ -58,7 +50,6 @@ class Vector2d
|
|
58
50
|
# Vector2d(4, 2) / Vector2d(2, 1) # => Vector2d(2, 2)
|
59
51
|
# Vector2d(4, 2) / 2 # => Vector2d(2, 1)
|
60
52
|
#
|
61
|
-
Contract VectorLike => Vector2d
|
62
53
|
def /(other)
|
63
54
|
calculate_each(:/, other)
|
64
55
|
end
|
@@ -68,7 +59,6 @@ class Vector2d
|
|
68
59
|
# Vector2d(1, 2) + Vector2d(2, 3) # => Vector2d(3, 5)
|
69
60
|
# Vector2d(1, 2) + 2 # => Vector2d(3, 4)
|
70
61
|
#
|
71
|
-
Contract VectorLike => Vector2d
|
72
62
|
def +(other)
|
73
63
|
calculate_each(:+, other)
|
74
64
|
end
|
@@ -78,7 +68,6 @@ class Vector2d
|
|
78
68
|
# Vector2d(2, 3) - Vector2d(2, 1) # => Vector2d(0, 2)
|
79
69
|
# Vector2d(4, 3) - 1 # => Vector2d(3, 2)
|
80
70
|
#
|
81
|
-
Contract VectorLike => Vector2d
|
82
71
|
def -(other)
|
83
72
|
calculate_each(:-, other)
|
84
73
|
end
|
@@ -89,7 +78,6 @@ class Vector2d
|
|
89
78
|
# v2 = Vector2d(5, 6)
|
90
79
|
# v1.distance(v2) # => 1.4142..
|
91
80
|
#
|
92
|
-
Contract VectorLike => Num
|
93
81
|
def distance(other)
|
94
82
|
Math.sqrt(squared_distance(other))
|
95
83
|
end
|
@@ -100,12 +88,11 @@ class Vector2d
|
|
100
88
|
# v2 = Vector2d(5, 6)
|
101
89
|
# v1.distance_squared(v2) # => 18
|
102
90
|
#
|
103
|
-
Contract VectorLike => Num
|
104
91
|
def squared_distance(other)
|
105
|
-
v,
|
92
|
+
v, = coerce(other)
|
106
93
|
dx = v.x - x
|
107
94
|
dy = v.y - y
|
108
|
-
dx * dx + dy * dy
|
95
|
+
(dx * dx) + (dy * dy)
|
109
96
|
end
|
110
97
|
|
111
98
|
# Dot product of this vector and another vector.
|
@@ -114,9 +101,8 @@ class Vector2d
|
|
114
101
|
# v2 = Vector2d(2, 3)
|
115
102
|
# v1.dot_product(v2) # => 10
|
116
103
|
#
|
117
|
-
Contract VectorLike => Num
|
118
104
|
def dot_product(other)
|
119
|
-
v,
|
105
|
+
v, = coerce(other)
|
120
106
|
self.class.dot_product(self, v)
|
121
107
|
end
|
122
108
|
|
@@ -126,9 +112,8 @@ class Vector2d
|
|
126
112
|
# v2 = Vector2d(2, 3)
|
127
113
|
# v1.cross_product(v2) # => 4
|
128
114
|
#
|
129
|
-
Contract VectorLike => Num
|
130
115
|
def cross_product(other)
|
131
|
-
v,
|
116
|
+
v, = coerce(other)
|
132
117
|
self.class.cross_product(self, v)
|
133
118
|
end
|
134
119
|
|
@@ -138,16 +123,15 @@ class Vector2d
|
|
138
123
|
# v2 = Vector2d(4, 5)
|
139
124
|
# v1.angle_between(v2) # => 0.0867..
|
140
125
|
#
|
141
|
-
Contract VectorLike => Num
|
142
126
|
def angle_between(other)
|
143
|
-
v,
|
127
|
+
v, = coerce(other)
|
144
128
|
self.class.angle_between(self, v)
|
145
129
|
end
|
146
130
|
|
147
131
|
private
|
148
132
|
|
149
133
|
def calculate_each(method, other)
|
150
|
-
v,
|
134
|
+
v, = coerce(other)
|
151
135
|
self.class.new(
|
152
136
|
x.send(method, v.x),
|
153
137
|
y.send(method, v.y)
|
data/lib/vector2d/coercions.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Vector2d
|
4
4
|
module Coercions
|
5
|
-
include Contracts
|
6
|
-
|
7
|
-
Contract VectorLike => [Vector2d, Vector2d]
|
8
5
|
def coerce(other)
|
9
6
|
case other
|
10
7
|
when Vector2d
|
@@ -20,7 +17,6 @@ class Vector2d
|
|
20
17
|
#
|
21
18
|
# Vector2d(2, 3).inspect # => "Vector2d(2,3)"
|
22
19
|
#
|
23
|
-
Contract None => String
|
24
20
|
def inspect
|
25
21
|
"Vector2d(#{x},#{y})"
|
26
22
|
end
|
@@ -29,7 +25,6 @@ class Vector2d
|
|
29
25
|
#
|
30
26
|
# Vector2d(2, 3).to_a # => [2,3]
|
31
27
|
#
|
32
|
-
Contract None => [Num, Num]
|
33
28
|
def to_a
|
34
29
|
[x, y]
|
35
30
|
end
|
@@ -38,7 +33,6 @@ class Vector2d
|
|
38
33
|
#
|
39
34
|
# Vector2d(2, 3).to_hash # => {x: 2, y: 3}
|
40
35
|
#
|
41
|
-
Contract None => Hash
|
42
36
|
def to_hash
|
43
37
|
{ x: x, y: y }
|
44
38
|
end
|
@@ -47,7 +41,6 @@ class Vector2d
|
|
47
41
|
#
|
48
42
|
# Vector2d(2.0, 3.0).to_i_vector # => Vector2d(2,3)
|
49
43
|
#
|
50
|
-
Contract None => Vector2d
|
51
44
|
def to_i_vector
|
52
45
|
self.class.new(x.to_i, y.to_i)
|
53
46
|
end
|
@@ -56,7 +49,6 @@ class Vector2d
|
|
56
49
|
#
|
57
50
|
# Vector2d(2, 3).to_f_vector # => Vector2d(2.0,3.0)
|
58
51
|
#
|
59
|
-
Contract None => Vector2d
|
60
52
|
def to_f_vector
|
61
53
|
self.class.new(x.to_f, y.to_f)
|
62
54
|
end
|
@@ -65,7 +57,6 @@ class Vector2d
|
|
65
57
|
#
|
66
58
|
# Vector2d.new(150, 100).to_s # => "150x100"
|
67
59
|
#
|
68
|
-
Contract None => String
|
69
60
|
def to_s
|
70
61
|
"#{x}x#{y}"
|
71
62
|
end
|
data/lib/vector2d/fitting.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Vector2d
|
4
4
|
module Fitting
|
5
|
-
include Contracts
|
6
|
-
|
7
5
|
# Scales down the given vector unless it fits inside.
|
8
6
|
#
|
9
7
|
# vector = Vector2d(20, 20)
|
@@ -11,46 +9,52 @@ class Vector2d
|
|
11
9
|
# vector.contain(Vector2d(40, 20)) # => Vector2d(20,10)
|
12
10
|
# vector.contain(Vector2d(20, 40)) # => Vector2d(10,20)
|
13
11
|
#
|
14
|
-
Contract VectorLike => Vector2d
|
15
12
|
def contain(other)
|
16
|
-
v,
|
17
|
-
|
13
|
+
v, = coerce(other)
|
14
|
+
v.x > x || v.y > y ? other.fit(self) : other
|
18
15
|
end
|
19
16
|
|
20
|
-
# Scales the vector to fit inside another vector, retaining the
|
17
|
+
# Scales the vector to fit inside another vector, retaining the
|
18
|
+
# aspect ratio.
|
21
19
|
#
|
22
20
|
# vector = Vector2d(20, 10)
|
23
21
|
# vector.fit(Vector2d(10, 10)) # => Vector2d(10,5)
|
24
22
|
# vector.fit(Vector2d(20, 20)) # => Vector2d(20,10)
|
25
23
|
# vector.fit(Vector2d(40, 40)) # => Vector2d(40,20)
|
26
24
|
#
|
27
|
-
# Note: Either axis will be disregarded if zero or nil. This is a
|
25
|
+
# Note: Either axis will be disregarded if zero or nil. This is a
|
26
|
+
# feature, not a bug.
|
28
27
|
#
|
29
|
-
Contract VectorLike => Vector2d
|
30
28
|
def fit(other)
|
31
|
-
v,
|
29
|
+
v, = coerce(other)
|
32
30
|
scale = v.to_f_vector / self
|
33
|
-
self * (
|
31
|
+
self * (
|
32
|
+
if scale.y.zero? || (scale.x.positive? && scale.x < scale.y)
|
33
|
+
scale.x
|
34
|
+
else
|
35
|
+
scale.y
|
36
|
+
end
|
37
|
+
)
|
34
38
|
end
|
35
|
-
|
39
|
+
alias constrain_both fit
|
36
40
|
|
37
|
-
# Constrain/expand so that one of the coordinates fit within (the
|
41
|
+
# Constrain/expand so that one of the coordinates fit within (the
|
42
|
+
# square implied by) another vector.
|
38
43
|
#
|
39
44
|
# constraint = Vector2d(5, 5)
|
40
45
|
# Vector2d(20, 10).fit_either(constraint) # => Vector2d(10,5)
|
41
46
|
# Vector2d(10, 20).fit_either(constraint) # => Vector2d(5,10)
|
42
47
|
#
|
43
|
-
Contract VectorLike => Vector2d
|
44
48
|
def fit_either(other)
|
45
|
-
v,
|
49
|
+
v, = coerce(other)
|
46
50
|
scale = v.to_f_vector / self
|
47
|
-
if
|
48
|
-
scale =
|
51
|
+
if scale.x.positive? && scale.y.positive?
|
52
|
+
scale = [scale.x, scale.y].max
|
49
53
|
self * scale
|
50
54
|
else
|
51
55
|
fit(v)
|
52
56
|
end
|
53
57
|
end
|
54
|
-
|
58
|
+
alias constrain_one fit_either
|
55
59
|
end
|
56
60
|
end
|
data/lib/vector2d/properties.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Vector2d
|
4
4
|
module Properties
|
5
|
-
include Contracts
|
6
|
-
|
7
5
|
# Angle of vector.
|
8
6
|
#
|
9
7
|
# Vector2d(2, 3).angle # => 0.9827..
|
10
8
|
#
|
11
|
-
Contract None => Num
|
12
9
|
def angle
|
13
10
|
Math.atan2(y, x)
|
14
11
|
end
|
@@ -17,16 +14,14 @@ class Vector2d
|
|
17
14
|
#
|
18
15
|
# Vector2d(2, 3).aspect_ratio # => 0.6667..
|
19
16
|
#
|
20
|
-
Contract None => Num
|
21
17
|
def aspect_ratio
|
22
|
-
(x.to_f / y
|
18
|
+
(x.to_f / y).abs
|
23
19
|
end
|
24
20
|
|
25
21
|
# Length of vector.
|
26
22
|
#
|
27
23
|
# Vector2d(2, 3).length # => 3.6055..
|
28
24
|
#
|
29
|
-
Contract None => Num
|
30
25
|
def length
|
31
26
|
Math.sqrt(squared_length)
|
32
27
|
end
|
@@ -35,9 +30,8 @@ class Vector2d
|
|
35
30
|
#
|
36
31
|
# Vector2d(2, 3).squared_length # => 13
|
37
32
|
#
|
38
|
-
Contract None => Num
|
39
33
|
def squared_length
|
40
|
-
x * x + y * y
|
34
|
+
(x * x) + (y * y)
|
41
35
|
end
|
42
36
|
|
43
37
|
# Is this a normalized vector?
|
@@ -45,9 +39,8 @@ class Vector2d
|
|
45
39
|
# Vector2d(0, 1).normalized? # => true
|
46
40
|
# Vector2d(2, 3).normalized? # => false
|
47
41
|
#
|
48
|
-
Contract None => Bool
|
49
42
|
def normalized?
|
50
|
-
|
43
|
+
(length.to_f - 1.0).abs < Float::EPSILON
|
51
44
|
end
|
52
45
|
end
|
53
46
|
end
|