SurfaceDomainとSurfaceEvaluateでサーフェスのドメイン・情報を取得する方法|Grasshopper Python × RhinoScriptSyntax入門

RhinoScriptSyntax GHPython
SurfaceDomain
SurfaceEvaluate

SurfaceDomain関数とSurfaceEvaluate関数で、サーフェスのドメイン・情報を取得することができます。

本記事のGrasshopperファイルのダウンロードはこちら

例

今回は、上の画像のように、サーフェスから情報を取得し、作業平面を作成し、円柱をサーフェス上に作成します。

コード

使用コンポーネント 1: Python 3 Script 2: Surface 3: plane 4: Brep

import rhinoscriptsyntax as rs
# RhinoをPythonから操作するためのライブラリを読み込む

pts = [(0,0,0),(10,0,5),(10,10,0),(0,10,5)]
# サーフェスを作成するための4点座標を定義

surface = rs.AddSrfPt(pts)
# 4点を使ってサーフェス(面)を作成する

domainU = rs.SurfaceDomain(surface, 0)
# サーフェスのU方向のドメイン範囲を取得する
domainV = rs.SurfaceDomain(surface, 1)
# サーフェスのV方向のドメイン範囲を取得する

u_norm = 0.2
# U方向の正規化された位置を定義(0〜1の範囲)
v_norm = 0.2
# V方向の正規化された位置を定義(0〜1の範囲)

u = domainU[0] + u_norm * (domainU[1] - domainU[0])
# 正規化した値を、実際のUパラメータ範囲へ変換する
v = domainV[0] + v_norm * (domainV[1] - domainV[0])
# 正規化した値を、実際のVパラメータ範囲へ変換する

srf_eva = rs.SurfaceEvaluate(surface, (u, v), 1)
# 指定したUV位置の情報を取得する
# 「1」を指定することで、点情報に加えて接線ベクトルも取得する

plane = rs.PlaneFromFrame(srf_eva[0], srf_eva[1], srf_eva[2])
# 取得した点と接線ベクトルを使って作業平面を作成する

cylinder = rs.AddCylinder(plane, 5, 1)
# 作成した平面を基準に円柱を作成する

Python 3 Script」には、上記のコードが記載されています。

順番に、コードの解説をしていきます。

pts = [(0,0,0),(10,0,5),(10,10,0),(0,10,5)]

pts = [(0,0,0),(10,0,5),(10,10,0),(0,10,5)] では、サーフェスを作成するための4点座標を、リストで定義しています。

リストに関してはこちら

surface = rs.AddSrfPt(pts)

AddSrfPt 関数で、4点を使ってサーフェス(面)を作成しています。

domainU = rs.SurfaceDomain(surface, 0)
domainV = rs.SurfaceDomain(surface, 1)

SurfaceDomain 関数で、サーフェスのU方向とV方向のパラメータ(ドメイン)範囲を取得しています。

第1引数では、サーフェスを指定します。

第2引数では、0 の場合はU方向のドメイン範囲、1 の場合はV方向のドメイン範囲を取得できます。

u_norm = 0.2
v_norm = 0.2

u_norm = 0.2v_norm = 0.2 では、U方向とV方向の位置を、0〜1の範囲で定義しています。

今回は、どちらも0.2の位置にしています。

これは、GrasshopperのReparameterizeと同様のことをするためです。

u = domainU[0] + u_norm * (domainU[1] - domainU[0])
v = domainV[0] + v_norm * (domainV[1] - domainV[0])

この計算は、「0〜1で指定した割合の値」を、実際のサーフェスのUV範囲へ変換するための計算です。

例として、domainU = (5.0, 15.0) のようなドメイン範囲があるとします。

これは、U方向が5〜15の範囲であることを意味しています。

実際のUV値を直接扱うと、u = 8.245 のようになり、直感的ではありません。

そこで、u_norm = 0.2 のように、0〜1の範囲で考えるようにします。

これは、

  • 0 → 始点側
  • 0.5 → 中央
  • 1 → 終点側

という意味になります。

つまり、u_norm = 0.2 は、「U方向の20%位置」という意味になります。

しかし、SurfaceEvaluate 関数では、実際のUVパラメータ値が必要になります。

実際のUVパラメータ値に戻すための式が、u = domainU[0] + u_norm * (domainU[1] - domainU[0]) になります。

例えば、domainU = (5.0, 15.0) とすると、

この範囲の最小値は 5 、最大値は 15 です。

範囲の長さは、15 - 5 = 10 になります。

もし、u_norm = 0.2 なら、「全体の20%位置」を求めたいことになります。

まず、u_norm * (domainU[1] - domainU[0]) を計算すると、0.2 * (15 - 5) = 2 になります 。

これは、「開始位置から2だけ進んだ位置」という意味です。

ただし、この 2 は「範囲内の移動量」でしかありません。

実際のU値にするには、開始位置 5 を足す必要があります。

u = 5 + 2 = 7 になります。

つまり、u = domainU[0] + u_norm * (domainU[1] - domainU[0]) は、「範囲の始点から、指定割合だけ進んだ位置」を求めている計算です。

srf_eva = rs.SurfaceEvaluate(surface, (u, v), 1)

SurfaceEvaluate 関数では、指定したUV位置のサーフェス上の点座標や方向ベクトルを取得できます。

第1引数にはサーフェスデータ、第2引数にはUV値を指定します。

第3引数に 0 を指定した場合、点情報のみが取得されます。

第3引数に 1 を指定すると、点情報だけでなく、U方向・V方向の接線ベクトルも取得しています。

点、接線ベクトルのように複数データを取得する場合、リストとしてまとまったデータが出力されます。

plane = rs.PlaneFromFrame(srf_eva[0], srf_eva[1], srf_eva[2])

PlaneFromFrame 関数では、点情報と2つのベクトルから、作業平面を作成しています。

第1引数には点データ、第2引数にはx軸のベクトル、第3引数にはy軸のベクトルを指定します。

今回の場合、srf_eva のリストの最初に点データ、2つ目と3つ目にベクトルデータがあります。

そのため、srf_eva[0] では1つ目の点データ、srf_eva[1] では2つ目のベクトルデータ、srf_eva[2] では3つ目のベクトルデータを取得しています。

cylinder = rs.AddCylinder(plane, 5, 1)

AddCylinder 関数で、作成した作業平面上に、円柱を作成しています。

第1引数には作業平面データ、第2引数には高さの数値、第3引数には半径の数値を指定します。

Python 3 Script」の右側の端子名を「surface」に設定するとサーフェスデータ、「plane」に設定すると作業平面データ、「cylinder」に設定すると円柱データがGH上に出力されます。

Comment

Translate »