今回は、任意のポリラインを元に配管を生成し、配管の長さ・数量・エルボの数などを取得していこうと思います。初学者の方にとってはややこしいかもしれません、データツリーをしっかり理解している必要があります。また、今回はプラグインや Python・C#などを使用せず実装していますが、所々スクリプトを書けば楽な箇所はあります。より効率の良い方法はいくらでもあると思いますので、自分なりに修正してみてください。
概要
上画像がプログラムの全体像となっております。各ブロックごとに説明していこうと思います。
ベースとなるポリラインを生成
- まずは Rhinoceros で Polyline を生成します。今回は 75Φ の配管を実装していこうと思いますので、各辺 400mm 以上はあるかなといった感じです。小さすぎるスケールにしないようご注意ください(※例えば 1 辺 10mm とかだと、そもそも 75Φ の配管できませんので・・・)上画像では X・Y・Z 方向に垂直なポリラインになっておりますが、斜めも対応できるようにプログラムは組んでいきます。
- Grasshopper に移動し、Curve コンポーネントにセットします。
コーナー位置を取得
- コーナー部分にはコーナー材(エルボ)が来ますので、その位置を取得していきます。
- Explode コンポーネントでポリラインを直線に分解していきます。
- Length コンポーネントで直線の長さを取得します。
- 今回はコーナー位置からそれぞれ 100mm 返った箇所でジョイントしたいので、100mm ÷ (直線の長さ)と、(直線の長さ-100mm)÷ 直線の長さの 2 つの値を取得します。この 2 つの値は、直線の始点・終点を 0 ~ 1 とした際に、始点・終点から 100mm 返った位置となります。
- Evaluate Curve コンポーネントを 2 つ用意し、Reparametrizeして分割したポリラインを接続します。先ほど取得した、直線の始点から 100mm 返った位置と終点から 100mm 返った位置を接続し、実際のポイントを取得します。
- Weave コンポーネントで取得した点を 1 つのリストにしていきます。Pattern は右クリックでSet Multiple Integerで「0,1,2」と入力します。0 にExplode コンポーネントから始点を、1 には始点から 100mm 返った位置を、2 には終点から 100mm 返った位置を接続します。
配管の中心線を取得
- 先ほど作成した点のリストから配管の中心線を生成します。Polyline コンポーネントで再度最初の状態に戻します。
- Fillet コンポーネントでコーナー部分を曲げていきます。角から 100mm 返った位置を取得したので、100mm を半径としています。
- ここで問題が起きてきます。最初に設定する曲線が直線だった場合、Fillet コンポーネントは機能せずエラーを吐いてしまいます。なので、Stream Filter コンポーネントを使って工夫します。
- 最初に設定する曲線が直線だった場合、当たり前ですが、Polyline コンポーネントからは PolylineCurve ではなく Linear Curve が取得できます。とりあえずPolyline コンポーネントの出力端子をReplace Text コンポ―テントで「Linear Curve」⇒「This is Linear Curve」とでも置き換えましょう。
- Member Index コンポーネントで「This is Linear Curve」のテキストが List 内にいくつあるか取得します。この値が Polyline だったら 0 だし、直線だったら 1 になりますね。この値を利用していきます。
- Stream Filter コンポーネントの Gate にMember Index コンポーネントの N を接続します。0 の場合は Fillet されたポリラインが出力されます。次の項で 1 の時に出力される直線を生成していきます。
直線だった場合
- 最初に設定する曲線が直線だった場合、Stream Filter コンポーネントにそのまま最初のCurves コンポーネントを接続すればいいじゃんと思った方もいるかもしれませんが、今回はそうしません。後々わかってくると思いますが、今回はパイプの長さが一定以上の場合、継手を設けるようなプログラムを書いていこうと思います。もし設定された直線の頂点が、始点と終点のみのではなく、中間にも頂点があってしまった場合に都合が悪くなるので、その場合でも頂点が始点・終点のみの直線となるようなプログラムを書いていこうと思います。
- End Points コンポーネントで始点と終点を取得し、Line コンポーネントで直線を初期化します。これをStream Filter コンポーネントの 1 の端子に接続します。
- これで、最初の曲線が直線の時は、配管の中心線は直線が返され、そうでない場合はフィレットされた曲線が返されます。
一定以上の長さより長い箇所を取得
- 配管にも定尺がありますよね。今回は一定以上の長さの場合に継ぎ手を設けたいので、指定した長さ以上の直線を取得していきます。
- Explode コンポーネントで直線と円弧に分割します。
- Length コンポーネントで分割した直線・円弧の長さを取得します。
- Larger Than コンポーネントで取得した長さが 1000mm より大きいかどうかを Bool 値で取得します。この 1000mm は目的とする材料の定尺など入れてみてください。
- Member Index コンポーネントで True の場合の Index 番号を取得します。Construct Path コンポーネントで取得したインデックス番号で Path を生成します。入力値はGraftして出力値はSimplifyしておきましょう。
- Explode コンポーネントにEntwine コンポーネントを接続します。Entwine コンポーネントはGraftで使用し{0;x}にGraft・simplifyした分割した曲線を、{1;x}にはPanel コンポーネントで適当に dummy data を生成しときます。これをする理由は後ほど説明します。
- 出力値をFlattenし、Graft コンポーネントで再度Graftします。これをする理由はブランチの番号をきれいにしたいからです。
- Split Tree コンポーネントで接続したデータツリーから一定以上の長さの直線が格納されているブランチを取得します。出力端子 P からは一定以上の長さの直線が格納されているブランチが、N からはそうでない直線・円弧が取得できます。
- 先ほど dummy data を設けたのは、最初に設定するが直線だった場合にSplit Tree コンポーネントが機能しないためです。直線だった場合、Explode しても直線なので値は 1 つです。それをSplit Tree コンポーネントで検索を掛けても検索がかかりません。なのであえてダミーデータを設けてブランチが最低でも 2 つになるようにしています。
継手位置取得
- Divide Curve コンポーネントで先ほど取得した 1000mm 以上の直線を分割していきます。
- Length コンポーネントで長さを取得します。
- Division コンポーネントで取得した長さを、1000mm(先ほど指定した材料の定尺などの値)で割り、Round コンポーネントで切り上げた数値で分割していきます。
- Shatter コンポーネントで一定以上の長さの直線をDivide Curve コンポーネントで取得した分割点位置のパラメーターで切断します。出力端子はSimplifyします。
- Merge コンポーネントで一定以上の長さではない曲線と一定以上の長さを分割した直線をマージし、Flattenしておきます。
- 前項で作成した dummy data が邪魔なので、Cull Index コンポーネントで‐1 番目を削除し、dummy data を消します。
- Join Curves コンポーネントで曲線を結合します。
配管の生成
- Join Curves コンポーネントで結合する前の分割状態の曲線に対して、Perp Frames コンポーネントを使用し、Count に 1 を指定することで、始点と終点に曲線に直行する平面を取得します。
- Circle コンポーネントで取得した平面に円を生成します。半径は配管の半径としたいので、75Φ の半分で 37.5mm としています。出力端子はFlattenしてSimplifyしておきます。
- List Item コンポーネントで 0 番目の値を取得し、全体の曲線の始点位置にある円を取得します。
- Sweep1 コンポーネントでJoin Curves コンポーネントから出力される、配管の中心線をレールにして円を押し出します。とりあえず配管部分の完成です。
継手・仕口部作成
- Offset Curve コンポーネントで先ほど生成した円をオフセットします。7.5mm 外側にオフセットしています。
- Entwine コンポーネントでオフセット前と後の円をそれぞれブランチに格納しています。
- Flip Matrix コンポーネントで行列を反転させることで、それぞれ対応する円同士でブランチに格納します。
- Boundary Surface コンポーネントでオフセット前と後との間にサーフェイスを張ります。
- Offset Surface コンポーネントで生成したサーフェイスを今度はパイプの方向にオフセットします。今回は適当に 5mm オフセットします。
- Brep Edges コンポーネントでオフセット前と後のサーフェイスそれぞれのエッジを取得します。
- Ruled Surface コンポーネントでエッジ同士の間にサーフェイスを張ります。
- Merge コンポーネントで仕口・継手部のサーフェイスをまとめます。
- 最後にMerge コンポーネントで配管部と継手・仕口部をまとめて完成です。
配管データ取得 ①(径)
- それではデータを取得していきます。まずは配管の直径を取得します。これは簡単ですね。
- 配管の半径を使用しているので、それを 2 倍するだけです。
- 私はサムネイルをつくる都合上、Rhinoceros に情報を Bake したかったので、テキスト化して、Concatenate コンポーネントで「"Pipe_Size=>" + "75" + "Φ"」として「Pipe_Size=>75Φ」という文字列を取得しています。
配管データ取得 ②(長さ・コーナーの数)
- 結合する前の配管の中心線をData コンポ―ネントで持ってきます。Flattenしておきます。
- Replace Text コンポーネントで Data の List のうちコーナー部分(Arc-Like Curve)を適当に「This is Pipe corner」というテキストに置き換えておきましょう。
- Member Index コンポーネントで「This is Pipe corner」に置き換わったリストの Index 番号を取得します。
- Cull Index コンポーネントで取得した Index 番号のデータを削除すれば、直線部分のみが残るります。Length コンポーネントで長さを取得することで、各配管の長さが取得できます。
- 私はサムネの都合上、「Pipe_Length:○○mm」
- List Item コンポーネントで Arc 部分を取得すれば、コーナー部分のみのリストになります。List Length コンポーネントで数量を取得します。
- 私はサムネの都合上、「Num_of_Pipe_Corner => ○○」という文字列で取得しています。
完成
最後は Text Tag 3D コンポーネントで取得した文字列をテクストオブジェクトに変換して Rhinoceros 上に張っているだけです。途中のごちゃごちゃしているのは単純に、どの位置に張り付けるかを書いているだけなので割愛します。
いかがだったでしょうか。たぶん意味不明な箇所が多々あったかと思います。とりあえずベタ打ちしながら Panel コンポーネントでリストの中身を確認しながら進めることをお勧めします。また、もっと簡単な実装方法はいくらでもあると思います。スクリプトを書けば楽になる箇所もあります。是非自分なりに修正してみてください。