歯車のベース部分をスクリプトで効率化してモデリング

  • スクリプトを使って作業を効率化

前回の歯車のベースをモデリングする手順は、大きく以下の流れで行いました。

  • 円周上の1つの歯の長さを計算
  • 1つの歯を「開いた線形状」でモデリング
  • 「開いた線形状」を計算した「歯の長さ」になるようにリサイズ
  • 1つの歯の「開いた線形状」を円周上に複製して並べる
  • 複数の歯の「開いた線形状」を連結して1つの「開いた線形状」にする
  • 不要になった「開いた線形状」を削除
  • 「開いた線形状」を「閉じた線形状」に変換

歯車の入力情報は、数値指定する「半径」「歯の数」と、1つの歯の「開いた線形状」になります。
このうち、はじめの「円周上の1つの歯の長さを計算」だけスクリプトを使用していました。

ただ、作業はかなり機械的になり、繰り返し作業も多いです。
こういった箇所は、スクリプトにしてしまうとかなり効率化できる部分になります。

スクリプトの各命令や意味については、スクリプトリファレンスをご参照くださいませ。

「1つの歯の「開いた線形状」を円周上に複製して並べる」をスクリプト化

操作をスクリプトとして「記録」

どんな作業をスクリプトにできるのかというのは
プログラムに慣れていないとなかなか分からないため、簡単に確認してみましょう。
スクリプトウィンドウの左上に「記録」チェックボックスがあります。
これをオンにしてモデリング作業を行うと、一部の動作はスクリプトとして出力されます。

「1つの歯の「開いた線形状」を円周上に複製して並べる」の操作で、
原点を中心に時計回りに回転して複製、というのを指定回数行っています。
この操作を以下の手順で行います。

  • ブラウザで1つの歯の「開いた線形状」を選択
  • スクリプトウィンドウで「記録」チェックボックスをオンにする
  • ツールボックスの「作成」-「移動/複製」-「複製」-「回転」を選択
  • 上面図で原点をクリック
  • 上面図でドラッグして、時計回りに20度近く回転


スクリプトウィンドウの「記録」チェックボックスがオンの場合は、
スクリプトウィンドウ内に以下のような内容が表示されました。


xshade.scene().copy_object([0, 0, 0], None, [0, 339.95, 0], None)

これは一回分の複製操作になります。
[0, 0, 0]は原点を表し、3つめの[0, 339.95, 0]はXYZ軸ごとの回転角度になります。
20度時計回りに回転させる場合は[0, 360 – 20, 0]の指定になります。

スクリプトを実行

では、この複製操作をスクリプトで実行してみます。
スクリプトウィンドウの「記録」チェックボックスをオフにして、
1つだけの「開いた線形状」がある状態に戻します。
スクリプトウィンドウに以下のように入力します。


xshade.scene().copy_object([0, 0, 0], None, [0, 360 - 20, 0], None)

スクリプトウィンドウで「実行」ボタンを何回か押します。

回転しながら複製されていますね。
20度ごとの回転を行っているため、
これを17回(360 / 20 = 18回分からはじめの1つを引いた数値)繰り返すと、一周することになります。

この繰り返す操作をスクリプトで書くと、以下のようになります。


for i in range(17):
  xshade.scene().copy_object([0, 0, 0], None, [0, 360 - 20, 0], None)

これで、1回の「実行」で17回分処理が繰り返されます。

もう少し進めて、歯の数の「18」が分かれば回転角度の20度が分かりますので、
歯の数を「変数」に入れて自動化させます。
「変数」とは、プログラムでの値を入れる入れ物になります。


gCount = 18    # 歯の数.
angle = 360.0 / gCount  # 円上の、1つの歯の角度.
for i in range(gCount - 1):
  xshade.scene().copy_object([0, 0, 0], None, [0, 360 - angle, 0], None)

これを実行しても結果は同じになります。
1行のうち「#」から後はコメントになり、これは実行では無視されます。

これは、「1つの歯の「開いた線形状」を円周上に複製して並べる」という工程をプログラム化したもの、と言えます。

「複数の歯の「開いた線形状」を連結して1つの「開いた線形状」にする」をスクリプト化

「複数の歯の「開いた線形状」を連結して1つの「開いた線形状」も、
「記憶」と「追加」を駆使して手間のかかる作業でした。
この作業1回分をスクリプトウィンドウの「記録」チェックボックスをオンにして、
どのようなスクリプトになるか確認すると以下のようになりました。


xshade.scene().memory()
xshade.scene().select_sister(1)
xshade.scene().append()

これを歯の数の分だけ繰り返すスクリプトは以下のようになります。


gCount = 18    # 歯の数.
for i in range(gCount - 1):
  xshade.scene().memory()
  xshade.scene().select_sister(1)
  xshade.scene().append()

このように、「記録」でスクリプトで行われることを確認しながらプログラムを書いていくことになります。

全体を通してスクリプト化

では、一連の流れを改めてスクリプトにします。
入力要素は以下の3つとなり、それ以外を自動化します。

    • R : 歯車の半径
    • gCount : 歯の数
    • 1つの歯の「開いた線形状」

なお、このスクリプトを書く工程は結構経験が必要になりますので、
はじめは流れを追いかけるだけでよいかと思います。


import math

R = 50.0       # 歯車の半径.
gCount = 18    # 歯の数.
angle = 360.0 / gCount  # 円上の、1つの歯の角度.

# 円周上の、歯1つ分の長さを計算.
D = (R * math.sin((angle / 2.0) * math.pi / 180.0)) * 2

scene = xshade.scene()

# 選択された線形状を複製.
scene.copy()
scene.paste()

# 形状の作成開始.
scene.begin_creating()

# 図形ウィンドウを強制的に再描画して、バウンディングボックス計算を行う.
scene.update_figure_window()

# 選択された形状のX方向のサイズが「D」の長さになるようにスケーリング.
shape = scene.active_shape()      # 選択されている形状.
type = shape.type                 # 選択されている形状の種類。4の場合は線形状.
bbSize = shape.bounding_box_size  # shapeの形状のバウンディングボックスサイズ.
scale = D / bbSize[0]
bbSize = [bbSize[0] * scale, bbSize[1] * scale, bbSize[2] * scale]
shape.bounding_box_size = bbSize
scene.update_figure_window()  # 図形ウィンドウを強制的に再描画.

# 選択された形状のX方向が、X=0となるように位置調整.
centerPos = shape.center_position  # shapeの中心位置.
centerPos = [0.0, centerPos[1], centerPos[2]]
shape.center_position = centerPos
scene.update_figure_window()  # 図形ウィンドウを強制的に再描画.

# 半径方向の移動距離(半径Rよりも少し短くなる).
R2 = math.cos((angle / 2.0) * math.pi / 180.0) * R

# 選択された形状のZ方向に-R2分移動.
centerPos = shape.center_position
centerPos = [centerPos[0], centerPos[1], (-bbSize[2] * 0.5) - R2]
shape.center_position = centerPos
scene.update_figure_window()  # 図形ウィンドウを強制的に再描画.

# 「開いた線形状」を円周上に複製する.
for i in range(gCount - 1):
  scene.copy_object([0, 0, 0], None, [0, 360 - angle, 0], None)

if type == 4:  # 線形状の場合.
  # 「開いた線形状」を連結.
  for i in range(gCount - 1):
    scene.memory()
    scene.select_sister(1)
    scene.append()

  # 不要な「開いた線形状」を削除していく.
  for i in range(gCount - 1):
    scene.select_brother(1)
    scene.clear()
  
  # 「開いた線形状」を「閉じた線形状」にする.
  scene.active_shape().closed = 1

# 形状の作成終了.
scene.end_creating()

使用方法

上記のスクリプトは以下のように使用します。

      • 1つの歯の「開いた線形状」を上面図で作成し、ブラウザで選択。
        「開いた線形状」は、下画像のように上面図から見て左から右にポイントを指定していきます。

        サイズや位置はスクリプトで自動的に調整されるため、調整不要です。
      • 上記のスクリプトをスクリプトウィンドウに貼り付け
      • スクリプトの先頭で「R = 50.0」としている箇所は歯車の半径なので、
        任意の数値を入れる
      • スクリプトの「gCount = 18」としている箇所は歯の個数なので、
        任意の整数値を入れる
      • スクリプトウィンドウの「実行」ボタンを押す

はじめの1つの歯の「開いた線形状」は、
後々再利用できるようにスクリプトでコピー&ペーストして残すようにしました。

このスクリプトを使用することで
歯車のベースのモデリングは、1つの歯の「開いた線形状」を与えれば後は自動化できるようになります。
また、半径や歯の数を変えて何回も繰り返し作成できるようになりました。

このように、スクリプトを使用すると作業が大幅に短縮できます。
次回、歯車に厚みを付けていきます。

カテゴリー: 歯車を作る