diff --git a/vec2/vec2.c b/vec2/vec2.c new file mode 100644 index 0000000000000000000000000000000000000000..9c680e62c2a7fd29b38a91f2eb6c4d44d940b5e0 --- /dev/null +++ b/vec2/vec2.c @@ -0,0 +1,112 @@ +#include "vec2.h" +#include <math.h> +#include <stdio.h> + +/// Create a 2d vector. +/// @param x_ The first component. +/// @param y_ The second component. +/// @return The newly created vector. +vec2 vec2_create(double x_, double y_) +{ + vec2 res = {x_, y_}; + return res; +} + +/// Create a zero 2d vector. +/// @return The newly created zero vector. +vec2 vec2_create_zero() { return vec2_create(0.0, 0.0); } + +/// Add two vectors. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @return The sum in a new vector. +vec2 vec2_add(vec2 lhs, vec2 rhs) +{ + return vec2_create(lhs.x + rhs.x, lhs.y + rhs.y); +} + +/// Substract two vectors. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @return The difference in a new vector. +vec2 vec2_sub(vec2 lhs, vec2 rhs) +{ + return vec2_create(lhs.x - rhs.x, lhs.y - rhs.y); +} + +/// Multiply a vector by a scalar. +/// @param lhs The left operand, a vector. +/// @param scalar The right operand, a scalar. +/// @return The product in a new vector. +vec2 vec2_mul(vec2 lhs, double scalar) +{ + return vec2_create(lhs.x * scalar, lhs.y * scalar); +} + +/// Divide a vector by a scalar. +/// @param lhs The left operand, a vector. +/// @param scalar The right operand, a scalar. +/// @return The quotien in a new vector. +vec2 vec2_div(vec2 lhs, double scalar) +{ + return vec2_create(lhs.x / scalar, lhs.y / scalar); +} + +/// Compute the dot product (scalar product) between two vectors. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @return The dot product. +double vec2_dot(vec2 lhs, vec2 rhs) +{ + return (lhs.x * rhs.x) + (lhs.y * rhs.y); +} + +/// Compute the square of the euclidean norm of a given vector. +/// @param v The vector. +/// @return The square of the norm. +double vec2_norm_sqr(vec2 v) { return pow(v.x, 2) + pow(v.y, 2); } + +/// Compute the euclidean norm of a given vector. +/// @param v The vector. +/// @return The norm. +double vec2_norm(vec2 v) { return sqrt(pow(v.x, 2) + pow(v.y, 2)); } + +/// Compute the normalization of a given vector. +/// @param v The vector. +/// @return The new normalized vector. +vec2 vec2_normalize(vec2 v) +{ + return vec2_create(v.x / vec2_norm(v), v.y / vec2_norm(v)); +} + +/// Check whether two vectors are approximately equals within a given +/// tolerance. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @param eps The tolerance. +/// @return true if vector are approximately equal, false otherwise. +bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps) +{ + double diff = fabs(vec2_norm(lhs) - vec2_norm(rhs)); + return diff <= eps; +} + +/// Compute the coordinates of a 2d vector (with components between 0 and 1) +/// in a given screen matrix. +/// @param v The 2d vector. +/// @param width The screen width. +/// @param height The screen height. +/// @return The coordinates (rwo, column). +coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height) +{ + width--; + height--; + coordinates coord = {.row = floor((height / 2.0) + (v.y * (height / 2.0))), + .column = + floor((width / 2.0) + (v.x * (width / 2.0)))}; + return coord; +} + +/// Print a vector in the standard output. +/// @param v The vector. +void vec2_print(vec2 v) { printf("x = %g, y = %g\n", v.x, v.y); } diff --git a/vec2/vec2.h b/vec2/vec2.h new file mode 100644 index 0000000000000000000000000000000000000000..af101bfd1dcdf20ba89d8106ba8013375d9429b1 --- /dev/null +++ b/vec2/vec2.h @@ -0,0 +1,43 @@ +#ifndef _VEC2_H_ +#define _VEC2_H_ + +#include <stdbool.h> +#include <stdint.h> + +typedef struct +{ + double x, y; +} vec2; + +typedef struct +{ + uint32_t row, column; +} coordinates; + +vec2 vec2_create(double x_, double y_); + +vec2 vec2_create_zero(); + +vec2 vec2_add(vec2 lhs, vec2 rhs); + +vec2 vec2_sub(vec2 lhs, vec2 rhs); + +vec2 vec2_mul(vec2 lhs, double scalar); + +vec2 vec2_div(vec2 lhs, double scalar); + +double vec2_dot(vec2 lhs, vec2 rhs); + +double vec2_norm_sqr(vec2 v); + +double vec2_norm(vec2 v); + +vec2 vec2_normalize(vec2 v); + +bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps); + +coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height); + +void vec2_print(vec2 v); + +#endif diff --git a/vector/test.c b/vector/test.c deleted file mode 100644 index 7bd51baadccd26adfa240b7deb5381763dd6cd0d..0000000000000000000000000000000000000000 --- a/vector/test.c +++ /dev/null @@ -1,96 +0,0 @@ -// cmocka includes -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -// vector include -#include <stdio.h> -#include <stdbool.h> -#include "vector.h" - -//* ==================== -//* Tests descriptions -//* ==================== -static void vector_initialization() { - vec2 v = {2, 3}; - - assert_non_null(&v); -} - -static void vector_addition() { - vec2 v1 = {2, 5}; - vec2 v2 = {3, 7}; - vec2 v3; - - vec2 target = {5, 12}; - - v3 = add_vector(v1, v2); - - assert_memory_equal(&v3, &target, sizeof(target)); -} - -static void vector_substraction() { - vec2 v1 = {2, 5}; - vec2 v2 = {3, 7}; - vec2 v3; - - vec2 target = {-1, -2}; - - v3 = sub_vector(v1, v2); - - assert_memory_equal(&v3, &target, sizeof(target)); -} - -static void vector_multiplication_scalar() { - vec2 v1 = {2, 5}; - int scal = 2; - vec2 v2; - - vec2 target = {4, 10}; - - v2 = mult_by_scalar(v1, scal); - - assert_memory_equal(&v2, &target, sizeof(target)); -} - -static void vector_to_polar_convertion() { - vec2 c_v = {84.85, -84.85}; - polarVector p_v; - - polarVector target = {119.996, -45}; - - p_v = to_polar(c_v); - - assert_float_equal(p_v.a, target.a, 1e-3); - assert_float_equal(p_v.f, target.f, 1e-3); -} - -static void vector_to_cartesian_convertion() { - polarVector p_v = {200, 60}; - vec2 c_v; - - vec2 target = {100, 173.205}; - - c_v = to_cartesian(p_v); - - assert_float_equal(c_v.x, target.x, 1e-3); - assert_float_equal(c_v.y, target.y, 1e-3); -} - -//* ==================== -//* Run test -//* ==================== -int main(void) { - const struct CMUnitTest tests[] = { - cmocka_unit_test(vector_initialization), - cmocka_unit_test(vector_addition), - cmocka_unit_test(vector_substraction), - cmocka_unit_test(vector_multiplication_scalar), - cmocka_unit_test(vector_to_polar_convertion), - cmocka_unit_test(vector_to_cartesian_convertion), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); -} \ No newline at end of file diff --git a/vector/vector.c b/vector/vector.c deleted file mode 100644 index bbe8504b89a1c90e8409972b9db91909ee77989c..0000000000000000000000000000000000000000 --- a/vector/vector.c +++ /dev/null @@ -1,108 +0,0 @@ -/*! \file Library for vector operations - All the operations are made with a Cartesian vector. If you want a Polar vector, call to_polar(). -*/ - -// To be able to use mathematical constant defined in math.h -#ifndef __USE_MISC -#define __USE_MISC -#endif - -#include <math.h> -#include <stdio.h> -#include "vector.h" - -vec2 init_vector(double x, double y) { - vec2 v = {x, y}; - - return v; -} - -/*! \fn vector add_vector(vector v1, vector v2) - \brief Add two vector and return the final vector - \param v1 First vector to add - \param v2 Second vector to add -*/ -vec2 add_vector(vec2 v1, vec2 v2) { - vec2 resultVector; - - double finalX = v1.x + v2.x; - double finalY = v1.y + v2.y; - - resultVector.x = finalX; - resultVector.y = finalY; - - return resultVector; -} - -/*! \fn vector sub_vector(vector v1, vector v2) - \brief Substract two vector and return the final vector - \param v1 First vector - \param v2 Vector we want to substract to the first -*/ -vec2 sub_vector(vec2 v1, vec2 v2) { - // First we reverse the direction of the vector we want to substract - v2.x *= -1; - v2.y *= -1; - - // Then add them as usual - return add_vector(v1, v2); -} - -/*! \fn vector mult_by_scalar(vector v1, int scalar) - \brief Multiply a vector by a scalar - \param v1 Vector to multiply - \param scalar Scalar to use for the multiplication -*/ -vec2 mult_by_scalar(vec2 v1, int scalar) { - vec2 resultVector = {v1.x * scalar, v1.y * scalar}; - - return resultVector; -} - -/*! \fn double norm(vector v1) - \brief Get the norm of a given vector - \param v1 Vector to multiply -*/ -double norm(vec2 v1) { - double vectorNorm; - - vectorNorm = sqrt(pow(v1.x, 2) + pow(v1.y, 2)); - - return vectorNorm; -} - -/*! \fn double dot_multiply(vector v1, vector v2) - \brief Multiply two vector with the dot product formula - \param v1 First vector to multiply - \param v2 Second vector to multiply -*/ -double dot_multiply(vec2 v1, vec2 v2) { - return (v1.x * v2.x) + (v1.y * v2.y); -} - -/*! \fn polarVector to_polar(vector v1) - \brief Convert a Cartesian vector to a Polar vector - \param v1 Cartesian vector -*/ -polarVector to_polar(vec2 v1) { - polarVector p_vector; - - p_vector.f = norm(v1); - p_vector.a = atan(v1.y / v1.x) * (180.0 / M_PI); // The atan return a radian angle. Use `* 180 / M_PI` to convert it in degree - - return p_vector; -} - -/*! \fn vector to_cartesian(polarVector v1) - \brief Convert a Polar vector to a Cartesian vector - \param v1 Polar vector -*/ -vec2 to_cartesian(polarVector v1) { - vec2 c_vector; - - // The cos work with radian angle. Convert degree to radiant inside the cos function to have the correct force - c_vector.x = v1.f * cos(v1.a * (M_PI / 180.0)); - c_vector.y = v1.f * sin(v1.a * (M_PI / 180.0)); - - return c_vector; -} diff --git a/vector/vector.h b/vector/vector.h deleted file mode 100644 index 205768d70c343e518640243199fca8aa8014c0cd..0000000000000000000000000000000000000000 --- a/vector/vector.h +++ /dev/null @@ -1,35 +0,0 @@ -/*! \file Abstract of the vector-lib file - Contains the skeleton of the vector-lib file. All the functions and structs are defined here. -*/ - -#ifndef VECTOR_H_ /* Header guard. Prevent the error of double inclusion inside a program. See : https://fr.wikipedia.org/wiki/Include_guard */ -#define VECTOR_H_ - -/** - * @brief Cartesian vector - */ -typedef struct { - double x; - double y; -} vec2; - -/** - * @brief Polar vector used for representation only - */ -typedef struct { - double f; /* Force of the vector */ - double a; /* Angle of the vector */ -} polarVector; - -vec2 init_vector(double x, double y); /* Initialize a new vector */ -vec2 add_vector(vec2 v1, vec2 v2); /* Add a vector to another and return the result as a vector */ -vec2 sub_vector(vec2 v1, vec2 v2); /* Substract a vector to another vector and return the result as a vector */ -vec2 mult_by_scalar(vec2 v1, int scalar); /* Multiply a vector by a scalar */ -double dot_multiply(vec2 v1, vec2 v2); /* Multiply two vectors with the dot product formula */ -double norm(vec2 v1); /* Get the norm of a given vector */ -polarVector to_polar(vec2 v1); /* Convert a Cartesian vector to a Polar vector */ -vec2 to_cartesian(polarVector v1); /* Convert a Polar vector to a Cartesian vector */ - -/* For the moment, the cross product hasn't be inplemented because it only work with vectors on 3 dimentionals plan. */ - -#endif /* VECTOR_H_ */