LoginSignup
4
9

More than 3 years have passed since last update.

PythonでRhinocerosのコマンドを作成する。

Posted at

はじめに

Qitaはプログラムを書く際に参考にさせて頂いていましたが投稿自体は初です。
Rhinoceros上でのPython使用に関する記事はあまりないのと自身のメモ代わりとして今後は投稿していこうと思います。

いまは学生でして、普段はRhinoとPythonでろくでもないものを制作しています。そのへんのことも後々記事にできればと。

概要

さて今回はPythonを使用してRhinoで使用できるコマンドを作成していく方法です。
作成する機能は同一のCurveの位置を合わせるコマンド。(機能はサンプルなので。。。必要にかられて僕が作成しているものです。)
OSはwindows10
RhinoのバージョンはRhino6です。

EditPythonScriptについて

まずはRhinoのコマンドラインにEditPythonScriptと打ち込みEnterを押します。

すると以下のような画面が表示されるかと思います。
スクリーンショット (6).png

Editer上部のタブのファイルマークをクリック。
どの種類のFileを作成するか聞かれますのでCommandをクリックします。
スクリーンショット (7).png

Command NameとPlug-Inの名前を聞かれますので作成する機能に合わせたコマンドの名前と作成するコマンドを格納するプラグインの名前を入力。
今回はCommandNameとしてCrvFitMove、PlugInとしてSampleと入力します。

余談ですが、コマンドを作成するのではなく、Pythonコードを実行する形でRhinoになにか作成したい場合はEmpty Scriptを選択します。(他にもPycharmなどで作成したPythonファイルを開いて実行することももちろん可能です。この辺も後々記事に書いていこうと思います。)

さて、ここまでがEditPythonScriptのEditorの設定の話です。
続いて実際にコードを記述しコマンドを制作していこうと思います。

Pythonによるコードの記述。rhinoscriptsyntaxについて。

現在うまく行っていれば画面に次のようなコードが表示されていると思います。
スクリーンショット (8).png

順にコードの説明をしていきます。
1行目の
import rhinoscriptsyntx as rs
はrhinoscriptsyntaxというパッケージをrsという収縮名でインポートしますと宣言しています。(この辺はPython側のはなしなので。。。わからない方はPythonを少し学習しましょう。)

ちなみにrhinoscriptsyntaxの中にはRhinoのオブジェクトをいろいろと操作できるメソッドが詰まっています。
基本的にはRhinoのコマンドで実行できることはほぼrhinoscriptsyntaxで可能と考えてもらって大丈夫です。(rhinoscriptsyntaxに関しましても時間があれば記事にしますね。)
ほんとに色々なことをしようと思ったり、プログラムの実行速度のことを考えたりするとimport RhinoでインポートできるRhinoCommonを使用するほうが効率いいです。

話がそれました。
3行目のダブルクオーテーションで囲まれている部分がコマンドの名前になります。

7行目から20行目は関数定義部分です。
ここに実装したいコマンドの機能を記述していくことになります。

さて、次は実際にコードを書いていきます。

コマンド作成!

今回の記事はRhinoで呼び出せるコマンドの実装が目的ですのでコマンドの実際の機能について、またコードの中身に関しての説明は省かさせていただきます。ご了承ください。
今回、def内は次のように記述しました。


# -*- coding:utf-8 -*-

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext
import math

__commandname__ = "CrvFitMove"

def RunCommand( is_interactive ):
    print  __commandname__

    # 一致させたいcrvを取得
    base_crv = rs.GetObject('select base crv', rs.filter.curve)
    if not base_crv:
        return 1

    # 一致させるcrvを取得
    ori_fit_crv = rs.GetObject('select fit crv', rs.filter.curve)
    if not ori_fit_crv:
        return 1

    # RhinoCommonで扱うRhino.Geometryに変換。これしないとRhinoCommonのメソッド使用できない。
    base_crv = rs.coercecurve(base_crv)
    fit_crv = rs.coercecurve(ori_fit_crv)

    # 両端点と中点(パラメータ上の)を取得
    b_start_p = base_crv.PointAtStart
    b_end_p = base_crv.PointAtEnd

    bool, curve_parameter = base_crv.NormalizedLengthParameter(0.5)
    b_mid_p = base_crv.PointAt(curve_parameter)

    f_start_p = fit_crv.PointAtStart
    f_end_p = fit_crv.PointAtEnd

    # Moveで端点をあわせる。
    vec_move = b_start_p - f_start_p
    xf = Rhino.Geometry.Transform.Translation(vec_move)
    fit_crv.Transform(xf)

    # ベクトルを用いてMoveとRotateを行っている。
    f_end_p = fit_crv.PointAtEnd
    f_start_p = fit_crv.PointAtStart

    r_vec1 = f_end_p - f_start_p
    r_vec2 = b_end_p - f_start_p

    cross_vec = Rhino.Geometry.Vector3d.CrossProduct(r_vec1, r_vec2)
    degree = Rhino.Geometry.Vector3d.VectorAngle(r_vec1, r_vec2, cross_vec)

    xf = Rhino.Geometry.Transform.Rotation(degree, cross_vec, b_start_p)
    fit_crv.Transform(xf)

    bool, f_crv_para = fit_crv.NormalizedLengthParameter(0.5)
    bool, b_crv_para = base_crv.NormalizedLengthParameter(0.5)
    f_mid_p = fit_crv.PointAt(f_crv_para)
    b_mid_p = base_crv.PointAt(b_crv_para)


    axis_crv = Rhino.Geometry.Line(b_start_p, b_end_p)
    a_crv_para = axis_crv.ClosestParameter(b_mid_p)
    a_mid_p = axis_crv.PointAt(a_crv_para)
    a_start_p = axis_crv.PointAt(0)
    a_end_p = axis_crv.PointAt(1)

    r_vec1 = f_mid_p - a_mid_p
    r_vec2 = b_mid_p - a_mid_p
    cross_vec = Rhino.Geometry.Vector3d.CrossProduct(r_vec1, r_vec2)
    degree = Rhino.Geometry.Vector3d.VectorAngle(r_vec1, r_vec2, cross_vec)

    xf = Rhino.Geometry.Transform.Rotation(degree, cross_vec, a_mid_p)
    fit_crv.Transform(xf)

    # 移動させたCurveをデリート。Rhino.GeometryをRhinoに描画(型変換している)
    rs.DeleteObject(ori_fit_crv)
    scriptcontext.doc.Objects.AddCurve(fit_crv)

    return 0

結局のところRhinoCommonを使用して記述してしまいましたが、結果的にこちらのほうが良いと思います。rhinoscriptsyntaxはメソッドを使用するたびにRhinoに描画されてしまいますのでどうしても実行速度が遅くなってしまいます。一方でRhinoCommonは明示的に描画しないとRhinoに描画されない性質を持っています。

最後に作成したファイルをCtrl+Cかなにかで上書き保存しRhinoのコマンドラインにCrvFitMoveと入力すると作成したコマンドが実行されると思います。
スクリーンショット (10).png

実行し、選択すると。。。
スクリーンショット (13).png

こう、重なります。。わかりにくいですが。。。笑

終わりに

後半は駆け足になってしまいましたが、いかがでしたでしょうか。
Pythonを使用しRhinoをカスタマイズすることで可能なことは多いと思います。
僕自身も色々と試しながら記事を書いていこうと思っていますので皆さんよろしくお願いいたします。
最後までご拝読いただきありがとうございました。

4
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
9