Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
Leap Motion実用サンプル(Visual Basic編)

Leap Motion実用サンプル(Visual Basic編)

Leap MotionによるWPFアプリ上のオブジェクトの移動

2013年9月4日

Leap Motionの動くサンプルを実際に作ってみる。今回はWPFの画面上に配置したオブジェクトを、Leap Motionによる操作で移動させるアプリを作成。

  • このエントリーをはてなブックマークに追加

 今回は、画面上に配置したオブジェクトを、Leap Motionによる操作で移動させるデスクトップ・アプリを作成する。さっそく、その開発内容を説明していこう。

まずWPFプロジェクトを作成しよう

 今回のLeap Motionのデスクトップ・アプリは、WPFで作成する。

 これには、Visual Studio 2012(以下、VS 2012)のIDEを起動して、メニューバーから[ファイル]-[新規作成]-[プロジェクト]と選択して、それにより表示される[新しいプロジェクト]ダイアログで「Visual Basic」のテンプレートから「WPF アプリケーション」を選択する(Leap Motionは、.NET Framework 3.5と4.0に対応しているが、.NET Framework 4.5でも動作する。今回のアプリは全て.NET Framework 4.5で作成している。しかし、あくまでも対応しているのは、.NET Framework 3.5と4.0だ。心配な方は、.NET Framework 4.0で作成すると安心だろう)。[名前]欄には、ここでは「SelectedObjectMove」と指定する。

 [ソリューション エクスプローラー]内に「Images」というフォルダーを作成して、4枚の(任意の)画像を配置しておく。

 WPFの基本的な作成手順は、第1回と同じ手順となるので、説明を割愛する。具体的な手順は、第1回の「参照の追加」「プロジェクトのルートに「LeapCSharp.dll」と「Leapd.dll」を追加する」「プロパティを設定する」を参考にしてほしい。

今回のLeap Motionアプリについて

 今回のアプリは、画面上に配置した4枚の画像を、Leap Motionでタッチして、任意の場所に移動するアプリだ(次の画面を参照)。画像が重なっている場合は、選択された画像が一番前面に表示され、移動が可能になる。

Leap Motionで画像を選択して移動できる

画面のレイアウト(MainWindow.xaml)

 前回と同じように、デフォルトでGridコントロールが配置されているのをCanvasコントロールに変更する。その理由は、座標値が取得しやすいからだ。

 XAMLデザイナー画面上で、先ほどのCanvasコントロール上に、Imageコントロールを4個配置する。名前には「Image1」~「Image4」としておく。各ImageコントロールのSourceプロパティに、あらかじめ[ソリューション エクスプローラー]内に作成しておいたImagesフォルダー内の画像を指定する。

 またLeap Motionのタッチ・ポイントを表示させるために、「paintCanvas」という名前のInkPresenterコントロールをCanvasコントロール上に配置する。このInkPresenterコントロールは、どのコントロールよりも一番手前に配置しておく必要がある、レイアウト配置は次のようになる。

各コントロールをレイアウトした結果

名前が「Image1」~「Image4」のImageコントロールを4個配置し、それぞれのSourceプロパティにImagesフォルダー内の画像を指定する。
全てのコントロールの一番前面に「paintCanvas」という名前のInkPresenterコントロールを配置する。この領域にタッチ・ポイントが表示される。

 XAMLデザイナーで上記のレイアウトを行うと、書き出されるXAMLコードはリスト1のようになる。

XAML
<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="1080" Width="1920" WindowState="Maximized">
  <Canvas>
    <Image x:Name="Image1" HorizontalAlignment="Left" Height="240" VerticalAlignment="Top" Width="320" Source="Images/林_01.png" Canvas.Left="91" Canvas.Top="26" />
    <Image x:Name="Image2" HorizontalAlignment="Left" Height="240" VerticalAlignment="Top" Width="320" Source="Images/林_02.png" Canvas.Left="432" Canvas.Top="26" />
    <Image x:Name="Image3" HorizontalAlignment="Left" Height="240" VerticalAlignment="Top" Width="320" Source="Images/林_03.png" Canvas.Left="777" Canvas.Top="26" />
    <Image x:Name="Image4" HorizontalAlignment="Left" Height="240" VerticalAlignment="Top" Width="320" Source="Images/林_04.png" Canvas.Left="1111" Canvas.Top="26" />
    <InkPresenter Name="paintCanvas"/>
  </Canvas>
</Window>
リスト1 書き出されたXAMLコード(MainWindows.xaml)

前回も説明したが、ルートのCanvasコントロールの最後に<InkPresenter>要素が記載されているが、これによりInkPresenterコントロールが最前面に表示されるようになる。

プログラム・コード(MainWindow.xaml.vb)

 では、次にプログラム・コード(MainWindows.xaml.vbファイル)を見ていこう。プログラム・コードも、タッチ処理以外は第1回と基本的に同じ内容となるので、説明を割愛する。まずは第1回の「名前空間の読み込み」「メンバー変数の宣言」「MainWindow_Loadedメソッドの処理」「Updateメソッドの処理」の開発手順を参考にタッチ処理の前までを実装してほしい。相違点として、下記の2点を修正してほしい。

(1)第1回のリスト3にある「Private Message As String」という行を削除して、「Private no As Integer」という行を追加: 今回はメッセージは表示せず、代わりにZインデックス番号を管理する必要があるため。
(2)第1回のリスト4にある「TextBlock1.Foreground = New SolidColorBrush(Colors.White)」という行を削除: 今回はTextBlockコントロールを使わないので。

Updateメソッドの処理(タッチ処理部分)

 第1回でも説明したが、Leap Motionのタッチ処理について簡単に説明しておこう。

 次の図に示すように、Leap Motionでは手前側が「ホバー状態(hovering)」、奥側が「タッチ状態(touching)」を表す。空間の範囲は前後「1」~「-1」となっている。

Leap Motionのタッチ検出イメージ(Leap Motion SDKのAPIドキュメントから引用)
Leap Motionのタッチ検出イメージ(Leap Motion SDKのAPIドキュメントから引用)

 今回のサンプルでホバーの場合は、表示されている円の色をNavyにする。その際、タッチ・ポイントの位置をメンバー変数「x」と「y」に格納する。

 画面に表示されている指の数をleap.Frame.Fingers.Countプロパティで取得して、メンバー変数「FingersCount」に格納しておく。

 具体的には下記のコードのようになる。

Visual Basic
For Each Pointable As Pointable In leap.Frame.Pointables
  ……コード略(前述)……

  ' ホバー状態のときの処理
  If Pointable.TouchDistance > 0 AndAlso Pointable.TouchZone <> Global.Leap.Pointable.Zone.ZONENONE Then
    touchIndicator.Color = Colors.Navy

    ' タッチ・ポイントの位置をメンバー変数「x」と「y」に格納する
    x = touchPoint.X
    y = touchPoint.Y

    ' 表示されている指の本数を取得して、メンバー変数FingersCountに格納しておく
    FingersCount = leap.Frame.Fingers.Count

    ……コード略(続きは後述)……
  End If
Next
リスト8 ホバー時の処理(MainWindow.xaml.vb)

 次に、タッチした際の処理になる。タッチした場合は、表示されている円の色がRedに変わる。

 それと同時に、タッチした各Imageコントロールの座標を取得して、どのImageがタッチされたかを判別する。タッチされたImageによって、メンバー変数「Index」に値を格納する。

 Indexの値によって条件分岐を行う。例えばImage1がタッチされたときは、メンバー変数「Index」は「1」で初期化される。Indexが「1」のとき、Image1のSetValueメソッドで、画像のTopPropertyとLeftPropertyに、タッチ・ポイントのY座標とX座標を指定する。こうすることで、移動するタッチ・ポイントに追従して画像が移動する。選択した画像が前面に表示されるには、Canvas.ZIndexPropertyに1ずつ増加するメンバー変数「no」の値を指定する。こうすることで、選択された画像が前面に表示される。移動している画像の移動をやめるには、Redタッチ・ポイントをNavyまたは、それ以外(Gold)の色に変えればよい。

 具体的には次のコードのようになる。

Visual Basic
If Pointable.TouchDistance > 0 AndAlso Pointable.TouchZone <> Global.Leap.Pointable.Zone.ZONENONE Then
  ……コード略(前述)……
ElseIf Pointable.TouchDistance <= 0 Then

  touchIndicator.Color = Colors.Red

  ' Image1の座標を取得し、メンバー変数「Index」を「1」で初期化する
  If x > Image1.GetValue(Canvas.LeftProperty) And x < Image1.GetValue(Canvas.LeftProperty) + Image1.Width AndAlso y > Image1.GetValue(Canvas.TopProperty) And y < Image1.GetValue(Canvas.TopProperty) + Image1.Height Then
    Index = 1
  End If

  ' Image2の座標を取得し、メンバー変数「Index」を「2」で初期化する
  If x > Image2.GetValue(Canvas.LeftProperty) And x < Image2.GetValue(Canvas.LeftProperty) + Image2.Width AndAlso y > Image2.GetValue(Canvas.TopProperty) And y < Image2.GetValue(Canvas.TopProperty) + Image2.Height Then
    Index = 2
  End If

  ' Image3の座標を取得し、メンバー変数「Index」を「3」で初期化する
  If x > Image3.GetValue(Canvas.LeftProperty) And x < Image3.GetValue(Canvas.LeftProperty) + Image3.Width AndAlso y > Image3.GetValue(Canvas.TopProperty) And y < Image3.GetValue(Canvas.TopProperty) + Image3.Height Then
    Index = 3
  End If

  ' Image4の座標を取得し、メンバー変数「Index」を「4」で初期化する
  If x > Image4.GetValue(Canvas.LeftProperty) And x < Image4.GetValue(Canvas.LeftProperty) + Image4.Width AndAlso y > Image4.GetValue(Canvas.TopProperty) And y < Image4.GetValue(Canvas.TopProperty) + Image4.Height Then
    Index = 4
  End If

  ' 画面上に表示されている指が1本の場合は、メンバー変数「Index」の値で条件分岐を行う。
  ' Indexの値で、各ImageのTopPropertyとLeftPropertyに、タッチ・ポイントのY/X座標を指定する。
  ' ZIndexPropertyにも1ずつ増加するメンバー変数「no」の値を指定する。これで、選択されたImageが前面に表示される。
  If FingersCount = 1 Then
    Select Case Index
      Case 1
        Image1.SetValue(TopProperty, touchPoint.Y)
        Image1.SetValue(LeftProperty, touchPoint.X)
        Image1.SetValue(Canvas.ZIndexProperty, no)
        Exit Select

      Case 2
        Image2.SetValue(TopProperty, touchPoint.Y)
        Image2.SetValue(LeftProperty, touchPoint.X)
        Image2.SetValue(Canvas.ZIndexProperty, no)
        Exit Select

      Case 3
        Image3.SetValue(TopProperty, touchPoint.Y)
        Image3.SetValue(LeftProperty, touchPoint.X)
        Image3.SetValue(Canvas.ZIndexProperty, no)
        Exit Select

      Case 4
        Image4.SetValue(TopProperty, touchPoint.Y)
        Image4.SetValue(LeftProperty, touchPoint.X)
        Image4.SetValue(Canvas.ZIndexProperty, no)
        Exit Select

      Case Else
        Exit Select
    End Select
  End If
  no += 1
  ' タッチ対象外
Else
  touchIndicator.Color = Colors.Gold

  Image1.SetValue(Canvas.ZIndexProperty, 0)
  Image2.SetValue(Canvas.ZIndexProperty, 0)
  Image3.SetValue(Canvas.ZIndexProperty, 0)
  Image4.SetValue(Canvas.ZIndexProperty, 0)
End If
リスト9 タッチしたImageの座標を取得し、メンバー変数「Index」の値を初期化し、そのIndexの値で条件分岐を行う(MainWindow.xaml.vb

 なお、実際にこのサンプルを試す際に、Imageをうまく選択できない場合は、一度、Leap Motionの範囲から指を離して、再度トライするとうまくいく。

 このサンプルのコードは、下記のリンク先よりダウンロードできる*1

  • *1サンプルをダウンロードして動かす場合は、「LeapCSharp.NET4.0.dll」や「LeapCSharp.dll」、「Leap.dll」を読者自身のフォルダー内にあるDLLファイルに指定し直さなければ動かない可能性があるので、動かない場合は再指定していただきたい。

 今回はこれで終わりだ。第1回目もそうであったように、配置したオブジェクトの座標値さえ取得できれば、いろいろな処理を行える。しかし、この方法では、動的に作成したImageオブジェクトには使用できない。

 次回は動的に作成したImageオブジェクトのイベント取得方法を解説する。

 では、また次回の記事でお会いしよう。

※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

Leap Motion実用サンプル(Visual Basic編)
1. オブジェクト(Button)をLeap Motionでタッチして背景色を変化させる

Leap Motionの動くサンプルを実際に作ってみる連載スタート。今回はLeap Motionのタッチ操作で背景色を変化させるWPFアプリをVBで開発する。

Leap Motion実用サンプル(Visual Basic編)
2. 【現在、表示中】≫ Leap MotionによるWPFアプリ上のオブジェクトの移動

Leap Motionの動くサンプルを実際に作ってみる。今回はWPFの画面上に配置したオブジェクトを、Leap Motionによる操作で移動させるアプリを作成。

Leap Motion実用サンプル(Visual Basic編)
3. Leap Motionによる、WPFアプリ上に動的に作成したオブジェクトのイベント処理

Leap Motionの動くサンプルを実際に作ってみる。今回はWPFの画面上に動的に作成したオブジェクトを、Leap Motionによる操作でアニメーションさせるアプリを作成。

Leap Motion実用サンプル(Visual Basic編)
4. Leap Motionでパーティクルを使用して軌跡に無数の円や画像を表示する

さまざまな色の粒子(パーティクル)が、Leap Motionによる手の指の動きに合わせて飛び散りながら追従するサンプル・アプリを作ってみよう。

Leap Motion実用サンプル(Visual Basic編)
5. Leap MotionでBing Mapsを扱う

リスト内に表示された住所項目をLeap Motionによりタッチすることで、Web上のサービス「Bing Maps」での地図検索を行うサンプル・アプリを作ってみよう。

サイトからのお知らせ

Twitterでつぶやこう!