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