#ifndef __GE_VECTOR2_H__ #define __GE_VECTOR2_H__ /** * @file ge_vector2i.h * @brief 2D整数向量库 (仿Godot Vector2i设计) 不依赖任何库的单文件 * @defgroup Vector2 2D向量操作 */ #include typedef int32_t ge_unit_t; /**< 坐标值类型定义 */ // #define GE_VEC2I_USE_SHORT_NAMES #ifdef GE_ABS #undef GE_ABS #define GE_ABS(x) ((x) > 0 ? (x) : -(x)) #endif /** * @struct ge_vector2_t * @brief 2D整数向量结构体 * @ingroup Vector2 */ typedef struct { ge_unit_t x; /**< X轴坐标 */ ge_unit_t y; /**< Y轴坐标 */ } ge_vector2i_t; // ========================= 构造函数 ========================= /** * @def GE_VEC2I * @brief 创建向量 (x, y) * @param x_val X坐标值 * @param y_val Y坐标值 * @return 构造的向量 * @ingroup Vector2 */ #define GE_VEC2I(x_val, y_val) ((ge_vector2i_t){(x_val), (y_val)}) // ========================= 常量定义 ========================= /** @def GE_VEC2I_ZERO 零向量 (0, 0) */ #define GE_VEC2I_ZERO GE_VEC2I(0, 0) /** @def GE_VEC2I_ONE 单位向量 (1, 1) */ #define GE_VEC2I_ONE GE_VEC2I(1, 1) /** @def GE_VEC2I_LEFT 左方向向量 (-1, 0) */ #define GE_VEC2I_LEFT GE_VEC2I(-1, 0) /** @def GE_VEC2I_RIGHT 右方向向量 (1, 0) */ #define GE_VEC2I_RIGHT GE_VEC2I(1, 0) /** @def GE_VEC2I_UP 上方向向量 (0, -1) */ #define GE_VEC2I_UP GE_VEC2I(0, -1) /** @def GE_VEC2I_DOWN 下方向向量 (0, 1) */ #define GE_VEC2I_DOWN GE_VEC2I(0, 1) // ========================= 运算宏定义 ========================= /** * @def GE_VEC2I_ADD * @brief 向量加法 * @param a 第一个向量 * @param b 第二个向量 * @return a + b * @ingroup Vector2 */ #define GE_VEC2I_ADD(a, b) GE_VEC2I((a).x + (b).x, (a).y + (b).y) /** * @def GE_VEC2I_SUB * @brief 向量减法 * @param a 被减向量 * @param b 减数向量 * @return a - b * @ingroup Vector2 */ #define GE_VEC2I_SUB(a, b) GE_VEC2I((a).x - (b).x, (a).y - (b).y) /** * @def GE_VEC2I_MUL * @brief 向量分量乘法 * @param a 第一个向量 * @param b 第二个向量 * @return a * b (分量相乘) * @ingroup Vector2 */ #define GE_VEC2I_MUL(a, b) GE_VEC2I((a).x * (b).x, (a).y * (b).y) /** * @def GE_VEC2I_DIV * @brief 向量分量除法 * @param a 被除向量 * @param b 除数向量 * @return a / b (分量相除),如果分母为0会出现严重错误 * @ingroup Vector2 */ #define GE_VEC2I_DIV(a, b) GE_VEC2I( \ (a).x / (b).x, \ (a).y / (b).y \ ) /** * @def GE_VEC2I_DIV_SAFE * @brief 向量分量除法 * @param a 被除向量 * @param b 除数向量 * @return a / b (分量相除),除零保护(分母为0返回0) * @ingroup Vector2 */ #define GE_VEC2I_DIV_SAFE(a, b) GE_VEC2I( \ (b).x ? (a).x / (b).x : 0, \ (b).y ? (a).y / (b).y : 0 \ ) /** * @def GE_VEC2I_MUL_SCALAR * @brief 向量标量乘法 * @param v 目标向量 * @param s 标量值 * @return v * s * @ingroup Vector2 */ #define GE_VEC2I_MUL_SCALAR(v, s) GE_VEC2I((v).x * (s), (v).y * (s)) /** * @def GE_VEC2I_DOT * @brief 向量点积 * @param a 第一个向量 * @param b 第二个向量 * @return a · b * @ingroup Vector2 */ #define GE_VEC2I_DOT(a, b) ((a).x * (b).x + (a).y * (b).y) /** * @def GE_VEC2I_LENGTH_SQR * @brief 向量长度平方 * @param v 目标向量 * @return |v|² * @ingroup Vector2 */ #define GE_VEC2I_LENGTH_SQR(v) (GE_VEC2I_DOT(v, v)) /** * @def GE_VEC2I_DISTANCE_SQR * @brief 两点间距离平方 * @param a 起点向量 * @param b 终点向量 * @return |a - b|² * @ingroup Vector2 */ #define GE_VEC2I_DISTANCE_SQR(a, b) GE_VEC2I_LENGTH_SQR(GE_VEC2I_SUB(a, b)) /** * @def GE_VEC2I_MIN * @brief 分量最小值 * @param a 第一个向量 * @param b 第二个向量 * @return (min(a.x, b.x), min(a.y, b.y)) * @ingroup Vector2 */ #define GE_VEC2I_MIN(a, b) GE_VEC2I( \ ((a).x < (b).x) ? (a).x : (b).x, \ ((a).y < (b).y) ? (a).y : (b).y \ ) /** * @def GE_VEC2I_MAX * @brief 分量最大值 * @param a 第一个向量 * @param b 第二个向量 * @return (max(a.x, b.x), max(a.y, b.y)) * @ingroup Vector2 */ #define GE_VEC2I_MAX(a, b) GE_VEC2I( \ ((a).x > (b).x) ? (a).x : (b).x, \ ((a).y > (b).y) ? (a).y : (b).y \ ) /** * @def GE_VEC2I_CLAMP * @brief 分量钳制(钳制操作的意思是:如果某个分量小于最小值, * 则将其设置为最小值;如果大于最大值,则设置为最大值; * 如果在最小值和最大值之间,则保持不变。) * @param v 目标向量 * @param min_vec 最小值向量 * @param max_vec 最大值向量 * @return 钳制后的向量 * @ingroup Vector2 */ #define GE_VEC2I_CLAMP(v, min_vec, max_vec) \ GE_VEC2I_MIN(GE_VEC2I_MAX(v, min_vec), max_vec) // ========================= 操作符 ========================= /** * @def GE_VEC2I_EQUAL * @brief 判断两个向量是否相等(分量完全相等) * @param a 第一个向量 * @param b 第二个向量 * @return 1 表示相等,0 表示不相等 * @ingroup Vector2 */ #define GE_VEC2I_EQUAL(a, b) (((a).x == (b).x) && ((a).y == (b).y)) /** * @def GE_VEC2I_NOT_EQUAL * @brief 判断两个向量是否不相等 * @param a 第一个向量 * @param b 第二个向量 * @return 1 表示不相等,0 表示相等 * @ingroup Vector2 */ #define GE_VEC2I_NOT_EQUAL(a, b) (((a).x != (b).x) || ((a).y != (b).y)) /** * @def GE_VEC2I_APPROX_EQUAL * @brief 判断两个向量是否近似相等(在容忍度范围内) * @param a 第一个向量 * @param b 第二个向量 * @param tolerance 容忍度值 * @return 1 表示近似相等,0 表示不近似相等 * @note 对于整数向量,通常使用精确比较,但此宏提供了容忍度机制 * @ingroup Vector2 */ #define GE_VEC2I_APPROX_EQUAL(a, b, tolerance) \ ((GE_ABS((a).x - (b).x) <= tolerance) && \ (GE_ABS((a).y - (b).y) <= tolerance)) // ========================= 可选前缀模式 ========================= #ifdef GE_VEC2I_USE_SHORT_NAMES #define vec2i(x, y) GE_VEC2I(x, y) #define vec2i_zero GE_VEC2I_ZERO #define vec2i_one GE_VEC2I_ONE #define vec2i_add(a, b) GE_VEC2I_ADD(a, b) #define vec2i_sub(a, b) GE_VEC2I_SUB(a, b) #define vec2i_mul(a, b) GE_VEC2I_MUL(a, b) #define vec2i_mul_scalar(v, s) GE_VEC2I_MUL_SCALAR(v, s) #define vec2i_div(a, b) GE_VEC2I_DIV(a, b) #define vec2i_div_safe(a, b) GE_VEC2I_DIV_SAFE(a, b) #define vec2i_dot(a, b) GE_VEC2I_DOT(a, b) #define vec2i_length_sqr(v) GE_VEC2I_LENGTH_SQR(v) #define vec2i_min(a, b) GE_VEC2I_MIN(a, b) #define vec2i_max(a, b) GE_VEC2I_MAX(a, b) #define vec2i_clamp(v, min, max) GE_VEC2I_CLAMP(v, min, max) #define vec2i_equal(a, b) GE_VEC2I_EQUAL(a, b) #define vec2i_not_equal(a, b) GE_VEC2I_NOT_EQUAL(a, b) #define vec2i_approx_equal(a, b, tol) GE_VEC2I_APPROX_EQUAL(a, b, tol) #endif #endif // __GE_VECTOR2_H__