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:



274
275
276
# File 'lib/math2d/vector2d.rb', line 274

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:



369
370
371
372
# File 'lib/math2d/vector2d.rb', line 369

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)


393
394
395
396
397
# File 'lib/math2d/vector2d.rb', line 393

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) ⇒ Object



130
131
132
# File 'lib/math2d/vector2d.rb', line 130

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)


282
283
284
# File 'lib/math2d/vector2d.rb', line 282

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:



211
212
213
214
215
216
217
218
219
# File 'lib/math2d/vector2d.rb', line 211

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)


152
153
154
# File 'lib/math2d/vector2d.rb', line 152

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

#distance(other) ⇒ Float

Returns the Euclidean distance between self and other.

Parameters:

Returns:

  • (Float)


178
179
180
# File 'lib/math2d/vector2d.rb', line 178

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)


139
140
141
# File 'lib/math2d/vector2d.rb', line 139

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)


257
258
259
# File 'lib/math2d/vector2d.rb', line 257

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:



331
332
333
# File 'lib/math2d/vector2d.rb', line 331

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:



322
323
324
# File 'lib/math2d/vector2d.rb', line 322

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:



193
194
195
196
197
198
199
200
201
# File 'lib/math2d/vector2d.rb', line 193

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)


168
169
170
# File 'lib/math2d/vector2d.rb', line 168

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:



237
238
239
# File 'lib/math2d/vector2d.rb', line 237

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)


247
248
249
# File 'lib/math2d/vector2d.rb', line 247

def normalized?
  magnitude == 1
end

#opposite?(other) ⇒ Boolean

Checks if self is facing the opposite direction of other.

Parameters:

Returns:

  • (Boolean)


290
291
292
# File 'lib/math2d/vector2d.rb', line 290

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

#ratioFloat

Returns the ratio (x / y) of self.

Returns:

  • (Float)


185
186
187
# File 'lib/math2d/vector2d.rb', line 185

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:



340
341
342
343
344
345
346
# File 'lib/math2d/vector2d.rb', line 340

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:



356
357
358
359
360
361
362
363
364
# File 'lib/math2d/vector2d.rb', line 356

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:



298
299
300
301
302
303
# File 'lib/math2d/vector2d.rb', line 298

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:



310
311
312
313
314
315
# File 'lib/math2d/vector2d.rb', line 310

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:



227
228
229
230
231
# File 'lib/math2d/vector2d.rb', line 227

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)


161
162
163
# File 'lib/math2d/vector2d.rb', line 161

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

#to_aArray<Numeric>

Converts self to an array.

Returns:

  • (Array<Numeric>)


377
378
379
# File 'lib/math2d/vector2d.rb', line 377

def to_a
  [@x, @y]
end

#to_sString

Converts self to a string.

Returns:

  • (String)


384
385
386
# File 'lib/math2d/vector2d.rb', line 384

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)


265
266
267
# File 'lib/math2d/vector2d.rb', line 265

def y_heading
  Utils2D::HALF_PI - heading
end