4.4 FreeCAD基本形状を使った細分化領域設定
領域内部を細分化指定する際に、DEXCSマクロではBOX領域指定しかできなかったが、cfMesh本来の設定では、球や円錐といった基本形状で領域を指定する事ができる。しかしこの機能を使いたい場合には、出力されたmeshDict中、下記のコメント行(冒頭に//のある行)の冒頭の//を削除して、数値を手修正して使うという方法しかなかった。
//coneExample
//{
// type cone;
// cellSize 7.51;
// p0 (-100 1873 -320);
// p1 (-560 1400 0);
// radius0 200;
// radius1 300;
//}
//hollowConeExample
//{
// type hollowCone;
// additionalRefinementLevels 2;
// dditional refinement relative to maxCellSize
// p0 (-100 1873 -320);
// p1 (-560 1400 0);
// radius0_Inner 200;
// radius0_Outer 300;
// radius1_Inner 200;
// radius1_Outer 300;
//}
//sphereExample
//{
// type sphere;
// cellSize 7.51;
// centre (0 700 0);
// radius 200;
// refinementThickness 40;
//}
//lineExample
//{
// type line;
// cellSize 7.51;
// p0 (-750 1000 450);
// p1 (-750 1500 450);
// refinementThickness 40;
//}
一方、FreeCADを使えば、これらの基本形状は容易に作成することが出来て、今回の改変したメッシュ細分化コンテナを使って細分化領域対象パーツとして容易に指定できるようになる(図40)。したがって、選択したパーツの種類に応じた特徴量を取得してmeshDictに反映できるようコード改変を試みた。
これまで、3-6-(2)において、領域内部を細分化対象とするリージョン名リスト(__region__)を取得できているが、さらにその対象オブジェクト(obj)が基本形状であるかどうかを判定して、基本形状である場合はそのタイプに応じて出力書式を変更することにした(以下の朱字部分を追加)。
if __region__ :
regionNumber = 0
for objList in __region__ :
for obj in doc.Objects:
if obj.Label == objList :
RefStr = str(__reflevel__[regionNumber])
if obj.isDerivedFrom("Part::Box"):
(Box用 Dict作成)
elif obj.isDerivedFrom("Part::Spher"):
(Sphere用 Dict作成)
elif obj.isDerivedFrom("Part::Cylinder"):
(Cylinder用 Dict作成)
elif obj.isDerivedFrom("Part::Cone"):
(Cone用 Dict作成)
else:
(DEXCSマクロオリジナルのDict作成)
(1) Box
DEXCSオリジナルマクロでもBoxタイプで指定しているが、Boxタイプということがわかっていれば、中心座標の計算方法が簡略化される(朱字部分)。
centerX = obj.Placement.Base.x + obj.Length.Value * 0.5
centerY = obj.Placement.Base.y + obj.Width.Value * 0.5
centerZ = obj.Placement.Base.z + obj.Height.Value * 0.5
strings7 = [
'\t' + objList + '\n',
'\t{\n',
'\t\ttype box;\n',
'\t\tadditionalRefinementLevels\t' + RefStr + ';\n',
'\t\tcentre (' + str(centerX) + MainControl.SPACE_STR + str(centerY) + MainControl.SPACE_STR + str(centerZ) + ');\n',
'\t\tlengthX\t' + str(obj.Length.Value) + ';\n',
'\t\tlengthY\t' + str(obj.Width.Value) + ';\n',
'\t\tlengthZ\t' + str(obj.Height.Value) + ';\n',
'\t}\n'
]
ちなみに、DEXCSオリジナルマクロでは、中心座標を以下のようにして取得しており、これだと対象パーツ(obj)がShape属性を有しているものであれば何であってもよかった。
xmax = obj.Shape.BoundBox.XMax
xmin = obj.Shape.BoundBox.XMin
ymax = obj.Shape.BoundBox.YMax
ymin = obj.Shape.BoundBox.YMin
zmax = obj.Shape.BoundBox.ZMax
zmin = obj.Shape.BoundBox.ZMin
centerX = 0.5*(xmax+xmin)
centerY = 0.5*(ymax+ymin)
centerZ = 0.5*(zmax+zmin)
(2) Sphere
球(Sphere)の場合は、FreeCADにおける球の基準座標(obj.Placement.Base)と、cfMeshで定義する球の中心座標は同じであるので、もっと簡単である。
centerX = obj.Placement.Base.x
centerY = obj.Placement.Base.y
centerZ = obj.Placement.Base.z
strings7 = [
'\t' + objList + '\n',
'\t{\n',
'\t\ttype sphere;\n',
'\t\tadditionalRefinementLevels\t' + RefStr + ';\n',
'\t\tcentre (' + str(centerX) + MainControl.SPACE_STR + str(centerY) + MainControl.SPACE_STR + str(centerZ) + ');\n',
'\t\tradius\t' + str(obj.Radius.Value) + ';\n',
'\t\trefinementThickness\t' + '0' + ';\n',
'\t}\n'
]
なお、パラメタとして、refinementThickness も指定できるが、球の径を大きくすることと同じになり、2つのパラメタに区分して定義することにあまり意味があるとも思えなかったので、この値は0としてこれを変更する方法までは考えていない(手作業での変更は可能)。
(3) Cylinder
円柱(Cylinder)を使って、cfMesh のtype line; セクションを作成することができる。但し、円柱は平行移動だけでなく、傾けて配置する(注記1)ことができ、平行移動量の取得は容易であるが、傾けた時の円柱上面の中心座標を求めるのには多大な試行錯誤が必要であった。
pos = FreeCAD.Vector(obj.Placement.Base.x, obj.Placement.Base.y, obj.Placement.Base.z + obj.Height.Value)
center = FreeCAD.Vector(0, 0, - obj.Height.Value)
rot = FreeCAD.Rotation(obj.Placement.Rotation)
cylinderHead = FreeCAD.Placement(pos, rot, center)
p0X = obj.Placement.Base.x
p0Y = obj.Placement.Base.y
p0Z = obj.Placement.Base.z
p1X = cylinderHead.Base.x
p1Y = cylinderHead.Base.y
p1Z = cylinderHead.Base.z
strings7 = [
'\t' + objList + '\n',
'\t{\n',
'\t\ttype line;\n',
'\t\tadditionalRefinementLevels\t' + RefStr + ';\n',
'\t\tp0 (' + str(p0X) + MainControl.SPACE_STR + str(p0Y) + MainControl.SPACE_STR + str(p0Z) + ');\n',
'\t\tp1 (' + str(p1X) + MainControl.SPACE_STR + str(p1Y) + MainControl.SPACE_STR + str(p1Z) + ');\n',
'\t\trefinementThickness\t' + str(obj.Radius.Value) + ';\n',
'\t}\n'
]
回転前の円柱上面の中心座標(pos)を円柱下面の中心座標(center)を回転中心として、モデルの回転角(rot)相当回転移動して、回展後の円柱状面の中心座標(cylinderhead)を求めれば良いということであるが、centerは、posに対する相対移動量を指定するところがミソであった。
(4) Cone
円錐(Cone)は、円柱の上面と下面で径が異なるだけであるので、Cylinderの座標指定と同じ方法が使える。2つの径を指定する必要があるというだけの違いである。
center = FreeCAD.Vector(0, 0, - obj.Height.Value)
pos = FreeCAD.Vector(obj.Placement.Base.x, obj.Placement.Base.y, obj.Placement.Base.z + obj.Height.Value)
rot = FreeCAD.Rotation(obj.Placement.Rotation)
cylinderHead = FreeCAD.Placement(pos, rot, center)
p0X = obj.Placement.Base.x
p0Y = obj.Placement.Base.y
p0Z = obj.Placement.Base.z
p1X = cylinderHead.Base.x
p1Y = cylinderHead.Base.y
p1Z = cylinderHead.Base.z
strings7 = [
'\t' + objList + '\n',
'\t{\n',
'\t\ttype cone;\n',
'\t\tadditionalRefinementLevels\t' + RefStr + ';\n',
'\t\tp0 (' + str(p0X) + MainControl.SPACE_STR + str(p0Y) + MainControl.SPACE_STR + str(p0Z) + ');\n',
'\t\tp1 (' + str(p1X) + MainControl.SPACE_STR + str(p1Y) + MainControl.SPACE_STR + str(p1Z) + ');\n',
'\t\tradius0\t' + str(obj.Radius1.Value) + ';\n',
'\t\tradius1\t' + str(obj.Radius2.Value) + ';\n',
'\t}\n'
]
以上、4種類の基本形状以外に、cfMeshで定義できるものとして、hollowConeタイプが存在するが、FreeCAD上で相応する基本形状が存在しないので、これについては実装を見送って、従来通りコメントアウト出力を残すようにした。また、内側か外側のどちらかのConeを作成しておいて、両端面における外側または内側の径だけを手作業で追加することはさほど面倒な作業にはならないと思われ、これが実装できていないからといって致命的ではないと考えている。
メッシュ確認例
注記1
傾けるに関しては、BoxタイプであってもFreeCAD上では傾けることはできるが、cfMeshでは傾きを考慮したBox指定ができないので、傾いたBoxタイプを指定すると、傾いていない状態のデータで設定されることになるという点はお断りしておく。