手書きで入力した住所の位置をBing Maps SDKで地図上に表示するには2カ月で160本作った還暦開発者が送る10のアプリ開発ノウハウ(8)(4/5 ページ)

» 2013年12月02日 18時00分 公開
[薬師寺国安,PROJECT KySS]

要素内で、プレス アクションを開始したポインタ デバイスが離された時に発生するイベント(myCanvas_PointerReleasedイベント処理)

 イベントデータを提供するPointerIdが、入力ポインタの一意の識別子と同じである場合の処理だ。

    Private Sub myCanvas_PointerReleased(sender As Object, e As PointerRoutedEventArgs)
        If e.Pointer.PointerId = myPenID Then
            Dim myPointer As PointerPoint = e.GetCurrentPoint(myCanvas)
            myInkManager.ProcessPointerUp(myPointer)
        End If
        myPenID = 0
        e.Handled = True
    End Sub

 GetCurrentPointメソッドで、Canvas内の現在のポインタを取得する。

 InkManagerクラスのProcessPointerUpメソッドで、ポインタの位置と圧力の傾きを処理する。このメソッドは ProcessPointerUpdateメソッドを呼び出した後で呼び出す必要がある。

「文字認識」ボタンをクリックした時の処理(recognizeButton_Clickイベント処理)

 このアプリの肝となる部分だ。手書きで入力した文字の認識を行う

    Private Async Sub recognizeButton_Click(sender As Object, e As RoutedEventArgs) Handles recognizeButton.Click
        backButton.IsEnabled = True
        clearButton.IsEnabled = False
        myFrame.Visibility = Xaml.Visibility.Visible
        Dim myStroke = myInkManager.GetStrokes
        For i As Integer = 0 To myStroke.Count - 1
            myStroke(i).Selected = True
        Next
      ‘ このアプリの肝。「Microsoft 日本語手書き認識エンジン」をデフォルトとする。
        Dim myRecName = "Microsoft 日本語手書き認識エンジン" 
        Dim myRecognizer = myInkManager.GetRecognizers
        For i As Integer = 0 To myRecognizer.Count - 1
            If myRecName = myRecognizer(i).Name Then
                myInkManager.SetDefaultRecognizer(myRecognizer(i))
            End If
        Next
        Dim result As IReadOnlyList(Of InkRecognitionResult) = Await myInkManager.RecognizeAsync(InkRecognitionTarget.All)
        myInkManager.UpdateRecognitionResults(result)
        Dim myAlternate = String.Empty
        For Each myResult In result
            Dim myText = myResult.GetTextCandidates
            myAlternate = myAlternate & " " & myText(0)
            TextBox1.Text = myAlternate
        Next
        Dim myUri As String = String.Format("http://www.geocoding.jp/api/?v=1.1&q={0}", Uri.EscapeDataString(TextBox1.Text))
        Dim myHttpClient As New HttpClient
        Dim myResponse = myHttpClient.GetStringAsync(New Uri(myUri, UriKind.Absolute))
        Dim myContent = myResponse.Result
        Dim xmldoc As XElement = XElement.Parse(myContent)
        myMapPosition.myLatitude = xmldoc.Descendants("coordinate").Elements("lat").Value
        myMapPosition.myLogitude = xmldoc.Descendants("coordinate").Elements("lng").Value
        myMapPosition.myAddress = TextBox1.Text
        myFrame.Navigate(GetType(BingMapsPage), myMapPosition)
        myFrame.SetValue(Canvas.ZIndexProperty, 10)
        backButton.Visibility = Xaml.Visibility.Visible
    End Sub

 まず、非同期処理で行われるので、メソッドの先頭にAsyncを追加する。

 InkManagerのGetStrokesメソッドで、InkManagerの位置を管理するコレクション内の全てのInkStrokeオブジェクトを取得し、変数myStrokeに格納する。InkStrokeのコレクションの数だけ繰り返し処理を行う。すべてのInkStrokeを選択状態にする。

 文字列変数myRecNameを「Microsoft 日本語手書き認識エンジン」で初期化しておく。

 英語の認識エンジンを使用する場合は「Microsoft English (US) Handwriting Recognizer」と指定する。

 InkManagerのGetRecognizersメソッドで、手書き認識エンジンのコレクションを取得する。

 取得したコレクションの数だけ反復処理を行う。変数myRecNameの値が、手書き認識エンジンのコレクションのNameと一致する場合は、その手書き認識エンジンを、SetDefaultRecognizerメソッドで規定値として設定する。「Microsoft 日本語手書き認識エンジン」が規定値に設定される。

 RecognizeAsyncメソッドで、1つまたは複数のInkStrokeオブジェクトに対して手書き認識を実行し、コレクション変数resultで参照しておく。InkRecognitionTarget.Allで、ストロークコレクション内のすべてのストロークを認識エンジンに渡す。UpdateRecognitionResultsメソッドにコレクション変数resultを渡し、潜在的なテキストのコレクションが、手書きの認識からマッチするよう更新する。

 認識された手書きの結果テキストのコレクション内を反復処理しながら、以下の処理を行う。

 InkRecognitionResult.GetTextCandidatesメソッドで、手書き認識と一致する可能性のある候補として識別された文字列のコレクションを取得して、変数myTextに格納する。認識された文字列を非表示としているTextBox1に表示する。

 変数myUriにGeocodingのWeb APIを使用して、以下のように指定する。

String.Format("http://www.geocoding.jp/api/?v=1.1&q={0}", Uri.EscapeDataString(TextBox1.Text))

 「q」には、非表示となっているTextBox1内に表示されている、認識された文字列を渡す。

 このWeb APIは住所から緯度、経度を取得できるWeb APIだ。詳細については下記のURLを参照してほしい。

 HttpClientクラスの新しいインスタンスmyHttpClientオブジェクトを作成する。HttpClientクラスは、URIで識別されるリソースにHTTP要求を送信し、そのリソースからHTTP応答を受信するためのクラスだ。

 HttpClientクラスのGetStringAsyncメソッドで、指定したURIにGET送信し、非同期操作で応答本体を文字列として受け取り、変数myResponseに格納する。返された結果XMLをResultプロパティで受け取り、変数myContentに格納しておく。XElement.Parseメソッドで、文字列として読み込まれたXML(myContent)を読み取る。

 MapPosition構造体のmyLatitudeにcoordinate要素の子要素latの値(緯度)を指定する。myLogitudeにlng要素の値(経度)を指定する。myAddressに非表示となっているTextBoxの値を指定する(認識された住所)。

 FrameのNavigateメソッドで、構造体オブジェクトであるmyMapPositionを引数に、BingMapsPageに遷移する。Frameを前面に出し、backButtonを表示する。

※注意

文字認識には「Microsoft 日本語手書き認識エンジン」を使用しているため、日本語版OS上でしか動作しない。Windowsストアに申請する際は、「日本語版OSでの確認を希望」と明確に書いておく必要がある。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。