openclonk/planet/Objects.ocd/Libraries.ocd/Vector.ocd/Script.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));
}
}