この記事で扱っていること
- ピクチャに角度指定で描画する方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
LabVIEWで図を描くための機能としては、ピクチャ関数を使用してピクチャ表示器に線や円を書くように関数を組む方法があります。
ただ、LabVIEWの関数で線を引くための関数を使用する場合、現在のペンの位置からどの座標位置に対して引くか、という「点と点」の指定による引き方しかできません。
しかし、例えば幾何模様を表現する際には、角度による指定を行えた方が便利なことが多いです。
イメージとしては、というかこの記事でベースにしている考えとしては、Pythonのモジュールの一つであるTurtleモジュールを使用するような方法が作図に便利だ、ということで、LabVIEWでTurtleモジュールの一通りの機能を実現する方法を考えました。
PythonのTurtleモジュールを知らなくても、実際に幾何模様を描いた例を紹介するので、「このような図形が(比較的)簡単に書けるようになる」ものとして参考にしてもらえればと思います。
どんな結果になるか
LabVIEWで図形を描くのに用いる機能としてピクチャが挙げられます。
ピクチャを扱う関数を駆使することにより、ピクチャ表示器上に様々な幾何模様を描くことができます。
本記事で紹介する方法を使えば、以下の図のような幾何模様が(比較的)簡単に書けます。
上の図の右下、三角形が6つ並んだものは、一見簡単そうですが、座標に依る指定だけでランダムな位置に三角形を描画するのは結構大変だと思います。
プログラムの構造
LabVIEWに入っている関数をそのまま使用するだけでは、上で示した結果図のような図形を描くのは相当難しいと思います。
なぜなら、LabVIEWに入っているピクチャ用の関数は基本的に座標を指定して線やポイント、円を書くことになり、引きたい線分の座標を計算しないと意図したとおりの結果が得られにくいからです。
一方、Pythonのモジュールの一つであるTurtleモジュールは、「今向いている方向」に対していくつ進む、時計回りに何度向きを変える、といった、角度と長さを基準にした命令を並べて描画ができます。
場合によると思いますが、角度と長さを基準にした命令の方が直感的に分かりやすいと思います。
ここでは、Turtleモジュールに含まれる個々の機能(メソッド)をLabVIEWで実現する方法を紹介します。
いわゆるモジュールのプロパティにあたる部分をまずはタイプ定義したクラスタで用意しておきます。
このクラスタにはvectorというクラスタを入れており、そこには「x」に1を、「y」に0を、それぞれ入れてデフォルト設定(各制御器を右クリックして「データ操作」から「現在の値をデフォルトに設定」)しておきます。
このvectorが「今向いている方向」を指し示し、デフォルトでは(1,0)というベクトル(座標系で言えばx軸に平行にx軸の正方向に向いている)を持つという状態にしておきます。
タイプ定義にしておくことは必須ではないですが、後からこのクラスタにパラメタを追加したいとなった場合にタイプ定義していないと機能の拡張が面倒になるのでタイプ定義しておくことをオススメします。
このクラスタをこれから紹介する各関数間で渡して、図形を書けるようにしていきます。
まずはforwardメソッドです。
長さの部分に入力することで、「今向いている方向」に対してその長さの分だけ直線を引きます。
これ以降はフロントパネルの紹介は省略します(どれも見た目は同じで、「長さ」などのパラメタを変更する制御器などだけの違いなので)。
ブロックダイアグラムは以下のようにしておきます。
次にbackwardメソッドです。
Forwardとは違い、反対向きのベクトル方向に長さの分だけ直線を引くことになります。
次はleftメソッドです。
今向いている方向に対して、反時計周りに何度、向いている方向を回転させるかを指定します。
次はrightメソッドです。
left.viの逆で、今向いている方向に対して時計回りにvectorを回転させます。
left.viとは、「角度」の入力に対して「反転」をさせるかどうかの違いがあります。
次はpendownメソッドです。
penというのは、ピクチャに描画を行うためのペンだと考えてください。
これがピクチャという紙の上に「落とされた」状態をpendown状態とします。
つまり、既に紹介したforward.viやbackward.viは、pendown状態じゃないと描画を行いません。
次はpenupメソッドです。
これは、pendownの逆で、ペンをピクチャという紙から上げる(up)させることとなります。
ペンが紙から離れているので、penup状態では、forwardやbackwardの関数を使用しても、描画は行われない、ということになります。
pendownと合わせて使用することで、例えばペンの移動は行うけれども描画はしたくないなどといった場合に、penupしておいてペンの移動が完了したらpendownさせて再び描画を行う、ということができます。
次はcircleメソッドです。
円を描くのですが、その円の中心は、今向いている方向とは垂直で、「左手方向」になります。
円を描くという機能自体は元々「円を半径で描画」関数でできますが、この関数をそのまま用いると、今向いている方向を反映させた状態では書けません。
なので、vectorに対して法線方向のベクトルを求め、これを指定した半径の長さ倍して円の中心を決めるといった処理を行っています。
少し細かいですが、配線を間違えないように注意してください。
ここまでで一通り準備はそろいました。
ここからは、補助的な役割をする関数を紹介します。
まずはgetangleメソッドです。
現在の向いている方向の角度を、x軸の正の方向から考えた角度で表します。
例えばy軸と並行で正の方向に向いているのであれば「90」となります。
次はgetpositionメソッドです。
現在の座標位置を表します。
次はdistanceメソッドです。
現在の位置と、指定した位置の間の距離を測ります。
2点間の距離を求めるということで、三平方の定理を使用しています。
次はpensizeメソッドです。
ペンで描画する際の線の太さを指定します。
次はpencolorメソッドです。
ペンの色を指定します。
今回は、列挙体を使用し、ユーザーがカラーボックス定数(下の図のcolorとなっているU32の端子)から選ぶ「任意入力」以外に、予め色を定数で定義しておいてそれぞれに「黒」とか「赤」といった項目を割り当てています。
次はsetheadingメソッドです。
leftやrightと違い、今向いている方向とは関係なく、指定した角度を向きます。
この角度は、x軸の正の方向から考えた角度となります。
setheading.viのケースストラクチャの中身は以下を参考にしてください。
次はsetpositionメソッドです。
座標を指定して描画する、ということで、LabVIEWで元々標準的に描画をしていたのと同じ感覚で描画する際に使用します。
次はteleportメソッドです。
こちらはペンの移動だけ行います。
penup状態だろうとpendown状態だろうと関係なくペンの移動をさせ、描画は行いません。
他の関数を使用する前に、まず最初のペンの位置を座標で指定する際に使用するイメージです。
次はtowardsメソッドです。
今の座標に対して、目標の座標を入力することで、それらの座標間を線で結んだときの、x軸に対する角度を計算しています。
PythonのTurtleモジュールにあってここで紹介していないメソッドについても大体は実装可能と思います。
ただ、上記で紹介したメソッドがあれば多くの場合事足りるかと思うので、紹介はここまでにします。
関数の使用例
それでは、上で用意した各関数を使用して図形を描く際の例を紹介していきます。
まずは、三角形が渦を巻きながら大きくなっていくような描画です。
Forループを使用して、長さを変えていくのがポイントですね。
くるくると回転するような図形の描画は、left.viなどで中途半端な角度分回転させるとできます。
色の指定をループごとに行わせることで、鮮やかな表現もできます。
直線の真ん中に円を書く、ということを90度ずつ回転させれば直線同士が最後は閉じて正方形になり、それぞれの辺に円があらわれます。
次は三平方の定理の証明にも使われる図形です。
少しプログラムが長いので前半部分を書いています。
このプログラムの性質上、演算処理を行って得られるangleという数値表示器の値は必ず90になります。
最後に、バラバラな三角形を任意の角度や長さで描いています。
「2辺と間の成す角」がわかれば三角形は一意に決まるので、towards.viやdistance.viを使用することで、乱数的に生成された辺の長さや角度があっても残りの辺の長さを決めることができます。
draw_triangle.viは以下を参考にしてみてください。
本記事では、ピクチャに角度指定で線を書く方法を紹介しました。
実際のアプリケーションとしてこうした幾何模様を描くことは少ないかもしれませんが、何か特定のデータを図示する際に角度で指定する方法を知っておくことで、LabVIEWの標準関数を単に組み合わせるだけでは表現が難しい描画が簡単にできるかもしれません。
あるいは、単に色々な幾何模様で「遊ぶ」ことも面白いと思います。
ここまで読んでいただきありがとうございました。
コメント