forked from Mirrors/openclonk
275 lines
5.6 KiB
C
275 lines
5.6 KiB
C
/**
|
|
Library for vector operations.
|
|
|
|
@author Marky
|
|
@credits Randrian, since many functions have their origin in the rope physics library.
|
|
*/
|
|
|
|
|
|
/**
|
|
Addition of two vectors of the same dimension.
|
|
Note: Cannot be named 'Add' because the scenario
|
|
save mechanism will throw a lot of warnings.
|
|
@par a The first vector.
|
|
@par b The second vector.
|
|
@return array The vector (a_i + b_i), i=1,...,n.
|
|
*/
|
|
public func Sum(array a, array b)
|
|
{
|
|
AssertVectorOperation(a, b);
|
|
|
|
var vector = [];
|
|
|
|
for (var i = 0; i < GetLength(a); i++)
|
|
{
|
|
vector[i] = a[i] + b[i];
|
|
}
|
|
|
|
return vector;
|
|
}
|
|
|
|
|
|
/**
|
|
Subtraction of two vectors of the same dimension.
|
|
@par a The first vector.
|
|
@par b The second vector.
|
|
@return array The vector (a_i - b_i), i=1,...,n.
|
|
*/
|
|
public func Subtract(array a, array b)
|
|
{
|
|
AssertVectorOperation(a, b);
|
|
|
|
var vector = [];
|
|
|
|
for (var i = 0; i < GetLength(a); i++)
|
|
{
|
|
vector[i] = a[i] - b[i];
|
|
}
|
|
|
|
return vector;
|
|
}
|
|
|
|
|
|
/**
|
|
Multiplication of a vector and a number.
|
|
@par a The vector
|
|
@par b The number
|
|
@return array The vector (b * a_i), i=1,...,n.
|
|
*/
|
|
public func Multiply(array a, int b)
|
|
{
|
|
AssertNotNil(a, "vector 'a'");
|
|
|
|
var vector = [];
|
|
|
|
for (var i = 0; i < GetLength(a); i++)
|
|
{
|
|
vector[i] = b * a[i];
|
|
}
|
|
|
|
return vector;
|
|
}
|
|
|
|
|
|
/**
|
|
Division of a vector and a number.
|
|
@par a The vector
|
|
@par b The number
|
|
@return array The vector (a_i / b), i=1,...,n.
|
|
*/
|
|
public func Divide(array a, int b)
|
|
{
|
|
AssertNotNil(a, "vector 'a'");
|
|
|
|
var vector = [];
|
|
|
|
for (var i = 0; i < GetLength(a); i++)
|
|
{
|
|
vector[i] = a[i] / b;
|
|
}
|
|
|
|
return vector;
|
|
}
|
|
|
|
|
|
/**
|
|
Dot product of two vectors of the same dimension.
|
|
@par a The first vector
|
|
@par b The second vector
|
|
@return int Sum of a_i * b_i, for i = 1,...,n
|
|
*/
|
|
public func DotProduct(array a, array b)
|
|
{
|
|
AssertVectorOperation(a, b);
|
|
|
|
var sum = 0;
|
|
|
|
for (var i = 0; i < GetLength(a); i++)
|
|
{
|
|
sum += a[i] * b[i];
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
/**
|
|
Product of the elements of vectors of the same dimension.
|
|
@par a The first vector
|
|
@par b The second vector
|
|
@return array the vector c_i of c_i = a_i * b_i, for i = 1,...,n
|
|
*/
|
|
public func Product(array a, array b)
|
|
{
|
|
AssertVectorOperation(a, b);
|
|
|
|
var vector = [];
|
|
|
|
for (var i = 0; i < GetLength(a); i++)
|
|
{
|
|
vector[i] = a[i] * b[i];
|
|
}
|
|
|
|
return vector;
|
|
}
|
|
|
|
/**
|
|
Euclidean length of a vector.
|
|
@par a The vector.
|
|
@return int Square root of the sum of a_i * a_i, for i=1,...,n.
|
|
*/
|
|
public func Length(array a)
|
|
{
|
|
return Sqrt(DotProduct(a, a));
|
|
}
|
|
|
|
|
|
/**
|
|
The dimension of a vector.
|
|
@par a The vector
|
|
@return int The number of elements of the vector.
|
|
*/
|
|
public func Dimension(array a)
|
|
{
|
|
AssertNotNil(a, "vector 'a'");
|
|
|
|
return GetLength(a);
|
|
}
|
|
|
|
|
|
/**
|
|
Angle between two vectors.
|
|
@par a A two-dimensional vector.
|
|
@par b A two-dimensional vector.
|
|
@return int The angle between a and b. If you rotate a by this angle,
|
|
then it will point in the same direction as b.
|
|
*/
|
|
public func AngleBetween(array a, array b, int precision)
|
|
{
|
|
AssertVectorOperation(a, b);
|
|
if (!precision) precision = 1;
|
|
|
|
var rot_a = GetRotation(a, precision);
|
|
var rot_b = GetRotation(b, precision);
|
|
return rot_b - rot_a;
|
|
}
|
|
|
|
|
|
/**
|
|
Angle of a vector.
|
|
@par a A two-dimensional vector.
|
|
@par precision [opt] Multiplied with the angle, for higher precision. A precision of 10 will produce values from 0 to 3600.
|
|
@return int The angle of a, relative to the coordinate system.
|
|
*/
|
|
public func GetRotation(array a, int precision)
|
|
{
|
|
AssertDimension(a, 2);
|
|
if (!precision) precision = 1;
|
|
|
|
return Angle(0, 0, a[0], a[1], precision);
|
|
}
|
|
|
|
|
|
/**
|
|
Normalizes a vector with precision.
|
|
@par a The vector.
|
|
@par precision Factor for the resultion length.
|
|
@return array The normalized vector with length = 1 * precision
|
|
*/
|
|
public func Normalize(array a, int precision)
|
|
{
|
|
if (!precision) precision = 1;
|
|
return Divide(Multiply(a, precision), Length(a));
|
|
}
|
|
|
|
|
|
/**
|
|
Rotates a vector by an angle.
|
|
@par a The vector.
|
|
@par angle The angle that the vector is rotated by, clockwise.
|
|
@return array The rotated vector.
|
|
*/
|
|
public func Rotate(array a, int angle, int precision)
|
|
{
|
|
AssertDimension(a, 2);
|
|
if (!precision) precision = 1;
|
|
var length_precision = 1000;
|
|
|
|
var cos = Cos(angle, length_precision, precision);
|
|
var sin = Sin(angle, length_precision, precision);
|
|
|
|
var rotated_x = cos * a[0] - sin * a[1];
|
|
var rotated_y = sin * a[0] + cos * a[1];
|
|
|
|
return [rotated_x / length_precision, rotated_y / length_precision];
|
|
}
|
|
|
|
|
|
/**
|
|
Assert that a vector operation can be done with these two vectors.
|
|
The vectors have to be of the same dimension and their elements
|
|
must have the same names.
|
|
@par a The first vector, must not be nil.
|
|
@par b The second vector, must not be nil.
|
|
*/
|
|
public func AssertVectorOperation(array a, array b)
|
|
{
|
|
AssertNotNil(a, "vector 'a'");
|
|
AssertNotNil(b, "vector 'b'");
|
|
|
|
var length_a = GetLength(a);
|
|
var length_b = GetLength(b);
|
|
if (length_a != length_b)
|
|
{
|
|
FatalError(Format("This method only works with vectors of the same length. Vector 'a' has %d elements, vector 'b' has %d elements", length_a, length_b));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Asserts that a vector has a specific dimesion.
|
|
@par a The vector.
|
|
@par dimension The dimension.
|
|
*/
|
|
public func AssertDimension(array a, int dimension)
|
|
{
|
|
var dim = Dimension(a);
|
|
if (dim != dimension)
|
|
{
|
|
FatalError(Format("The function expects a vector of length %d, got length %d", dimension, dim));
|
|
}
|
|
}
|
|
|
|
/**
|
|
Asserts that a parameter is not nil.
|
|
@par parameter The parameter that is checked.
|
|
@par message [optional] a descriptive message for the parameter that is printed in the fatal error.
|
|
*/
|
|
public func AssertNotNil(parameter, string message)
|
|
{
|
|
if (parameter == nil)
|
|
{
|
|
if (!message) message = "parameter";
|
|
|
|
FatalError(Format("Expected %s that is not nil", message));
|
|
}
|
|
} |