Геометрические примитивы
Линейное преобразование
Ортогональное линейное преобразование (класс gp_Trsf)
В OpenCascade ортогональное линейное преобразование описывается объектом класса gp_Trsf. Преобразование определяется следующими параметрами
Standard_Real scale; // Масштабный множитель
gp_TrsfForm shape; // Тип преобразования (перечисляемый, см. ниже)
gp_Mat matrix; // Матрица оператора размера 3 х 3
gp_XYZ loc; // Вектор переноса (3 компоненты)
Тип преобразования — перечисляемый тип, имеющий значения:
enum gp_TrsfForm {
gp_Identity, // Тождественное
gp_Rotation, // Поворот
gp_Translation, // Перенос
gp_PntMirror, // Отражение относительно точки
gp_Ax1Mirror, // Отражение относительно оси
gp_Ax2Mirror, // Отражение относительно плоскости
gp_Scale, // Масштабирование
gp_CompoundTrsf, // Комбинация преобразований
gp_Other // Другое
};
Обращаем внимание на то, что преобразование хранится не как матрица $4 \times 4$, а отдельно хранятся матрица $3 \times 3$ и вектор переноса. Масштабный множитель вычисляется таким образом, чтобы определитель матрицы равнялся единице, т.е. матрица описывала поворот.
Начнем с нескольких простых примеров. Преобразование переноса, т.е. перемещение точек пространства, описывается вектором сдвига $\mathbf{t}=(t_x, t_y, t_z)$: точка $A$ с радиус-вектором $\mathbf{r}_A=(x_A, y_A, z_A)$ переходит в точку $B$ с радиус-вектором $\mathbf{r}_B=\mathbf{r}_A+\mathbf{t}$:
gp_Trsf trans; // Создаем преобразование
gp_Vec shift(1., 2, 3.); // Вектор сдвига
trans.SetTranslation(shift);// Преобразование сдвига
gp_XYZ point(3., 2., 1.); // Некоторая точка
fprintf(fp,"before\t %f %f %f\n",point.X(),point.Y(),point.Z());
trans.Transforms(point); // Преобразуем ее
fprintf(fp,"after\t %f %f %f\n",point.X(),point.Y(),point.Z());
Результат:
before 3.000000 2.000000 1.000000
after 4.000000 4.000000 4.000000
Преобразование поворота характеризуется тем, что точки пространства перемещаются как твердое тело: расстояния между точками не изменяются, а также не изменяются углы между отрезками, соединяющими точки. Впрочем, второе вытекает из первого.
gp_Trsf transY;
// Поворот вокруг оси Y (0.,1.,0.) с неподвижной точкой (1.,0.,0.)
transY.SetRotation(gp_Ax1(gp_Pnt(1.,0.,0.),gp_Dir(0.,1.,0.)),M_PI);
fprintf(fp," Matrix:\n");
for( int row=1; row<4; row++ ) {
for( int col=1; col<5; col++ ) {
fprintf(fp," %f ",transY.Value(row,col));
}
fprintf(fp,"\n");
}
gp_XYZ point(2., 0., 0.); // Точка
fprintf(fp,"before\t %f %f %f\n",point.X(),point.Y(),point.Z());
transY.Transforms(point);
fprintf(fp,"after\t %f %f %f\n",point.X(),point.Y(),point.Z());
Результат:
Matrix:
-1.000000 0.000000 0.000000 2.000000
0.000000 1.000000 0.000000 0.000000
-0.000000 0.000000 -1.000000 0.000000
before 2.000000 0.000000 0.000000
after 0.000000 0.000000 -0.000000
Результат двух последовательных поворотов зависит от порядка их выполнения.
gp_Trsf transY, transZ;
// Повороты вокруг осей Y и Z на 90 градусов
transY.SetRotation(gp_Ax1(gp_Pnt(0.,0.,0.),gp_Dir(0.,1.,0.)),M_PI/2.);
transZ.SetRotation(gp_Ax1(gp_Pnt(0.,0.,0.),gp_Dir(0.,0.,1.)),M_PI/2.);
gp_XYZ point(0., 1., 0.);
fprintf(fp,"before ZY\t %f %f %f\n",point.X(),point.Y(),point.Z());
transY.Transforms(point);
fprintf(fp,"after Y\t %f %f %f\n",point.X(),point.Y(),point.Z());
transZ.Transforms(point);
fprintf(fp,"after Z\t %f %f %f\n",point.X(),point.Y(),point.Z());
point.SetCoord(0., 1., 0.);
fprintf(fp,"before YZ\t %f %f %f\n",point.X(),point.Y(),point.Z());
transZ.Transforms(point);
fprintf(fp,"after Z\t %f %f %f\n",point.X(),point.Y(),point.Z());
transY.Transforms(point);
fprintf(fp,"after Y\t %f %f %f\n",point.X(),point.Y(),point.Z());
Результат:
before ZY 0.000000 1.000000 0.000000
after Y 0.000000 1.000000 0.000000
after Z -1.000000 0.000000 0.000000
before YZ 0.000000 1.000000 0.000000
after Z -1.000000 0.000000 0.000000
after Y -0.000000 0.000000 1.000000
Два последовательных поворота представляют собой также поворот на некоторый угол вокруг некоторой оси.
// Повороты вокруг осей Y и Z на 90 градусов
gp_Trsf transY, transZ, transZY;
transY.SetRotation(gp_Ax1(gp_Pnt(0.,0.,0.),gp_Dir(0.,1.,0.)),M_PI/2.);
transZ.SetRotation(gp_Ax1(gp_Pnt(0.,0.,0.),gp_Dir(0.,0.,1.)),M_PI/2.);
transZY = transZ.Multiplied(transY);
gp_XYZ theAxis;
Standard_Real theAngle;
bool isTrue = transZY.GetRotation(theAxis, theAngle);
gp_XYZ point = transZY.TranslationPart();
fprintf(fp,"Axis\t %f %f %f\n",theAxis.X(),theAxis.Y(),theAxis.Z());
fprintf(fp,"Angle\t %f\n",theAngle);
fprintf(fp,"Point\t %f %f %f\n",point.X(),point.Y(),point.Z());
Результат:
Axis -0.577350 0.577350 0.577350
Angle 2.094395
Point 0.000000 0.000000 0.000000
Перейдем к подробному описанию процедур класса. Конструктор создает тождественное преобразование, при котором матрица вращения — единичная, вектор переноса — нулевой, а масштабный множитель — единица:
// Создает тождественное преобразование
gp_Trsf()
Для задания параметров преобразования предназначены процедуры:
// Задание коэффициентов преобразования, переводящего
// точку x,y,z в точку x',y',z'по закону:
// x' = a11 x + a12 y + a13 z + a14 <br>
// y' = a21 x + a22 y + a23 z + a24 <br>
// z' = a31 x + a32 y + a43 z + a34 <br>
// Tolang и TolDist используются для проверке нулевых значений
// угла расстояния при определении типа преобразования
void SetValues(
const Standard_Real a11, const Standard_Real a12,
const Standard_Real a13, const Standard_Real a14,
const Standard_Real a21, const Standard_Real a22,
const Standard_Real a23, const Standard_Real a24,
const Standard_Real a31, const Standard_Real a32,
const Standard_Real a33, const Standard_Real a34,
const Standard_Real Tolang, const Standard_Real TolDist
)
// Замена вектора переноса преобразования на вектор V
void SetTranslationPart(const gp_Vec& V)
// Замена масштабного множителя преобразования на число S
void SetScaleFactor(const Standard_Real S)
Следующие процедуры устанавливают параметры, отвечающие преобразованиям конкретного типа:
// Задание коэффициентов, отвечающих преобразованию
// переноса на вектор V
void SetTranslation(const gp_Vec& V)
// Задание коэффициентов, отвечающих преобразованию
// переноса на вектор, проведенный из точки P1 в точку P2
void SetTranslation(const gp_Pnt& P1,const gp_Pnt& P2)
// Задание коэффициентов, отвечающих преобразованию
// отражения относительно точки P.
void SetMirror(const gp_Pnt& P)
// Задание коэффициентов, отвечающих преобразованию
// отражения относительно оси A1.
void SetMirror(const gp_Ax1& A1)
// Задание коэффициентов, отвечающих преобразованию
// отражения относительно плоскости, задаваемой системой координат A2.
void SetMirror(const gp_Ax2& A2)
// Задание коэффициентов, отвечающих преобразованию
// поворота вокруг оси A1 на угол Ang (радианы). Поворот выполняется
// с неподвижной точкой "начала" оси вокруг "направления" оси
void SetRotation(const gp_Ax1& A1,const Standard_Real Ang)
// Задание коэффициентов, отвечающих преобразованию
// масштабирования с множителем S относительно точки P
void SetScale(const gp_Pnt& P,const Standard_Real S)
// Задание коэффициентов, отвечающих преобразованию,
// переводящему систему координат (начало и тройку векторов)FromSystem1
// в систему координат ToSystem2
void SetDisplacement(const gp_Ax3& FromSystem1,const gp_Ax3& ToSystem2)
// Задание коэффициентов, отвечающих преобразованию,
// переводящему координаты вектора, заданного в системе координат FromSystem1,
// в координаты этого вектора в системе координат ToSystem2.
// Например:
// Real x1, y1, z1; // координаты точки в системе координат FromSystem1
// Real x2, y2, z2; // координаты точки в системе координат ToSystem2
// gp_Pnt P1 (x1, y1, z1);
// Trsf T;
// T.SetTransformation (FromSystem1, ToSystem2);
// gp_Pnt P2 = P1.Transformed (T);
// P2.Coord (x2, y2, z2);
void SetTransformation(const gp_Ax3& FromSystem1,const gp_Ax3& ToSystem2)
// Задание коэффициентов, отвечающих преобразованию,
// переводящему координаты вектора, заданного в системе координат по умолчанию
// {P(0.,0.,0.), VX (1.,0.,0.), VY (0.,1.,0.), VZ (0., 0. ,1.) }
// в координаты этого вектора в системе координат ToSystem.
void SetTransformation(const gp_Ax3& ToSystem)
Следующие процедуры позволяют опросить параметры преобразования:
// Опрос масштабного множителя преобразования
Standard_Real ScaleFactor()
// Опрос вектора переноса преобразования
gp_XYZ& TranslationPart()
// Опрос матрицы преобразования
// Это матрица 3*3 с учетом масштабного множителя
gp_Mat VectorialPart()
// Опрос матрицы преобразования без учета масштабного множителя.
// Коэффициенты матрицы должны быть умножены на масштабный множитель,
// чтобы получились элементы истинной матрицы.
gp_Mat& HVectorialPart()
// Опрос коэффицента преобразованияс индексами (Row, Col).
// Должны выполняться условия 1 <= Row <= 3, 1<= Col <= 4
Standard_Real Value( const Standard_Integer Row,
const Standard_Integer Col)
// Опрос оси theAxis и угла поворота theAngle преобразования
Standard_Boolean GetRotation(gp_XYZ& theAxis,Standard_Real& theAngle)
// Процедура возвращает значение "истина", если
// определитель матрицы 3х3 преобразования отрицателен
Standard_Boolean IsNegative()
// Опрос типа преобразования (см. выше)
gp_TrsfForm Form()
Процедуры выполнения комбинации преобразований:
// Замена преобразования на обратное
void Invert()
// Получение обратного преобразования
gp_Trsf Inverted() const;
// Умножение данного преобразования справа на T
void Multiply(const gp_Trsf& T)
// Оператор умножения справа
void operator *=(const gp_Trsf& T)
// Вычисление преобразования <me> * T
gp_Trsf Multiplied(const gp_Trsf& T)
// Оператор вычисление преобразования <me> * T
gp_Trsf operator *(const gp_Trsf& T)
// Умножение преобразования T на данное слева,
// т.е. <me> = T * <me>
void PreMultiply(const gp_Trsf& T)
// Замена преобразования на его N-ую степень
// Если N = 0 <me> = Identity -- тождественное преобразование
// Если N < 0 -- степень обратного преобразования
void Power(const Standard_Integer N)
// Вычисление N-ой степени преобразования
gp_Trsf Powered(const Standard_Integer N)
// Применение преобразования к компонентам вектора
void Transforms(Standard_Real& X,Standard_Real& Y,Standard_Real& Z)
// Применение преобразования к тройке чисел
void Transforms(gp_XYZ& Coord)