Module: Vector2d::Projection
- Included in:
- Vector2d
- Defined in:
- lib/vector2d/projection.rb
Overview
Products of two vectors, and the projection, reflection and refraction built on them.
Defined Under Namespace
Modules: ClassMethods
Instance Method Summary collapse
-
#cross_product(other) ⇒ Integer, ...
Cross product of this vector and another vector.
-
#dot_product(other) ⇒ Integer, ...
(also: #inner_product, #dot)
Dot product of this vector and another vector.
-
#project(other) ⇒ self
Vector projection of this vector onto another vector.
-
#reflect(normal) ⇒ self
Reflects this vector about the line perpendicular to the normal, the way a ray bounces off a surface.
-
#refract(normal, refractive_index) ⇒ self
Refracts this vector through a surface with the given normal and ratio of refractive indices, the way a ray bends entering a different medium.
-
#reject(other) ⇒ self
Vector rejection of this vector from another vector, the component left over when the projection is subtracted.
-
#scalar_projection(other) ⇒ Float
Scalar projection of this vector onto another vector, the signed length of the projection.
Instance Method Details
#cross_product(other) ⇒ Integer, ...
Cross product of this vector and another vector. In two dimensions this is a scalar, the z component of the equivalent three dimensional cross product. Vector#cross_product returns a perpendicular vector instead, which is #perpendicular here.
v1 = Vector2d(2, 1)
v2 = Vector2d(2, 3)
v1.cross_product(v2) # => 4
66 67 68 69 |
# File 'lib/vector2d/projection.rb', line 66 def cross_product(other) v = coerce_vector(other) self.class.cross_product(self, v) end |
#dot_product(other) ⇒ Integer, ... Also known as: inner_product, dot
48 49 50 51 |
# File 'lib/vector2d/projection.rb', line 48 def dot_product(other) v = coerce_vector(other) self.class.dot_product(self, v) end |
#project(other) ⇒ self
Vector projection of this vector onto another vector. The argument is coerced, so scalars work too.
v1 = Vector2d(2, 3)
v2 = Vector2d(4, 0)
v1.project(v2) # => Vector2d(2.0,0.0)
The zero vector has no direction, and there is nothing to project onto. The zero vector is returned.
v1.project(Vector2d(0, 0)) # => Vector2d(0.0,0.0)
85 86 87 88 89 90 91 |
# File 'lib/vector2d/projection.rb', line 85 def project(other) v = coerce_vector(other) return build(0.0, 0.0) if v.zero? scale = dot_product(v).to_f / v.length_squared build(v.x * scale, v.y * scale) end |
#reflect(normal) ⇒ self
Reflects this vector about the line perpendicular to the normal, the way a ray bounces off a surface. The normal is normalized internally, so it can be of any length.
vector = Vector2d(2, 3)
vector.reflect(Vector2d(0, 1)) # => Vector2d(2.0,-3.0)
vector.reflect(Vector2d(0, 5)) # => Vector2d(2.0,-3.0)
The zero vector has no direction, and defines no surface to reflect off. Nothing is reflected, and the vector is returned.
vector.reflect(Vector2d(0, 0)) # => Vector2d(2.0,3.0)
148 149 150 151 152 153 154 |
# File 'lib/vector2d/projection.rb', line 148 def reflect(normal) v = coerce_vector(normal) return to_f_vector if v.zero? n = v.normalize self - (n * (2 * dot_product(n))) end |
#refract(normal, refractive_index) ⇒ self
Refracts this vector through a surface with the given normal and ratio of refractive indices, the way a ray bends entering a different medium. The normal is normalized internally, so it can be of any length.
ray = Vector2d(1, -1).normalize
ray.refract(Vector2d(0, 1), 0.5) # => Vector2d(0.3535..,-0.9354..)
ray.refract(Vector2d(0, 5), 0.5) # => Vector2d(0.3535..,-0.9354..)
A ratio of one leaves the ray on its course.
ray.refract(Vector2d(0, 1), 1.0) # => Vector2d(0.7071..,-0.7071..)
Past the critical angle the ray does not cross the surface at all. This is total internal reflection, and the zero vector is returned.
ray.refract(Vector2d(0, 1), 2.0) # => Vector2d(0.0,0.0)
The zero vector has no direction, and defines no surface to refract through. Nothing is refracted, and the vector is returned.
ray.refract(Vector2d(0, 0), 0.5) # => Vector2d(0.7071..,-0.7071..)
Raises ArgumentError unless the ratio is a real number.
ray.refract(Vector2d(0, 1), Complex(1, 2)) # => ArgumentError
188 189 190 191 192 193 194 |
# File 'lib/vector2d/projection.rb', line 188 def refract(normal, refractive_index) v = coerce_vector(normal) eta = coordinate(refractive_index) return to_f_vector if v.zero? refract_through(v.normalize, eta) end |
#reject(other) ⇒ self
Vector rejection of this vector from another vector, the component left over when the projection is subtracted.
v1 = Vector2d(2, 3)
v2 = Vector2d(4, 0)
v1.reject(v2) # => Vector2d(0.0,3.0)
The zero vector has no direction, and nothing is projected away.
v1.reject(Vector2d(0, 0)) # => Vector2d(2.0,3.0)
106 107 108 |
# File 'lib/vector2d/projection.rb', line 106 def reject(other) self - project(other) end |
#scalar_projection(other) ⇒ Float
Scalar projection of this vector onto another vector, the signed length of the projection. It is negative when the vectors point in opposite directions.
v1 = Vector2d(2, 3)
v2 = Vector2d(4, 0)
v1.scalar_projection(v2) # => 2.0
v1.scalar_projection(Vector2d(-4, 0)) # => -2.0
The zero vector has no direction, and there is nothing to project onto. The scalar projection is zero.
v1.scalar_projection(Vector2d(0, 0)) # => 0.0
126 127 128 129 130 131 |
# File 'lib/vector2d/projection.rb', line 126 def scalar_projection(other) v = coerce_vector(other) return 0.0 if v.zero? dot_product(v) / v.length end |