Class: Vector2d

Inherits:
Object
  • Object
show all
Extended by:
Angles::ClassMethods, Constructors, Coordinates, Parsing, Projection::ClassMethods
Includes:
Angles, Arithmetic, Comparison, Componentwise, Conversions, Coordinates, Deprecation, Dimensions, Interpolation, Lengths, MatrixInterop, Projection
Defined in:
lib/vector2d.rb,
lib/vector2d/angles.rb,
lib/vector2d/lengths.rb,
lib/vector2d/parsing.rb,
lib/vector2d/version.rb,
lib/vector2d/arithmetic.rb,
lib/vector2d/comparison.rb,
lib/vector2d/dimensions.rb,
lib/vector2d/projection.rb,
lib/vector2d/conversions.rb,
lib/vector2d/coordinates.rb,
lib/vector2d/deprecation.rb,
lib/vector2d/constructors.rb,
lib/vector2d/componentwise.rb,
lib/vector2d/interpolation.rb,
lib/vector2d/matrix_interop.rb

Overview

An immutable two dimensional vector.

Coordinates are real numbers, and keep the type they were given. Integer coordinates stay exact through arithmetic with integers, and widen to floats when a float is involved.

Vector2d(2, 3) * 2   # => Vector2d(4,6)
Vector2d(2, 3) * 0.5 # => Vector2d(1.0,1.5)

Instances are frozen, so every operation returns a new vector instead of changing the receiver. New vectors are built through #build, which a subclass overrides to carry its own state across operations.

.parse is the permissive constructor, and Vector2d() is shorthand for it. .new takes exactly two coordinates.

Vector2d("2x3")    # => Vector2d(2,3)
Vector2d.new(2, 3) # => Vector2d(2,3)

Defined Under Namespace

Modules: Angles, Arithmetic, Comparison, Componentwise, Constructors, Conversions, Coordinates, Deprecation, Dimensions, Interpolation, Lengths, MatrixInterop, Parsing, Projection

Constant Summary collapse

VERSION =

The version of the gem.

"3.0.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(x, y) ⇒ Vector2d

Creates a vector from two coordinates, which must be real numbers. Every vector is constructed through here, so this is what keeps a coordinate from being anything else. Instances are frozen.

Vector2d.new(2, 3)                    # => Vector2d(2,3)
Vector2d.new(Complex(1, 2), 3)        # => ArgumentError
Vector2d.new(2, 3).frozen?            # => true
Ractor.shareable?(Vector2d.new(2, 3)) # => true

Parameters:

  • x (Integer, Float, Rational, BigDecimal)

    the x coordinate

  • y (Integer, Float, Rational, BigDecimal)

    the y coordinate



108
109
110
111
112
# File 'lib/vector2d.rb', line 108

def initialize(x, y)
  @x = coordinate(x)
  @y = coordinate(y)
  freeze
end

Instance Attribute Details

#xInteger, ... (readonly)

The coordinates.

Vector2d(2, 3).x # => 2
Vector2d(2, 3).y # => 3

Returns:

  • (Integer, Float, Rational, BigDecimal)


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

def x
  @x
end

#yInteger, ... (readonly)

The coordinates.

Vector2d(2, 3).x # => 2
Vector2d(2, 3).y # => 3

Returns:

  • (Integer, Float, Rational, BigDecimal)


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

def y
  @y
end

Class Method Details

.build(x, y) ⇒ Vector2d

Builds a new vector of this class from two coordinates, the way .parse and .from_angle do. Override it in a subclass whose constructor requires more than the coordinates, and see #build for the instance side.

class Labeled < Vector2d
attr_reader :label

def initialize(x, y, label = nil)
  @label = label
  super(x, y)
end

def self.build(x, y) = new(x, y, "unlabeled")
end

Labeled.parse("2x3").label # => "unlabeled"

Parameters:

  • x (Integer, Float, Rational, BigDecimal)

    the x coordinate

  • y (Integer, Float, Rational, BigDecimal)

    the y coordinate

Returns:



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

def self.build(x, y)
  new(x, y)
end

Instance Method Details

#==(other) ⇒ Boolean

Compares two vectors

Vector2d(2, 3) == Vector2d(2, 3) # => true
Vector2d(2, 3) == Vector2d(1, 0) # => false
Vector2d(2, 3) == [2, 3]         # => false

Parameters:

  • other (Object)

    any object

Returns:

  • (Boolean)


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

def ==(other)
  other.is_a?(Vector2d) && other.x == x && other.y == y
end

#build(x, y) ⇒ self

Builds a new vector of this class from two coordinates. Every method that returns a new vector goes through here, so a subclass whose constructor takes more than the coordinates only has to override this to have its own state carried across operations.

class Labeled < Vector2d
attr_reader :label

def initialize(x, y, label = nil)
  @label = label
  super(x, y)
end

def build(x, y) = self.class.new(x, y, label)
end

Labeled.new(2, 3, "point").abs.label # => "point"

Class level constructors have no instance to carry state from, and use .build instead.

Parameters:

  • x (Integer, Float, Rational, BigDecimal)

    the x coordinate

  • y (Integer, Float, Rational, BigDecimal)

    the y coordinate

Returns:

  • (self)


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

def build(x, y)
  self.class.build(x, y)
end

#eql?(other) ⇒ Boolean

Compares two vectors for hash equality. Unlike #==, the other object must be a vector of the same class, and the coordinates must be of the same type.

Vector2d(2, 3).eql?(Vector2d(2, 3))     # => true
Vector2d(2, 3).eql?(Vector2d(2.0, 3.0)) # => false

Parameters:

  • other (Object)

    any object

Returns:

  • (Boolean)


146
147
148
# File 'lib/vector2d.rb', line 146

def eql?(other)
  other.instance_of?(self.class) && x.eql?(other.x) && y.eql?(other.y)
end

#hashInteger

Hash value of the vector, consistent with #eql?.

Vector2d(2, 3).hash == Vector2d(2, 3).hash # => true

Returns:

  • (Integer)


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

def hash
  [self.class, x, y].hash
end

#initialize_copy(other) ⇒ void

This method returns an undefined value.

Copies are frozen too.

Vector2d(2, 3).dup.frozen? # => true

Parameters:

  • other (Vector2d)

    the vector being copied



120
121
122
123
# File 'lib/vector2d.rb', line 120

def initialize_copy(other)
  super
  freeze
end