loose read about Sverchok documents (Introduction Unit 02)
Lesson 02 - A Circle
概要
このレッスンでは、以下のノードを利用して円を作成する。
- List Length
- List Shift
- List Zip
- Formula
- Lesson 01で既に利用しているノードたち
A Circle
最も手っ取り早い方法は、 blender 標準の circle オブジェクトやカーブを用いる方法がある。
次に簡単な方法は、 Sverchok
が標準で提供している Circle Generator
ノードを用いること。
ここでは、上記を用いずに正方形メッシュを作成した時と同じように頂点位置の計算や設定を全てノードを使って生成する方法で説明している。
Dynamic Polygons
正方形を作成した時のようにすれば頂点さえ作成できればポリゴンを生成することができる。
しかし、頂点数が増えると頂点の管理やインデックスの把握が困難になるので、複雑な頂点情報は変更が発生した時の修正をある程度自動化しなければならない。
Sverchok
では UV Connect
ノードというものがそれに該当するが、本チュートリアルではこのノードも未使用ということになっている。
利用しない理由は、基本的なノードの使い方やVisual Programmingでの位置づけを学ぶために頂点やインデックスの生成を自分で構築させるのも本チュートリアルで目指しているとのこと。
Generating an index list for the polygon
自動的に頂点のリストを作成するためには、処理の瞬間に何個の頂点があるのかを知る必要がある。
List Length
を使うと、リストがネストしていてもネストの深さに合わせた閲覧ができる。
Add -> List Main -> List Length
ここからは [0,1,2,...n]のようなシーケンス(リスト)を生成していく。Pythonとして書く場合には以下のようなコードになる。
n = 4 range(start=0, end=n, step=1) >> [0, 1, 2, 3]
まずは Lesson.1 で頂点インデックスを手動で指定していたが、ここを Number Range
ノードだけで処理していくようにする。
ここまでのノード画面を見ると、 List Length
で n=4
に相当する出力を作成したことが分かる。
n=4
に該当するノードができたのであれば、次は range(start=0, end=n, step=1)
に相当するノードが必要となる。
そのためのノードが Number Range
ということになる。
Add -> Numbers -> Number Range
List Length -> Number Range
とする。
Number Range
の step
モードは python の range
とほぼ同じ名前のソケットがあるので、画面のように range(start=0, end=n, step=1)
対応するような設定をすれば、 [0, 1, 2, 3]
という結果が得られた。
ここまでの処理で頂点インデックスを自動生成するところまでは実現できたが、このインデックスをそのまま Viewer Draw
へ接続してもポリゴンは生成してくれない。
その理由は、 Number Range
の出力結果がblender がポリゴンとして認識できる形となっていないためである。
この問題を修正するために、 Add -> Numbers -> Fomula
ノードを追加してデータの形を修正する。
Number Range
が Fomula
を経由する前と後のデータの形と、 正方形ポリゴンを出力するために利用している Simple Topology
の出力しているデータの形を比較すると、違いが分かりやすい。
ここまでできれば頂点インデックスの形が正方形ポリゴンの出力に使っているものと同じになるので、 Viewer Draw
に接続すればポリゴンを生成してくれるようになる。
Generating the set of circular verts
ここではあくまで円形のポリゴンを作成することが目的なので、いよいよ頂点データを円形のものへと差し替えていく。
今使っている頂点データは正方形を描画するために Number Range
を使って生成したものとなっている。
円形(のように見えるポリゴン)の場合は正方形よりも多くの頂点データが必要となるので、 ノードの先頭にある Number Range
の設定を変更して 円形になるように単位円辺りのポリゴンの数を増やせばいい。
Forcing an even spread of Vertices
頂点インデックスをノードだけで生成できるようになったので、今度は頂点の数を指定すれば円に必要な頂点もノードだけで計算してくれるようにする。
今は
Number Range
を使って頂点の数がどれだけ必要かを考えてから円を作っている状態。
そのためには、 一番最初に作成した Number Range
の Step
で指定している数値を計算で算出する必要がある。
頂点の数に合わせた円周上の頂点の間隔を計算するには、以下のような式となる。
step_distance = 2.0 / n # n は円を表現するために利用する頂点の数
まずは step_distance = 2.0 / n
の式を表現するノードを追加する。
Add -> Numbers -> Scalar Math
次に、利用する頂点の数を表現するノードを追加する。
'Add -> Numbers -> A Number'
後は n
を表現する Number
と step_disance
を算出するための Scalar Math
を接続すれば計算は完了。
Scalar Math
を Number Range -> Step
へとつなげば、直接ステップ数を指定しないで円を表現できるようになる。
円はできたが、元々表示していた円よりも頂点の数が多いという現象が発生している。
これは Number Range
で設定している Stop
を Step
へ接続した 計算結果によるもの。
Step = 0.1
となっている状態なので Start (=0.0) から Stop (=2.0) まで 0.1刻みで数値を生成している
状態となっている。
接続する前は
Step = 2.0
だった
ただし、単純に Stop = 1.0
にして出力される値の数を半減させると下図のようになる。
この解決方法として、 Sverchok
のドキュメントでは tau (タウ)
による計算へと切り替えていた。
別解。
Polygon was easy, what about Edges?
ここまでで円形のポリゴンを作成してきたが、ここからは円形のエッジを作成していく。
円形の頂点を用いてエッジを生成する場合、エッジの生成に必要な頂点インデックスの指定方法は以下のようになる。
[[0,1],[1,2],[2,3],[3,0]]. # n個の頂点を用いた円形のエッジを生成するために必要なインデックスはこんな感じ [[0,1],[1,2],...,[n-1,n],[n,0]] # 上記のリストを n 個の頂点が収まったリストだけで頂点インデックスを生成する場合は、for文を使えばよい n = 5 for i in range(n): print(i, (i+1) % n) >>> 0 1 >>> 1 2 >>> 2 3 >>> 3 4 >>> 4 0 # 頂点インデックスを sverchok がエッジの組み合わせと認識できるような形へ整形する必要がある n = 5 edges = [[i, (i+1) % n] for i in range(n)] print(edges) >>> [[0, 1], [1, 2], [2, 3], [3, 4], [4, 0]] # 上の頂点インデックスの組み合わせを見ると、基本的に 元の配列と中身が1つズレている配列の組み合わせということが分かる # そのため、pythonのzipメソッドを用いれば、for文を簡略化できる indices = [0, 1, 2, 3, 4] indices_shifted_by_one = [1, 2, 3, 4, 0] # indicesの中身を1つずらした for a, b in zip(indices, indices_shifted_by_one): print([a, b]) >>> [0, 1] >>> [1, 2] >>> [2, 3] >>> [3, 4] >>> [4, 0]
pythonを知らなければ上の式は意味不明に見えるが、 for a, b in zip(indices, indices_shifted_by_one):
の部分を Sverchook
で表現しようということになる。
難しいこと言っているように見えるが、今回のケースに限っては Sverchok
にそのまんまのノードがあるためそれらを利用する。
利用するのは以下の2つのノード。
add -> List Struct -> List Shift
add -> List Main -> List Zip