ghPython での、RhinoScriptSyntax と RhinoCommon のパフォーマンス比較

# ghPython での、RhinoScriptSyntax と RhinoCommon のパフォーマンス比較

Grasshopper 上で Python を書くサンプルとして、RhinoScriptSyntax を使っているものをよく見かけるが、RhinoScriptSyntax ではなく、RhinoCommon を使うという方法がある。（そもそも別のモノであるので、互換という意味ではないので、あしからず。）

ご認識があったらすみません。

### 参考記事

[RhinocerosとGrasshopperでPythonを使う方法(Qiita)](https://qiita.com/o-kei/items/cfa3980d88e982eed3f5)

[Rhinoceros / Grasshopperでコーディングしたい人のためのレファレンス参照先(Qiita)](https://qiita.com/jhorikawa_err/items/c450a558af9a0fda82ec)

# RhinoScriptSyntax と RhinoCommmon

RhinoScriptSyntax では、RhinoCommon を Python でラップしているので、早くなる理由が無い。RhinoScriptSyntax の中身を見たければここ。

> C:\Users\NAME\AppData\Roaming\McNeel\Rhinoceros\6.0\Plug-ins\IronPython (XXXX-XXX-XXXX-XXXX)\settings\lib\rhinoscript

参考までに、rs.AddLine() の実装は以下。

```python
### curve.py

def AddLine(start, end):
    """Adds a line curve to the current model.
    Parameters:
      start, end (point|guid) end points of the line
    Returns:
      guid: id of the new curve object
    Example:
      import rhinoscriptsyntax as rs
      start = rs.GetPoint("Start of line")
      if start:
          end = rs.GetPoint("End of line")
          if end: rs.AddLine(start, end)
    See Also:
      CurveEndPoint
      CurveStartPoint
      IsLine
    """
    start = rhutil.coerce3dpoint(start, True)
    end = rhutil.coerce3dpoint(end, True)
    rc = scriptcontext.doc.Objects.AddLine(start, end)
    if rc==System.Guid.Empty: raise Exception("Unable to add line to document")
    scriptcontext.doc.Views.Redraw()
    return rc
```

# パフォーマンス比較

話題がそれたが、ghPython での、RhinoScriptSyntax と RhinoCommon のパフォーマンス比較をざっくり書く。把握できていない関数や引数もおそらく多くあるので厳密ではないです。

```python
#######################################
##  Grasshopper Performance Test     ##
##  RhinoScriptSyntax / RhinoCommon  ##
#######################################


import time
import Rhino.Geometry as rg
import rhinoscriptsyntax as rs


### RhinoScriptSyntax
def center_box_by_rss(cx, cy, cz, w, h, d):
    pl_base = rs.MovePlane(rs.WorldXYPlane(), (cx, cy, cz))
    rc = rs.AddRectangle(pl_base, w, h)
    rc_c = rs.CopyObject(rc)
    rc_mv = rs.MoveObject(rc_c, ((-1)*0.5*w, (-1)*0.5*h, (-1)*0.5*d))
    bx = rs.ExtrudeCurveStraight(rc_mv, (0,0,0), (0,0,d))
    cap_tf = rs.CapPlanarHoles(bx)
    return pl_base, bx


### RhinoCommon
def center_box_by_rg(cx, cy, cz, w, h, d):
    pl_base = rg.Plane.WorldXY
    pl_base.Translate(rg.Vector3d(cx,cy,cz))
    w_i = rg.Interval((-1)*0.5*w, 0.5*w)
    h_i = rg.Interval((-1)*0.5*h, 0.5*h)
    rc = rg.Rectangle3d(pl_base, w_i, h_i)
    rc.Transform(rg.Transform.Translation(0, 0, (-1)*0.5*d))
    rc_curve = rc.ToNurbsCurve()
    bx = rg.Extrusion.Create(rc_curve, d, True)
    return pl_base, bx





COUNT = 1000

########################
time1 = time.time()
########################


### Run RhinoScriptSyntax
pl = []
bx = []
for i in xrange(COUNT):
    p, b = center_box_by_rss((i+1)*3, (i+1)*3 ,(i+1)*3, 1,1,1)
    pl.append(p)
    bx.append(b)


########################
time2 = time.time()
########################


### Run RhinoCommon
pl = []
bx = []
for i in xrange(COUNT):
    p, b = center_box_by_rg((i+1)*3, (i+1)*3 ,(i+1)*3, 1,1,1)
    pl.append(p)
    bx.append(b)


########################
time3 = time.time()
########################



time_rss  = time2 - time1
time_rg  = time3 - time2

print("RhinoScriptSyntax - time : {} sec".format(time_rss))
print("RhinoCommon  - time : {} sec".format(time_rg))

```

結果は以下の通り。環境は、Intel Core i5 第四世代、メモリ8GB

```
RhinoScriptSyntax - time : 1.26507568359 sec
RhinoCommon  - time : 0.0220031738281 sec
```

RhinoCommon のほうが早く、かなりの差がある（RhinoScriptSyntax のほうの実装でパフォーマンスが悪い関数を使ってしまっているいう可能性はある）。コード内の COUNT の値を変えても、この傾向は変わらない。

RhinoScriptSyntax には高級な関数がそろっているため比較的簡単に書けるというメリットがあると思うが、パフォーマンスは落ちてしまうということがわかる。

ほかにも、RhinoCommonと RhinoScriptSyntax に加えて、ghpythonlib という、Grasshopper のコンポーネントを呼び出すという方法もある。これは、csharp で書かれビルド済みのコンポーネントを呼び出しているので、おそらく RhinoScriptSyntax より早いかと（確認はしていません）。


（終わり）