Улучшение документации
This commit is contained in:
parent
b5aa39c145
commit
c7e39e1527
13 changed files with 439 additions and 239 deletions
|
@ -93,7 +93,7 @@ void list_work(const uint_fast32_t amount, structure_fp32_t* list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
const unsigned int amount = 1000000;
|
const unsigned int amount = 1000000;
|
||||||
|
@ -135,3 +135,17 @@ int main()
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include <stdio.h>
|
||||||
|
//#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
0
docs/contents-eng.md
Normal file
0
docs/contents-eng.md
Normal file
|
@ -1,4 +1,6 @@
|
||||||
# Prefixes and Suffixes
|
# Naming
|
||||||
|
|
||||||
|
## Prefixes
|
||||||
|
|
||||||
The library uses prefixes in names of types, constants and functions.
|
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:
|
The functions have prefix in the form **bgc_**. For example:
|
||||||
bgc_versor_combine_fp32, bgc_matrix3x3_subtract_fp32.
|
bgc_versor_combine_fp32, bgc_matrix3x3_subtract_fp32.
|
||||||
|
|
||||||
|
## Suffixes
|
||||||
|
|
||||||
Suffixs of type ends the names of constats, types and functions of the library.
|
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**
|
The library uses two types of floating point numbers: **float** and **double**
|
||||||
(**binary32** and **binary64** types of the **IEEE 754** standard).
|
(**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 functions which works with data of the **double** type have **_fp64** as
|
||||||
the type suffix: bgc_vector3_reset_fp64, bgc_radians_normalize_fp64.
|
the type suffix: bgc_vector3_reset_fp64, bgc_radians_normalize_fp64.
|
||||||
|
|
||||||
|
## Entities
|
||||||
|
|
||||||
|
- Vectors 2D and 3D
|
||||||
|
- [Versors](./versor-eng.md)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Префиксы
|
# Названия
|
||||||
|
|
||||||
|
## Префиксы
|
||||||
|
|
||||||
Библиотека использует префиксы в названиях типов, констант и функций.
|
Библиотека использует префиксы в названиях типов, констант и функций.
|
||||||
|
|
||||||
|
@ -14,6 +16,8 @@ BGC_TWO_PI_FP64.
|
||||||
Функции имеют префикс в виде **bgc_**, например: bgc_versor_combine_fp32,
|
Функции имеют префикс в виде **bgc_**, например: bgc_versor_combine_fp32,
|
||||||
bgc_matrix3x3_subtract_fp64.
|
bgc_matrix3x3_subtract_fp64.
|
||||||
|
|
||||||
|
## Cуффиксы
|
||||||
|
|
||||||
Названия констант, типов и функций оканчиваются суффиксом, указывающим на
|
Названия констант, типов и функций оканчиваются суффиксом, указывающим на
|
||||||
базовый тип. Библиотека использует два типа чисел с плавающей запятой:
|
базовый тип. Библиотека использует два типа чисел с плавающей запятой:
|
||||||
**float** и **double** (типы **binary32** и **binary64** стандарта
|
**float** и **double** (типы **binary32** и **binary64** стандарта
|
||||||
|
@ -43,3 +47,8 @@ bcg_vector2_get_modulus_fp32, bgc_radians_to_degrees_fp32.
|
||||||
|
|
||||||
Функции, которые работают с данными типа **double** имеют суффикс **_fp64**:
|
Функции, которые работают с данными типа **double** имеют суффикс **_fp64**:
|
||||||
bgc_vector3_reset_fp64, bgc_radians_normalize_fp64.
|
bgc_vector3_reset_fp64, bgc_radians_normalize_fp64.
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
- 2D и 3D векторы
|
||||||
|
- [Versors](./versor-rus.md)
|
|
@ -23,3 +23,154 @@ binary32 стандарта IEEE 754).
|
||||||
double x1, x2;
|
double x1, x2;
|
||||||
} BgcVector2FP64;
|
} 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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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**) и будет работать с геометрическими структурами и
|
||||||
|
функциями выбранного типа.
|
||||||
|
|
||||||
|
Тем не менее, в библиотеке есть функции, которые позволяют преобразовать данные
|
||||||
|
одного типа в данные другого типа.
|
||||||
|
|
|
@ -1,78 +1,48 @@
|
||||||
# Versors
|
# Versors
|
||||||
|
|
||||||
Quaternions are complex numbers which have one real component and three
|
[Quaternions](./quaternion-eng.md) are complex numbers which have one real component and three imaginary components.
|
||||||
imaginary components.
|
|
||||||
|
|
||||||
A quaternion can be viewed as a four-dimensional vector:
|

|
||||||
|
|
||||||
1. summation and subtraction of quaternions are same as for four-dimensional
|
Quaternions were discovered by mathematician William Hamilton and introduced to the public in 1843.
|
||||||
vectors in Euclidean space;
|
|
||||||
|
|
||||||
2. quaternions can be multiplied by real numbers the same way as
|
In the same way, William Hamilton proposed a special class of quaternions, which he called versors.
|
||||||
four-dimensional vectors;
|
|
||||||
|
|
||||||
3. the modulus of a quaternion is calculated in exactly the same way as
|
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.
|
||||||
the modulus of a vector in four-dimensional Euclidean space;
|
|
||||||
|
|
||||||
4. the multiplication of two quaternions can be represented as the product
|

|
||||||
of a 4x4 matrix and a four-dimensional vector.
|
|
||||||
|
|
||||||
A quaternion has four degrees of freedom. But if we introduce a constraint in
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
These quaternions represent a sphere of radius 1 in four-dimensional space.
|
Literally, the Latin word "versor" can be translated as "rotator" or "turner".
|
||||||
The "surface" of this sphere has a dimension equal to three.
|
|
||||||
|
|
||||||
Quaternions of unit length describe rotations in three-dimensional space very
|
Versors turned out to be a pretty good tool for describing rotations in three-dimensional space.
|
||||||
well. And this is logical, because rotations in three-dimensional space have
|
|
||||||
three degrees of freedom, just like a sphere in four-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
|
## 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
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
Thus, the modulus of a versor is always equal to one, unlike a regular
|
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.
|
||||||
quaternion.
|
|
||||||
|
|
||||||
In practice, the modulus of a versor is not always equal to one, but is close
|
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.
|
||||||
to one due to the presence of an error in the **float** and **double**
|
|
||||||
(**binary32** and **binary64**) types.
|
|
||||||
|
|
||||||
The second advantage of versors is that the library functions take on the task
|
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).
|
||||||
of maintaining the versor modulus so that it does not deviate too much from one.
|
|
||||||
|
|
||||||
Thus, the developer does not need to perform normalization, as he would have
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
## Implementation of versors in the library
|
## Implementation of versors in the library
|
||||||
|
|
||||||
The library has a separate implementation for versors in the form of special
|
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.
|
||||||
structures and a set of functions that keep the modulus of a versorclose to one.
|
|
||||||
|
|
||||||
There are two structures for versors: **BgcVersorFP32** and **BgcVersorFP64**:
|
There are two structures for describing a versor:
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const float s0, x1, x2, x3;
|
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;
|
const double s0, x1, x2, x3;
|
||||||
} BgcVersorFP64;
|
} BgcVersorFP64;
|
||||||
|
|
||||||
The fields are deliberately declared const so that a developer using these
|
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.
|
||||||
structures is not tempted to change the values of the fields directly.
|
|
||||||
|
|
||||||
With these structures, it is better to use special functions that allow you
|
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.
|
||||||
to save new values in the structure fields of **BgcVersorFP32** and
|
|
||||||
**BgcVersorFP64**.
|
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
|
## Operation with versors
|
||||||
|
|
||||||
- Resetting the state to idle (reset)
|
- [Reset state](./versor-reset-eng.md)
|
||||||
- Setting the values of components (set values)
|
- [Specify component values](./versor-set-values-eng.md)
|
||||||
- Copying the state (copy)
|
- Copy component values
|
||||||
- Swapping the states (swap)
|
- Swap component values
|
||||||
- Making a versor with turn (set turn)
|
- Build based on rotation
|
||||||
- Checking the state is idle (is idle)
|
- Check for absence of rotation
|
||||||
- Convertation of type (convert)
|
- Type conversion
|
||||||
- Shortening of the turn (shorten)
|
- Rotation reduction
|
||||||
- Inversion (invert)
|
- Inversion
|
||||||
- Combination (combine)
|
- Combination
|
||||||
- Getting description of the turn (get rotation)
|
- Get rotation description
|
||||||
- Getting the rotation matrix (get rotation matrix)
|
- Get rotation matrix
|
||||||
- Getting the reverse rotation matrix (get reverse matrix)
|
- Get inverse rotation matrix
|
||||||
- Turning a vector (turn vector)
|
- Rotate vector
|
||||||
- Turning a vector backward (turn vector back)
|
- Inverse vector rotation
|
||||||
- Comparsion (are close)
|
- Compare
|
||||||
|
|
||||||
### 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 <stdio.h>
|
|
||||||
#include <basic-geometry.h>
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
43
docs/versor-reset-eng.md
Normal file
43
docs/versor-reset-eng.md
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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)
|
43
docs/versor-reset-rus.md
Normal file
43
docs/versor-reset-rus.md
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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)
|
|
@ -1,71 +1,51 @@
|
||||||
# Версоры
|
# Версоры
|
||||||
|
|
||||||
[Кватернионы](./quaternion-rus.md) - это гиперкомплексные числа, у которых
|
[Кватернионы](./quaternion-rus.md) - это гиперкомплексные числа, у которых имеется одна действительная компонента и три мнимых компоненты:
|
||||||
имеется одна действительная компонента и три комплексных компоненты:
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Кватернион имеет четыре степени свободы. Но если ввести ограничение в виде
|
q = w + ix + jy + kz
|
||||||
требования, чтобы модуль этого кватерниона был равен единице, то такое множество
|
i<sup>2</sup> = j<sup>2</sup> = k<sup>2</sup> = -1
|
||||||
кватернионов будет иметь только три степени свободы.
|
|
||||||
|
|
||||||
Эти кватернионы представляют собой сферу радиуса 1 в четырёхмерном пространстве.
|
Кватернионы были открыты математиком Уильямом Гамильтоном и представлены публике в 1843 году.
|
||||||
"Поверхность" этой сферы имеет размерность равную трём.
|
|
||||||
|
|
||||||
Кватернионы единичной длины очень хорошо описывают повороты в трёхмерном
|
Вское Уильям Гамильтон предложил особый класс кватернионов, которые назвал версорами.
|
||||||
пространстве. Вращения в трёхмерном пространстве имеют три степени свободы,
|
|
||||||
что совпадает с размерностю поверхности сферы в четырёхмерном пространстве.
|
|
||||||
|
|
||||||
Для кватерниона единичной длины существует специальное название: **версор**.
|
Версор - это кватернион, модуль которого равен единице. То есть, к формулам, определяющим квартернионы, необходимо добавить услвие, что модуль кватериона равен единице.
|
||||||
|
|
||||||
**Версоры** - это кватернионы единичной длины. К определению кватерниона
|

|
||||||
необходимо просто добавить одно уравнение:
|
|
||||||
|
|
||||||

|
Название происходит от латинского глагола "versare", означаюшего "поворачивать", "вращать", к которому добавлено латнское окончание -or, которое обозначает субъект, выполняющий действие.
|
||||||
|
|
||||||
Несмотря на то, что версоны как класс кватернионов были предложены ещё Уильямом
|
Дословно латинское слово "versor" можно перевести как "вращатель" или "поворачиватель".
|
||||||
Гамильтоном для описаний поворотв, в русскоязычной литературе термин "версор",
|
|
||||||
можно сказать, что не употребляется.
|
Версоры оказались довольно хорошим инструментом для описания поворотов в трёхмерном пространстве.
|
||||||
|
|
||||||
|
Для комбинации двух последовательных поворотов оказалось полезной операция умножения кватернионов, а для получения обратного поворота - операция получения сопряжённого кватерниона.
|
||||||
|
|
||||||
|
При умножении двух версоров (кватернионов единичной длины) и при взятии сопряжённого версора результат также будет версором, то есть кватернионом единичной длины.
|
||||||
|
|
||||||
|
Сложение и вычитание двух кватернионов, а также умножение и деление кватерниона на число оказались не нужны для описания поворотов в трёхмерном пространстве.
|
||||||
|
|
||||||
|
Несмотря на то, что версоры как класс кватернионов были предложены ещё Уильямом Гамильтоном для описаний поворотов ещё в середине 19 века, в русскоязычной литературе термин "версор" встречается настолько редко, что можно сказать, что не употребляется.
|
||||||
|
|
||||||
## Преимущества версоров над кватернионами
|
## Преимущества версоров над кватернионами
|
||||||
|
|
||||||
Основным преимуществом версоров заключается в том, что они не деградируют.
|
Главным преимуществом выделения версоров как отдельной от кватернионов абстрации заключается в том, что версоры сохраняют модуль равный единице, то есть, версоры не вырождаются.
|
||||||
|
|
||||||
Если умножить два кватерниона, модули которых равны единице, то результатом
|
Кватернионы, модуль которых не равен единице в результате множества операций умножения могут дать кватернион, модуль которого может оказаться настолко близок к нулю, что будет сопоставим с величиной погрешности.
|
||||||
будет также кватернион с модулем, равным единице. В то время как произведение
|
|
||||||
двух кватернионов, у которых модули отличаются от единицы, даст кватернион,
|
|
||||||
модуль которого, скорее всего, также будет отличаться от единицы. А произведение
|
|
||||||
ряда кватернионов может дать кватернион, у которого модуль будет близок к нулю.
|
|
||||||
|
|
||||||
Таком образом, модуль версора всегда равен единице в отличие от обычного
|
На практике модуль версора не всегда равен единице, но близок к единице из-за наличия погрешности типов **float** и **double** (**binary32** и **binary64**). Но функции библиотеки BGC обеспечивают, чтобы модуль веросра, полученного в результате некоторой операции, не отколнялся от единицы на величину не превышающую заданную погрешность.
|
||||||
кватерниона.
|
|
||||||
|
|
||||||
На практике модуль веросна не всегда равен единице, но близок к единице из-за
|
И это является вторым преимуществом применения именно версоров для описания поворотов. Разработчику, который использует библиотеку, не нужно производить нормализацию, как это пришлось бы делать с обычными кватернионами.
|
||||||
наличия погрешности типов **float** и **double** (**binary32** и **binary64**).
|
|
||||||
|
|
||||||
Вторым преимуществом версоров в том, что функции библиотеки берут на себя
|
Но функции библиотеки не всегда производят нормализацию версоров, а только тогда, когда это необходимо. Функции библиотеки нормализуют полученный версор только тогда, когда модуль версора отклоняется от единицы больше, чем на предопределенную величину погрешности (эпсилон).
|
||||||
задачу поддержания модуля версора, чтобы оно не сильно отклонялось от единицы.
|
|
||||||
|
|
||||||
Таким образом, разработчику не нужно производить нормализацию, как это пришлось
|
В большинстве случаев, когда входные параметры являются версорами (нормализованными кватернионами), модуль полученного версора также не сильно отклоняется от единицы, а потому нет необходимости производить нормализацию. Таким образом, можно избежать трудоемких операций, таких как вычисление квадратных корней и деление. Такой подход позволяет повысить производительность и поддерживать версоры нормализованными.
|
||||||
бы делать с обычными кватернионами.
|
|
||||||
|
|
||||||
Третьим преимуществом версоров является то, что функции библиотеки не всегда
|
|
||||||
производят нормализацию версоров, а только тогда, когда это необходимо.
|
|
||||||
|
|
||||||
Функции библиотеки проверяют разницу между модулем версора и единицей, и только
|
|
||||||
больше предопределенного порога (эпсилон), функция нормализует полученный
|
|
||||||
версор.
|
|
||||||
|
|
||||||
В большинстве случаев, когда входные параметры являются версорами
|
|
||||||
(нормализованными кватернионами), нет необходимости нормализовать результат
|
|
||||||
функции. Таким образом, можно избежать трудоемких операций, таких как вычисление
|
|
||||||
квадратных корней и деление. Такой подход позволяет повысить производительность
|
|
||||||
и поддерживать версоры нормализованными.
|
|
||||||
|
|
||||||
## Версоры в библиотеке
|
## Версоры в библиотеке
|
||||||
|
|
||||||
Библиотека имеет отдельную реализацию для версоров в виде специальных структур и
|
Библиотека имеет отдельную реализацию для версоров в виде специальных структур и набора функций, которые поддерживают модуль версоров близким к единице, посольку необходимо поддерживать модуль веросоров близким к единице, а также версорам не нужны сложение и вычитание, а также умножение и деление на число.
|
||||||
набора функций, которые поддерживают модуль версоров близким к единице.
|
|
||||||
|
|
||||||
Для описания версора имеется две структуры:
|
Для описания версора имеется две структуры:
|
||||||
|
|
||||||
|
@ -77,19 +57,16 @@
|
||||||
const double s0, x1, x2, x3;
|
const double s0, x1, x2, x3;
|
||||||
} BgcVersorFP64;
|
} BgcVersorFP64;
|
||||||
|
|
||||||
Поля структур намеренно объявлены констрантными (const), чтобы побудить
|
Поле **s0** вещественной частю версора (нормализованного кватерниона), а поля **x1**, **x2** и **x3** являются мнимыми компонентами версора.
|
||||||
разработчика использовать функции работы с версорами, вместо того, чтобы
|
|
||||||
непосредственно задавать значения полей. Функции работы с версорами поддерживают
|
|
||||||
модуль версора равным единицы.
|
|
||||||
|
|
||||||
С данными структурами лучше использовать специальные функции, которые позволяют
|
Поля структур намеренно объявлены констрантными (const), чтобы побудить разработчика использовать функции работы с версорами, вместо того, чтобы непосредственно задавать значения полей. Функции отвечающие за операции над версорами поддерживают модуль полученных версоров равным единице.
|
||||||
устанавливать новые значения в поля структур **BgcVersorFP32** и
|
|
||||||
**BgcVersorFP64**.
|
С данными структурами лучше использовать специальные функции, которые позволяют устанавливать новые значения в поля структур **BgcVersorFP32** и **BgcVersorFP64**.
|
||||||
|
|
||||||
## Операции с версорами
|
## Операции с версорами
|
||||||
|
|
||||||
- Сброс состояния (reset)
|
- [Сброс состояния (reset)](./versor-reset-rus.md)
|
||||||
- Указание значений компонент (set values)
|
- [Указание значений компонент (set values)](./versor-set-values-rus.md)
|
||||||
- Копирование значений компонент (copy)
|
- Копирование значений компонент (copy)
|
||||||
- Обмен значений компонент (swap)
|
- Обмен значений компонент (swap)
|
||||||
- Построение на основе поворота (set turn)
|
- Построение на основе поворота (set turn)
|
||||||
|
|
45
docs/versor-set-values-eng.md
Normal file
45
docs/versor-set-values-eng.md
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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)
|
47
docs/versor-set-values-rus.md
Normal file
47
docs/versor-set-values-rus.md
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <basic-geometry.h>
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
|
@ -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 <stdio.h>
|
|
||||||
#include <basic-geometry.h>
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
|
@ -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 <stdio.h>
|
|
||||||
#include <basic-geometry.h>
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue