Геометрические примитивы
Кривая
Мы дадим вначале краткий математический обзор свойств кривой, а затем поговорим о классах OpenCascade, связанных с этим понятием.
Математическое описание
Рассмотрим некоторые свойства векторной функции одного скалярного аргумента. Геометрическим образом такой функции служит кривая (линия) в пространстве. Пусть каждому значению скалярной величины $t$ из области допустимых значений $T$ поставлен в соответствие вектор ${\bf a}(t)$. В этом случае говорят, что задана векторная функция скалярного аргумента. В дальнейшем мы будем считать, что область допустимых значений $T$ представляет собой отрезок вещественной оси.
Зафиксируем в пространстве некоторую точку отсчета $O$ и будем откладывать все векторы ${\bf a}(t)$ от этой точки. Если функция непрерывная, то при изменении параметра $t$ конец вектора будет описывать некоторую кривую в пространстве, называемую годографом функции ${\bf a}(t)$.
Пусть в пространстве задана некоторая непрерывная кривая. При фиксированной точке отсчета $O$ каждую точку кривой можно характеризовать радиус-вектором ${\bf r}$, проведенным в эту точку из точки отсчета. Если кривая является годографом некоторой векторной функции ${\bf r}(t)$, то говорят, что задано параметрическое уравнение кривой. Запишем координатное представление вектор-функции: ${\bf r}(t) = x(t){\bf i}+y(t){\bf j}+z(t){\bf k}$, так что параметрическое задание кривой эквивалентно заданию трех функций $x(t)$, $y(t)$, $z(t)$.
Производной функции ${\bf a}(t)$ в точке $t_0$ называют предел
(1)Если векторная функция имеет постоянную длину $|{\bf a}(t)|=\text{const}$ , то векторы ${\bf a}(t)$ и ${\bf a}'(t)$ ортогональны.
Пусть ${\bf e}(t)$ — единичный вектор в направлении ${\bf a}(t)$, так что ${\bf a}(t)=|{\bf a}(t)|{\bf e}(t)$. Дифференцируя это равенство, получаем
(2)Поскольку ${\bf e}(t)$ единичный вектор, то ${\bf e}'\perp {\bf e}$, так что последнее равенство дает разложение вектора производной на вектор параллельный ${\bf a}(t)$ и перпендикулярный ему.
Длина дуги кривой определяется как предел длины вписанной в нее ломаной. Зафиксируем на линии некоторую точку $M_0$, отвечающую параметру $t_0$. Пусть точка $M$ отвечает значению параметра $t$. Длина дуги $M_0M$ равна
(3)При этом при $t>t_0$ длина дуги положительна, а при $t<t_0$ — отрицательна. Таким образом, зафиксировав точку $t_0$, мы можем поставить в соответствие каждой точке кривой параметр $s(t)$ — длину дуги, отсчитываемую от точки $M_0$. Дифференцируя последнее соотношение, получаем
(4)Если в качестве параметра в уравнении линии выбрана длина дуги, т.е. уравнение линии представлено в виде ${\bf r}={\bf r}(s)$, то говорят, что использована естественная параметризация. Удобство ее заключается в том, что
(5)С пространственной кривой связаны такие понятия, как касательная, нормаль и бинормаль — тройка единичных векторов, образующих сопровождающий трехгранник кривой.
Пусть задана пространственная кривая и пусть $s$ — длина дуги этой кривой до точки $M$, отсчитываемая от некоторой фиксированной точки $M_0$ на линии. При этом уравнение кривой может быть записано как ${\bf r}={\bf r}(s)$. Вычислим производную $d{\bf r}/ds$ в точке $M$. Этот вектор направлен по касательной к кривой и имеет единичную длину. Вектор
(6)называется вектором касательной к линии.
Плоскость, проходящая через заданную точку $M$ на кривой и перпендикулярная вектору касательной к линии в этой точке, называется нормальной плоскостью.
Построим плоскость, наиболее "пригнанную" к кривой. Рассмотрим произвольную плоскость, проходящую через заданную точку $M$. Положение плоскости будем характеризовать единичным вектором ${\bf N}$ нормали к ней. Дадим параметру $s$ приращение $\Delta s$, в результате чего мы сдвинемся по кривой из точки $M$ в точку $M'$. Вычислим расстояние $l=M'P$ от этой точки до плоскости. Поскольку расстояние до плоскости измеряется по перпендикуляру
(7)где точкой обозначена производная по параметру $s$. Говорят, что кривая и плоскость имеют в точке касание $n$-го порядка, если $l=O(\Delta s^{n+1})$. В частности, если $\left(\dot{{\bf r}}(s),{\bf N}\right)\ne 0$, кривая "протыкает" плоскость — имеем касание нулевого порядка. Если $\left(\dot{{\bf r}}(s),{\bf N}\right)= 0$, то вектор касательной к линии лежит в плоскости, но плоскость может произвольно вращаться вокруг него. При этом осуществляется касание первого порядка. Наконец, среди таких плоскостей есть одна, для которой $\left({\bf r}''(s),{\bf N}\right)= 0$. Эта плоскость имеет касание второго порядка и называется соприкасающейся плоскостью. Нормаль к соприкасающейся плоскости перпендикулярна векторам $\dot{{\bf r}}$ и $\ddot{{\bf r}}$, так что она направлена по их векторному произведению.
Проведем через точку $M$ на кривой нормальную плоскость, т.е. плоскость, перпендикулярную касательной. Все единичные векторы, лежащие в этой плоскости, называются нормалями к кривой. Нормаль, лежащая в соприкасающейся плоскости, называется главной нормалью, а нормаль, перпендикулярная соприкасающейся плоскости — бинормалью. Если вектор касательной обозначить через ${\bf t}$, вектор главной нормали через ${\bf n}$, а вектор бинормали через ${\bf b}$, то тройка векторов $({\bf t}, {\bf n}, {\bf b})$ образует сопровождающий трехгранник линии в точке $M$. Найдем выражения для его векторов.
Вектор касательной равен ${\bf t}=\dot{{\bf r}}(s)$. Рассмотрим вектор $\dot{{\bf t}}(s)=\ddot{{\bf r}}(s)$. Поскольку ${\bf t}$ единичный вектор, его производная перпендикулярна ему, т.е. лежит в нормальной плоскости. Кроме того, как мы видели выше, она лежит в соприкасающейся плоскости, т.е. коллинеарна вектору главной нормали. Скорость поворота касательной как функции длины дуги называется кривизной линии, а обратная ей величина — радиусом кривизны:
(8)Отсюда вытекает определение вектора главной нормали: \nopagebreak
(9)Вектор бинормали перпендикулярен ${\bf t}$ и ${\bf n}$ и по определению равен ${\bf b} = [{\bf t},{\bf n}]$. Производная бинормали направлена по вектору нормали:
(10)Величину $1/T$, характеризующую скорость поворота бинормали при движении вдоль кривой, называют кручением кривой, а $T$ — радиусом кручения.
Скорости изменения касательной, нормали и бинормали при движении вдоль кривой даются выражениями:
(11)Эти три обыкновенных дифференциальных уравнения называются уравнениями Френе. Они показывают, что пространственная кривая определяется зависимостями кривизны и кручения от расстояния вдоль кривой.
Описание кривой в OpenCascade
В OpenCascade описание кривой основывается на абстрактном классе Geom_Curve. Классы описания прямой, конических сечений, кривой Безье, B-сплайна и другие наследуют свойства и методы этого класса. К ним относятся:
- параметрическое задание кривой;
- вычисление значения точки на кривой по ее параметру, а также вычисление прозводных;
- общие характеристкики кривой, такие как гладкость, замкнутость, периодичность, нтервал измененя параметра;
- изменение параметризации кривой.
Метод Value(const Standard_Real U) возвращает значение точки на кривой для заданного значения параметра. Например, построим прямую, проходящую через точку gp_Pnt(0.,0.,1.) в направлении вектора gp_Dir(1.,1.,0.) и вычислим точки на ней для значений параметра 0 и 1:
Geom_Line geomLine(gp_Pnt(0.,0.,1.), gp_Dir(1.,1.,0.));
gp_Pnt point;
point = geomLine.Value(0.); // ( 0.0000, 0.0000, 1.0000 )
point = geomLine.Value(1.); // ( 0.7071, 0.7071, 1.0000 )
Диапазон изменения параметра опрашивается процедурами FirstParameter() и LastParameter(). Прямая — бесконечная линия так что возвращаемые значения для прямой есть RealFirst() ($-\infty$) и RealLast() ($+\infty$). Но для окружности параметр изменяется от $0$ до $2\pi$:
double parMin = geomLine.FirstParameter(); // -2.0000000000000e+100
double parMax = geomLine.LastParameter(); // 2.0000000000000e+100
Geom_Circle circle(gp::XOY(), sqrt(2.)); // окружность в плоскости (X,Y)
parMin = circle.FirstParameter(); // 0.0000
parMax = circle.LastParameter(); // 6.2831
Методы D0, D1 … позволяют узнать значения точки и производных различного порядка для данного значения параметра. Например
gp_Pnt point;
gp_Vec deriv;
double par = 3.14159/4.;
circle.D0(par,point); // point = ( 1.0000, 1.0000, 0.0000 )
circle.D1(par,point,deriv); // deriv = (-1.0000, 1.0000, 0.0000 )
Для вычисления таких характеристик кривой как касательная, нормаль, кривизна нужно воспользоваться процедурами класса GeomLProp_CLProps. При создании объекта даного класса нужно указать кривую, для которой вычисляются характеристики, значение параметра, порядок производных, участвующих в вычислении характеристики и точность вычисления (чтобы избежать, например, деления на ноль). Выполним вычисления для окружности:
Handle(Geom_Circle) circle = new Geom_Circle(gp::XOY(), 1.); // окружность в плоскости (X,Y)
double phi = 3.14159/4.; // значене параметра: 45 градусов
GeomLProp_CLProps curveProps(circle, phi, 2, 1.e-8);
gp_Dir tang, normal;
curveProps.Tangent(tang); // tang = (-0.7071, 0.7071, 0.0000 )
curveProps.Normal(normal); // normal = (-0.7071,-0.7071, 0.0000 )
Standard_Real curv = curveProps.Curvature(); // curv = 1.0000
gp_Pnt center;
curveProps.CentreOfCurvature(center); // center = ( 0.0000, 0.0000, 0.0000 )
Класс GCPnts_AbscissaPoint предоставляет алгоритмы для вычисления точки (значения параметра) на кривой по длине дуги от заданной точки, а также для вычисления длины дуги в зависимости от параметра. Иначе говоря, методы этого класса устанавливают соответствие между параметризацией кривой и ее естественной параметризацией: $t(s)$ и $s(t)$.
Первый пример: вычисление параметра по длине дуги (для окружности)
// Окружность радиуса 5 в плоскости (x,y)
Standard_Real radius = 5;
Handle(Geom_Circle) cicle = new Geom_Circle(gp::XOY(),radius);
// startParam - параметр начальной тоски на кривой
Standard_Real startParam = 0.;
gp_Pnt point;
cicle->D0(startParam,point); // point = ( 5.0000, 0.0000, 0.0000 )
// abscissa - длина дуги от начальной тоски до искомой
// Standard_Real abscissa = radius*3.14159;
Standard_Real abscissa = radius*PI;
// abscissa is the distance along the curve from startparam
GeomAdaptor_Curve adaptorCicle(cicle);
GCPnts_AbscissaPoint abscissaPoint(adaptorCicle, abscissa, startParam);
if( ! abscissaPoint.IsDone() ) {
// Обработка ошибки
}
Standard_Real endParam = abscissaPoint.Parameter();
cicle->D0(endParam,point); // point = ( -5.0000, 0.0000, 0.0000 )
Второй пример: вычисление длины дуги по параметру (для окружности)
startParam = 0.;
endParam = PI;
Standard_Real length = GCPnts_AbscissaPoint::Length(adaptorCicle, startParam, endParam);
// length = 15.7079
Для вычисления проекции точки на кривую общего вида предназначен класс GeomAPI_ProjectPointOnCurve.
Его конструкторы выглядят так:
// Нахождение проекции точки <P> на кривую <Curve>
GeomAPI_ProjectPointOnCurve( const gp_Pnt& P,const Handle(Geom_Curve)& Curve)
// Нахождение проекции точки <P> на участок кривой <Curve>,
// ограниченный параметрами Umin и Usup
GeomAPI_ProjectPointOnCurve( const gp_Pnt& P, const Handle(Geom_Curve)& Curve,
const Quantity_Parameter Umin, const Quantity_Parameter Usup)
Создав объект класса GeomAPI_ProjectPointOnCurve, можно опросить:
- число проекций
// Процедура возвращает число найденных проекций.
// Если проекции не найдены, возвращается 0
Standard_Integer NbPoints()
- точку проекции или параметр на кривой, соответствующий этой точке, а также расстояние до проекции
// Процедура возвращает точку проекции номер Index
// Значение Index должно лежать в диапазоне от 1 до NbPoints
gp_Pnt Point(const Standard_Integer Index)
// Процедура возвращает параметр на кривой, отвечающий точке проекции номер Index
Quantity_Parameter Parameter(const Standard_Integer Index)
// Процедура возвращает расстояние от проектируемой точки до точки проекции номер Index
Quantity_Length Distance(const Standard_Integer Index)
- ближайшую точку проекции, т.е. точку с минимальным расстоянием
// Процедура возвращает ближайшую точку проекции
gp_Pnt NearestPoint()
// Процедура возвращает параметр на кривой, отвечающий ближайшей точке проекции
Quantity_Parameter LowerDistanceParameter()
// Процедура возвращает минимальное расстояние от проектируемой точки до кривой
Quantity_Length LowerDistance()
Класс ElCLib provides functions for basic geometric computations on elementary curves such as conics and lines in 2D and 3D space.