math2d 1.1.0
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 +7 -0
- data/lib/math2d/utils2d.rb +158 -0
- data/lib/math2d/vector2d.rb +340 -0
- data/lib/math2d.rb +9 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f3a494b2da989404d96ad8034d4b68f1ee7fa8280ce6f10e673e193fba05dc3b
|
4
|
+
data.tar.gz: 8f137444c95142d170c666456419ed07a601dd01f5593492ab0131909d3d3195
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d2a54a7a4cdfb1a84553a5fe8ec22c4cfb1680273ce69d98c5979d0eec65cae88bb4072fa69aebf0b44a9d1f6d67c5a291d3207d44ff6e1c926b685007db8a98
|
7
|
+
data.tar.gz: b0a32b1a0b168ff16e6c8e0aec72e828df677035e031f4870fb2c62994f8b9dfa37d86be0d8738bf6816d6645ab9f6e8a3296600468b61ad4ed852f3abb9e598
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# Namespace for the Math2D library
|
2
|
+
module Math2D
|
3
|
+
# A collection of useful Mathematical tools in 2D space
|
4
|
+
#
|
5
|
+
# @author Ualace Henrique <ualacehenrique@hotmail.com>
|
6
|
+
# @note Most if not all methods descriptions here present come from the p5.js website.
|
7
|
+
# @see https://p5js.org/
|
8
|
+
module Utils2D
|
9
|
+
# Half the mathematical constant PI.
|
10
|
+
HALF_PI = Math::PI / 2
|
11
|
+
# A quarter of the mathematical constant PI.
|
12
|
+
QUARTER_PI = Math::PI / 4
|
13
|
+
# Twice the mathematical constant PI.
|
14
|
+
TWO_PI = Math::PI * 2
|
15
|
+
|
16
|
+
# Returns +angle+ radians in degrees.
|
17
|
+
#
|
18
|
+
# @param [Numeric] angle
|
19
|
+
# @return [Float]
|
20
|
+
def self.to_deg(angle)
|
21
|
+
(180 * angle) / Math::PI
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns +angle+ degrees in radians.
|
25
|
+
#
|
26
|
+
# @param [Numeric] angle
|
27
|
+
# @return [Float]
|
28
|
+
def self.to_rad(angle)
|
29
|
+
(Math::PI * angle) / 180
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the distance between two cartesian points.
|
33
|
+
#
|
34
|
+
# @param [Numeric] x1
|
35
|
+
# @param [Numeric] y1
|
36
|
+
# @param [Numeric] x2
|
37
|
+
# @param [Numeric] y2
|
38
|
+
# @return [Float]
|
39
|
+
def self.distance(x1, y1, x2, y2)
|
40
|
+
Math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Calculates a number between two numbers at a specific increment.
|
44
|
+
# The amt parameter is the amount to interpolate between the two
|
45
|
+
# values where 0.0 equal to the first point, 0.1 is very near the
|
46
|
+
# first point, 0.5 is half-way in between, and 1.0 is equal to the
|
47
|
+
# second point.
|
48
|
+
#
|
49
|
+
# @param [Numeric] a
|
50
|
+
# @param [Numeric] b
|
51
|
+
# @return [Float]
|
52
|
+
def self.lerp(a, b, amt)
|
53
|
+
(b - a) * (3.0 - amt * 2.0) * amt * amt + a
|
54
|
+
end
|
55
|
+
|
56
|
+
# Re-maps a number from one range (+a1+..+a2+) to another (+b1+..+b2+).
|
57
|
+
#
|
58
|
+
# @param [Numeric] value
|
59
|
+
# @param [Numeric] a1
|
60
|
+
# @param [Numeric] a2
|
61
|
+
# @param [Numeric] b1
|
62
|
+
# @param [Numeric] b2
|
63
|
+
# @return [Float]
|
64
|
+
def self.map(value, a1, a2, b1, b2)
|
65
|
+
raise ArgumentError, 'Division by 0 - a1 cannot be equal to a2' if a2 == a1
|
66
|
+
|
67
|
+
slope = 1.0 * (b2 - b1) / (a2 - a1)
|
68
|
+
b1 + slope * (value - a1)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Normalizes a number from another range (+a+..+b+) into a value between 0 and 1.
|
72
|
+
#
|
73
|
+
# @param [Numeric] value
|
74
|
+
# @param [Numeric] a
|
75
|
+
# @param [Numeric] b
|
76
|
+
# @return [Float]
|
77
|
+
def self.normalize(value, a, b)
|
78
|
+
map(value, a, b, 0.0, 1.0)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Constrains a value +x+ between a minimum value +a+ and maximum value +b+.
|
82
|
+
#
|
83
|
+
# @param [Numeric] x
|
84
|
+
# @param [Numeric] a
|
85
|
+
# @param [Numeric] b
|
86
|
+
# @return [Numeric]
|
87
|
+
def self.constrain(x, a, b)
|
88
|
+
[[x, a].max, b].min
|
89
|
+
end
|
90
|
+
|
91
|
+
class << self
|
92
|
+
alias clamp constrain
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns the Perlin noise value at specified coordinates.
|
96
|
+
# Perlin noise is a random sequence generator producing a more naturally
|
97
|
+
# ordered, harmonic succession of numbers compared to the standard rand() method.
|
98
|
+
# The main difference to the rand() method is that Perlin noise is defined in an
|
99
|
+
# infinite n-dimensional space where each pair of coordinates corresponds to a fixed
|
100
|
+
# semi-random value. Utils2D can compute 1D and 2D noise, depending on the number of
|
101
|
+
# coordinates given. The resulting value will always be between 0.0 and 1.0.
|
102
|
+
# @see https://en.wikipedia.org/wiki/Perlin_noise
|
103
|
+
#
|
104
|
+
# @param [Numeric] x
|
105
|
+
# @param [Numeric] y
|
106
|
+
# @return [Float]
|
107
|
+
def self.noise(x, y = 0)
|
108
|
+
x0 = x.to_i
|
109
|
+
x1 = x0 + 1
|
110
|
+
y0 = y.to_i
|
111
|
+
y1 = y0 + 1
|
112
|
+
|
113
|
+
sx = x - x0.to_f
|
114
|
+
sy = y - y0.to_f
|
115
|
+
|
116
|
+
n0 = dot_grid_gradient(x0, y0, x, y)
|
117
|
+
n1 = dot_grid_gradient(x1, y0, x, y)
|
118
|
+
ix0 = lerp(n0, n1, sx)
|
119
|
+
|
120
|
+
n0 = dot_grid_gradient(x0, y1, x, y)
|
121
|
+
n1 = dot_grid_gradient(x1, y1, x, y)
|
122
|
+
ix1 = lerp(n0, n1, sx)
|
123
|
+
lerp(ix0, ix1, sy)
|
124
|
+
end
|
125
|
+
|
126
|
+
# If no argument is passed, randomly generates a greyscale RGB array.
|
127
|
+
# Otherwise, returns a greyscale array with that argument normalized.
|
128
|
+
#
|
129
|
+
# @param [Numeric] val
|
130
|
+
# @return [Array<Float>]
|
131
|
+
def self.grayscale(val = nil)
|
132
|
+
c = if val
|
133
|
+
normalize(val, 0, 255).abs
|
134
|
+
else
|
135
|
+
rand
|
136
|
+
end
|
137
|
+
[c, c, c, 1.0]
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
# @private
|
143
|
+
# @see https://en.wikipedia.org/wiki/Perlin_noise
|
144
|
+
def self.random_gradient(ix, iy)
|
145
|
+
random = 2920.0 * Math.sin(ix * 21_942.0 + iy * 171_324.0 + 8912.0) * Math.cos(ix * 23_157.0 * iy * 217_832.0 + 9758.0)
|
146
|
+
[Math.cos(random), Math.sin(random)]
|
147
|
+
end
|
148
|
+
|
149
|
+
# @private
|
150
|
+
# @see https://en.wikipedia.org/wiki/Perlin_noise
|
151
|
+
def self.dot_grid_gradient(ix, iy, x, y)
|
152
|
+
gradient = random_gradient(ix, iy)
|
153
|
+
dx = x - ix.to_f
|
154
|
+
dy = y - iy.to_f
|
155
|
+
(dx * gradient[0]) + (dy * gradient[1])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,340 @@
|
|
1
|
+
# Namespace for the Math2D gem
|
2
|
+
module Math2D
|
3
|
+
# Vector2D
|
4
|
+
#
|
5
|
+
# - An implementation of various 2-dimensional vector methods.
|
6
|
+
#
|
7
|
+
# @author Ualace Henrique <ualacehenrique@hotmail.com>
|
8
|
+
# @note MOST methods return a NEW Vector2D instead of changing
|
9
|
+
# self and returning it, so be careful.
|
10
|
+
# @attr [Numeric] x The x coordinate of the Vector
|
11
|
+
# @attr [Numeric] y The y coordinate of the Vector
|
12
|
+
class Vector2D
|
13
|
+
attr_accessor :x, :y
|
14
|
+
|
15
|
+
# Creates a new vector (x, y).
|
16
|
+
#
|
17
|
+
# @param [Numeric] x
|
18
|
+
# @param [Numeric] y
|
19
|
+
# @return [Vector2D]
|
20
|
+
def initialize(x = 0, y = 0)
|
21
|
+
@x = x
|
22
|
+
@y = y
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets the +x+ and +y+ components of the vector.
|
26
|
+
# Each argument is optional, so you can change a single component
|
27
|
+
# and keep the other one's current value.
|
28
|
+
#
|
29
|
+
# @param [Numeric] x
|
30
|
+
# @param [Numeric] y
|
31
|
+
# @return [Vector2D] self
|
32
|
+
def set(x = self.x, y = self.y)
|
33
|
+
@x = x
|
34
|
+
@y = y
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Shorthand for writing Vector2D.new(0, 0).
|
39
|
+
#
|
40
|
+
# @return [Vector2D]
|
41
|
+
def self.zero
|
42
|
+
Vector2D.new(0, 0)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Shorthand for writing Vector2D.new(1, 1).
|
46
|
+
#
|
47
|
+
# @return [Vector2D]
|
48
|
+
def self.one
|
49
|
+
Vector2D.new(1, 1)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Shorthand for writing Vector2D.new(0, -1).
|
53
|
+
# NOTE: the y-axis is inverted as per Ruby2D's y-axis orientation
|
54
|
+
#
|
55
|
+
# @return [Vector2D]
|
56
|
+
def self.up
|
57
|
+
Vector2D.new(0, -1)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Shorthand for writing Vector2D.new(0, 1).
|
61
|
+
#
|
62
|
+
# @return [Vector2D]
|
63
|
+
def self.down
|
64
|
+
Vector2D.new(0, 1)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Shorthand for writing Vector2D.new(-1, 0).
|
68
|
+
#
|
69
|
+
# @return [Vector2D]
|
70
|
+
def self.left
|
71
|
+
Vector2D.new(-1, 0)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Shorthand for writing Vector2D.new(1, 0).
|
75
|
+
#
|
76
|
+
# @return [Vector2D]
|
77
|
+
def self.right
|
78
|
+
Vector2D.new(1, 0)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Negates both x and y values of +self+ and returns a new Vector2D.
|
82
|
+
#
|
83
|
+
# @return [Vector2D]
|
84
|
+
def -@
|
85
|
+
Vector2D.new(-@x, -@y)
|
86
|
+
end
|
87
|
+
|
88
|
+
alias negate -@
|
89
|
+
|
90
|
+
# Adds +self+ to another vector or to a scalar.
|
91
|
+
#
|
92
|
+
# @param [Numeric, Vector2D] other
|
93
|
+
# @return [Vector2D]
|
94
|
+
def +(other)
|
95
|
+
return Vector2D.new(@x + other.x, @y + other.y) if other.instance_of?(Vector2D)
|
96
|
+
|
97
|
+
Vector2D.new(@x + other, @y + other)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Subtracts +self+ to another vector or to a scalar.
|
101
|
+
#
|
102
|
+
# @param [Numeric, Vector2D] other
|
103
|
+
# @return [Vector2D]
|
104
|
+
def -(other)
|
105
|
+
return Vector2D.new(@x - other.x, @y - other.y) if other.instance_of?(Vector2D)
|
106
|
+
|
107
|
+
Vector2D.new(@x - other, @y - other)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Multiplies +self+ by another vector or by a scalar.
|
111
|
+
#
|
112
|
+
# @param [Numeric, Vector2D] other
|
113
|
+
# @return [Vector2D]
|
114
|
+
def *(other)
|
115
|
+
return Vector2D.new(@x * other.x, @y * other.y) if other.instance_of?(Vector2D)
|
116
|
+
|
117
|
+
Vector2D.new(@x * other, @y * other)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Divides +self+ by another vector or by a scalar.
|
121
|
+
#
|
122
|
+
# @param [Numeric, Vector2D] other
|
123
|
+
# @return [Vector2D]
|
124
|
+
def /(other)
|
125
|
+
return Vector2D.new(@x / other.x, @y / other.y) if other.instance_of?(Vector2D)
|
126
|
+
|
127
|
+
Vector2D.new(@x / other, @y / other)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Calculates the dot product between +self+ and +other+, where:
|
131
|
+
# A.B (A dot B) = (Ax * Bx) + (Ay * By)
|
132
|
+
#
|
133
|
+
# @param [Vector2D] other
|
134
|
+
# @return [Numeric]
|
135
|
+
def dot(other)
|
136
|
+
(@x * other.x) + (@y * other.y)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Calculates the cross product between +self+ and +other+, where:
|
140
|
+
# AxB (A cross B) = (Ax * By) - (Bx * Ay)
|
141
|
+
# HOWEVER, the cross product is NOT defined in a 2D space, so the operation
|
142
|
+
# simply returns the magnitude of the resulting cross-product 3D vector.
|
143
|
+
#
|
144
|
+
# @param [Vector2D] other
|
145
|
+
# @return [Numeric]
|
146
|
+
def cross(other)
|
147
|
+
(@x * other.y) - (other.x * @y)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns the magnitude squared of +self+.
|
151
|
+
#
|
152
|
+
# @return [Numeric]
|
153
|
+
def squared
|
154
|
+
(@x**2) + (@y**2)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns the magnitude of +self+.
|
158
|
+
#
|
159
|
+
# @return [Float]
|
160
|
+
def magnitude
|
161
|
+
Math.sqrt(@x**2 + @y**2)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns the Euclidean distance between +self+ and +other+.
|
165
|
+
#
|
166
|
+
# @param [Vector2D] other
|
167
|
+
# @return [Float]
|
168
|
+
def distance(other)
|
169
|
+
Math.sqrt((other.x - @x)**2 + (other.y - @y)**2)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns the ratio (x / y) of +self+.
|
173
|
+
#
|
174
|
+
# @return [Float]
|
175
|
+
def ratio
|
176
|
+
x.to_f / y
|
177
|
+
end
|
178
|
+
|
179
|
+
# Limit the magnitude of +self+ to +max+ and returns a new vector.
|
180
|
+
#
|
181
|
+
# @param [Numeric] max
|
182
|
+
# @return [Vector2D]
|
183
|
+
def limit(max)
|
184
|
+
msq = squared
|
185
|
+
vec = self
|
186
|
+
if msq > (max**2)
|
187
|
+
vec /= Math.sqrt(msq)
|
188
|
+
vec *= max
|
189
|
+
end
|
190
|
+
vec
|
191
|
+
end
|
192
|
+
|
193
|
+
# Constrains the magnitude of +self+ between a minimum value +a+ and maximum value +b+.
|
194
|
+
#
|
195
|
+
# @note I haven't experienced this with other methods (yet), so I'm only going to document this
|
196
|
+
# here: you may end up with a broken magnitude (1.99999999 instead of 2, for example),
|
197
|
+
# so always remember to check and round according to your need.
|
198
|
+
# @param [Numeric] a
|
199
|
+
# @param [Numeric] b
|
200
|
+
# @return [Vector2D]
|
201
|
+
def constrain(a, b)
|
202
|
+
mag = magnitude
|
203
|
+
v = Vector2D.one
|
204
|
+
if mag > b
|
205
|
+
v.set_magnitude(b)
|
206
|
+
elsif mag < a
|
207
|
+
v.set_magnitude(a)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
alias clamp constrain
|
212
|
+
|
213
|
+
# Sets the magnitude of +self+ to +new_mag+.
|
214
|
+
#
|
215
|
+
# @param [Numeric] new_mag
|
216
|
+
# @return [Vector2D]
|
217
|
+
def set_magnitude(new_mag)
|
218
|
+
mag = magnitude
|
219
|
+
mag = mag.zero? ? Float::INFINITY : mag
|
220
|
+
Vector2D.new((@x * new_mag) / mag, (@y * new_mag) / mag)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Normalizes +self+ (set the magnitude to 1).
|
224
|
+
# +unit+ is an alias for this method.
|
225
|
+
#
|
226
|
+
# @return [Vector2D]
|
227
|
+
def normalize
|
228
|
+
set_magnitude(1)
|
229
|
+
end
|
230
|
+
|
231
|
+
alias unit normalize
|
232
|
+
|
233
|
+
# Returns true if the magnitude of +self+ is equal to 1, false otherwise.
|
234
|
+
# +unit?+ is an alias for this method.
|
235
|
+
#
|
236
|
+
# @return [Boolean]
|
237
|
+
def normalized?
|
238
|
+
magnitude == 1
|
239
|
+
end
|
240
|
+
|
241
|
+
alias unit? normalized?
|
242
|
+
|
243
|
+
# Returns the x-heading angle of +self+ in radians.
|
244
|
+
# The x-heading angle is the angle formed between +self+ and the x-axis.
|
245
|
+
#
|
246
|
+
# @return [Float]
|
247
|
+
def heading
|
248
|
+
Math.atan2(@y.to_f, @x)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Returns the y-heading angle of +self+ in radians.
|
252
|
+
# The y-heading angle is the angle formed between +self+ and the y-axis.
|
253
|
+
#
|
254
|
+
# @return [Float]
|
255
|
+
def y_heading
|
256
|
+
Utils2D::HALF_PI - heading
|
257
|
+
end
|
258
|
+
|
259
|
+
# Returns a new Vector2D from a given angle +theta+ with length +len+.
|
260
|
+
#
|
261
|
+
# @param [Numeric] theta
|
262
|
+
# @param [Numeric] len
|
263
|
+
# @return [Vector2D]
|
264
|
+
def self.from_angle(theta, len = 1)
|
265
|
+
Vector2D.new(len * Math.cos(theta), len * Math.sin(theta))
|
266
|
+
end
|
267
|
+
|
268
|
+
# Returns the angle between +self+ and +other+ in radians.
|
269
|
+
#
|
270
|
+
# @param [Vector2D] other
|
271
|
+
# @return [Float]
|
272
|
+
def angle_between(other)
|
273
|
+
Math.acos((@x * other.x + @y * other.y) / (magnitude * other.magnitude))
|
274
|
+
end
|
275
|
+
|
276
|
+
# Rotates +self+ +angle+ radians and returns it as a new Vector2D.
|
277
|
+
#
|
278
|
+
# @param [Numeric] angle
|
279
|
+
# @return [Vector2D]
|
280
|
+
def rotate(angle)
|
281
|
+
Vector2D.new(@x * Math.cos(angle) - @y * Math.sin(angle),
|
282
|
+
@x * Math.sin(angle) + @y * Math.cos(angle))
|
283
|
+
end
|
284
|
+
|
285
|
+
# Linear interpolate +self+ and +other+ with an amount +amt+.
|
286
|
+
#
|
287
|
+
# @param [Numeric, Vector2D] other
|
288
|
+
# @param [Numeric] amt
|
289
|
+
# @return [Vector2D]
|
290
|
+
def lerp(other, amt)
|
291
|
+
self + (other - self) * amt
|
292
|
+
end
|
293
|
+
|
294
|
+
# Reflects +self+ and returns it as a new Vector2D.
|
295
|
+
# +other+ is the normal of the plane where +self+ is reflected.
|
296
|
+
#
|
297
|
+
# @param [Vector2D] other
|
298
|
+
# @return [Vector2D]
|
299
|
+
def reflect(other)
|
300
|
+
other = other.normalize
|
301
|
+
dot_prod = other.dot(self)
|
302
|
+
x = @x - dot_prod * other.x * 2
|
303
|
+
y = @y - dot_prod * other.y * 2
|
304
|
+
Vector2D.new(x, y)
|
305
|
+
end
|
306
|
+
|
307
|
+
# Returns a new Vector2D with random components but magnitude equal to 1.
|
308
|
+
#
|
309
|
+
# @return [Vector2D]
|
310
|
+
def self.random
|
311
|
+
theta = rand(-Utils2D::TWO_PI..Utils2D::TWO_PI)
|
312
|
+
Vector2D.new(Math.cos(theta), Math.sin(theta))
|
313
|
+
end
|
314
|
+
|
315
|
+
# Converts +self+ to an array.
|
316
|
+
#
|
317
|
+
# @return [Array<Numeric>]
|
318
|
+
def to_a
|
319
|
+
[@x, @y]
|
320
|
+
end
|
321
|
+
|
322
|
+
# Converts +self+ to a string.
|
323
|
+
#
|
324
|
+
# @return [String]
|
325
|
+
def to_s
|
326
|
+
to_a.to_s
|
327
|
+
end
|
328
|
+
|
329
|
+
# Returns a new Vector2D from an array +arr+.
|
330
|
+
# If the array is bigger than 2 elements, only the first 2 will be considered.
|
331
|
+
#
|
332
|
+
# @param [Array<Numeric>] arr
|
333
|
+
# @return [Vector2D]
|
334
|
+
def self.to_vector(arr)
|
335
|
+
raise ArgumentError, '`arr` must be an Array' if arr.class != Array
|
336
|
+
|
337
|
+
Vector2D.new(arr[0], arr[1])
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
data/lib/math2d.rb
ADDED
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: math2d
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ualace Henrique
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-25 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A collection of useful Mathematical and Vector tools in 2D space
|
14
|
+
email:
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/math2d.rb
|
20
|
+
- lib/math2d/utils2d.rb
|
21
|
+
- lib/math2d/vector2d.rb
|
22
|
+
homepage: https://rubygems.org/gems/math2d
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubygems_version: 3.2.16
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: Math2D
|
45
|
+
test_files: []
|