Current section

Files

Jump to
graphmath lib Vec2.ex
Raw

lib/Vec2.ex

defmodule Graphmath.Vec2 do
@moduledoc """
This is the 2D mathematics library for graphmath.
"""
@doc"""
`create()` creates a zero vec2.
It will return a list of the form [0.0,0.0].
"""
@spec create() :: [float]
def create() do
[0.0,0.0]
end
@doc"""
`create(x,y)` creates a vec2 of value (x,y).
It will return a list of the form [x,y].
"""
@spec create(float,float) :: [float]
def create(x,y) do
[x,y]
end
@doc"""
`create(vec)` creates a vec2 of value (x,y) out of a list of 2 or more numbers.
It will return a list of the form [x,y].
"""
@spec create([float]) :: [float]
def create( vec ) do
[x,y | _] = vec
[x,y]
end
@doc """
`add( a, b)` adds a vec2 (a) to a vec2 (b).
It returns a list of the form [ ax + bx, ay + by ].
"""
@spec add( [float], [float]) :: [float]
def add( a, b ) do
[ x,y | _] = a
[ u,v | _] = b
[ x+u, y+v ]
end
@doc """
`subtract(a, b)` subtracts a vec2 (b) from a vec2 (a).
It returns a list of the form [ ax - bx, ay - by ].
"""
@spec subtract( [float], [float] ) :: [float]
def subtract( a, b) do
[ x,y | _] = a
[ u,v | _] = b
[x-u,y-v]
end
@doc """
`multiply( a, b)` mulitplies element-wise a vec2 (a) by a vec2 (b).
It returns a list of the form [ ax*bx, ay*by ].
"""
@spec multiply( [float], [float] ) :: [float]
def multiply( a, b ) do
[ x,y | _ ] = a
[ u,v | _ ] = b
[ x*u, y * v]
end
@doc """
`scale( a, scale)` uniformly scales a vec2 (a) by an amount (x).
It returns a list of the form [ ax*scale, ay*scale ].
"""
@spec scale( [float], float ) :: [float]
def scale( a, scale ) do
[ x,y | _ ] = a
[ x*scale, y*scale ]
end
@doc """
`dot( a, b)` finds the dot (inner) product of a vec2 (a) with another vec2 (b).
It returns a float of the value (ax*bx + ay*by).
"""
@spec dot( [float], [float] ) :: float
def dot( a, b) do
[ x,y | _ ] = a
[ u,v | _ ] = b
(x*u)+(y*v)
end
@doc """
`perp_prod( a, b)` finds the perpindicular product of a vec2 (a) with another vec2 (b).
The perpindicular product is the magnitude of the cross-product between the two vectors.
It returns a float of the value (ax*by - bx*ay).
"""
@spec perp_prod( [float], [float] ) :: float
def perp_prod( a, b ) do
[ x,y | _ ] = a
[ u,v | _ ] = b
(x*v) -( u*y)
end
@doc """
`length(a)` finds the length (L2 norm) of a vec2 (a).
The length is the square root of the sum of the squares of the components.
It returns a float of the value ( sqrt(ax*ax + ay*ay).
"""
@spec length( [float] ) :: float
def length( a ) do
[ x,y | _ ] = a
:math.sqrt( (x*x) + (y*y) )
end
@doc """
`length_squared(a)` finds the square of the length of a vec2 (a).
In many cases, this is sufficient for comparisions and avaoids a sqrt.
It returns a float of the value (ax*ax + ay*ay).
"""
@spec length_squared( [float] ) :: float
def length_squared( a ) do
[ x,y | _ ] = a
(x*x) + (y*y)
end
@doc """
`length_manhattan(a)` finds the Manhattan (L1 norm) length of a vec2 (a).
The Manhattan length is the sum of the components.
It returns a float of the value (ax + ay).
"""
@spec length_manhattan( [float] ) :: float
def length_manhattan( a ) do
[ x,y | _ ] = a
x + y
end
@doc """
`normalize(a)` finds the unit vector with the same direction as a vec2 (a).
This is done by dividing each component by the vector's magnitude.
It returns a list of the form [ normx, normy ].
"""
@spec normalize( [float] ) :: [float]
def normalize( a ) do
[ x,y | _ ] = a
invmag = 1 / :math.sqrt( (x*x) + (y*y) )
[x * invmag, y * invmag]
end
@doc """
`lerp(a,b,t)` is used to linearly interpolate between two given vectors a and b along an interpolant t.
The interpolant `t` is on the domain [0,1]. Behavior outside of that is undefined.
"""
@spec lerp( [float], [float], float) :: [float]
def lerp( a, b, t ) do
[ x,y | _ ] = a
[ u,v | _ ] = b
[ ( t*u) + ((1-t)*x), (t*v) + ((1-t)*y)]
end
@doc """
`rotate(a,theta)` rotates a vec2 (a) CCW about the +Z axis `theta` radians.
"""
@spec rotate( [float], float) :: [float]
def rotate( a, theta) do
[ x,y | _ ] = a
ct = :math.cos(theta)
st = :math.sin(theta)
[ x*ct + y*st, x*st - y*ct]
end
@doc """
`near(a,b, distance)` checks whether two vectors are within a length of each other.
"""
@spec near( [float], [float], float) :: boolean
def near( a, b, distance) do
[ x,y | _ ] = a
[ u,v | _ ] = b
dx = x-u
dy = y-v
distance > :math.sqrt( dx*dx + dy*dy )
end
@doc """
`project(a,b)` projects one vector onto another, and returns the resulting image.
"""
@spec project( [float], [float]) :: [float]
def project( a,b ) do
[ x,y | _ ] = a
[ u,v | _ ] = b
coeff = ((x*u) +(y*v)) / (u*u + v*v)
[u*coeff, v*coeff]
end
end