Gama C Library
Gama C API Documentation
position.h
Go to the documentation of this file.
1#pragma once
2
3#include "../_math.h"
4#include <stddef.h>
5#include <string.h>
6
7#include "../str.h"
8/**
9 * @brief Represents a 3D position or vector.
10 */
11typedef struct {
12 double x, y, z; /**< The X, Y, and Z coordinates. */
13} gm3Pos;
14
15/**
16 * @brief Creates a new `gm3Pos` struct with the given coordinates.
17 * @param x The X-coordinate.
18 * @param y The Y-coordinate.
19 * @param z The Z-coordinate.
20 * @return A new `gm3Pos` instance.
21 */
22#define gm3pos(x, y, z) ((gm3Pos){x, y, z})
23
24/**
25 * @brief Sets the coordinates of an existing `gm3Pos` struct.
26 * @param p A pointer to the `gm3Pos` struct to modify.
27 * @param x The new X-coordinate.
28 * @param y The new Y-coordinate.
29 * @param z The new Z-coordinate.
30 */
31static inline void gm3_pos_set(gm3Pos *p, double x, double y, double z) {
32 p->x = x;
33 p->y = y;
34 p->z = z;
35}
36
37/**
38 * @brief Calculates the magnitude (length) of a `gm3Pos` vector.
39 * @param p The `gm3Pos` vector.
40 * @return The magnitude of the vector.
41 */
42#define gm3_pos_magnitude(p) sqrt((p).x *(p).x + (p).y * (p).y + (p).z * (p).z)
43
44/**
45 * @brief Calculates the Euclidean distance between two `gm3Pos` points.
46 * @param a The first `gm3Pos` point.
47 * @param b The second `gm3Pos` point.
48 * @return The distance between the two points.
49 */
50#define gm3_pos_distance(a, b) \
51 sqrt(pow((a).x - (b).x, 2) + pow((a).y - (b).y, 2) + pow((a).z - (b).z, 2))
52
53/**
54 * @brief Creates a `gm3Pos` from a 2D `gmPos` and a Z-coordinate.
55 * @param p The 2D `gmPos`.
56 * @param z The Z-coordinate.
57 * @return A new `gm3Pos` instance.
58 */
59#define gm3_pos_from2(p, z) gm3pos((p).x, (p).y, z)
60
61/**
62 * @brief Performs a simple perspective projection of a 3D point onto a 2D plane.
63 *
64 * This macro assumes a camera at the origin looking down the Z-axis, and
65 * projects the point onto the Z=1 plane.
66 *
67 * @param p The `gm3Pos` to project.
68 * @return A `gmPos` representing the 2D projected coordinates.
69 */
70#define gm3_pos_project_simple(p) gmpos((p).x / (p).z, (p).y / (p).z)
71
72/**
73 * @brief Calculates the midpoint between two `gm3Pos` points.
74 * @param p A pointer to the `gm3Pos` to store the result.
75 * @param va The first `gm3Pos` point.
76 * @param vb The second `gm3Pos` point.
77 */
78static inline void gm3_pos_center(gm3Pos *p, const gm3Pos *va,
79 const gm3Pos *vb) {
80 p->x = (va->x + vb->x) / 2.0;
81 p->y = (va->y + vb->y) / 2.0;
82 p->z = (va->z + vb->z) / 2.0;
83}
84/**
85 * @brief Calculates the centroid of three `gm3Pos` points (e.g., a triangle).
86 * @param p A pointer to the `gm3Pos` to store the result.
87 * @param va The first `gm3Pos` point.
88 * @param vb The second `gm3Pos` point.
89 * @param vc The third `gm3Pos` point.
90 */
91static inline void gm3_pos_center3(gm3Pos *p, const gm3Pos *va,
92 const gm3Pos *vb, const gm3Pos *vc) {
93 p->x = (va->x + vb->x + vc->x) / 3.0;
94 p->y = (va->y + vb->y + vc->y) / 3.0;
95 p->z = (va->z + vb->z + vc->z) / 3.0;
96}
97
98/**
99 * @brief Subtracts one `gm3Pos` vector from another (va = va - vb).
100 * @param va A pointer to the first `gm3Pos` vector (modified in place).
101 * @param vb The second `gm3Pos` vector.
102 */
103static inline void gm3_pos_substract(gm3Pos *va, const gm3Pos *vb) {
104 va->x -= vb->x;
105 va->y -= vb->y;
106 va->z -= vb->z;
107}
108
109/**
110 * @brief Adds one `gm3Pos` vector to another (va = va + vb).
111 * @param va A pointer to the first `gm3Pos` vector (modified in place).
112 * @param vb The second `gm3Pos` vector.
113 */
114static inline void gm3_pos_add(gm3Pos *va, const gm3Pos *vb) {
115 va->x += vb->x;
116 va->y += vb->y;
117 va->z += vb->z;
118}
119
120/**
121 * @brief Normalizes a `gm3Pos` vector to a unit length (magnitude of 1).
122 * @param v A pointer to the `gm3Pos` vector to normalize (modified in place).
123 */
124static inline void gm3_pos_normalize(gm3Pos *v) {
125 double m = gm3_pos_magnitude(*v);
126 if (m == 0) return; // Avoid division by zero
127 v->x /= m;
128 v->y /= m;
129 v->z /= m;
130}
131
132/**
133 * @brief Calculates the dot product of two `gm3Pos` vectors.
134 * @param a The first `gm3Pos` vector.
135 * @param b The second `gm3Pos` vector.
136 * @return The dot product (scalar value).
137 */
138#define gm3_pos_dot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z)
139
140/**
141 * @brief Calculates the cross product of two `gm3Pos` vectors (a x b).
142 * @param a The first `gm3Pos` vector.
143 * @param b The second `gm3Pos` vector.
144 * @return A new `gm3Pos` vector representing the cross product.
145 */
146#define gm3_pos_cross(a, b) \
147 ((gm3Pos){(a).y * (b).z - (a).z * (b).y, (a).z * (b).x - (a).x * (b).z, \
148 (a).x * (b).y - (a).y * (b).x})
149
150/**
151 * @brief Resets the coordinates of a `gm3Pos` struct to (0, 0, 0).
152 * @param p A pointer to the `gm3Pos` struct to reset.
153 */
154#define gm3_pos_reset(p) memset(p, 0, sizeof(*p))
155
156/**
157 * @brief Calculates the center of a given array of `gm3Pos` points.
158 * @param arr An array of `gm3Pos` points.
159 * @param n The number of points in the array.
160 * @return A new `gm3Pos` representing the average center of the points.
161 */
162static inline gm3Pos gm3_pos_centerN(const gm3Pos *arr, const size_t n) {
163 gm3Pos res = {0};
164 if (n == 0) return res;
165 double dn = (double)n;
166 for (size_t i = 0; i < n; i++) {
167 res.x += arr[i].x / dn;
168 res.y += arr[i].y / dn;
169 res.z += arr[i].z / dn;
170 }
171 return res;
172}
173
174/**
175 * @brief Multiplies the components of a `gm3Pos` vector by the corresponding
176 * components of another `gm3Pos` vector (component-wise multiplication).
177 * @param res A pointer to the `gm3Pos` vector to modify (result stored here).
178 * @param trans The `gm3Pos` vector to multiply by.
179 */
180void gm3_pos_mul(gm3Pos *res, const gm3Pos *trans) {
181 res->x *= trans->x;
182 res->y *= trans->y;
183 res->z *= trans->z;
184}
185/**
186 * @brief Multiplies the components of a `gm3Pos` vector by a scalar value.
187 * @param res A pointer to the `gm3Pos` vector to modify (result stored here).
188 * @param s The scalar value to multiply by.
189 */
190void gm3_pos_mul_scalar(gm3Pos *res, double s) {
191 res->x *= s;
192 res->y *= s;
193 res->z *= s;
194}
195
196/**
197 * @brief Converts a `gm3Pos` struct to a string representation for debugging.
198 * @param str A pointer to a `gmStr` buffer to append the string to.
199 * @param pos The `gm3Pos` struct to convert.
200 * @return 0 on success.
201 */
202int gmg_pos3(gmStr *str, gm3Pos pos) {
203 char buffer[128];
204 snprintf(buffer, sizeof(buffer), "(gm3Pos){%.6g, %.6g, %.6g}", pos.x, pos.y,
205 pos.z);
206 gm_str_append(str, buffer);
207 return 0;
208}
int gmg_pos3(gmStr *str, gm3Pos pos)
Converts a gm3Pos struct to a string representation for debugging.
Definition position.h:202
void gm3_pos_mul(gm3Pos *res, const gm3Pos *trans)
Multiplies the components of a gm3Pos vector by the corresponding components of another gm3Pos vector...
Definition position.h:180
#define gm3_pos_magnitude(p)
Calculates the magnitude (length) of a gm3Pos vector.
Definition position.h:42
void gm3_pos_mul_scalar(gm3Pos *res, double s)
Multiplies the components of a gm3Pos vector by a scalar value.
Definition position.h:190
Defines a dynamic string structure and provides utility functions for its manipulation.
Represents a 3D position or vector.
Definition position.h:11
double y
Definition position.h:12
double z
Definition position.h:12
double x
Definition position.h:12
Represents a dynamic, heap-allocated string.
Definition str.h:21