スパイラルベベルギア
このチュートリアルは,OpenCascadeLinkを使った,スパイラルベベルギヤ(まがりばかさ歯車)の生成方法を示すためのものである.その形状と作成過程は,コンピュータを使用した設計(CAD)のチュートリアル[1]に基づく.
歯車の作成は,数ステップに分けて行う.まず,軸(シャフト)を作成する.次に歯車(ギア)を作成する.軸と歯車を繋げる.軸にボスを加え,最後に歯車に穴を開ける.
Needs["OpenCascadeLink`"]
Needs["NDSolve`FEM`"]軸
軸は,X-Z平面の横断面を指定して作成する.この横断面が,X軸の周りで回転させて作成する立体の基礎となる.
length = 163;
radius = 11;
s1 = Line[{{0, 0, 0}, {0, 0, 45}, {5, 0, 45}, {5, 0, 39}, {-112 + length, 0, 39}, {-112 + length, 0, 38}, {-80 + length - 2 radius, 0, 38}, {-80 + length - 2 radius, 0, 36}}];
s2 = OpenCascadeCircle[{{length - 80 - radius, 0, 36}, {0, -1, 0}}, radius, {π, 2π}];
s3 = Line[{{-80 + length, 0, 36}, {-32 + length, 0, 36}, {-32 + length, 0, 32.5}, {length, 0, 32.5}, {length, 0, 0}, {0, 0, 0}}];ここで線分の方向が重要となる.線分の方向が逆であると,回転の結果できる立体は,軸外の領域を指定することになる.線分の方向が逆向きになっている場合には,回転軸を正反対の方向にすればよい.こうすれば,線分を再度指定せずに済む.
crossSection = {s1, s2, s3};Show[
Graphics3D[crossSection /. OpenCascadeCircle -> Circle3D], OpenCascadeAxis3D[{0, 0, 0}, {200, 25, 50}], Boxed -> False]s = OpenCascadeShape /@ crossSectionshape = OpenCascadeShapeWire[s]
OpenCascadeShapeType[shape]OpenCascadeShapeUnionを使って線分を組み合せて単一のオブジェクトにすることも可能だが, そうするとOpenCascadeShapeUnionが複合物を返す.複合物だと,中に何があるのかが分かりにくい.
rotationAxis = {{0, 0, 0}, {200, 0, 0}};
Graphics3D[{crossSection /. OpenCascadeCircle -> Circle3D, {Red, Arrow[rotationAxis]}}]shaft = OpenCascadeShapeRotationalSweep[shape, rotationAxis]OpenCascadeShapeType[shaft]横断面を回転させて出来たものは,殻である.回転させた入力がワイヤであったからである.しかし,ここで必要なのは中空ではない立体である.
shaft = OpenCascadeShapeSolid[shaft]
OpenCascadeShapeType[shaft]横断面を作成するもう一つの方法として,Polygonを使うこともできる.これらは,面タイプの OpenCascade オブジェクトであり,回転させると OpenCascade の立体になる.
bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shaft(*,"ShapeSurfaceMeshOptions"->{"LinearDeflection"->0.001}*)]Show[
shaftGR = bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightGray]]]],
OpenCascadeAxis3D[{-10, 0, 0}, {200, 75, 75}]]意図した通りに境界メッシュが構築できたかどうかを確かめるために,完全な要素メッシュを生成する.
ToElementMesh[bmesh, "MeshOrder" -> 1]デフォルトよりも小さい"LinearDeflection"の値で境界要素メッシュを作成した場合には,警告メッセージは表示されない.
歯車
歯車の作成は,2ステップで行う.まず,歯車の歯の半分をYZ平面でモデル化する.半分の歯は,円の3つのセクションを組み合せることによって構築する.この半分の歯を軸で鏡映して完全な歯を作る.この1つの歯を回転させ,YZ平面で歯車の歯一式を作る.その後,YZ平面の歯車をYZ平面に平行な2つめの平面で平行移動,回転,スケールさせる.この過程をもう一度繰り返して,YZ平面に平行な3つ目の平面に3つ目の歯一式を作る.実際の歯車は,これらの平面を押し出す形で作成する.これでロフトが作成される.
歯車の歯
歯車の歯は,3つの円を交差させ,その境界部分を取ることで作成する.
r1 = 85;
r2 = 50;
r3 = 65;N[p1 = r1 {Cos[θ], Sin[θ]} /. θ -> (π - ArcCos[6 / r1])]
N[p2 = r2{Cos[θ], Sin[θ]} /. θ -> (π - ArcCos[15 / r2])]eqn = (x - x1) ^ 2 + (y - y1) ^ 2 == r3 ^ 2;
N[p3 = {x, y} /. Solve[{eqn /. Thread[Rule[{x1, y1}, p1]], eqn /. Thread[Rule[{x1, y1}, p2]], x > 0, y > 0}, {x, y}][[1]]]Graphics[{Circle[{0, 0}, r1], Circle[{0, 0}, r2], Circle[p3, r3], {Green, Dashed, Arrow[{{0, 0}, {0, 120}}]}, {Red, PointSize[0.02], Point[p1], Point[p2]},
{Gray, Dashed, Line[{{0, 0}, 120{Cos[θ], Sin[θ]} /. θ -> (π / 2 + 2 π / 16)}]}}]N[θ1 = (θ /. Solve[r3 {Cos[θ], Sin[θ]} + p3 == p1, θ] /. C[1] -> 0)[[1]]]
N[θ2 = (θ /. Solve[r3 {Cos[θ], Sin[θ]} + p3 == p2, θ] /. C[1] -> 0)[[1]]]Graphics[{
{LightGray, Circle[{0, 0}, r1], Circle[{0, 0}, r2], Circle[p3, r3]},
Circle[{0, 0}, r1, {π / 2, π - ArcCos[6 / r1]}],
Circle[{0, 0}, r2, {π - ArcCos[15 / r2], (π / 2 + 2 π / 16)}],
Circle[p3, r3, {θ1, 2π + θ2}],
{Red, PointSize[0.02], Point[p1], Point[p2]},
{Blue, PointSize[0.02], Point[p3]},
{Blue, Dashed, Line[{p3, p1}], Line[{p3, p2}]},
{Green, Dashed, Arrow[{{0, 0}, {0, 120}}]},
{Gray, Dashed, Line[{{0, 0}, 120{Cos[θ], Sin[θ]} /. θ -> (π / 2 + 2 π / 16)}]}}]halfTooth = {
Circle[{0, 0}, r1, {π / 2, π - ArcCos[6 / r1]}],
Circle[{0, 0}, r2, {π - ArcCos[15 / r2], (π / 2 + 2 π / 16)}],
Circle[p3, r3, {θ1, 2π + θ2}]};
rft = ReflectionTransform[{1, 0}];
tooth = {halfTooth, GeometricTransformation[halfTooth, rft]};
rot = RotationTransform[2π / 8];
gr2D = Graphics[NestList[GeometricTransformation[#, rot]&, tooth, 7]]次に,この方法を3Dに応用する.Wolfram言語には,3Dで使えるCircleプリミティブがないので,OpenCascadeLinkを使う.プリミティブを使うと,円が通過する座標を指定することができる.
N[p4 = r2{Cos[θ], Sin[θ]} /. θ -> (π / 2 + 2 π / 16)]c1 = OpenCascadeCircle[{{0, 0, 0}, {1, 0, 0}}, r1, {{0, 0, r1}, Join[{0}, p1]}];
c2 = OpenCascadeCircle[{Join[{0}, p3], {1, 0, 0}}, r3, {Join[{0}, p1], Join[{0}, p2]}];
c3 = OpenCascadeCircle[{{0, 0, 0}, {1, 0, 0}}, r2, {Join[{0}, p2], Join[{0}, p4]}];shapes = OpenCascadeShape /@ {c1, c2, c3};ocHalfTooth = OpenCascadeShapeWire[shapes]OpenCascadeShapeType[ocHalfTooth]rot1 = RotationTransform[Pi, {0, 0, 1}]ocTooth = OpenCascadeShapeWire[{ocHalfTooth, OpenCascadeShape[ocHalfTooth, rot1]}]rott = Table[RotationTransform[k * 2π / 8, {1, 0, 0}], {k, 0, 7}];ocGearProfile1 = OpenCascadeShapeWire[OpenCascadeShapeTransformation[ocTooth, #]& /@ rott]3Dで作成した歯車の輪郭を可視化するために, X軸方向に平坦な輪郭を拡張させる.この作業は可視化のために行うことであり,歯車の構築には必要ない.
temp = OpenCascadeShapeLinearSweep[ocGearProfile1, {{0, 0, 0}, {1, 0, 0}}];
Show[OpenCascadeShapeSurfaceMeshToBoundaryMesh[temp]["Wireframe"], shaftGR, OpenCascadeAxis3D[{-10, 0, 0}, {200, 75, 75}]]平面を作成する
歯車の輪郭を作った後は,その輪郭をスケール,回転,平行移動させて,互いに平行な歯車の輪郭をYZ平面に作成する.
ocGearProfile2 = OpenCascadeShapeTransformation[ocGearProfile1, ScalingTransform[0.75 * {1, 1, 1}, {0, 0, 0}]];
ocGearProfile2 = OpenCascadeShapeTransformation[ocGearProfile2, RotationTransform[-15 Degree, {1, 0, 0}]];
ocGearProfile2 = OpenCascadeShapeTransformation[ocGearProfile2, TranslationTransform[{-45, 0, 0}]];ocGearProfile3 = OpenCascadeShapeTransformation[ocGearProfile1, ScalingTransform[0.5 * {1, 1, 1}, {0, 0, 0}]];
ocGearProfile3 = OpenCascadeShapeTransformation[ocGearProfile3, RotationTransform[-30 Degree, {1, 0, 0}]];
ocGearProfile3 = OpenCascadeShapeTransformation[ocGearProfile3, TranslationTransform[{-95, 0, 0}]];temp = OpenCascadeShapeLinearSweep[#, {{0, 0, 0}, {2, 0, 0}}]& /@ {ocGearProfile1, ocGearProfile2, ocGearProfile3};
Show[OpenCascadeShapeSurfaceMeshToBoundaryMesh[#]["Wireframe"["MeshElementStyle" -> FaceForm[Red]]]& /@ temp]gear = OpenCascadeShapeLoft[{ocGearProfile1, ocGearProfile2, ocGearProfile3}, "BuildSolid" -> True]bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[gear];Show[
gearGR = bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightGray]]]],
OpenCascadeAxis3D[{-100, 0, 0}, {120, 75, 75}]]意図した通りに境界メッシュが構築されたことを確かめるために,完全な要素メッシュを生成する.
ToElementMesh[bmesh, "MeshOrder" -> 1]組み合せる
bevelGear = OpenCascadeShapeUnion[shaft, gear]bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[bevelGear];Show[
bevelGearGR = bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightGray]]]],
OpenCascadeAxis3D[{-100, 0, 0}, {300, 75, 75}]]意図した通りに境界メッシュが構築されたことを確かめるために,完全な要素メッシュを生成する.
ToElementMesh[bmesh, "MeshOrder" -> 1]ボス
boss = Cuboid[{length - 80, -5, 36 - 2}, {length - 32, 5, 36 + 5}]Show[bevelGearGR, Graphics3D[boss]]Show[bevelGearGR, Graphics3D[boss], PlotRange -> ((# + {-10, 10})& /@ Transpose[List@@boss])]s = OpenCascadeShape[boss];
num = 13;
s = OpenCascadeShapeTransformation[s, #]& /@ Table[RotationTransform[k * 2π / num, {1, 0, 0}], {k, 1, num}];bevelGearBoss = OpenCascadeShapeUnion[Flatten[{bevelGear, s}]]bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[bevelGearBoss];Show[
bevelGearGR = bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightGray]]]],
OpenCascadeAxis3D[{-100, 0, 0}, {300, 75, 75}]]意図した通りに境界メッシュが構築されたことを確かめるために,完全な要素メッシュを生成する.
ToElementMesh[bmesh, "MeshOrder" -> 1]中空軸
cyl = Cylinder[{{-120, 0, 0}, {200, 0, 0}}, 35 / 2]Show[bevelGearGR, Graphics3D[cyl]]bevelGearBoss = OpenCascadeShapeDifference[bevelGearBoss, OpenCascadeShape[cyl]]bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[bevelGearBoss];Show[
bevelGearGR = bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightGray]]]],
OpenCascadeAxis3D[{-100, 0, 0}, {300, 75, 75}]]意図した通りに境界メッシュが構築されたことを確かめるために,完全な要素メッシュを生成する.
ToElementMesh[bmesh, "MeshOrder" -> 1]bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[bevelGearBoss, "ShapeSurfaceMeshOptions" -> {"LinearDeflection" -> 0.001}];Show[
bevelGearGR = bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightGray]]]],
OpenCascadeAxis3D[{-100, 0, 0}, {300, 75, 75}]]mesh = ToElementMesh[bmesh, "MeshOrder" -> 1, "MaxCellMeasure" -> Infinity];
Show[mesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightGray], EdgeForm[]]]],
mesh["Edgeframe"]]初期化
以下のヘルパ関数は,3D空間で円を可視化するためのものである.
Circle3D[{centre_, normal_}, radius_ : 1, angle_ : {0, 2 Pi}] :=
Module[{r, mp, mp3D},
r = DiscretizeGraphics[Circle[centre[[{1, 2}]], radius, angle]];
mp = MeshPrimitives[r, 1, Multicells -> True];
mp3D = mp /. {x_Real, y_Real} :> {x, y, centre[[3]]};
RotationTransform[{{0, 0, 1}, normal}, centre] /@ mp3D
]