From c7e39e1527d5a88ae0f26e304c55deccb8dd97ac Mon Sep 17 00:00:00 2001 From: Andrey Pokidov Date: Fri, 7 Feb 2025 22:43:32 +0700 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- basic-geometry-dev/main.c | 16 ++- docs/contents-eng.md | 0 docs/{prefixes-eng.md => intro-eng.md} | 12 +- docs/{prefixes-rus.md => intro-rus.md} | 11 +- docs/vector2-rus.md | 151 +++++++++++++++++++++++++ docs/versor-eng.md | 148 +++++++----------------- docs/versor-reset-eng.md | 43 +++++++ docs/versor-reset-rus.md | 43 +++++++ docs/versor-rus.md | 89 ++++++--------- docs/versor-set-values-eng.md | 45 ++++++++ docs/versor-set-values-rus.md | 47 ++++++++ docs/versor_reset-eng.md | 36 ------ docs/versor_reset-rus.md | 37 ------ 13 files changed, 439 insertions(+), 239 deletions(-) create mode 100644 docs/contents-eng.md rename docs/{prefixes-eng.md => intro-eng.md} (94%) rename docs/{prefixes-rus.md => intro-rus.md} (95%) create mode 100644 docs/versor-reset-eng.md create mode 100644 docs/versor-reset-rus.md create mode 100644 docs/versor-set-values-eng.md create mode 100644 docs/versor-set-values-rus.md delete mode 100644 docs/versor_reset-eng.md delete mode 100644 docs/versor_reset-rus.md diff --git a/basic-geometry-dev/main.c b/basic-geometry-dev/main.c index c5412f9..1725c3e 100644 --- a/basic-geometry-dev/main.c +++ b/basic-geometry-dev/main.c @@ -93,7 +93,7 @@ void list_work(const uint_fast32_t amount, structure_fp32_t* list) } } } - +/* int main() { const unsigned int amount = 1000000; @@ -135,3 +135,17 @@ int main() return 0; } +*/ + +//#include +//#include + +int main() { + BgcVersorFP64 versor; + + bgc_versor_set_values_fp64(0, 0, 0, 0, &versor); + + printf("Versor: (%lf, %lf, %lf, %lf)\n", versor.s0, versor.x1, versor.x2, versor.x3); + + return 0; +} diff --git a/docs/contents-eng.md b/docs/contents-eng.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/prefixes-eng.md b/docs/intro-eng.md similarity index 94% rename from docs/prefixes-eng.md rename to docs/intro-eng.md index 097aaec..f2f305a 100644 --- a/docs/prefixes-eng.md +++ b/docs/intro-eng.md @@ -1,4 +1,6 @@ -# Prefixes and Suffixes +# Naming + +## Prefixes The library uses prefixes in names of types, constants and functions. @@ -13,6 +15,8 @@ BGC_TWO_PI_FP64. The functions have prefix in the form **bgc_**. For example: bgc_versor_combine_fp32, bgc_matrix3x3_subtract_fp32. +## Suffixes + Suffixs of type ends the names of constats, types and functions of the library. The library uses two types of floating point numbers: **float** and **double** (**binary32** and **binary64** types of the **IEEE 754** standard). @@ -42,3 +46,9 @@ the type suffix: bgc_vector2_get_modulus_fp64, bgc_radians_to_degrees_fp32. The functions which works with data of the **double** type have **_fp64** as the type suffix: bgc_vector3_reset_fp64, bgc_radians_normalize_fp64. + +## Entities + +- Vectors 2D and 3D +- [Versors](./versor-eng.md) + diff --git a/docs/prefixes-rus.md b/docs/intro-rus.md similarity index 95% rename from docs/prefixes-rus.md rename to docs/intro-rus.md index 2a623ed..3c4be2f 100644 --- a/docs/prefixes-rus.md +++ b/docs/intro-rus.md @@ -1,4 +1,6 @@ -# Префиксы +# Названия + +## Префиксы Библиотека использует префиксы в названиях типов, констант и функций. @@ -14,6 +16,8 @@ BGC_TWO_PI_FP64. Функции имеют префикс в виде **bgc_**, например: bgc_versor_combine_fp32, bgc_matrix3x3_subtract_fp64. +## Cуффиксы + Названия констант, типов и функций оканчиваются суффиксом, указывающим на базовый тип. Библиотека использует два типа чисел с плавающей запятой: **float** и **double** (типы **binary32** и **binary64** стандарта @@ -43,3 +47,8 @@ bcg_vector2_get_modulus_fp32, bgc_radians_to_degrees_fp32. Функции, которые работают с данными типа **double** имеют суффикс **_fp64**: bgc_vector3_reset_fp64, bgc_radians_normalize_fp64. + +## Contents + +- 2D и 3D векторы +- [Versors](./versor-rus.md) diff --git a/docs/vector2-rus.md b/docs/vector2-rus.md index d497297..808a485 100644 --- a/docs/vector2-rus.md +++ b/docs/vector2-rus.md @@ -23,3 +23,154 @@ binary32 стандарта IEEE 754). double x1, x2; } BgcVector2FP64; +Операции: +- сбос состояния +- указание координат +- копирование +- обмен +- конвертация типа +- получение обратного вектора + +### Сброс состояния + +Для сброса координат в нулевое значение предлагаются следующие функции: + + inline void bgc_vector2_reset_fp32(BgcVector2FP32* vector); + inline void bgc_vector2_reset_fp64(BgcVector2FP64* vector); + +Каждая из данных функции эквивалентна следующим строкам кода: + + vector->x1 = 0; + vector->x2 = 0; + +В данные функции не следует передавать некорректные указатели. Значение NULL (0) +в качестве параметра также считается некорректным. + +Пример применения: + + #include + #include + + int main() + { + BgcVector2FP32 my_vector; + + bgc_vector2_reset_fp32(&my_vector); + + printf("x1 = %f, x2 = %f\n", my_vector.x1, my_vector.x2); + + return 0; + } + +### Указание координат + +Для прямого указания координат предлагаются следующие две функции: + + inline void bgc_vector2_set_values_fp32(const float x1, const float x2, BgcVector2FP32* to); + inline void bgc_vector2_set_values_fp64(const double x1, const double x2, BgcVector2FP64* to); + +Каждая из данных функции эквивалентна следующим строкам кода: + + vector->x1 = x1; + vector->x2 = x2; + +В данные функции не следует передавать некорректные указатели. Значение NULL (0) +в качестве параметра также считается некорректным. + +Пример применения: + + #include + #include + + int main() + { + BgcVector2FP32 my_vector; + + bgc_vector2_set_values_fp32(-2, 7, &my_vector); + + printf("x1 = %f, x2 = %f\n", my_vector.x1, my_vector.x2); + + return 0; + } + +### Копирование + +Функции копирования позволяют +Для копирования координат векторов предлагаются данные функции: + + inline void bgc_vector2_copy_fp32(const BgcVector2FP32* from, BgcVector2FP32* to); + inline void bgc_vector2_copy_fp64(const BgcVector2FP64* from, BgcVector2FP64* to); + +Каждая из данных функции эквивалентна следующим строкам кода: + + to->x1 = from->x1; + to->x2 = from->x2; + +В данные функции не следует передавать некорректные указатели. Значение NULL (0) +в качестве параметра также считается некорректным. + +Пример применения: + + #include + #include + + int main() + { + BgcVector2FP32 my_vector1, my_vector2; + + bgc_vector2_set_values_fp32(-2, 7, &my_vector1); + + bgc_vector2_copy_fp32(&my_vector1, &my_vector2); + + printf("x1 = %f, x2 = %f\n", my_vector2.x1, my_vector2.x2); + + return 0; + } + +### Обмен + +Функции обмена позволяют двум векторам одного типа обменяться значениями +координат. + +Для обмена значениями координат векторов определены следующие функции: + + inline void bgc_vector2_swap_fp32(BgcVector2FP32* vector1, BgcVector2FP32* vector2); + inline void bgc_vector2_swap_fp64(BgcVector2FP64* vector1, BgcVector2FP64* vector2); + +В данные функции не следует передавать некорректные указатели. Значение NULL (0) +также считается некорректным. + +Пример применения: + + #include + #include + + int main() + { + BgcVector2FP32 my_vector1, my_vector2; + + bgc_vector2_set_values_fp32(-2, 7, &my_vector1); + bgc_vector2_set_values_fp32(10, -1, &my_vector2); + + bgc_vector2_swap_fp32(&my_vector1, &my_vector2); + + printf("Vector #1: x1 = %f, x2 = %f\n", my_vector1.x1, my_vector1.x2); + printf("Vector #2: x1 = %f, x2 = %f\n", my_vector2.x1, my_vector2.x2); + + return 0; + } + +### Конвертация типа + +Функции конвертации типа позволяют преобразовать + + inline void bgc_vector2_convert_fp64_to_fp32(const BgcVector2FP64* from, BgcVector2FP32* to); + inline void bgc_vector2_convert_fp32_to_fp64(const BgcVector2FP32* from, BgcVector2FP64* to); + +Функции библиотеки проектировались из предпосылки, что разработчик, использующий +данную библиотеку, выберет один из двух типов чисел с плавающей запятой +(**float** или **double**) и будет работать с геометрическими структурами и +функциями выбранного типа. + +Тем не менее, в библиотеке есть функции, которые позволяют преобразовать данные +одного типа в данные другого типа. diff --git a/docs/versor-eng.md b/docs/versor-eng.md index 9b4f19f..86a5a3d 100644 --- a/docs/versor-eng.md +++ b/docs/versor-eng.md @@ -1,78 +1,48 @@ # Versors -Quaternions are complex numbers which have one real component and three -imaginary components. +[Quaternions](./quaternion-eng.md) are complex numbers which have one real component and three imaginary components. -A quaternion can be viewed as a four-dimensional vector: +![Formulas defining a quaternion](./media/quaternion_definition.png) -1. summation and subtraction of quaternions are same as for four-dimensional -vectors in Euclidean space; +Quaternions were discovered by mathematician William Hamilton and introduced to the public in 1843. -2. quaternions can be multiplied by real numbers the same way as -four-dimensional vectors; +In the same way, William Hamilton proposed a special class of quaternions, which he called versors. -3. the modulus of a quaternion is calculated in exactly the same way as -the modulus of a vector in four-dimensional Euclidean space; +A versor is a quaternion whose modulus is equal to one. That is, the formulas defining quaternions must be supplemented with the condition that the modulus of a quaternion is equal to one. -4. the multiplication of two quaternions can be represented as the product -of a 4x4 matrix and a four-dimensional vector. +![Formulas defining a versor](./media/versor_definition.png) -A quaternion has four degrees of freedom. But if we introduce a constraint in -the form of a requirement that the modulus of this quaternion be equal to one, -then such a set of quaternions will have only three degrees of freedom. +The name comes from the Latin verb "versare", meaning "to turn", "to rotate", to which is added the Latin ending -or, which denotes the subject performing the action. -These quaternions represent a sphere of radius 1 in four-dimensional space. -The "surface" of this sphere has a dimension equal to three. +Literally, the Latin word "versor" can be translated as "rotator" or "turner". -Quaternions of unit length describe rotations in three-dimensional space very -well. And this is logical, because rotations in three-dimensional space have -three degrees of freedom, just like a sphere in four-dimensional space. +Versors turned out to be a pretty good tool for describing rotations in three-dimensional space. -There is a special name for a quaternion of unit length: versor. +For the combination of two consecutive rotations, the operation of multiplying quaternions has proven useful, and for obtaining the inverse rotation, the operation of obtaining the conjugate quaternion. -Versors are quaternions of unit length. +When multiplying two versors (quaternions of unit length) and taking the conjugate versor, the result will also be a versor, that is, a quaternion of unit length. + +Addition and subtraction of two quaternions, as well as multiplication and division of a quaternion by a number, turned out to be unnecessary for describing rotations in three-dimensional space. ## Advantages of versors over quaternions -The main advantage of versors is that they do not degrade. +The main advantage of isolating versors as a separate abstraction from quaternions is that versors retain a modulus equal to one, i.e., versors do not degenerate. -If you multiply two quaternions whose moduli are equal to one, the result will -also be a quaternion with a modulus equal to one. While the product of two -quaternions whose moduli differ from one will yield a quaternion whose modulus -will most likely also differ from one. And the product of several quaternions -can yield a quaternion whose modulus will be close to zero. +Quaternions whose modulus is not equal to one can, as a result of many multiplication operations, yield a quaternion whose modulus can be so close to zero that it will be comparable to the magnitude of the error. -Thus, the modulus of a versor is always equal to one, unlike a regular -quaternion. +In practice, the versor module is not always equal to one, but is close to one due to the presence of the **float** and **double** (**binary32** and **binary64**) error types. But the BGC library functions ensure that the modulus of the vertex obtained as a result of some operation does not deviate from unity by an amount not exceeding a specified error. -In practice, the modulus of a versor is not always equal to one, but is close -to one due to the presence of an error in the **float** and **double** -(**binary32** and **binary64**) types. +And this is the second advantage of using versors to describe rotations. The developer who uses the library does not need to perform normalization, as would have to be done with ordinary quaternions. -The second advantage of versors is that the library functions take on the task -of maintaining the versor modulus so that it does not deviate too much from one. +But the library functions do not always perform versor normalization, but only when necessary. The library functions normalize the resulting versor only when the versor module deviates from unity by more than a predetermined error value (epsilon). -Thus, the developer does not need to perform normalization, as he would have -to do with regular quaternions. - -The third advantage of versors is that the library functions do not always -perform versor normalization, but only when it is necessary. - -The library functions check the difference between the versor modulus and 1, and -if the error is greater than a predefined threshold (epsilon), the function -normalizes the resulting versor. - -In most cases, when the input parameters are versors (normalized quaternions), -there is no need to normalize the function result. This way, time-consuming -operations such as square root calculations and division can be avoided. This -approach allows to improve performance and keep versions normalized. +In most cases, when the input parameters are versors (normalized quaternions), the magnitude of the resulting versor also does not deviate much from one, and therefore there is no need to perform normalization. Thus, time-consuming operations such as calculating square roots and division can be avoided. This approach improves performance and keeps versors normalized. ## Implementation of versors in the library -The library has a separate implementation for versors in the form of special -structures and a set of functions that keep the modulus of a versorclose to one. +The library has a separate implementation for versors in the form of special structures and a set of functions that support the versor module close to one, since it is necessary to support the versor module close to one, and versors do not need addition and subtraction, as well as multiplication and division by a number. -There are two structures for versors: **BgcVersorFP32** and **BgcVersorFP64**: +There are two structures for describing a versor: typedef struct { const float s0, x1, x2, x3; @@ -82,63 +52,27 @@ There are two structures for versors: **BgcVersorFP32** and **BgcVersorFP64**: const double s0, x1, x2, x3; } BgcVersorFP64; -The fields are deliberately declared const so that a developer using these -structures is not tempted to change the values of the fields directly. +The field **s0** is the real part of the versor (normalized quaternion), and the fields **x1**, **x2**, and **x3** are the imaginary components of the versor. -With these structures, it is better to use special functions that allow you -to save new values in the structure fields of **BgcVersorFP32** and -**BgcVersorFP64**. +The fields of the structures are intentionally declared as const to encourage the developer to use functions for working with versors, instead of directly setting the field values. The functions responsible for operations on versors maintain the module of the obtained versors equal to one. + +With these structures, it is better to use special functions that allow setting new values ​​in the fields of the **BgcVersorFP32** and **BgcVersorFP64** structures. ## Operation with versors -- Resetting the state to idle (reset) -- Setting the values of components (set values) -- Copying the state (copy) -- Swapping the states (swap) -- Making a versor with turn (set turn) -- Checking the state is idle (is idle) -- Convertation of type (convert) -- Shortening of the turn (shorten) -- Inversion (invert) -- Combination (combine) -- Getting description of the turn (get rotation) -- Getting the rotation matrix (get rotation matrix) -- Getting the reverse rotation matrix (get reverse matrix) -- Turning a vector (turn vector) -- Turning a vector backward (turn vector back) -- Comparsion (are close) - -### Resetting the state to idle - -A versor which describes an idle turn has these values of the components: - - s0 = 1, x1 = 0, x2 = 0, x3 = 0 - -There is a function which resets the state of a versor to that state. - -For **BgcVersorFP32**: - - inline void bgc_versor_reset_fp32(BgcVersorFP32* versor); - -For **BgcVersorFP64**: - - inline void bgc_versor_reset_fp64(BgcVersorFP64* versor); - -Example of usage: - - #include - #include - - int main() { - BgFP32Versor versor; - - bgc_versor_reset_fp32(&versor); - - printf("Versor: (%f, %f, %f, %f)\n", versor.s0, versor.x1, versor.x2, versor.x3); - - return 0; - } - -Result: - - Versor: (1.000000, 0.000000, 0.000000, 0.000000) +- [Reset state](./versor-reset-eng.md) +- [Specify component values](./versor-set-values-eng.md) +- Copy component values +- Swap component values +- Build based on rotation +- Check for absence of rotation +- Type conversion +- Rotation reduction +- Inversion +- Combination +- Get rotation description +- Get rotation matrix +- Get inverse rotation matrix +- Rotate vector +- Inverse vector rotation +- Compare diff --git a/docs/versor-reset-eng.md b/docs/versor-reset-eng.md new file mode 100644 index 0000000..c6bbd69 --- /dev/null +++ b/docs/versor-reset-eng.md @@ -0,0 +1,43 @@ +# State reset functions for versors + +[A versor](./versor-eng.md) that corresponds to no rotation has the following component values: + + s0 = 1; + x1 = 0; + x2 = 0; + x3 = 0; + +To set such a state for the versor components, the library has the corresponding functions. + +For the **BgFP32Versor** type, the function is: + + void bgc_versor_reset_fp32(BgFP32Versor* versor); + +For the **BgFP64Versor** type, the function is: + + void bgc_versor_reset_fp64(BgFP64Versor* versor); + +The **versor** parameter must be a valid pointer and must not be NULL. + +These functions are well suited for initializing the state of variables of the **BgFP32Versor** and **BgFP64Versor** types. + +Usage example: + + #include + #include + + int main() { + BgFP32Versor versor; + + bgc_versor_reset_fp32(&versor); + + printf("Versor: (%f, %f, %f, %f)\n", versor.s0, versor.x1, versor.x2, versor.x3); + + return 0; + } + +Result: + + Versor: (1.000000, 0.000000, 0.000000, 0.000000) + +[Versors](./versor-eng.md) diff --git a/docs/versor-reset-rus.md b/docs/versor-reset-rus.md new file mode 100644 index 0000000..b229b07 --- /dev/null +++ b/docs/versor-reset-rus.md @@ -0,0 +1,43 @@ +# Функции сброса состояния для версоров + +[Версор](./versor-rus.md), который соответствует отсутствию поворота, имеет следующие значеия компонент: + + s0 = 1; + x1 = 0; + x2 = 0; + x3 = 0; + +Чтобы установить такое состояние для компонент версора, в библиотеке есть соответствующие функции. + +Для типа **BgFP32Versor** функция имеет вид: + + inline void bgc_versor_reset_fp32(BgFP32Versor* versor); + +Для типа **BgFP64Versor** функция имеет вид: + + inline void bgc_versor_reset_fp64(BgFP64Versor* versor); + +Параметр **versor** должен быть корректным указателем, а также не должен быть равен NULL. + +Эти функции хорошо подходят для инициализации состояния переменных типов **BgFP32Versor** и **BgFP64Versor**. + +Пример использования: + + #include + #include + + int main() { + BgFP32Versor versor; + + bgc_versor_reset_fp32(&versor); + + printf("Versor: (%f, %f, %f, %f)\n", versor.s0, versor.x1, versor.x2, versor.x3); + + return 0; + } + +Результат: + + Versor: (1.000000, 0.000000, 0.000000, 0.000000) + +[Версоры](./versor-rus.md) diff --git a/docs/versor-rus.md b/docs/versor-rus.md index 4d6454c..60f24ef 100644 --- a/docs/versor-rus.md +++ b/docs/versor-rus.md @@ -1,71 +1,51 @@ # Версоры -[Кватернионы](./quaternion-rus.md) - это гиперкомплексные числа, у которых -имеется одна действительная компонента и три комплексных компоненты: +[Кватернионы](./quaternion-rus.md) - это гиперкомплексные числа, у которых имеется одна действительная компонента и три мнимых компоненты: -![Определение кватерниона](./media/quaternion_definition.png) +![Формулы определяющие кватернион](./media/quaternion_definition.png) -Кватернион имеет четыре степени свободы. Но если ввести ограничение в виде -требования, чтобы модуль этого кватерниона был равен единице, то такое множество -кватернионов будет иметь только три степени свободы. + q = w + ix + jy + kz + i2 = j2 = k2 = -1 -Эти кватернионы представляют собой сферу радиуса 1 в четырёхмерном пространстве. -"Поверхность" этой сферы имеет размерность равную трём. +Кватернионы были открыты математиком Уильямом Гамильтоном и представлены публике в 1843 году. -Кватернионы единичной длины очень хорошо описывают повороты в трёхмерном -пространстве. Вращения в трёхмерном пространстве имеют три степени свободы, -что совпадает с размерностю поверхности сферы в четырёхмерном пространстве. +Вское Уильям Гамильтон предложил особый класс кватернионов, которые назвал версорами. -Для кватерниона единичной длины существует специальное название: **версор**. +Версор - это кватернион, модуль которого равен единице. То есть, к формулам, определяющим квартернионы, необходимо добавить услвие, что модуль кватериона равен единице. -**Версоры** - это кватернионы единичной длины. К определению кватерниона -необходимо просто добавить одно уравнение: +![Формулы определяющие версор](./media/versor_definition.png) -![Определение версора](./media/versor_definition.png) +Название происходит от латинского глагола "versare", означаюшего "поворачивать", "вращать", к которому добавлено латнское окончание -or, которое обозначает субъект, выполняющий действие. -Несмотря на то, что версоны как класс кватернионов были предложены ещё Уильямом -Гамильтоном для описаний поворотв, в русскоязычной литературе термин "версор", -можно сказать, что не употребляется. +Дословно латинское слово "versor" можно перевести как "вращатель" или "поворачиватель". + +Версоры оказались довольно хорошим инструментом для описания поворотов в трёхмерном пространстве. + +Для комбинации двух последовательных поворотов оказалось полезной операция умножения кватернионов, а для получения обратного поворота - операция получения сопряжённого кватерниона. + +При умножении двух версоров (кватернионов единичной длины) и при взятии сопряжённого версора результат также будет версором, то есть кватернионом единичной длины. + +Сложение и вычитание двух кватернионов, а также умножение и деление кватерниона на число оказались не нужны для описания поворотов в трёхмерном пространстве. + +Несмотря на то, что версоры как класс кватернионов были предложены ещё Уильямом Гамильтоном для описаний поворотов ещё в середине 19 века, в русскоязычной литературе термин "версор" встречается настолько редко, что можно сказать, что не употребляется. ## Преимущества версоров над кватернионами -Основным преимуществом версоров заключается в том, что они не деградируют. +Главным преимуществом выделения версоров как отдельной от кватернионов абстрации заключается в том, что версоры сохраняют модуль равный единице, то есть, версоры не вырождаются. -Если умножить два кватерниона, модули которых равны единице, то результатом -будет также кватернион с модулем, равным единице. В то время как произведение -двух кватернионов, у которых модули отличаются от единицы, даст кватернион, -модуль которого, скорее всего, также будет отличаться от единицы. А произведение -ряда кватернионов может дать кватернион, у которого модуль будет близок к нулю. +Кватернионы, модуль которых не равен единице в результате множества операций умножения могут дать кватернион, модуль которого может оказаться настолко близок к нулю, что будет сопоставим с величиной погрешности. -Таком образом, модуль версора всегда равен единице в отличие от обычного -кватерниона. +На практике модуль версора не всегда равен единице, но близок к единице из-за наличия погрешности типов **float** и **double** (**binary32** и **binary64**). Но функции библиотеки BGC обеспечивают, чтобы модуль веросра, полученного в результате некоторой операции, не отколнялся от единицы на величину не превышающую заданную погрешность. -На практике модуль веросна не всегда равен единице, но близок к единице из-за -наличия погрешности типов **float** и **double** (**binary32** и **binary64**). +И это является вторым преимуществом применения именно версоров для описания поворотов. Разработчику, который использует библиотеку, не нужно производить нормализацию, как это пришлось бы делать с обычными кватернионами. -Вторым преимуществом версоров в том, что функции библиотеки берут на себя -задачу поддержания модуля версора, чтобы оно не сильно отклонялось от единицы. +Но функции библиотеки не всегда производят нормализацию версоров, а только тогда, когда это необходимо. Функции библиотеки нормализуют полученный версор только тогда, когда модуль версора отклоняется от единицы больше, чем на предопределенную величину погрешности (эпсилон). -Таким образом, разработчику не нужно производить нормализацию, как это пришлось -бы делать с обычными кватернионами. - -Третьим преимуществом версоров является то, что функции библиотеки не всегда -производят нормализацию версоров, а только тогда, когда это необходимо. - -Функции библиотеки проверяют разницу между модулем версора и единицей, и только -больше предопределенного порога (эпсилон), функция нормализует полученный -версор. - -В большинстве случаев, когда входные параметры являются версорами -(нормализованными кватернионами), нет необходимости нормализовать результат -функции. Таким образом, можно избежать трудоемких операций, таких как вычисление -квадратных корней и деление. Такой подход позволяет повысить производительность -и поддерживать версоры нормализованными. +В большинстве случаев, когда входные параметры являются версорами (нормализованными кватернионами), модуль полученного версора также не сильно отклоняется от единицы, а потому нет необходимости производить нормализацию. Таким образом, можно избежать трудоемких операций, таких как вычисление квадратных корней и деление. Такой подход позволяет повысить производительность и поддерживать версоры нормализованными. ## Версоры в библиотеке -Библиотека имеет отдельную реализацию для версоров в виде специальных структур и -набора функций, которые поддерживают модуль версоров близким к единице. +Библиотека имеет отдельную реализацию для версоров в виде специальных структур и набора функций, которые поддерживают модуль версоров близким к единице, посольку необходимо поддерживать модуль веросоров близким к единице, а также версорам не нужны сложение и вычитание, а также умножение и деление на число. Для описания версора имеется две структуры: @@ -77,19 +57,16 @@ const double s0, x1, x2, x3; } BgcVersorFP64; -Поля структур намеренно объявлены констрантными (const), чтобы побудить -разработчика использовать функции работы с версорами, вместо того, чтобы -непосредственно задавать значения полей. Функции работы с версорами поддерживают -модуль версора равным единицы. +Поле **s0** вещественной частю версора (нормализованного кватерниона), а поля **x1**, **x2** и **x3** являются мнимыми компонентами версора. -С данными структурами лучше использовать специальные функции, которые позволяют -устанавливать новые значения в поля структур **BgcVersorFP32** и -**BgcVersorFP64**. +Поля структур намеренно объявлены констрантными (const), чтобы побудить разработчика использовать функции работы с версорами, вместо того, чтобы непосредственно задавать значения полей. Функции отвечающие за операции над версорами поддерживают модуль полученных версоров равным единице. + +С данными структурами лучше использовать специальные функции, которые позволяют устанавливать новые значения в поля структур **BgcVersorFP32** и **BgcVersorFP64**. ## Операции с версорами -- Сброс состояния (reset) -- Указание значений компонент (set values) +- [Сброс состояния (reset)](./versor-reset-rus.md) +- [Указание значений компонент (set values)](./versor-set-values-rus.md) - Копирование значений компонент (copy) - Обмен значений компонент (swap) - Построение на основе поворота (set turn) diff --git a/docs/versor-set-values-eng.md b/docs/versor-set-values-eng.md new file mode 100644 index 0000000..5c28d32 --- /dev/null +++ b/docs/versor-set-values-eng.md @@ -0,0 +1,45 @@ +# Functions that set the values of the versor components + +Special functions are provided to specify specific values ??for the versor components. + +For the **BgFP32Versor** type, the function has the form: + + inline void bgc_versor_set_values_fp32(const float s0, const float x1, const float x2, const float x3, BgcVersorFP32* versor); + +For the **BgFP64Versor** type, the function has the form: + + inline void bgc_versor_set_values_fp64(const double s0, const double x1, const double x2, const double x3, BgcVersorFP64* versor); + +These functions set the values ??passed in the **s0**, **x1**, **x2**, and **x3** parameters to the corresponding components of the versor passed by pointer in the **versor** parameter. But if the resulting state is not a normalized quaternion, then the functions normalize the versor. + +The **versor** parameter must be a valid pointer and must not be NULL. + +These functions are also well suited for initializing the state of variables of types **BgFP32Versor** and **BgFP64Versor**, as are the functions [bgc_versor_reset_fp32 and bgc_versor_reset_fp64](./versor-reset-eng.md). + + + #include + #include + + int main() { + BgcVersorFP64 versor; + + bgc_versor_set_values_fp64(1, 2, 3, 4, &versor); + + printf("Versor: (%lf, %lf, %lf, %lf)\n", versor.s0, versor.x1, versor.x2, versor.x3); + + return 0; + } + +Result: + + Versor: (0.182574, 0.365148, 0.547723, 0.730297) + +If zeros are passed to the function as component values, then the versor, the pointer to which is passed in the **versor** parameter, will be set to the state corresponding to the absence of rotation: + + bgc_versor_set_values_fp64(0, 0, 0, 0, &versor); + +Result: + + Versor: (1.000000, 0.000000, 0.000000, 0.000000) + +[Versors](./versor-eng.md) diff --git a/docs/versor-set-values-rus.md b/docs/versor-set-values-rus.md new file mode 100644 index 0000000..74c4881 --- /dev/null +++ b/docs/versor-set-values-rus.md @@ -0,0 +1,47 @@ +# + + . + + **BgFP32Versor** : + + inline void bgc_versor_set_values_fp32(const float s0, const float x1, const float x2, const float x3, BgcVersorFP32* versor); + + **BgFP64Versor** : + + inline void bgc_versor_set_values_fp64(const double s0, const double x1, const double x2, const double x3, BgcVersorFP64* versor); + + , **s0**, **x1**, **x2** **x3**, , **versor**. , . + + **versor** , NULL. + + **BgFP32Versor** **BgFP64Versor** [bgc_versor_reset_fp32 bgc_versor_reset_fp64](./versor-reset-eng.md). + + : + + #include + #include + + int main() { + BgcVersorFP64 versor; + + bgc_versor_set_values_fp64(1, 2, 3, 4, &versor); + + printf("Versor: (%lf, %lf, %lf, %lf)\n", versor.s0, versor.x1, versor.x2, versor.x3); + + return 0; + } + +: + + Versor: (0.182574, 0.365148, 0.547723, 0.730297) + + , , **versor**, , : + + bgc_versor_set_values_fp64(0, 0, 0, 0, &versor); + +: + + Versor: (1.000000, 0.000000, 0.000000, 0.000000) + +[](./versor-rus.md) + diff --git a/docs/versor_reset-eng.md b/docs/versor_reset-eng.md deleted file mode 100644 index b61a1c8..0000000 --- a/docs/versor_reset-eng.md +++ /dev/null @@ -1,36 +0,0 @@ -# Reset functions for versors - -The functions reset the state of versors to the state of no turn: - - s0 = 1, x1 = 0, x2 = 0, x3 = 0 - -For the **BgFP32Versor** type the function is: - - void bgc_versor_reset_fp32(BgFP32Versor* versor); - -For the **BgFP64Versor** type the function is: - - void bgc_versor_reset_fp64(BgFP64Versor* versor); - -These functions are good for setting the initial state of variables and fields -of **BgFP32Versor** and **BgFP64Versor** types. - -Example of usage: - - #include - #include - - int main() { - BgFP32Versor versor; - - bgc_versor_reset_fp32(&versor); - - printf("Versor: (%f, %f, %f, %f)\n", versor.s0, versor.x1, versor.x2, versor.x3); - - return 0; - } - -Result: - - Versor: (1.000000, 0.000000, 0.000000, 0.000000) - diff --git a/docs/versor_reset-rus.md b/docs/versor_reset-rus.md deleted file mode 100644 index c27fb56..0000000 --- a/docs/versor_reset-rus.md +++ /dev/null @@ -1,37 +0,0 @@ -# Функции reset для версоров - -Фунции сбрасывают состояние версора на состояние, соответствующее нулевому -повороту: - - s0 = 1, x1 = 0, x2 = 0, x3 = 0 - -Для типа **BgFP32Versor** функция имеет вид: - - void bgc_versor_reset_fp32(BgFP32Versor* versor); - -Для типа **BgFP64Versor** функция имеет вид: - - void bgc_versor_reset_fp64(BgFP64Versor* versor); - -Данные функции хорошо подходят для инициализации состояния переменной типов -**BgFP32Versor** и **BgFP64Versor**. - -Пример использования: - - #include - #include - - int main() { - BgFP32Versor versor; - - bgc_versor_reset_fp32(&versor); - - printf("Versor: (%f, %f, %f, %f)\n", versor.s0, versor.x1, versor.x2, versor.x3); - - return 0; - } - -Результат: - - Versor: (1.000000, 0.000000, 0.000000, 0.000000) -