#ifndef _GEOMETRY_VECTOR2_H_ #define _GEOMETRY_VECTOR2_H_ #include "basis.h" #include "angle.h" #include typedef struct { float x1, x2; } SPVector2; typedef struct { double x1, x2; } DPVector2; // =================== Reset ==================== // static inline void sp_vector2_reset(SPVector2* vector) { vector->x1 = 0.0f; vector->x2 = 0.0f; } static inline void dp_vector2_reset(DPVector2* vector) { vector->x1 = 0.0; vector->x2 = 0.0; } // ==================== Set ===================== // static inline void sp_vector2_set_values(const float x1, const float x2, SPVector2* to) { to->x1 = x1; to->x2 = x2; } static inline void dp_vector2_set_values(const double x1, const double x2, DPVector2* to) { to->x1 = x1; to->x2 = x2; } // ==================== Copy ==================== // static inline void sp_vector2_copy(const SPVector2* from, SPVector2* to) { to->x1 = from->x1; to->x2 = from->x2; } static inline void dp_vector2_copy(const DPVector2* from, DPVector2* to) { to->x1 = from->x1; to->x2 = from->x2; } // ============= Copy to twin type ============== // static inline void sp_vector2_copy_from_double(const DPVector2* from, SPVector2* to) { to->x1 = (float)from->x1; to->x2 = (float)from->x2; } static inline void dp_vector2_copy_from_single(const SPVector2* from, DPVector2* to) { to->x1 = from->x1; to->x2 = from->x2; } // =================== Reverse ================== // static inline void sp_vector2_reverse(const SPVector2* from, SPVector2* to) { to->x1 = -from->x1; to->x2 = -from->x2; } static inline void dp_vector2_reverse(const DPVector2* from, DPVector2* to) { to->x1 = -from->x1; to->x2 = -from->x2; } // ============= Reverse twin type ============== // static inline void sp_vector2_reverse_double(const DPVector2* from, SPVector2* to) { to->x1 = -(float)from->x1; to->x2 = -(float)from->x2; } static inline void dp_vector2_reverse_single(const SPVector2* from, DPVector2* to) { to->x1 = -from->x1; to->x2 = -from->x2; } // =================== Module =================== // static inline float sp_vector2_get_square_module(const SPVector2* vector) { return vector->x1 * vector->x1 + vector->x2 * vector->x2; } static inline double dp_vector2_get_square_module(const DPVector2* vector) { return vector->x1 * vector->x1 + vector->x2 * vector->x2; } static inline float sp_vector2_get_module(const SPVector2* vector) { return sqrtf(sp_vector2_get_square_module(vector)); } static inline double dp_vector2_get_module(const DPVector2* vector) { return sqrt(dp_vector2_get_square_module(vector)); } // ================= Comparison ================= // static inline int sp_vector2_is_zero(const SPVector2* vector) { return sp_vector2_get_square_module(vector) <= SP_SQUARE_EPSYLON; } static inline int dp_vector2_is_zero(const DPVector2* vector) { return dp_vector2_get_square_module(vector) <= DP_SQUARE_EPSYLON; } static inline int sp_vector2_is_unit(const SPVector2* vector) { const float square_module = sp_vector2_get_square_module(vector); return 1.0f - SP_TWO_EPSYLON <= square_module && square_module <= 1.0f + SP_TWO_EPSYLON; } static inline int dp_vector2_is_unit(const DPVector2* vector) { const double square_module = dp_vector2_get_square_module(vector); return 1.0f - DP_TWO_EPSYLON <= square_module && square_module <= 1.0f + DP_TWO_EPSYLON; } // ==================== Add ===================== // static inline void sp_vector2_add(const SPVector2* vector1, const SPVector2* vector2, SPVector2* result) { result->x1 = vector1->x1 + vector2->x1; result->x2 = vector1->x2 + vector2->x2; } static inline void dp_vector2_add(const DPVector2* vector1, const DPVector2* vector2, DPVector2* result) { result->x1 = vector1->x1 + vector2->x1; result->x2 = vector1->x2 + vector2->x2; } // ================ Subtraction ================= // static inline void sp_vector2_subtract(const SPVector2* minuend, const SPVector2* subtrahend, SPVector2* result) { result->x1 = minuend->x1 - subtrahend->x1; result->x2 = minuend->x2 - subtrahend->x2; } static inline void dp_vector2_subtract(const DPVector2* minuend, const DPVector2* subtrahend, DPVector2* result) { result->x1 = minuend->x1 - subtrahend->x1; result->x2 = minuend->x2 - subtrahend->x2; } // =============== Multiplication =============== // static inline void sp_vector2_multiply(const SPVector2* multiplicand, const float multiplier, SPVector2* result) { result->x1 = multiplicand->x1 * multiplier; result->x2 = multiplicand->x2 * multiplier; } static inline void dp_vector2_multiply(const DPVector2* multiplicand, const double multiplier, DPVector2* result) { result->x1 = multiplicand->x1 * multiplier; result->x2 = multiplicand->x2 * multiplier; } // ================== Division ================== // static inline void sp_vector2_divide(const SPVector2* dividend, const float divisor, SPVector2* result) { result->x1 = dividend->x1 / divisor; result->x2 = dividend->x2 / divisor; } static inline void dp_vector2_divide(const DPVector2* dividend, const double divisor, DPVector2* result) { result->x1 = dividend->x1 / divisor; result->x2 = dividend->x2 / divisor; } // ================ Append scaled =============== // static inline void sp_vector2_append_scaled(SPVector2* basic_vector, const SPVector2* scalable_summand, const float scale) { basic_vector->x1 += scalable_summand->x1 * scale; basic_vector->x2 += scalable_summand->x2 * scale; } static inline void dp_vector2_append_scaled(DPVector2* basic_vector, const DPVector2* scalable_summand, const double scale) { basic_vector->x1 += scalable_summand->x1 * scale; basic_vector->x2 += scalable_summand->x2 * scale; } // ================== Average2 ================== // static inline void sp_vector2_get_mean2(const SPVector2* vector1, const SPVector2* vector2, SPVector2* result) { result->x1 = (vector1->x1 + vector2->x1) * 0.5f; result->x2 = (vector1->x2 + vector2->x2) * 0.5f; } static inline void dp_vector2_get_mean2(const DPVector2* vector1, const DPVector2* vector2, DPVector2* result) { result->x1 = (vector1->x1 + vector2->x1) * 0.5; result->x2 = (vector1->x2 + vector2->x2) * 0.5; } // ================== Average3 ================== // static inline void sp_vector2_get_mean3(const SPVector2* vector1, const SPVector2* vector2, const SPVector2* vector3, SPVector2* result) { result->x1 = (vector1->x1 + vector2->x1 + vector3->x1) * SP_ONE_THIRD; result->x2 = (vector1->x2 + vector2->x2 + vector3->x2) * SP_ONE_THIRD; } static inline void dp_vector2_get_mean3(const DPVector2* vector1, const DPVector2* vector2, const DPVector2* vector3, DPVector2* result) { result->x1 = (vector1->x1 + vector2->x1 + vector3->x1) * DP_ONE_THIRD; result->x2 = (vector1->x2 + vector2->x2 + vector3->x2) * DP_ONE_THIRD; } // =============== Scalar Product =============== // static inline float sp_vector2_scalar(const SPVector2* vector1, const SPVector2* vector2) { return vector1->x1 * vector2->x1 + vector1->x2 * vector2->x2; } static inline double dp_vector2_scalar(const DPVector2* vector1, const DPVector2* vector2) { return vector1->x1 * vector2->x1 + vector1->x2 * vector2->x2; } // =============== Cross Product ================ // static inline float sp_vector2_cross(const SPVector2* vector1, const SPVector2* vector2) { return vector1->x1 * vector2->x2 - vector1->x2 * vector2->x1; } static inline double dp_vector2_cross(const DPVector2* vector1, const DPVector2* vector2, DPVector2* result) { return vector1->x1 * vector2->x2 - vector1->x2 * vector2->x1; } // =============== Normalization ================ // static inline int sp_vector2_normalize(SPVector2* vector) { const float square_module = sp_vector2_get_square_module(vector); if (1.0f - SP_TWO_EPSYLON <= square_module && square_module <= 1.0f + SP_TWO_EPSYLON) { return 1; } if (square_module <= SP_SQUARE_EPSYLON) { sp_vector2_reset(vector); return 0; } sp_vector2_divide(vector, sqrtf(square_module), vector); return 1; } static inline int dp_vector2_normalize(DPVector2* vector) { const double square_module = dp_vector2_get_square_module(vector); if (1.0 - DP_TWO_EPSYLON <= square_module && square_module <= 1.0 + DP_TWO_EPSYLON) { return 1; } if (square_module <= DP_SQUARE_EPSYLON) { dp_vector2_reset(vector); return 0; } dp_vector2_divide(vector, sqrt(square_module), vector); return 1; } // =============== Get Normalized =============== // static inline int sp_vector2_get_normalized(const SPVector2* vector, SPVector2* result) { sp_vector2_copy(vector, result); return sp_vector2_normalize(result); } static inline int dp_vector2_get_normalized(const DPVector2* vector, DPVector2* result) { dp_vector2_copy(vector, result); return dp_vector2_normalize(result); } // =================== Angle ==================== // float sp_vector2_angle(const SPVector2* vector1, const SPVector2* vector2, const angle_unit_t unit); double dp_vector2_angle(const DPVector2* vector1, const DPVector2* vector2, const angle_unit_t unit); // =============== Square Distance ============== // static inline float sp_vector2_get_square_distance(const SPVector2* vector1, const SPVector2* vector2) { const float dx1 = (vector1->x1 - vector2->x1); const float dx2 = (vector1->x2 - vector2->x2); return dx1 * dx1 + dx2 * dx2; } static inline double dp_vector2_get_square_distance(const DPVector2* vector1, const DPVector2* vector2) { const double dx1 = (vector1->x1 - vector2->x1); const double dx2 = (vector1->x2 - vector2->x2); return dx1 * dx1 + dx2 * dx2; } // ================== Distance ================== // static inline float sp_vector2_get_distance(const SPVector2* vector1, const SPVector2* vector2) { return sqrtf(sp_vector2_get_square_distance(vector1, vector2)); } static inline double dp_vector2_get_distance(const DPVector2* vector1, const DPVector2* vector2) { return sqrt(dp_vector2_get_square_distance(vector1, vector2)); } // ================== Are Equal ================= // static inline int sp_vector2_are_equal(const SPVector2* vector1, const SPVector2* vector2) { const float square_module1 = sp_vector2_get_square_module(vector1); const float square_module2 = sp_vector2_get_square_module(vector2); const float square_module3 = sp_vector2_get_square_distance(vector1, vector2); // 2.0f means dimension amount if (square_module1 < SP_EPSYLON_EFFECTIVENESS_LIMIT || square_module2 < SP_EPSYLON_EFFECTIVENESS_LIMIT) { return square_module3 < (2.0f * SP_SQUARE_EPSYLON); } if (square_module1 <= square_module2) { return square_module3 <= (2.0f * SP_SQUARE_EPSYLON) * square_module2; } return square_module3 <= (2.0f * SP_SQUARE_EPSYLON) * square_module1; } static inline int dp_vector2_are_equal(const DPVector2* vector1, const DPVector2* vector2) { const double square_module1 = dp_vector2_get_square_module(vector1); const double square_module2 = dp_vector2_get_square_module(vector2); const double square_module3 = dp_vector2_get_square_distance(vector1, vector2); // 2.0 means dimension amount if (square_module1 < DP_EPSYLON_EFFECTIVENESS_LIMIT || square_module2 < DP_EPSYLON_EFFECTIVENESS_LIMIT) { return square_module3 < (2.0 * DP_SQUARE_EPSYLON); } if (square_module1 <= square_module2) { return square_module3 <= (2.0 * DP_SQUARE_EPSYLON) * square_module2; } return square_module3 <= (2.0 * DP_SQUARE_EPSYLON) * square_module1; } #endif