Class: Math2D::Vector2D

Inherits:
Object
  • Object
show all
Defined in:
lib/math2d/vector2d.rb

Overview

Note:

MOST methods return a NEW Vector2D instead of changing self and returning it, so be careful.

Vector2D

  • An implementation of various 2-dimensional vector methods.

Author:

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(x = 0, y = 0) ⇒ Vector2D

Creates a new vector (x, y).

Parameters:

  • x (Numeric) (defaults to: 0)
  • y (Numeric) (defaults to: 0)


20
21
22
23
# File 'lib/math2d/vector2d.rb', line 20

def initialize(x = 0, y = 0)
  @x = x
  @y = y
end

Instance Attribute Details

#xNumeric

The x coordinate of the Vector

Returns:

  • (Numeric)

    the current value of x



12
13
14
# File 'lib/math2d/vector2d.rb', line 12

def x
  @x
end

#yNumeric

The y coordinate of the Vector

Returns:

  • (Numeric)

    the current value of y



12
13
14
# File 'lib/math2d/vector2d.rb', line 12

def y
  @y
end

Class Method Details

.downVector2D

Shorthand for writing Vector2D.new(0, 1).

Returns:



63
64
65
# File 'lib/math2d/vector2d.rb', line 63

def self.down
  Vector2D.new(0, 1)
end

.from_angle(theta, len = 1) ⇒ Vector2D

Returns a new Vector2D from a given angle theta with length len.

Parameters:

  • theta (Numeric)
  • len (Numeric) (defaults to: 1)

Returns:



278
279
280
# File 'lib/math2d/vector2d.rb', line 278

def self.from_angle(theta, len = 1)
  Vector2D.new(len * Math.cos(theta), len * Math.sin(theta))
end

.leftVector2D

Shorthand for writing Vector2D.new(-1, 0).

Returns:



70
71
72
# File 'lib/math2d/vector2d.rb', line 70

def self.left
  Vector2D.new(-1, 0)
end

.oneVector2D

Shorthand for writing Vector2D.new(1, 1).

Returns:



48
49
50
# File 'lib/math2d/vector2d.rb', line 48

def self.one
  Vector2D.new(1, 1)
end

.randomVector2D

Returns a new Vector2D with random components but magnitude equal to 1.

Returns:



373
374
375
376
# File 'lib/math2d/vector2d.rb', line 373

def self.random
  theta = rand(-Utils2D::TWO_PI..Utils2D::TWO_PI)
  Vector2D.new(Math.cos(theta), Math.sin(theta))
end

.rightVector2D

Shorthand for writing Vector2D.new(1, 0).

Returns:



77
78
79
# File 'lib/math2d/vector2d.rb', line 77

def self.right
  Vector2D.new(1, 0)
end

.to_vector(arr) ⇒ Vector2D

Returns a new Vector2D from an array arr. If the array is bigger than 2 elements, only the first 2 will be considered.

Parameters:

  • arr (Array<Numeric>)

Returns:

Raises:

  • (ArgumentError)


397
398
399
400
401
# File 'lib/math2d/vector2d.rb', line 397

def self.to_vector(arr)
  raise ArgumentError, '`arr` must be an Array' if arr.class != Array

  Vector2D.new(arr[0], arr[1])
end

.upVector2D

Shorthand for writing Vector2D.new(0, -1). NOTE: the y-axis is inverted as per Ruby2D’s y-axis orientation

Returns:



56
57
58
# File 'lib/math2d/vector2d.rb', line 56

def self.up
  Vector2D.new(0, -1)
end

.zeroVector2D

Shorthand for writing Vector2D.new(0, 0).

Returns:



41
42
43
# File 'lib/math2d/vector2d.rb', line 41

def self.zero
  Vector2D.new(0, 0)
end

Instance Method Details

#*(other) ⇒ Vector2D

Multiplies self by another vector or by a scalar.

Parameters:

Returns:



114
115
116
117
118
# File 'lib/math2d/vector2d.rb', line 114

def *(other)
  return Vector2D.new(@x * other.x, @y * other.y) if other.instance_of?(Vector2D)

  Vector2D.new(@x * other, @y * other)
end

#+(other) ⇒ Vector2D

Adds self to another vector or to a scalar.

Parameters:

Returns:



94
95
96
97
98
# File 'lib/math2d/vector2d.rb', line 94

def +(other)
  return Vector2D.new(@x + other.x, @y + other.y) if other.instance_of?(Vector2D)

  Vector2D.new(@x + other, @y + other)
end

#-(other) ⇒ Vector2D

Subtracts self to another vector or to a scalar.

Parameters:

Returns:



104
105
106
107
108
# File 'lib/math2d/vector2d.rb', line 104

def -(other)
  return Vector2D.new(@x - other.x, @y - other.y) if other.instance_of?(Vector2D)

  Vector2D.new(@x - other, @y - other)
end

#-@Vector2D Also known as: negate

Negates both x and y values of self and returns a new Vector2D.

Returns:



84
85
86
# File 'lib/math2d/vector2d.rb', line 84

def -@
  Vector2D.new(-@x, -@y)
end

#/(other) ⇒ Vector2D

Divides self by another vector or by a scalar.

Parameters:

Returns:



124
125
126
127
128
# File 'lib/math2d/vector2d.rb', line 124

def /(other)
  return Vector2D.new(@x / other.x, @y / other.y) if other.instance_of?(Vector2D)

  Vector2D.new(@x / other, @y / other)
end

#==(other) ⇒ Boolean

Compares self and other according to their components.

Parameters:

Returns:

  • (Boolean)


134
135
136
# File 'lib/math2d/vector2d.rb', line 134

def ==(other)
  (@x == other.x) && (@y == other.y)
end

#angle_between(other) ⇒ Float

Returns the angle between self and other in radians.

Parameters:

Returns:

  • (Float)


286
287
288
# File 'lib/math2d/vector2d.rb', line 286

def angle_between(other)
  Math.acos((@x * other.x + @y * other.y) / (magnitude * other.magnitude))
end

#constrain(a, b) ⇒ Vector2D Also known as: clamp

Note:

I haven’t experienced this with other methods (yet), so I’m only going to document this here: you may end up with a broken magnitude (1.99999999 instead of 2, for example), so always remember to check and round according to your need.

Constrains the magnitude of self between a minimum value a and maximum value b.

Parameters:

  • a (Numeric)
  • b (Numeric)

Returns:



215
216
217
218
219
220
221
222
223
# File 'lib/math2d/vector2d.rb', line 215

def constrain(a, b)
  mag = magnitude
  v = Vector2D.one
  if mag > b
    v.set_magnitude(b)
  elsif mag < a
    v.set_magnitude(a)
  end
end

#cross(other) ⇒ Numeric Also known as: wedge

Note:

Strictly speaking, the cross product is not defined in a 2-dimensional space,

Calculates the “cross product” (see note) between self and other, where: A^B (A wedge B) = (Ax * By) - (Bx * Ay)

instead what is being calculated here is called a ‘wedge product`, which is defined in any space of dimension greater than 1.

Parameters:

Returns:

  • (Numeric)


156
157
158
# File 'lib/math2d/vector2d.rb', line 156

def cross(other)
  (@x * other.y) - (other.x * @y)
end

#distance(other) ⇒ Float

Returns the Euclidean distance between self and other.

Parameters:

Returns:

  • (Float)


182
183
184
# File 'lib/math2d/vector2d.rb', line 182

def distance(other)
  Math.sqrt((other.x - @x)**2 + (other.y - @y)**2)
end

#dot(other) ⇒ Numeric

Calculates the dot product between self and other, where: A.B (A dot B) = (Ax * Bx) + (Ay * By)

Parameters:

Returns:

  • (Numeric)


143
144
145
# File 'lib/math2d/vector2d.rb', line 143

def dot(other)
  (@x * other.x) + (@y * other.y)
end

#headingFloat

Returns the x-heading angle of self in radians. The x-heading angle is the angle formed between self and the x-axis.

Returns:

  • (Float)


261
262
263
# File 'lib/math2d/vector2d.rb', line 261

def heading
  Math.atan2(@y.to_f, @x)
end

#inverse_lerp(other, value) ⇒ Vector2D

Calculates the parameter t of the #lerp method between self and other given an interpolant value.

Parameters:

Returns:



335
336
337
# File 'lib/math2d/vector2d.rb', line 335

def inverse_lerp(other, value)
  (value - self) / (other - self)
end

#lerp(other, amt) ⇒ Vector2D

Linear interpolate self and other with an amount amt.

Parameters:

  • other (Numeric, Vector2D)
  • amt (Numeric)

Returns:



326
327
328
# File 'lib/math2d/vector2d.rb', line 326

def lerp(other, amt)
  self + (other - self) * amt
end

#limit(max) ⇒ Vector2D

Limit the magnitude of self to max and returns a new vector.

Parameters:

  • max (Numeric)

Returns:



197
198
199
200
201
202
203
204
205
# File 'lib/math2d/vector2d.rb', line 197

def limit(max)
  msq = squared
  vec = self
  if msq > (max**2)
    vec /= Math.sqrt(msq)
    vec *= max
  end
  vec
end

#magnitudeFloat Also known as: length

Returns the magnitude of self.

Returns:

  • (Float)


172
173
174
# File 'lib/math2d/vector2d.rb', line 172

def magnitude
  Math.sqrt(@x**2 + @y**2)
end

#normalizeVector2D Also known as: unit

Normalizes self (set the magnitude to 1). unit is an alias for this method.

Returns:



241
242
243
# File 'lib/math2d/vector2d.rb', line 241

def normalize
  set_magnitude(1)
end

#normalized?Boolean Also known as: unit?

Returns true if the magnitude of self is equal to 1, false otherwise. unit? is an alias for this method.

Returns:

  • (Boolean)


251
252
253
# File 'lib/math2d/vector2d.rb', line 251

def normalized?
  magnitude == 1
end

#opposite?(other) ⇒ Boolean

Checks if self is facing the opposite direction of other.

Parameters:

Returns:

  • (Boolean)


294
295
296
# File 'lib/math2d/vector2d.rb', line 294

def opposite?(other)
  dot(other) < 0
end

#ratioFloat

Returns the ratio (x / y) of self.

Returns:

  • (Float)


189
190
191
# File 'lib/math2d/vector2d.rb', line 189

def ratio
  x.to_f / y
end

#reflect(other) ⇒ Vector2D

Reflects self and returns it as a new Vector2D. other is the normal of the plane where self is reflected.

Parameters:

Returns:



344
345
346
347
348
349
350
# File 'lib/math2d/vector2d.rb', line 344

def reflect(other)
  other = other.normalize
  dot_prod = other.dot(self)
  x = @x - dot_prod * other.x * 2
  y = @y - dot_prod * other.y * 2
  Vector2D.new(x, y)
end

#refract(other, refractive_index) ⇒ Vector2D

Refracts self and returns it as a new Vector2D. other is the normal of the plane where self is refracted.

Parameters:

  • other (Vector2D)
  • refractive_index (Numeric)

Returns:

See Also:



360
361
362
363
364
365
366
367
368
# File 'lib/math2d/vector2d.rb', line 360

def refract(other, refractive_index)
  dot_prod = other.dot(self)
  k = 1.0 - refractive_index * refractive_index * (1.0 - dot_prod * dot_prod)
  return Vector2D.zero if k.negative?

  x = refractive_index * @x - (refractive_index * dot_prod * Math.sqrt(k)) * other.x
  y = refractive_index * @y - (refractive_index * dot_prod * Math.sqrt(k)) * other.y
  Vector2D.new(x, y)
end

#rotate(angle) ⇒ Vector2D

Clockwise rotates self angle radians and returns it as a new Vector2D.

Parameters:

  • angle (Numeric)

Returns:



302
303
304
305
306
307
# File 'lib/math2d/vector2d.rb', line 302

def rotate(angle)
  Vector2D.new(
    @x * Math.cos(angle) - @y * Math.sin(angle),
    @x * Math.sin(angle) + @y * Math.cos(angle)
  )
end

#rotate_around(pivot, angle) ⇒ Vector2D

Clockwise rotates self angle radians around a pivot point and returns it as a new Vector2D.

Parameters:

Returns:



314
315
316
317
318
319
# File 'lib/math2d/vector2d.rb', line 314

def rotate_around(pivot, angle)
  x_rotated = pivot.x + ((@x - pivot.x) * Math.cos(angle)) - ((@y - pivot.y) * Math.sin(angle))
  y_rotated = pivot.y + ((@x - pivot.x) * Math.sin(angle)) + ((@y - pivot.y) * Math.cos(angle))

  Vector2D.new(x_rotated, y_rotated)
end

#set(x = self.x, y = self.y) ⇒ Vector2D

Sets the x and y components of the vector. Each argument is optional, so you can change a single component and keep the other one’s current value.

Parameters:

  • x (Numeric) (defaults to: self.x)
  • y (Numeric) (defaults to: self.y)

Returns:



32
33
34
35
36
# File 'lib/math2d/vector2d.rb', line 32

def set(x = self.x, y = self.y)
  @x = x
  @y = y
  self
end

#set_magnitude(new_mag) ⇒ Vector2D

Sets the magnitude of self to new_mag.

Parameters:

  • new_mag (Numeric)

Returns:



231
232
233
234
235
# File 'lib/math2d/vector2d.rb', line 231

def set_magnitude(new_mag)
  mag = magnitude
  mag = mag.zero? ? Float::INFINITY : mag
  Vector2D.new((@x * new_mag) / mag, (@y * new_mag) / mag)
end

#squaredNumeric

Returns the magnitude squared of self.

Returns:

  • (Numeric)


165
166
167
# File 'lib/math2d/vector2d.rb', line 165

def squared
  (@x**2) + (@y**2)
end

#to_aArray<Numeric>

Converts self to an array.

Returns:

  • (Array<Numeric>)


381
382
383
# File 'lib/math2d/vector2d.rb', line 381

def to_a
  [@x, @y]
end

#to_sString

Converts self to a string.

Returns:

  • (String)


388
389
390
# File 'lib/math2d/vector2d.rb', line 388

def to_s
  to_a.to_s
end

#y_headingFloat

Returns the y-heading angle of self in radians. The y-heading angle is the angle formed between self and the y-axis.

Returns:

  • (Float)


269
270
271
# File 'lib/math2d/vector2d.rb', line 269

def y_heading
  Utils2D::HALF_PI - heading
end