過去の投稿で『Rhinoceros 鎚目の法線マップを作る』ということを取り上げました。
今回は Grasshopper を使って鎚目のオブジェクトを作ってみたいと思います。
抑えておきたいコンポーネント
抑えておきたいコンポーネントは以下の2つです。
- Voronoi コンポーネント
- Populate 2D コンポーネント
Voronoi コンポーネント
点群(Points)や平面(Plane)などを指定し、2D上にボロノイ曲線を作成するコンポーネント。

ボロノイという言葉に馴染みのない方も多いと思いますが、ボロノイをネット上で検索すると下記のようなボロノイ図として情報が得られます。

ある距離空間上の任意の位置に配置された複数個の点(母点)に対して、同一距離空間上の他の点がどの母点に近いかによって領域分けされた図のことである。
wikipedia
数学的に説明すると難しく思えるのですが、いろんな分野で応用されている割と身近なもののようです。
- 最も近い基地局を調べ、新しい基地局をどこに作ればよいかの指標を得る(交通機関・学区・避難所の設置など)
- 有限要素法の領域分割(CGの分野ではポリゴンメッシュ化する技術など)
- 散らばったデータを、いくつかのデータにまとめる
- 画像のデータ圧縮
ボロノイ図のような模様は自然界では割と目にするもので、例えば以下のようなものがあります。




鎚目のパターンを作る際はVoronoiコンポーネントを使うと簡単にボロノイ曲線が作れます。
Populate 2D コンポーネント
範囲となる長方形(Region)を指定し、2D平面に点(Point)を指定した数(Count)だけ発生させるコンポーネント。

ボロノイ曲線を作るためには基点となる点群が必要となり、その点群をランダムに生成するためにPopulate 2Dコンポーネントを使います。
Anemone によるループ処理
この2つのコンポーネントに加えて、今回は Grasshopper のプラグインの『Anemone』を使います。Anemone はループ処理をするためのコンポーネントが実装されています。基本的な使い方として、Loop Startコンポーネント・Loop Endコンポーネントの間に繰り返す処理を書き込み、ループさせます。

プラグインを使用するには food4rhino.com にて会員登録する必要がありますが、無料で利用可能です。以下ダウンロード先。
https://www.food4rhino.com/app/anemone
鎚目のオブジェクトを作るコンポーネントの全体図

完成したものが上記のコンポーネント群となります。では一つ一つ見ていきましょう。
ボロノイ曲線を作る
今回作る鎚目オブジェクトのサイズは5×5の正方形となります。まずはRectangleコンポーネントでXY平面に5×5の正方形を作ります。
Populate 2Dコンポーネントでランダムに点群を作ります。入力側のR端子にはRectangleコンポーネントで作った正方形(Regio)、N端子には発生させる点の数(Number)、S端子にはランダムな点を発生させるためのシード値(Seed)を接続します。N端子・S端子はNumber Sliderコンポーネントを使って数値入力しています。
下図は緑色になっているコンポーネントが小ウィンドウでプレビューされている状態です。5×5の正方形の中にランダムな点群が作られています。

次に、この点群を継ぎ目のないシームレスな鎚目パターンとするために、Rectangular Arrayコンポーネントで3×3個に配置します。入力G端子にはPopulate 2Dコンポーネントで作った点群を、入力C端子には配列間隔の基準となる長方形(Cell)としてRectangleコンポーネントで作った正方形を、入力X・Y端子にはX方向、Y方向それぞれ配列させる数として3を入力します。ここでRectangular Arrayコンポーネントの出力G端子は右クリックオプションからデータ階層を整えるFlattenを適用しておきます
正方形をMoveコンポーネントで点群の中央に移動しておきます。
そして、Voronoiコンポーネントには、入力P端子にRectangular Arrayコンポーネントで3×3個に配置された点群を、入力B端子にボロノイを作る範囲(Boundary)としてMoveコンポーネントで移動させた正方形を接続します。
プレビューを見てみると配列された点群の中央5×5の正方形内にボロノイ曲線が作られていることがわかります。

Populate 2Dコンポーネントに接続している入力N端子(鎚目の数)と入力S端子(パターン)の数値パラメーターを動かすことで、ボロノイ曲線の形状が変化していきます。

ここで作ったボロノイ曲線は、出来上がる鎚目のパターンの確認用としてのボロノイ曲線となります。
次に鎚目となるオブジェクト作っていきます。
ボロノイ用の点群を絞り、ループ処理に必要なオブジェクトを作る
ボロノイ用の点群は5×5の正方形よりもひと回り大きいものが必要となります。これは正方形の外側付近の点群も5×5の正方形内のボロノイ曲線に関わってくるためです。
新たにひと回り大きい正方形のサーフェスを作ります。今回はPlane Surfaceコンポーネントで中心を5×5正方形に合わせた、9×9の正方形を作りました。Project Pointコンポーネントで点群を9×9の正方形に投影して点群に絞ります。投影されなかった点群がリストに null として残るため、Clean Treeコンポーネントで取り除きます。これで鎚目用のVoronoiコンポーネントに使う点群が出来ました。(Point In Curveコンポーネントで閉じた曲線(Curve)と複数の点(Points)の内外判定を行うやり方もあります。)
ループ処理の回数は点群の数と同じなので、List Lengthコンポーネントを使って数値化します。出力された数値のまま扱うとループ処理が一回分多くなるため、Subtractionコンポーネントで1を引きます。
Sphereコンポーネントの入力B端子に点群を接続して中心座標として、鎚目の元となる球体を作ります。それぞれの球体をそれぞれのボロノイ曲線で分割したものが鎚目となります。球体の径が小さすぎると隣接するものと干渉し合わないの注意が必要です。ここでは半径2としています。
球体をボロノイ曲線で分割するためのオブジェクトを作ります。Voronoiコンポーネントの入力P端子に点群を接続してボロノイ曲線を作り、Extrudeコンポーネントで押し出してサーフェスにします。
これでループ処理の準備が整いました。下図はボロノイ用の点群とボロノイ曲線の押し出しサーフェスとなります。

ループ処理で鎚目オブジェクトを作る
プラグインの Anemone を使ってLoop Start・Loop Endコンポーネントの間に繰り返す処理を書き込み、ループさせます。
Loop Start・Loop Endコンポーネントの>端子・<端子を互いに接続し、Loop Startコンポーネントの入力側のN端子にはループの回数を接続します。
ループ処理の内容は、Split Brepコンポーネントを使って球体をサーフェスで分割するだけのシンプルなものです。ループ処理を行った回数はループする度に+1加算されていくので、Loop Startコンポーネントの出力C端子(Counter)をList Itemコンポーネントの入力i端子(Index)に接続することで、ループ処理数=インデックス番号という具合にアイテムを取り出します。それを利用して、それぞれの球体をそれぞれのサーフェスで分割していきます。
Loop Endコンポーネントの入力D0端子には、分割されたオブジェクトからList Itemコンポーネントを使ってインデックスが1のアイテムを取り出して接続します。今回の処理の場合、分割されたサーフェスのうち、インデックスが0には鎚目に使わない不要なサーフェスが、インデックスの1には鎚目として使いたいサーフェスが割り振られています。Loop Endコンポーネントのプレビューで鎚目のサーフェスと分割出来なかった球体が出力されていることが確認できます。
ここでLoop Endコンポーネントの出力D0端子は右クリックオプションからデータ階層を整えるFlattenを適用しておきます。これは鎚目を一体化するのにBrep Joinコンポーネントで必要となります。

分割出来なかった球体は必要ないので取り除きます。まずBrep Joinコンポーネントで鎚目サーフェスを一つに結合します。これによって鎚目サーフェスは一つのオブジェクトに、残りは個々の球体のままとなり、出力C端子から閉じたオブジェクトか否かを区別されて True/False の値で出力されます。Dispatchコンポーネントを使うと True/False の2つの値を分別できるので、必要な鎚目オブジェクトを出力B端子から出力します。

ちなみにループ処理はLoop Startコンポーネントをダブルクリックすることで開始されます。ループ数の進捗がLoop Startコンポーネントの出力C端子(Counter)から接続されたPanelコンポーネントで確認できます。

正方形にトリムするためのオブジェクトを作る
鎚目オブジェクトを正方形にするために、Box 2PtコンポーネントとSolid Differenceコンポーネントを使ってトリム用オブジェクトを作ります。そしてTrim Solidコンポーネントで鎚目オブジェクトをトリムします。

位置を調整して完成
Bounding Boxコンポーネントで鎚目オブジェクトのバウンディングボックスを作り、Volumeコンポーネントで中心座標点を取得します。DeconstructコンポーネントでZ座標のみ出力して、Unit ZコンポーネントでZ軸方向のベクトルを作り、Negativeコンポーネントで値をマイナスに反転します(Reverseコンポーネントでも可)。そして鎚目オブジェクトをMoveコンポーネントで移動させて完成です。

RhinocerosオブジェクトにBakeする
Rhinoceros 上で取り扱うにはBakeする必要がります。完成したコンポーネント上で右クリックしてオプションからBakeしましょう。

Bakeした鎚目オブジェクトを法線マップとして利用するのであれば、以前の投稿、Rhinoceros のモデルデータから法線マップを作るで紹介した xNormal などで法線マップに変換しましょう。

今回使った Anemone に限らず、Grasshopper には多くのプラグインがあります。中には無料で使えることを疑うほどのものもあり、Rhinoceros 本体に負けず劣らず Grasshopper 専用のプラグインが盛んに開発されていることに驚かされます。
Topic
ループ処理をしないコンポーネントの組み方
ループ処理に利用したプラグインの Anemone を使わずにコンポーネントを組むことも出来ます。今回はSplit Brepコンポーネントで分割する際に処理落ちすることが何度か見受けられたので、回避策として Anemone を採用してみました。むしろ必要なければ使わないほうがスッキリします。

Split Brepコンポーネントを思い通りの結果にするには、入力B・C端子のデータ階層を揃える必要があります。C端子を右クリックしてオプションからFlattenを適用し、入力B端子のデータと同じ階層にします。またList Itemコンポーネントの出力i端子にもFlattenを適用します。これはループ処理した場合にもLoop Endコンポーネントの出力D0端子に適用しており、鎚目を一体化するBrep Joinコンポーネントで必要となります。
Rhinoceros にも言えたことですがブール演算やトリム・分割などのコマンドは、オブジェクトの交差条件によっては正常に実行できない場合があります。Rhinoceros の場合には対象物を僅かに移動・回転・拡大縮小・変形することで回避できることも多いです。残念ながら Grasshopper でも同じようなことがあるようなので、その場合はコンポーネントの組み方を見直す必要があるかもしれません。