Module: Vector2d::Componentwise

Included in:
Vector2d
Defined in:
lib/vector2d/componentwise.rb

Overview

Operations applied to each coordinate on its own, the way Numeric applies them to a number.

Instance Method Summary collapse

Instance Method Details

#absself

Returns the absolute value of each axis. This is component-wise, not the magnitude of the vector, which is #length.

Vector2d(-2, 3).abs  # => Vector2d(2,3)
Vector2d(-2, -3).abs # => Vector2d(2,3)

Returns:

  • (self)


14
15
16
# File 'lib/vector2d/componentwise.rb', line 14

def abs
  build(x.abs, y.abs)
end

#ceil(digits = 0) ⇒ self

Rounds vector up to nearest integer.

Vector2d(2.4, 3.6).ceil        # => Vector2d(3,4)
Vector2d(2.441, 3.666).ceil(2) # => Vector2d(2.45,3.67)

Parameters:

  • digits (Integer) (defaults to: 0)

    the number of decimal places to keep

Returns:

  • (self)


25
26
27
# File 'lib/vector2d/componentwise.rb', line 25

def ceil(digits = 0)
  build(x.ceil(digits), y.ceil(digits))
end

#clamp(min, max) ⇒ self #clamp(range) ⇒ self

Clamps the vector between two others, one axis at a time. The bounds are coerced, so scalars work too.

vector = Vector2d(2, 8)
vector.clamp(Vector2d(3, 3), Vector2d(6, 6)) # => Vector2d(3,6)
vector.clamp(3, 6)                           # => Vector2d(3,6)

The bounds can also be given as a single range, which may be beginless or endless to clamp only one side.

vector.clamp(3..6) # => Vector2d(3,6)
vector.clamp(..6)  # => Vector2d(2,6)
vector.clamp(3..)  # => Vector2d(3,8)

The range must not exclude its end, as with Comparable#clamp.

vector.clamp(3...6) # => ArgumentError

Overloads:

  • #clamp(min, max) ⇒ self

    Parameters:

    • min (Vector2d, Array, String, Hash, Integer, Float, Rational, BigDecimal, ::Vector, ::Matrix)

      the lower bound, anything Vector2d.parse accepts

    • max (Vector2d, Array, String, Hash, Integer, Float, Rational, BigDecimal, ::Vector, ::Matrix)

      the upper bound

  • #clamp(range) ⇒ self

    Parameters:

    • range (Range)

      both bounds, and may be beginless or endless

Returns:

  • (self)


163
164
165
166
167
168
169
# File 'lib/vector2d/componentwise.rb', line 163

def clamp(min, max = nil)
  min_v, max_v = clamp_bounds(min, max)
  build(
    x.clamp(Range.new(min_v&.x, max_v&.x)),
    y.clamp(Range.new(min_v&.y, max_v&.y))
  )
end

#floor(digits = 0) ⇒ self

Rounds vector down to nearest integer.

Vector2d(2.4, 3.6).floor        # => Vector2d(2,3)
Vector2d(2.444, 3.669).floor(2) # => Vector2d(2.44,3.66)

Parameters:

  • digits (Integer) (defaults to: 0)

    the number of decimal places to keep

Returns:

  • (self)


36
37
38
# File 'lib/vector2d/componentwise.rb', line 36

def floor(digits = 0)
  build(x.floor(digits), y.floor(digits))
end

#max(other) ⇒ self

Returns the larger value of each axis. The other vector is coerced, so scalars work too.

vector = Vector2d(2, 8)
vector.max(Vector2d(5, 5)) # => Vector2d(5,8)
vector.max(5)              # => Vector2d(5,8)

Parameters:

  • other (Vector2d, Array, String, Hash, Integer, Float, Rational, BigDecimal, ::Vector, ::Matrix)

    anything Vector2d.parse accepts

Returns:

  • (self)


117
118
119
120
# File 'lib/vector2d/componentwise.rb', line 117

def max(other)
  v = coerce_vector(other)
  build([x, v.x].max, [y, v.y].max)
end

#min(other) ⇒ self

Returns the smaller value of each axis. The other vector is coerced, so scalars work too.

vector = Vector2d(2, 8)
vector.min(Vector2d(5, 5)) # => Vector2d(2,5)
vector.min(5)              # => Vector2d(2,5)

Parameters:

  • other (Vector2d, Array, String, Hash, Integer, Float, Rational, BigDecimal, ::Vector, ::Matrix)

    anything Vector2d.parse accepts

Returns:

  • (self)


131
132
133
134
# File 'lib/vector2d/componentwise.rb', line 131

def min(other)
  v = coerce_vector(other)
  build([x, v.x].min, [y, v.y].min)
end

#round(digits = 0) ⇒ self

Rounds vector to nearest integer.

Vector2d(2.4, 3.6).round         # => Vector2d(2,4)
Vector2d(2.4444, 3.666).round(2) # => Vector2d(2.44,3.67)

Parameters:

  • digits (Integer) (defaults to: 0)

    the number of decimal places to keep

Returns:

  • (self)


47
48
49
# File 'lib/vector2d/componentwise.rb', line 47

def round(digits = 0)
  build(x.round(digits), y.round(digits))
end

#signself

Returns the sign of each axis, -1, 0 or 1.

Vector2d(-2, 3).sign # => Vector2d(-1,1)
Vector2d(0, -3).sign # => Vector2d(0,-1)

The signs are integers, whatever the coordinates were. There are only three of them, and they are exact.

Vector2d(-2.5, 0.0).sign # => Vector2d(-1,0)

NaN has no sign, so ArgumentError is raised.

Vector2d(Float::NAN, 3).sign # => ArgumentError

Returns:

  • (self)

    a vector of -1, 0 and 1



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

def sign
  build(coordinate_sign(x), coordinate_sign(y))
end

#snap(step) ⇒ self

Snaps each axis to the nearest multiple of a step. The step is coerced, so scalars work too, and a vector gives each axis its own step.

vector = Vector2d(23, 47)
vector.snap(10)              # => Vector2d(20,50)
vector.snap(Vector2d(10, 5)) # => Vector2d(20,45)

Coordinates take the type of the step, so an integer step snaps to integers.

Vector2d(2.3, 3.7).snap(1)   # => Vector2d(2,4)
Vector2d(2.3, 3.7).snap(0.5) # => Vector2d(2.5,3.5)

A step of zero has no multiples to snap to, and leaves the axis unchanged.

vector.snap(0)               # => Vector2d(23,47)
vector.snap(Vector2d(10, 0)) # => Vector2d(20,47)

Parameters:

  • step (Vector2d, Array, String, Hash, Integer, Float, Rational, BigDecimal, ::Vector, ::Matrix)

    anything Vector2d.parse accepts

Returns:

  • (self)


103
104
105
106
# File 'lib/vector2d/componentwise.rb', line 103

def snap(step)
  v = coerce_vector(step)
  build(snap_coordinate(x, v.x), snap_coordinate(y, v.y))
end

#truncate(max) ⇒ self

Deprecated.

Use #limit_length instead. The name belongs to the

#ceil/#floor/#round family, which maps Numeric over both coordinates.

Parameters:

  • max (Integer, Float, Rational, BigDecimal)

    the maximum length

Returns:

  • (self)


57
58
59
60
# File 'lib/vector2d/componentwise.rb', line 57

def truncate(max)
  warn_deprecated("Vector2d#truncate is deprecated. Use #limit_length instead.")
  limit_length(max)
end

#with_x(value) ⇒ self

Returns the vector with x replaced.

Vector2d(2, 3).with_x(5) # => Vector2d(5,3)

Vectors are immutable, so this is how a single axis is changed. The value is a coordinate, not a vector, and is not coerced.

Vector2d(2, 3).with_x("5") # => ArgumentError

Parameters:

  • value (Integer, Float, Rational, BigDecimal)

    the new x coordinate

Returns:

  • (self)


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

def with_x(value)
  build(value, y)
end

#with_y(value) ⇒ self

Returns the vector with y replaced.

Vector2d(2, 3).with_y(5) # => Vector2d(2,5)

The value is a coordinate, not a vector, and is not coerced.

Vector2d(2, 3).with_y(nil) # => ArgumentError

Parameters:

  • value (Integer, Float, Rational, BigDecimal)

    the new y coordinate

Returns:

  • (self)


196
197
198
# File 'lib/vector2d/componentwise.rb', line 196

def with_y(value)
  build(x, value)
end