Scurry.Vector (Scurry v3.0.0)

View Source

Functions to work on 2D vectors.

Vectors are represented as tuples of x and y components, {x :: number, y :: number}. This module provides basic trigonometry functions.

See Euclidian Vector on Wikipedia for further descriptions of the maths and use cases.

Summary

Types

A line is represented by two vertices of type vector/0

A polygon is represented by a list of vector/0, each being a tuple of {x, y} coordinates, both number/0. To be properly defined, the vertices of the polygon must be non-closed and clockwise.

A vector is represented as a tuple {x, y}, it's x and y components, both number/0. These are used for vector math in Scurry.Vector and as 2D points in Scurry.Polygon and Scurry.PolygonMap.

Functions

Add two vectors together.

Get the angle of a vector in radians.

Get the cross product of two vectors.

This is a screen oriented degree.

This is a graph oriented degree.

Get the distance of two vectors.

Get the distance squared of two vectors.

Divide a vector by a constant.

Get the dot product of two vectors.

Get the length of a vector, aka magnitude.

Get the magnitude of a vector, aka len.

Multiply a vector by a constant.

Normalise a vector to length 1.

Calls round on a vector to make a vector with integer/0 instead of float/0.

Subtract a vector from another.

Calls round on a vector to make a vector with integer/0 instead of float/0.

Types

line()

@type line() :: {vector(), vector()}

A line is represented by two vertices of type vector/0

polygon()

@type polygon() :: [vector()]

A polygon is represented by a list of vector/0, each being a tuple of {x, y} coordinates, both number/0. To be properly defined, the vertices of the polygon must be non-closed and clockwise.

vector()

@type vector() :: {x :: number(), y :: number()}

A vector is represented as a tuple {x, y}, it's x and y components, both number/0. These are used for vector math in Scurry.Vector and as 2D points in Scurry.Polygon and Scurry.PolygonMap.

Functions

add(v1, v2)

@spec add(v1 :: vector(), v2 :: vector()) :: vector()

Add two vectors together.

Params

Returns

The resulting vector of adding v1 and v2 together.

Examples

iex> Vector.add({1, 2}, {3, 4})
{4, 6}

angle(v)

@spec angle(v :: vector()) :: float()

Get the angle of a vector in radians.

Params

  • v (vector/0) describing the vector to obtain the angle for.

Returns

The angle in radians in relationship to the x-axis.

Examples

iex> Vector.angle({1, 1})
0.7853981633974483
iex> Vector.angle({0, 1})
1.5707963267948966
iex> Vector.angle({1, 0})
0.0
iex> Vector.angle({-1, 1})
2.356194490192345
iex> Vector.angle({-1, 0})
3.141592653589793
iex> Vector.angle({-1, -1})
3.9269908169872414
iex> Vector.angle({0, -1})
4.71238898038469
iex> Vector.angle({1, -1})
5.497787143782138

cross(v1, v2)

@spec cross(v1 :: vector(), v2 :: vector()) :: float()

Get the cross product of two vectors.

Params

  • v1 (vector/0) describing the first vector.
  • v2 (vector/0) describing the second vector to 'cross' against v2.

Returns the cross product of v1 and v2, v1 × v2.

Examples

iex> Vector.cross({1, 2}, {3, 4})
-2

degrees(v)

@spec degrees(v :: vector()) :: integer()

This is a screen oriented degree.

Screen degrees are in

  • North=up (0)
  • South=down (180) degrees.

Vectors are in (x,y) screen coordinate, so (1,1) = 135 degrees (down to the right/ south-east) from 0,0, the top left corner is 0,0.

This layout maps how eg. :wx defines the coordinates.

Params

  • v (vector/0) of coordinates describing the vector to obtain the angle for.

Returns

The vector in degrees relative to the y-axis.

Examples

iex> Vector.degrees({0, -1})
0
iex> Vector.degrees({1, -1})
45
iex> Vector.degrees({1, 0})
90
iex> Vector.degrees({1, 1})
135
iex> Vector.degrees({0, 1})
180
iex> Vector.degrees({-1, 1})
225
iex> Vector.degrees({-1, 0})
270
iex> Vector.degrees({-1, -1})
315

degrees_graph(v)

@spec degrees_graph(v :: vector()) :: float()

This is a graph oriented degree.

Graph degrees are oriented as for a graph layout.

  • Right (along the x-axis) is 0°
  • Up (along y-axis) is 90°,
  • 45° is "north-east / up and to the left".

Params

  • v (vector/0) describing the vector to obtain the angle for.

Returns

The vector in degrees relative to the x-axis.

Examples

iex> Vector.degrees_graph({1, 1})
45.0
iex> Vector.degrees_graph({0, 1})
90.0
iex> Vector.degrees_graph({1, 0})
0.0
iex> Vector.degrees_graph({-1, 1})
135.0
iex> Vector.degrees_graph({-1, 0})
180.0
iex> Vector.degrees_graph({-1, -1})
225.0
iex> Vector.degrees_graph({0, -1})
270.0
iex> Vector.degrees_graph({1, -1})
315.0

distance(v1, v2)

@spec distance(v1 :: vector(), v2 :: vector()) :: float()

Get the distance of two vectors.

The distance is the length of the vector between the ends (second tuple) of the vectors.

This is equivalent to the square root of the distance_squared/2.

Params

  • v1 (vector/0) describing the first vector.
  • v2 (vector/0) describing the second vector to get the distance from v1.

Returns

The distance between the ends of v1 and v2.

Examples

iex> Vector.distance({0, 0}, {1, 1})
1.4142135623730951
iex> Vector.distance({5, 7}, {2, 3})
5.0

distance_squared(v1, v2)

@spec distance_squared(v1 :: vector(), v2 :: vector()) :: float()

Get the distance squared of two vectors.

This is equivalent to the square of the distance/2.

Params

  • v1 (vector/0) describing the first vector.
  • v2 (vector/0) describing the second vector to get the distance squared from v1.

Returns

The squared distance between the ends of v1 and v2.

Examples

iex> Vector.distance_squared({0, 0}, {1, 1})
2.0
iex> Vector.distance_squared({5, 7}, {2, 3})
25.0

div(v, c)

@spec div(v :: vector(), c :: number()) :: vector()

Divide a vector by a constant.

Dividing/multiplying a vector essentially shortens/lengthens it.

Params

Returns

The result of dividing v by c.

Examples

iex> Vector.div({10, 14}, 2)
{5.0, 7.0}

dot(v1, v2)

@spec dot(v1 :: vector(), v2 :: vector()) :: float()

Get the dot product of two vectors.

Params

  • v1 (vector/0) describing the first vector.
  • v2 (vector/0) describing the second vector to 'dot' against v1.

Returns

The dot product of v1 and v2, v1 · v2.

Examples

iex> Vector.dot({1, 2}, {3, 4})
11

len(v)

@spec len(v :: vector()) :: float()

Get the length of a vector, aka magnitude.

Params

  • v (vector/0) the vector to find the length for.

Returns

The length of the vector v.

Examples

iex> Vector.len({1, 1})
1.4142135623730951
iex> Vector.len({3, 4})
5.0
iex> Vector.len({12, 5})
13.0

mag(v)

@spec mag(v :: vector()) :: float()

Get the magnitude of a vector, aka len.

This is an alias for len/2.

Examples

iex> Vector.mag({1, 1})
1.4142135623730951
iex> Vector.mag({3, 4})
5.0
iex> Vector.mag({12, 5})
13.0

mul(v, c)

@spec mul(v :: vector(), c :: number()) :: vector()

Multiply a vector by a constant.

Params

Returns the result of multiplying v by c.

Examples

iex> Vector.mul({5, 7}, 2)
{10, 14}

normalise(v)

@spec normalise(v :: vector()) :: vector()

Normalise a vector to length 1.

This shortens the vector by it's length, so the resulting vector w has len(w) == 1, and same x/y ratio.

Params

  • v (vector/0) describing the vector to normalise.

Returns

A vector/0 with length 1, and same x/y ratio.

Examples

iex> Vector.normalise({0, 1})
{0.0, 1.0}
iex> Vector.normalise({10, 0})
{1.0, 0.0}
iex> Vector.normalise({10, 10})
{0.7071067811865475, 0.7071067811865475}

round_pos(v)

@spec round_pos(v :: vector()) :: {integer(), integer()}

Calls round on a vector to make a vector with integer/0 instead of float/0.

This is for interoperability with other libraries where coordinates must be expressed in integers, for example :wx operations for drawing.

The name ends in _pos to avoid any confusion/collision with Kernel.round/1 and to indicate the use in drawing "positions" on the screen.

Params

  • v (vector/0) describing the vector to round to integers.

Returns

Avector with it's components converted to integers using Kernel.round/1.

Examples

iex> Vector.round_pos({10.1, 10.9})
{10, 11}

sub(v1, v2)

@spec sub(v1 :: vector(), v2 :: vector()) :: vector()

Subtract a vector from another.

Params

  • v1 (vector/0) the first vector.
  • v2 (vector/0) the second vector to subtract from v1.

Returns

The resulting vector of subtracting of v2 from v1.

Examples

iex> Vector.sub({5, 7}, {1, 2})
{4, 5}

trunc_pos(v)

@spec trunc_pos(v :: vector()) :: {integer(), integer()}

Calls round on a vector to make a vector with integer/0 instead of float/0.

This is provided for interoperability with other libraries where coordinates must be expressed in integers, for example :wx operations for drawing.

The name ends in _pos to avoid any confusion/collision with Kernel.trunc/1 and to indicate the use in drawing "positions" on the screen.

Params

  • v (vector/0) describing the vector to round to integers.

Returns

The vector with it's components converted to integers using Kernel.trunc/1.

Examples

iex> Vector.trunc_pos({10.1, 10.9})
{10, 10}