From 421ca77cb41f4a6d12d7d4a2e4f9d9705e72df28 Mon Sep 17 00:00:00 2001 From: Andrey Pokidov Date: Wed, 5 Feb 2025 23:43:02 +0700 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D1=83=D1=89=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=BE=D0=B2=D0=B0=D0=B2=D1=88=D0=B8=D1=85=20=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D1=8B=D1=85=20=D1=84=D1=83=D0=BD=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=B9=20=D1=81=D1=80=D0=B0=D0=B2=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-Eng.md | 4 ++-- README.md | 8 +++---- basic-geometry/quaternion.c | 3 +++ basic-geometry/quaternion.h | 38 ++++++++++++++++++++++++++++++++ basic-geometry/tangent.c | 3 +++ basic-geometry/tangent.h | 18 +++++++++++++++ basic-geometry/utilities.c | 4 ++-- basic-geometry/utilities.h | 39 +++++++++++++++++--------------- basic-geometry/vector2.c | 7 ++++-- basic-geometry/vector2.h | 44 +++++++++++++++++++------------------ basic-geometry/vector3.c | 7 ++++-- basic-geometry/vector3.h | 44 +++++++++++++++++++------------------ basic-geometry/versor.c | 3 +++ basic-geometry/versor.h | 22 +++++++++++++++++++ docs/prefixes-rus.md | 4 ++-- 15 files changed, 174 insertions(+), 74 deletions(-) diff --git a/README-Eng.md b/README-Eng.md index 9c23e87..04d06b9 100644 --- a/README-Eng.md +++ b/README-Eng.md @@ -1,6 +1,6 @@ -# Basic Geometry +# Basic Geometry Computations -## Library of basic geometric computations +## Library of basic geometric computations for C [Версия на русском языке / Russian version](./README.md) diff --git a/README.md b/README.md index 43a5243..a81bd61 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Basic Geometry +# Basic Geometry Computations -## Библиотека базовых геометрических вычислений +## Библиотека базовых геометрических вычислений для Си (English: library of basic geometric computations) @@ -36,5 +36,5 @@ типа **float**, а другая - для данных типа **double**. Но между этими половинами есть мостики - функции преобразования типа. -Однако в библиотеке нет функций, которые используют для вычисления данные разных -типов (**float** и *double* одновременно). \ No newline at end of file +Однако в библиотеке мало функций, которые используют для вычисления данные разных +типов (**float** и **double** одновременно). \ No newline at end of file diff --git a/basic-geometry/quaternion.c b/basic-geometry/quaternion.c index 95bcd0c..2bbe84a 100644 --- a/basic-geometry/quaternion.c +++ b/basic-geometry/quaternion.c @@ -59,3 +59,6 @@ extern inline void bgc_quaternion_divide_fp64(const BgcQuaternionFP64* dividend, extern inline void bgc_quaternion_get_product_fp32(const BgcQuaternionFP32* left, const BgcQuaternionFP32* right, BgcQuaternionFP32* product); extern inline void bgc_quaternion_get_product_fp64(const BgcQuaternionFP64* left, const BgcQuaternionFP64* right, BgcQuaternionFP64* product); + +extern inline int bgc_quaternion_are_close_fp32(const BgcQuaternionFP32* quaternion1, const BgcQuaternionFP32* quaternion2); +extern inline int bgc_quaternion_are_close_fp32(const BgcQuaternionFP32* quaternion1, const BgcQuaternionFP32* quaternion2); diff --git a/basic-geometry/quaternion.h b/basic-geometry/quaternion.h index b4f2c7f..bfbb0ac 100644 --- a/basic-geometry/quaternion.h +++ b/basic-geometry/quaternion.h @@ -535,4 +535,42 @@ inline void bgc_quaternion_get_product_fp64(const BgcQuaternionFP64* left, const product->x3 = x3; } +// ================== Are Close ================= // + +inline int bgc_quaternion_are_close_fp32(const BgcQuaternionFP32* quaternion1, const BgcQuaternionFP32* quaternion2) +{ + const float ds0 = quaternion1->s0 - quaternion2->s0; + const float dx1 = quaternion1->x1 - quaternion2->x1; + const float dx2 = quaternion1->x2 - quaternion2->x2; + const float dx3 = quaternion1->x3 - quaternion2->x3; + + const float square_modulus1 = bgc_quaternion_get_square_modulus_fp32(quaternion1); + const float square_modulus2 = bgc_quaternion_get_square_modulus_fp32(quaternion2); + const float square_distance = (ds0 * ds0 + dx1 * dx1) + (dx2 * dx2 + dx3 * dx3); + + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { + return square_distance <= BGC_SQUARE_EPSYLON_FP32; + } + + return square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus2; +} + +inline int bgc_quaternion_are_close_fp64(const BgcQuaternionFP64* quaternion1, const BgcQuaternionFP64* quaternion2) +{ + const double ds0 = quaternion1->s0 - quaternion2->s0; + const double dx1 = quaternion1->x1 - quaternion2->x1; + const double dx2 = quaternion1->x2 - quaternion2->x2; + const double dx3 = quaternion1->x3 - quaternion2->x3; + + const double square_modulus1 = bgc_quaternion_get_square_modulus_fp64(quaternion1); + const double square_modulus2 = bgc_quaternion_get_square_modulus_fp64(quaternion2); + const double square_distance = (ds0 * ds0 + dx1 * dx1) + (dx2 * dx2 + dx3 * dx3); + + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { + return square_distance <= BGC_SQUARE_EPSYLON_FP64; + } + + return square_distance <= BGC_SQUARE_EPSYLON_FP64 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP64 * square_modulus2; +} + #endif // _BGC_QUATERNION_H_ diff --git a/basic-geometry/tangent.c b/basic-geometry/tangent.c index 6a798c4..ee74ca1 100644 --- a/basic-geometry/tangent.c +++ b/basic-geometry/tangent.c @@ -46,6 +46,9 @@ extern inline void bgc_tangent_turn_vector_fp64(const BgcTangentFP64* tangent, c extern inline void bgc_tangent_turn_vector_back_fp32(const BgcTangentFP32* tangent, const BgcVector2FP32* vector, BgcVector2FP32* result); extern inline void bgc_tangent_turn_vector_back_fp64(const BgcTangentFP64* tangent, const BgcVector2FP64* vector, BgcVector2FP64* result); +extern inline int bgc_tangent_are_close_fp32(const BgcTangentFP32* tangent1, const BgcTangentFP32* tangent2); +extern inline int bgc_tangent_are_close_fp64(const BgcTangentFP64* tangent1, const BgcTangentFP64* tangent2); + void _bgc_tangent_normalize_fp32(const float square_modulus, _BgcDarkTwinTangentFP32* twin) { // (square_modulus != square_modulus) is true when square_modulus is NaN diff --git a/basic-geometry/tangent.h b/basic-geometry/tangent.h index a323083..8e26e49 100644 --- a/basic-geometry/tangent.h +++ b/basic-geometry/tangent.h @@ -343,4 +343,22 @@ inline void bgc_tangent_turn_vector_back_fp64(const BgcTangentFP64* tangent, con result->x2 = x2; } +// ================== Are Close ================= // + +inline int bgc_tangent_are_close_fp32(const BgcTangentFP32* tangent1, const BgcTangentFP32* tangent2) +{ + const float d_cos = tangent1->cos - tangent2->cos; + const float d_sin = tangent1->sin - tangent2->sin; + + return d_cos * d_cos + d_sin * d_sin <= BGC_SQUARE_EPSYLON_FP32; +} + +inline int bgc_tangent_are_close_fp64(const BgcTangentFP64* tangent1, const BgcTangentFP64* tangent2) +{ + const double d_cos = tangent1->cos - tangent2->cos; + const double d_sin = tangent1->sin - tangent2->sin; + + return d_cos * d_cos + d_sin * d_sin <= BGC_SQUARE_EPSYLON_FP64; +} + #endif diff --git a/basic-geometry/utilities.c b/basic-geometry/utilities.c index 30e034f..cdd8ff8 100644 --- a/basic-geometry/utilities.c +++ b/basic-geometry/utilities.c @@ -10,5 +10,5 @@ extern inline int bgc_is_unit_fp64(const double square_value); extern inline int bgc_is_sqare_value_unit_fp32(const float square_value); extern inline int bgc_is_sqare_value_unit_fp64(const double square_value); -extern inline int bgc_are_equal_fp32(const float value1, const float value2); -extern inline int bgc_are_equal_fp64(const double value1, const double value2); +extern inline int bgc_are_close_fp32(const float value1, const float value2); +extern inline int bgc_are_close_fp64(const double value1, const double value2); diff --git a/basic-geometry/utilities.h b/basic-geometry/utilities.h index d2fe3f4..48c8d1e 100644 --- a/basic-geometry/utilities.h +++ b/basic-geometry/utilities.h @@ -1,7 +1,7 @@ #ifndef _BGC_UTILITIES_H_ #define _BGC_UTILITIES_H_ -#define BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 10.0f +#define BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 1.0f #define BGC_EPSYLON_FP32 5E-7f #define BGC_SQUARE_EPSYLON_FP32 2.5E-13f @@ -13,7 +13,7 @@ #define BGC_GOLDEN_RATIO_HIGH_FP32 1.618034f #define BGC_GOLDEN_RATIO_LOW_FP32 0.618034f -#define BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 10.0 +#define BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 1.0 #define BGC_EPSYLON_FP64 5E-14 #define BGC_SQUARE_EPSYLON_FP64 2.5E-27 @@ -57,31 +57,34 @@ inline int bgc_is_sqare_value_unit_fp64(const double square_value) return (1.0 - 2.0 * BGC_EPSYLON_FP64 <= square_value) && (square_value <= 1.0 + 2.0 * BGC_EPSYLON_FP64); } +// ================== Are Close ================= // -inline int bgc_are_equal_fp32(const float value1, const float value2) +inline int bgc_are_close_fp32(const float value1, const float value2) { - if (-BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 < value1 && value1 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { - return -BGC_EPSYLON_FP32 <= (value1 - value2) && (value1 - value2) <= BGC_EPSYLON_FP32; + const float difference = value1 - value2; + const float square_value1 = value1 * value1; + const float square_value2 = value2 * value2; + const float square_difference = difference * difference; + + if (square_value1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 || square_value2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { + return square_difference <= BGC_SQUARE_EPSYLON_FP32; } - if (value1 < 0.0f) { - return (1.0f + BGC_EPSYLON_FP32) * value2 <= value1 && (1.0f + BGC_EPSYLON_FP32) * value1 <= value2; - } - - return value2 <= value1 * (1.0f + BGC_EPSYLON_FP32) && value1 <= value2 * (1.0f + BGC_EPSYLON_FP32); + return square_difference <= BGC_SQUARE_EPSYLON_FP32 * square_value1 && square_difference <= BGC_SQUARE_EPSYLON_FP32 * square_value2; } -inline int bgc_are_equal_fp64(const double value1, const double value2) +inline int bgc_are_close_fp64(const double value1, const double value2) { - if (-BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 < value1 && value1 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { - return -BGC_EPSYLON_FP64 <= (value1 - value2) && (value1 - value2) <= BGC_EPSYLON_FP64; + const double difference = value1 - value2; + const double square_value1 = value1 * value1; + const double square_value2 = value2 * value2; + const double square_difference = difference * difference; + + if (square_value1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 || square_value2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { + return square_difference <= BGC_SQUARE_EPSYLON_FP64; } - if (value1 < 0.0) { - return (1.0 + BGC_EPSYLON_FP64) * value2 <= value1 && (1.0 + BGC_EPSYLON_FP64) * value1 <= value2; - } - - return value2 <= value1 * (1.0 + BGC_EPSYLON_FP64) && value1 <= value2 * (1.0 + BGC_EPSYLON_FP64); + return square_difference <= BGC_SQUARE_EPSYLON_FP64 * square_value1 && square_difference <= BGC_SQUARE_EPSYLON_FP64 * square_value2; } #endif diff --git a/basic-geometry/vector2.c b/basic-geometry/vector2.c index 1fa5ad7..dfb83af 100644 --- a/basic-geometry/vector2.c +++ b/basic-geometry/vector2.c @@ -75,8 +75,11 @@ extern inline double bgc_vector2_get_square_distance_fp64(const BgcVector2FP64* extern inline float bgc_vector2_get_distance_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2); extern inline double bgc_vector2_get_distance_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2); -extern inline int bgc_vector2_are_equal_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2); -extern inline int bgc_vector2_are_equal_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2); +extern inline int bgc_vector2_are_close_enough_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, const float distance); +extern inline int bgc_vector2_are_close_enough_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2, const double distance); + +extern inline int bgc_vector2_are_close_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2); +extern inline int bgc_vector2_are_close_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2); // =================== Angle ==================== // diff --git a/basic-geometry/vector2.h b/basic-geometry/vector2.h index 39c6e04..c1d81d4 100644 --- a/basic-geometry/vector2.h +++ b/basic-geometry/vector2.h @@ -396,42 +396,44 @@ inline double bgc_vector2_get_distance_fp64(const BgcVector2FP64* vector1, const return sqrt(bgc_vector2_get_square_distance_fp64(vector1, vector2)); } -// ================== Are Equal ================= // +// ============== Are Close Enough ============== // -inline int bgc_vector2_are_equal_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2) +inline int bgc_vector2_are_close_enough_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, const float distance) +{ + return bgc_vector2_get_square_distance_fp32(vector1, vector2) <= distance * distance; +} + +inline int bgc_vector2_are_close_enough_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2, const double distance) +{ + return bgc_vector2_get_square_distance_fp64(vector1, vector2) <= distance * distance; +} + +// ================== Are Close ================= // + +inline int bgc_vector2_are_close_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2) { const float square_modulus1 = bgc_vector2_get_square_modulus_fp32(vector1); const float square_modulus2 = bgc_vector2_get_square_modulus_fp32(vector2); - const float square_modulus3 = bgc_vector2_get_square_distance_fp32(vector1, vector2); + const float square_distance = bgc_vector2_get_square_distance_fp32(vector1, vector2); - // 2.0f means dimension amount - if (square_modulus1 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 || square_modulus2 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { - return square_modulus3 < (2.0f * BGC_SQUARE_EPSYLON_FP32); + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { + return square_distance <= BGC_SQUARE_EPSYLON_FP32; } - if (square_modulus1 <= square_modulus2) { - return square_modulus3 <= (2.0f * BGC_SQUARE_EPSYLON_FP32) * square_modulus2; - } - - return square_modulus3 <= (2.0f * BGC_SQUARE_EPSYLON_FP32) * square_modulus1; + return square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus2; } -inline int bgc_vector2_are_equal_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2) +inline int bgc_vector2_are_close_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2) { const double square_modulus1 = bgc_vector2_get_square_modulus_fp64(vector1); const double square_modulus2 = bgc_vector2_get_square_modulus_fp64(vector2); - const double square_modulus3 = bgc_vector2_get_square_distance_fp64(vector1, vector2); + const double square_distance = bgc_vector2_get_square_distance_fp64(vector1, vector2); - // 2.0 means dimension amount - if (square_modulus1 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 || square_modulus2 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { - return square_modulus3 < (2.0 * BGC_SQUARE_EPSYLON_FP64); + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { + return square_distance <= BGC_SQUARE_EPSYLON_FP64; } - if (square_modulus1 <= square_modulus2) { - return square_modulus3 <= (2.0 * BGC_SQUARE_EPSYLON_FP64) * square_modulus2; - } - - return square_modulus3 <= (2.0 * BGC_SQUARE_EPSYLON_FP64) * square_modulus1; + return square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus2; } #endif diff --git a/basic-geometry/vector3.c b/basic-geometry/vector3.c index c1534ab..3abd179 100644 --- a/basic-geometry/vector3.c +++ b/basic-geometry/vector3.c @@ -81,8 +81,11 @@ extern inline double bgc_vector3_get_square_distance_fp64(const BgcVector3FP64* extern inline float bgc_vector3_get_distance_fp32(const BgcVector3FP32* vector1, const BgcVector3FP32* vector2); extern inline double bgc_vector3_get_distance_fp64(const BgcVector3FP64* vector1, const BgcVector3FP64* vector2); -extern inline int bgc_vector3_are_equal_fp32(const BgcVector3FP32* vector1, const BgcVector3FP32* vector2); -extern inline int bgc_vector3_are_equal_fp64(const BgcVector3FP64* vector1, const BgcVector3FP64* vector2); +extern inline int bgc_vector3_are_close_enough_fp32(const BgcVector3FP32* vector1, const BgcVector3FP32* vector2, const float distance); +extern inline int bgc_vector3_are_close_enough_fp64(const BgcVector3FP64* vector1, const BgcVector3FP64* vector2, const double distance); + +extern inline int bgc_vector3_are_close_fp32(const BgcVector3FP32* vector1, const BgcVector3FP32* vector2); +extern inline int bgc_vector3_are_close_fp64(const BgcVector3FP64* vector1, const BgcVector3FP64* vector2); // =================== Angle ==================== // diff --git a/basic-geometry/vector3.h b/basic-geometry/vector3.h index 16f6fd7..1e1f8bc 100644 --- a/basic-geometry/vector3.h +++ b/basic-geometry/vector3.h @@ -476,42 +476,44 @@ inline double bgc_vector3_get_distance_fp64(const BgcVector3FP64* vector1, const return sqrt(bgc_vector3_get_square_distance_fp64(vector1, vector2)); } -// ================== Are Equal ================= // +// ============== Are Close Enough ============== // -inline int bgc_vector3_are_equal_fp32(const BgcVector3FP32* vector1, const BgcVector3FP32* vector2) +inline int bgc_vector3_are_close_enough_fp32(const BgcVector3FP32* vector1, const BgcVector3FP32* vector2, const float distance) +{ + return bgc_vector3_get_square_distance_fp32(vector1, vector2) <= distance * distance; +} + +inline int bgc_vector3_are_close_enough_fp64(const BgcVector3FP64* vector1, const BgcVector3FP64* vector2, const double distance) +{ + return bgc_vector3_get_square_distance_fp64(vector1, vector2) <= distance * distance; +} + +// ================== Are Close ================= // + +inline int bgc_vector3_are_close_fp32(const BgcVector3FP32* vector1, const BgcVector3FP32* vector2) { const float square_modulus1 = bgc_vector3_get_square_modulus_fp32(vector1); const float square_modulus2 = bgc_vector3_get_square_modulus_fp32(vector2); - const float square_modulus3 = bgc_vector3_get_square_distance_fp32(vector1, vector2); + const float square_distance = bgc_vector3_get_square_distance_fp32(vector1, vector2); - // 3.0f means dimension amount - if (square_modulus1 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 || square_modulus2 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { - return square_modulus3 < (3.0f * BGC_SQUARE_EPSYLON_FP32); + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { + return square_distance <= BGC_SQUARE_EPSYLON_FP32; } - if (square_modulus1 <= square_modulus2) { - return square_modulus3 <= (3.0f * BGC_SQUARE_EPSYLON_FP32) * square_modulus2; - } - - return square_modulus3 <= (3.0f * BGC_SQUARE_EPSYLON_FP32) * square_modulus1; + return square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus2; } -inline int bgc_vector3_are_equal_fp64(const BgcVector3FP64* vector1, const BgcVector3FP64* vector2) +inline int bgc_vector3_are_close_fp64(const BgcVector3FP64* vector1, const BgcVector3FP64* vector2) { const double square_modulus1 = bgc_vector3_get_square_modulus_fp64(vector1); const double square_modulus2 = bgc_vector3_get_square_modulus_fp64(vector2); - const double square_modulus3 = bgc_vector3_get_square_distance_fp64(vector1, vector2); + const double square_distance = bgc_vector3_get_square_distance_fp64(vector1, vector2); - // 3.0 means dimension amount - if (square_modulus1 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 || square_modulus2 < BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { - return square_modulus3 < (3.0 * BGC_SQUARE_EPSYLON_FP64); + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { + return square_distance <= BGC_SQUARE_EPSYLON_FP64; } - if (square_modulus1 <= square_modulus2) { - return square_modulus3 <= (3.0 * BGC_SQUARE_EPSYLON_FP64) * square_modulus2; - } - - return square_modulus3 <= (3.0 * BGC_SQUARE_EPSYLON_FP64) * square_modulus1; + return square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus2; } #endif diff --git a/basic-geometry/versor.c b/basic-geometry/versor.c index ce57261..96f6482 100644 --- a/basic-geometry/versor.c +++ b/basic-geometry/versor.c @@ -64,6 +64,9 @@ extern inline void bgc_versor_turn_vector_fp64(const BgcVersorFP64* versor, cons extern inline void bgc_versor_turn_vector_back_fp32(const BgcVersorFP32* versor, const BgcVector3FP32* vector, BgcVector3FP32* result); extern inline void bgc_versor_turn_vector_back_fp64(const BgcVersorFP64* versor, const BgcVector3FP64* vector, BgcVector3FP64* result); +extern inline int bgc_versor_are_close_fp32(const BgcVersorFP32* versor1, const BgcVersorFP32* versor2); +extern inline int bgc_versor_are_close_fp64(const BgcVersorFP64* versor1, const BgcVersorFP64* versor2); + // =============== Normalization ================ // void _bgc_versor_normalize_fp32(const float square_modulus, _BgcDarkTwinVersorFP32* twin) diff --git a/basic-geometry/versor.h b/basic-geometry/versor.h index b609a7f..99505f7 100644 --- a/basic-geometry/versor.h +++ b/basic-geometry/versor.h @@ -600,4 +600,26 @@ inline void bgc_versor_turn_vector_back_fp64(const BgcVersorFP64* versor, const result->x3 = x3; } +// ================== Are Close ================= // + +inline int bgc_versor_are_close_fp32(const BgcVersorFP32* versor1, const BgcVersorFP32* versor2) +{ + const float ds0 = versor1->s0 - versor2->s0; + const float dx1 = versor1->x1 - versor2->x1; + const float dx2 = versor1->x2 - versor2->x2; + const float dx3 = versor1->x3 - versor2->x3; + + return (ds0 * ds0 + dx1 * dx1) + (dx2 * dx2 + dx3 * dx3) <= BGC_SQUARE_EPSYLON_FP32; +} + +inline int bgc_versor_are_close_fp64(const BgcVersorFP64* versor1, const BgcVersorFP64* versor2) +{ + const double ds0 = versor1->s0 - versor2->s0; + const double dx1 = versor1->x1 - versor2->x1; + const double dx2 = versor1->x2 - versor2->x2; + const double dx3 = versor1->x3 - versor2->x3; + + return (ds0 * ds0 + dx1 * dx1) + (dx2 * dx2 + dx3 * dx3) <= BGC_SQUARE_EPSYLON_FP32; +} + #endif diff --git a/docs/prefixes-rus.md b/docs/prefixes-rus.md index 3051f21..2a623ed 100644 --- a/docs/prefixes-rus.md +++ b/docs/prefixes-rus.md @@ -33,9 +33,9 @@ BgcVector3FP32, BgcMatrix3x2FP32, BgcQuaternionFP32 Типы структур, использующие тип **double** имеют суффикс **FP64**: BgcVector2FP64, BgcMatrix2x3FP64, BgcVersorFP64 -Константы типа **float** имеют суффикс **FP32_**: BGC_PI_FP32, BGC_EPSYLON_FP32. +Константы типа **float** имеют суффикс **_FP32**: BGC_PI_FP32, BGC_EPSYLON_FP32. -Константы типа **double** имеют суффикс **FP64_**: BGC_HALF_PI_FP64, +Константы типа **double** имеют суффикс **_FP64**: BGC_HALF_PI_FP64, BGC_ONE_THIRD_FP64. Функции, которые работают с данными типа **float** имеют суффикс **_fp32**: