From 211942a8928c4abe9674214e30a0ed03dc85fc96 Mon Sep 17 00:00:00 2001 From: Boris Stefanovic <owldev@bluewin.ch> Date: Thu, 28 Apr 2022 11:59:07 +0200 Subject: [PATCH] ADD: vec2 --- utils/vec2/vec2.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++ utils/vec2/vec2.h | 43 +++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 utils/vec2/vec2.c create mode 100644 utils/vec2/vec2.h diff --git a/utils/vec2/vec2.c b/utils/vec2/vec2.c new file mode 100644 index 0000000..60a972b --- /dev/null +++ b/utils/vec2/vec2.c @@ -0,0 +1,114 @@ +#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_) { + return (vec2) {.x = x_, .y = y_}; +} + +/// 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) {.x = lhs.x + rhs.x, .y = 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) {.x = lhs.x - rhs.x, .y = lhs.y - rhs.y}; +} + +/// Multiply a vector by a scalar. +/// @param scalar The left operand, a scalar. +/// @param rhs The right operand, a vector. +/// @return The product in a new vector. +vec2 vec2_mul(double scalar, vec2 rhs) { + return (vec2) {.x = scalar * rhs.x, .y = scalar * rhs.y}; +} + +/// 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 v.x * v.x + v.y * v.y; +} + +/// Compute the euclidean norm of a given vector. +/// @param v The vector. +/// @return The norm. +double vec2_norm(vec2 v) { + return sqrt(vec2_norm_sqr(v)); +} + +/// Compute the normalization of a given vector. +/// @param v The vector. +/// @return The new normalized vector. +vec2 vec2_normalize(vec2 v) { + double norm = vec2_norm(v); + if (0 == norm) { return vec2_create_zero(); } + return (vec2) {.x = v.x / norm, .y = v.y / norm}; +} + +/// 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 Approx equality with range eps. +bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps) { + //return (fabs(lhs.x - rhs.x) < eps) && (fabs(lhs.y - rhs.y) < eps); + vec2 dif = vec2_sub(lhs, rhs); + double norm = vec2_norm(dif); + return norm < 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) { + return (coordinates) { + .column = (uint32_t)(v.x * width), + .row = (uint32_t)(v.y * height) + }; +} + +/// 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); +} + +/// Same as vec2_to_coordinates but (0,0) is at the center of the screen. +/// @param v The 2d vector: components between -1.0 and +1.0 +/// @param width The screen width. +/// @param height The screen height. +coordinates vec2_to_coordinates_centered(const vec2 v, const uint32_t width, const uint32_t height) { + return (coordinates) { + .column = (uint32_t)((v.x + 1.0) * width / 2), + .row = (uint32_t)((v.y + 1.0) * height / 2) + }; +} diff --git a/utils/vec2/vec2.h b/utils/vec2/vec2.h new file mode 100644 index 0000000..96ce1b7 --- /dev/null +++ b/utils/vec2/vec2.h @@ -0,0 +1,43 @@ +#ifndef _VEC2_H_ +#define _VEC2_H_ + +#include <stdbool.h> +#include <stdint.h> + +typedef struct _vec2 +{ + double x, y; +} vec2; + +typedef struct _coordinates +{ + 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(double scalar, vec2 rhs); + +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); + +coordinates vec2_to_coordinates_centered(const vec2 v, const uint32_t width, const uint32_t height); + +#endif -- GitLab