RHINOCEROSにはデフォルトでも断面を切るツールが幾つか用意されています。
ClippingPlaneを使用してMake2Dツールを使用する、Sectionツールを使う等が主にはありますが、
大量の断面をいっぺんに吐き出したい場合、面倒だな、、、って思ったことはありませんか。
そんな時にGrasshopperを使えば割と短いスクリプトでX,Y方向全ての通り芯上の断面を吐き出すことができます。
今回はelefrontというプラグインを使うので良かったらダウンロードしてみて下さい。
オブジェクトに対して情報を焼き付ける事ができるのでとても重宝します。
それではまず今回の目的と結果、そして手順を追って説明していきます。
毎度おなじみの変な形の建築(?)の断面を切っていきたいと思います。
よく考えてみたら柱を入れ忘れました。
目次
Grasshopperにおける断面図の作成結果
断面を切った結果は上の図のようになります。
X方向とY方向の通り芯上の断面線、断面を作成した通り芯名、直交する通り芯、その通り芯名等がプロットされています。
体裁は適当ですが、他に要素が必要であれば適宜追加することも可能ですので、一番基本のラインだけを吐き出すことを考えています。
例えばX方向の通り芯上の断面は下の図のようになります。
セクションとしての体裁はともかく、CAD図の下図になるものができているのが確認できます。
今回はこれをGrasshopperのスクリプトで書いていきます。
実際のスクリプトの全体像をスクショすると、これくらいの長さです。
比較的短いく書いたらできるので、セクションを一つづつ切るよりマシだと思います。
それから、モデルの変更にも対応しているのが嬉しいですね。
それでは具体的にスクリプトを細かく見ていきましょう。
Grasshopperにおける断面図の作成手順
まずは、赤の通り芯の作成から行います。
この時、通り芯にはキーとバリューにそれぞれ、gridlineと通り芯番号が入るようにしておきます。
これによって、断面を切ったときに通り芯も一緒に断面を切ってしまい、その通り芯番号を後々取得できるようにしたいと思います。
通り芯を作成する
まずサイトが入る四角(rectangle)を用意し、Explode curveで4辺に分割します。
それぞれをItemListで拾ってEntwineを使って、X軸方向とY軸方向のカーブを別々のブランチに格納しておきます。
これは何故こうしているかというとXとY軸で全く同じ処理をするのでどうせなら同じスクリプトで二つの処理をやってしまおうと考えました。
{0;0}がX方向で{0;1}がY方向になります。
4辺のうちの向かい合う2辺をDivideCurveし、(捻れないように片方をFlipCurve)
それぞれのポイントをLineで結んであげています。
この時、当然ながら、{0;0}同士と{0;1}同士で結ばれるのでXとY方向両方別々に通り芯ができることになります。
ここでできたラインはあくまでもDivideCurveでできたポイントを全て拾ってつなげてしまったものなので、通り芯としては要らないところがあります。
それを省くためにSeriesコンポーネントで中心部以外のインデックスの数列を作成し、ListLengthを使って引き算をすることで、前後のインデックスだけ取得します。
最後にツリーの形状を合わせ、Cull Indexで取り除きます。
当然X,Yと省きたいインデックスの数が違うのでSeriesはX、Y両方分を書くことにはなってしまいました。
通り芯にアトリビュートを付与する
できた通り芯にattributeを付与します。
これはElefrontのDefineObjectAttributesを用いて行います。
KeyがgridlineでバリューにそれぞれX0~X9、Y0~Y15が割り振られるようにします。
通り芯をExplodeTree(BANG!)し、X軸、Y軸それぞれのツリーに分割、ListIndexでインデックス値を取り出します。
それを一度グラフトして、各ブランチに格納した後、DuplicateDataMatchで同じツリー形状の接頭語X,Yを複製してTextJoinで頭につけます。
下のように、それぞれのツリーのブランチに入っているカーブと名前がきちんと一致するようにデータツリーを綺麗に保っています。
これで一度DefineObjectAttributesにValueを入れた状態でElefrontのBakeObjects でベイクします。
これによって各ラインデータにKeyとValueのアトリビュートが付与されました。
ベイクされた通り芯を選択して、プロパティから属性ユーザーテキストを参照すると、gridlineに通り芯の名前が値として入っていることが確認できます。
これによって、断面を切ったときにあたっている通り芯が何であるかを追跡することができるようになりました。
ちょっとREVITみたいですよね。
アトリビュートを取得する
この通り芯からどのようにvalueデータを取り出すかというと、ElefrontのGetUserValueを使います。
これを使ってKeyを入れてあげれば、それぞれのデータが返ってくることが分かります。
XとYと両方を別々に拾ってあげています。
余談ですが、この性質を利用することで、当たっている通り芯が不明の場合でも、
Brepと交差しているポイントがある場合をTrueそうでない場合をFalseとしてCullPatternしてから元の通り芯を直接叩けばデータが出てきます。
この場合は交差したポイント自体にはアトリビュートは付与されないので注意が必要です。
あくまでも元のアトリビュートを持つ直線からデータを取り出す必要があります。
Grasshopperによる断面ブロックの作成
モデルが重くなると好まれないやり方かもしれませんが、今回はモデルが軽量なので、BREP PLANEで全てのBREPと通り芯との交差を取ります。
実務で使用するのであれば範囲を絞ったりする必要がでてくるかもしれませんが、今回は断面を作成するという事が目的なので重いモデルのハンドリングについては触れません。
通り芯の両端点をEndPointsで取得しその平均点をArithmeticMeanを使って取得し断面Planeの原点とします。
この断面平面を基準に今回は断面のブロックを作成し、オリエントしていこうと思います。
それとは別に、交差する通り芯もブロックを作成し、同様にオリエントすることとします。
断面ブロックのデータツリーの構成
データツリーに慣れてる方は大丈夫だと思いますが、一応参考までにツリーの説明をしておきます。
BREPは1109個存在していて、Flattenされています。({0}に入っている)
それに対して、平面はグラフトされている状態({0;0}~{0;9})なので、Brep Planeでは掛け算が行われています。
それぞれのグラフトされている各ブランチあたり1109回の計算が走った結果がBrep Planeから出ているという状況です。
その計算結果が交差しているのであれば何らかのデータが返ってきますし、そうでなければnullが返ってきます。
よって、nullが入っているためBrep Planeコンポーネントは赤い警告を出している状態ですが、これは正しい結果です。
これだと10x1109ブランチができてしまい、そのそれぞれをオリエントするのは馬鹿げています。
そこで、まずはShiftPathをかませて、後ろの1109ブランチをFlattenしてしまい、({0;0}~{0;9})のブランチに次数を落とします。
これでハンドリングしやすい元の平面のツリーと同じ状態でデータを扱えるようになりました。
断面ブロックの作成とオリエント
{0;0}~{0;9}のブランチ毎に線をBlockコンポーネントのGに繋いで固めてしまいます。
その時のブロックの原点は、通り芯の平均点にしておきます。
これはたまたま全ての通り芯の長さが同じなので、中心がずれないため、そうしているだけです。
そもそも通り芯の長さが違う場合は原点がずれるため、あまり良い結果にならないかもしれませんので注意が必要です。
作成したBlockを、あらかじめSeriesで作成しておいたターゲット平面に合わせて、Orientで配置します。
この時、OrientのGにはブロックを、Aにはブロックの原点の平面を、Bにはターゲットの平面を入れてあげます。
片側はオリエントした後に方向が回転しているので、0.5*πを回転角に入れてターゲット平面に対して90度回転してあげています。
交差する通り芯の作成とオリエント
一方で、下部のスクリプトでは断面図に必要なドメインのサイズのRectangleに対してBoundarySurfaceを描いてあげています。
そのサーフェスと各通り芯Planeの交差をBrep Planeで取得し、断面図に通り芯を加えています。
これもオリエントを使用することになりますが、ブロックの原点と同じ点を合わせて、断面図を作ったときと同様にターゲット平面に対してオリエント、そして、片方は回転を行っています。
最後にテキストをText3dで入れて終了です。
上手くデータツリーにマッチさせて必要な通り芯情報を流し込んであげています。
それぞれの断面に投影されている通り芯ブロックを分解してその線毎に名前を紐付けています。
おわりに
割と少ない量のスクリプトで通り芯上の断面が切れたのではないかと思います。
データツリーの扱い方さえ間違えなければ正しく断面がプロットされるはずです。
逆に言うとその都度きちんとツリーが綺麗な状態かどうかのチェックが欠かせないのではないかと思います。
大きなファイルになるともう少し複雑な組み方をする必要があるかもしれません。
今後の課題としたいと思います。
それでは、また!