Автор посвящает эту статью своему брату - Карпову Вячеславу Яковлевичу - военному инженеру.
Пример. Зубчатое колесо (шестерня)
Параметры шестерни
При описании зубчатых колес вводятся понятия окружности вершин, делительной, основной и окружности впадин. Окружность вершин это внешняя оружность, окружность вершин зубьев. Делительная (начальная) окружность (pitch circle) — это воображаемая окружность, по которой колеса катятся без скольжения.
Толщина зуба, измеренная по дуге делительной окружности, называется делительной толщиной зуба (tooth thickness на рисунке), а расстояние между двумя зубьями, называется делительной шириной впадины. Длина дуги делительной окружности, вмещающая одну толщину зуба и одну ширину впадины, называется делительным шагом зацепления $h_p$ (circular pitch на рисунке). Если обозначить через $n$ — число зубьев колеса, то длина делительной окружности равна $l_p=nh_p$, а диаметр $d_p = nh_p/\pi$. Модулем $m$ зубчатого колеса называют отношение $m=h_p/\pi$ (измеряется в миллиметрах).
Модули зубчатых колес стандартизованы и служат основным параметром при их описании. В частности, диаметр делительной окружности равен произведению модуля на число зубьев:
(1)Делительные толщина зуба и ширина впадины равны и равны половине шага, так что длины их дуг составляют $h_p/2 = m\pi / 2$.
Высота головки зуба (расстояние между делительной окружностью и окружностью вершин, addendum на рисунке) принимается равной модулю $m$, а высота ножки зуба (расстояние между делительной окружностью и окружностью впадин, dedendum на рисунке), принимается равной $1.25m$, так что высота зуба равна $h_t=2.25m$. При этом диаметр окружности вершин равен $m(n+2)$, диаметр окружности впаден $m(n-2.5)$, а межосевое расстояние для пары зубчатых колес с числом зубьев $n_1$ и $n_2$ равно $0.5m(n_1+n_2)$.
Профиль зуба строится из требования того, чтобы при качении зуба по зубу плечо момента силы оставалось постоянным. Из этого следует, что нормаль к кривой профиля должна иметь постоянное расстояние до центра колеса, т.е. скользить (или катиться) по некоторой окружности, которую называют основной (base). На рисунке ниже точка касания зубьев обозначена буквой $O$. Перпендикуляр к плоскости касания зубьев (line of action) касается базовой окружности (base circle). Это означает, что кривая профиля зуба образуется точкой прямой, катящейся по базовой окружности, причем положение точки таково, что в каждый момент кривая перпендикулярна этой прямой. Кривая, обладающая таким свойством называется эвольвентой. Эвольвенту окружности можно получить, сматывая натянутую нить с цилиндрической поверхности (катушки). Конец такой нити будет описывать эвольвенту. Уравнение эвольвенты (при соответствующем выборе параметров)
(2)Возьмем некоторую точку на делительной окружности (на рисунке точка $O$) и проведем в ней касательнные к делительной и базовой окружности. Угол между ними называется углом профиля (на рисунке — pressure angle), обозначается через $\alpha$ и имеет стандартное значение $\alpha=20^\circ$. Поэтому диаметры делительной и базовой окружностей связаны соотношением $d_b = d_p \cos 20^\circ = 0.94 d_p$.
Построение шестерни в среде OpenCascade
Мы использовали в качестве образца материал Tutorial: How to model involute gears in SolidWorks and show design intent. Steen Winther
в котором описывается построение шестерни в \texttt{SolidWorks}.
Построим шестерню с диаметром делительной окружности 76 мм (естественно, можно было бы выбрать и другое
значение) и модулем $m=2$ мм, так что число зубьев будет равно $n=76/2=38$.
Шаг 1.
На плоскости $(x,y,z=0)$ построим делительную окружность диаметра 78 мм.
// Делительная окружность (pitch cicle)
double d_p = 76.;
double r_p = d_p / 2.;
Handle(Geom_Circle) pitchCircle = new Geom_Circle(gp::XOY(),r_p );
Шаг 2.
Проведем вертикальный радиус и горизонтальную касательную к делительной окружности. Точка их пересечения лежит на эвольвенте профиля зуба. Построим через эту точку прямую под угом 20 градусов к касательной. Это прямая (line of action на рисунке выше) — касательная к базовой окружности . Диаметр базовой окружности $d_b = d_p \cos 20^\circ = 0.94 d_p$ . Построим ее. Результат представлен на рисунке. Новые элементы выделены красным.
//
// Радиус и касательная к верхней точке
gp_Lin radLin(gp::Origin(),gp_Dir(0.,1.,0.));
gp_Lin tanLin(gp_Pnt(0.,r_p,0.),gp_Dir(1.,0.,0.));
//
// Базовая окружность
double angle = 20./180.*M_PI;
double d_b = d_p*cos(angle);
double r_b = d_b / 2.;
Handle(Geom_Circle) baseCircle = new Geom_Circle(gp::XOY(),r_b);
//
// Прямая под углом 20 град
gp_Trsf trsf;
gp_Ax1 ax1(gp_Pnt(0.,r_p,0.), gp_Dir(0.,0.,1.));
trsf.SetRotation(ax1,angle);
gp_Lin actLin = tanLin.Transformed( trsf );
Шаг 3.
Профиль зуба образуется точкой $A$ при качении прямой $AB$ по базовой окружности. В нашем случае уравнение эвольвенты (проходящей через точку $A$) записывается как
(3)где $\varphi+\varphi_0$ — угол положения точки качения (на рисунке это точка $B$ ), $\varphi_0$ — угол начального положения этой точки, а $\varphi$ — текущий угол поворота прямой. По смыслу эвольвенты расстояние $AB$ равно дуге окружности с углом $\varphi$, так что $\varphi+\varphi_0 = 90^\circ + 20^\circ$ и $\varphi = \tan(20^\circ)$. Отсюда $\varphi_0 = 1.5559 = 89.1461^\circ$.
Нарисуем несколько точек эвольвенты, чтобы посмотреть на ее поведение. Вот соответствующий
участок программы:
//
// Эвольвента
double angle = 20./180.*M_PI;
double phi = tan(angle);
double phi_0 = M_PI/2.+angle - phi;
// Поставим точки
double h_phi = M_PI/100.;
Handle(AIS_Point) aisPoint;
Handle(Geom_CartesianPoint) geomPoint;
Handle(Prs3d_PointAspect) pointAspect = aisDrawer->PointAspect();
pointAspect->SetColor(Quantity_NOC_RED);
pointAspect->SetTypeOfMarker (Aspect_TOM_POINT);
pointAspect->SetScale(3.);
double x, y, z=0.;
for( int i=0; i<50; i++ ) {
phi = i*h_phi;
double cs = cos(phi + phi_0);
double sn = sin(phi + phi_0);
x = r_b*(cs+phi*sn);
y = r_b*(sn-phi*cs);
geomPoint = new Geom_CartesianPoint(gp_Pnt(x,y,0.));
aisPoint = new AIS_Point(geomPoint);
myAISContext->Display(aisPoint,FALSE);
}
myAISContext->DisplayAll();
Шаг 4.
Зуб образует участок эвольвенты, заключенный между бвзовой окружностью и окружностью вершин. Радиус окружности вершин больше базовой на величину модуля (см. выше), так что в нашем случае диаметр окружности вершин $d_a=80$ мм. Проведем окружность вершин и вычислим несколько равноотстоящих (приблизительно) точек на эвольвенте (см. рисунок)
Чтобы построить профиль зуба, проведем интерполяционную кривую через эти точки
//
// Интерполяция
// Определяем массив из n_point точек
Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1,n_point);
for( i=0; i<n_point; i++ )
points->SetValue(i+1,pnt[i]);
// Создаем объект класса
GeomAPI_Interpolate interpolate(points,Standard_False,Precision::Approximation());
// Выполняем интерполяцию
interpolate.Perform();
// Возвращается построенная BSpline-кривая
Handle(Geom_BSplineCurve) toothCurve = interpolate.Curve();
Шаг 5.
Ножка зуба оканчивается на окружности впадин (см. выше), диаметр которой меньше диаметра делительной окружности на 2.5 модуля. Построим ее. Выполним сопряжение между участком эвольвенты и окружностью впадин с помощью кривой Безье.
// Ставим три точки: 0 -- конец дуги впадины, 1 -- угловая, 2 -- конец эвольвенты
// Точка 2 лежит на базовой окружности
pnt[2] = toothCurve->Value(toothCurve->FirstParameter());
// Переносим ее по радиусу на окружность впадин
phi = acos( pnt[2].X()/r_b );
pnt[1].SetCoord(r_d*cos(phi),r_d*sin(phi),0.);
// и сдвигаемся на такое же расстояние по окружности впаден
phi -= (r_b-r_d) / r_d;
pnt[0].SetCoord(r_d*cos(phi),r_d*sin(phi),0.);
//
// Строим сопряжение между дугой окружности впаден и эвольвентой (кривая Безье)
// Задаем опорные точки
TColgp_Array1OfPnt array1OfPnt(1,3);
array1OfPnt.SetValue(1, pnt[0]);
array1OfPnt.SetValue(2, pnt[1]);
array1OfPnt.SetValue(3, pnt[2]);
// Строим кривую
Handle(Geom_BezierCurve) filletCurve = new Geom_BezierCurve(array1OfPnt);
Шаг 6.
Теперь все кривые построены. Контур шестерни (точнее, ее части, связанной с одним зубом) идет вначале по окрудности впаден, потом по кривой Безье переходит на эвольвенту зуба, затем по окружности вершин идет до эвольвенты слева, причем левую сторону мы получим отражением правой. Итак, строим контур (wire).
//
// ----- Строим контур сектора зуба
BRepBuilderAPI_MakeWire mkWireTooth;
TopoDS_Edge wireEdge;
//
// Ребро: по окружности впаден справа
// Ставим две точки: 0 -- середина дуги впадины, 1 -- конец кривой сопряжения
double phi0 = M_PI*(0.5 - module/r_p/4.);
double phi1 = phi;
wireEdge = BRepBuilderAPI_MakeEdge(dedenCircle,phi0,phi1);
mkWireTooth.Add(wireEdge);
//
// Ребро: по кривой сопряжения
wireEdge = BRepBuilderAPI_MakeEdge(filletCurve);
mkWireTooth.Add(wireEdge);
//
// Ребро: по эвольвенте
wireEdge = BRepBuilderAPI_MakeEdge(toothCurve);
mkWireTooth.Add(wireEdge);
//
// Отражаем правую эвольвенту зуба относительно его средней линии
phi = M_PI/2./n_t;
gp_Ax2 ax2(gp_Pnt(0.,0.,0.), gp_Dir(d_p*cos(phi),d_p*sin(phi),0.));
Handle(Geom_Curve) toothMirr = Handle (Geom_Curve)::DownCast(toothCurve->Mirrored (ax2));
// Дуга верхушки зуба
pnt[0] = toothCurve->Value(toothCurve->LastParameter());
pnt[1] = toothMirr->Value(toothMirr->LastParameter());
phi0 = acos( pnt[0].X()/r_a);
phi1 = acos( pnt[1].X()/r_a);
wireEdge = BRepBuilderAPI_MakeEdge(addenCircle,phi0,phi1);
mkWireTooth.Add(wireEdge);
//
// Ребро: по левой эвольвенте
wireEdge = BRepBuilderAPI_MakeEdge(toothMirr);
mkWireTooth.Add(wireEdge);
//
// Отражаем правую кривую сопряжения
Handle(Geom_Curve) filletMirr = Handle (Geom_Curve)::DownCast(filletCurve->Mirrored (ax2));
wireEdge = BRepBuilderAPI_MakeEdge(filletMirr);
mkWireTooth.Add(wireEdge);
//
// Ребро: по окружности впаден слева
// Ставим две точки: 0 -- середина дуги впадины, 1 -- конец кривой сопряжения
phi0 = M_PI*(0.5 + 3.*module/r_p/4.);
pnt[0] = filletMirr->Value(filletMirr->FirstParameter());
phi1 = acos( pnt[0].X()/r_d);
wireEdge = BRepBuilderAPI_MakeEdge(dedenCircle,phi1,phi0);
mkWireTooth.Add(wireEdge);
Шаг 7.
Чтобы построить весь контур шестерни, нужно добавлять контур зуба, поворачивая его на угол шага.
TopoDS_Wire toothWire = mkWireTooth.Wire();
BRepBuilderAPI_MakeWire mkWireGear(toothWire);
// Поворачиваем и присоединяем
phi = 2.*M_PI/n_t;
trsf.SetRotation(gp_Ax1(gp::Origin(), gp_Dir(0.,0.,1.)),phi);
TopLoc_Location location(trsf);
for( int i=1; i<n_t; i++ ) {
toothWire.Move(location);
mkWireGear.Add(toothWire);
}
Шаг 8.
Строим саму шестерню. Сначала по контуру строим грань, а затем, выдаливая грань, строим тело. В центре делаем отверстие диаметром 10 мм.
//
// Строим грань по контуру
BRepBuilderAPI_MakeFace mkFace(mkWireGear.Wire());
//
// Выдавливаем грань
BRepPrimAPI_MakePrism mkPrism(mkFace.Shape(), gp_Vec(0.0, 0.0, 10.));
TopoDS_Shape gear = mkPrism.Shape();
//
// отверстие 10 мм
gp_Ax1 axHole(gp::Origin(), gp_Dir(0.,0.,1.));
Standard_Real d_hole = 10.;
BRepFeat_MakeCylindricalHole mkHole;
mkHole.Init(gear, axHole);
mkHole.Perform(d_hole/2.0);
gear = mkHole.Shape();
Шаг 9.
Наконец, сделаем кольцевое углубление в 1 мм, радиуса 10 мм и шириной 20 мм.
// Углубление
TopoDS_Shape ring;
{
// Точки профиля
TColgp_Array1OfPnt array1OfPnt(1,5);
double r = 10.;
double w = 20.;
array1OfPnt(1) = gp_Pnt( r, 0.0, 0.0 );
array1OfPnt(2) = gp_Pnt( r+w, 0.0, 0.0);
array1OfPnt(3) = gp_Pnt( r+w, 0.0, -1.0);
array1OfPnt(4) = gp_Pnt( r, 0.0, -1.0);
array1OfPnt(5) = gp_Pnt(r, 0.0, 0.0 );
// Строим по ним контур
BRepBuilderAPI_MakeWire mkWire;
for ( int i = 1; i < 5; i++) {
BRepBuilderAPI_MakeEdge mkEdge(array1OfPnt(i), array1OfPnt(i+1));
mkWire.Add(mkEdge);
}
// Превращаем контур в грань
TopoDS_Face face = BRepBuilderAPI_MakeFace(mkWire.Wire());
// Revolve the face around an axis
gp_Ax1 ax1(gp_Pnt(0,0,0),gp_Dir(0,0,1));
ring = BRepPrimAPI_MakeRevol(face, ax1).Shape();
}
//
// Делаем улубление сверху
gp_Trsf move = gp_Trsf();
move.SetTranslation(gp_Pnt(0,0,0), gp_Pnt(0,0, 10.0));
TopoDS_Shape moved_ring =
BRepBuilderAPI_Transform(ring, move, false);
gear = BRepAlgoAPI_Cut(gear, moved_ring).Shape();
// и снизу
move.SetTranslation(gp_Pnt(0,0,0), gp_Pnt(0,0, 1.0));
moved_ring = BRepBuilderAPI_Transform(ring, move, false);
gear = BRepAlgoAPI_Cut(gear, moved_ring).Shape();
Само колечко показано на рисунке слева, а результат его вычитания из построенной выше фигуры — справа. И это все, что мы хотели сделать.