フリーハンドで書いた住所を認識してBing Map上に表示する

Bing Maps Keyの取得方法
Bing Mapsを使用するには下記URLのBing Maps Account Centerに行って専用のライセンスキーを取得する必要があります。
→ Bing Maps Account Center
Windows Live IDを持っている方はSign Inします。持ってない方はCreateからWindows Live IDを作成してSign Inしてください。筆者はSign Inから入ります(図11)。
表示される画面の左にあるCreate or view keysをクリックします(図12)。
Create keyの画面が表示されますので、必要な項目を入力してSubmitしてください。筆者はすでにキーを持っていますので、下記にキーが表示されています(図13)。Key typeはBasicとなっています。BasicでPublic websiteの場合は、「アプリケーションが制限なしに利用され、500,000 のトランザクションの任意の種類の 12 ヶ月の期間内を超えない、公開ウェブサイトです。」となっているようです。
リスト2のレイアウトは図14のようになります。
次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbをダブルクリックしてリスト3のコードを記述します。前回の「フリーハンドの文字を認識する」と同じコードと解説は省略しています。
ロジックコードを記述する
リスト3 (MainWindow.xaml.vb)
~コード略~
MapPosition構造体で、文字列型のmyLatitude、myLogitude、myAddressを定義しておきます。
Public Structure MapPosition Public myLatitude As String Public myLogitude As String Public myAddress As String End Structure
MapPosition構造体のメンバ変数myMapPositionを宣言します。
Dim myMapPosition As MapPosition
[住所検索]ボタンをクリックした時の処理
[戻る]ボタンの使用を可能にします。[クリア]ボタンの使用を不可とします。Frameを表示します。
InkManagerのGetStrokesメソッドで、InkManager を管理するコレクション内のすべての InkStroke オブジェクトを取得し、変数myStrokeに格納します。InkStrokeのコレクションの数だけ繰り返し処理を行います。すべてのInkStrokeを選択状態にします。
文字列変数myRecNameを「Microsoft 日本語手書き認識エンジン」と初期化しておきます。
英語の認識エンジンを使用する場合は「Microsoft English (US) Handwriting Recognizer」と指定します。
InkManagerのGetRecognizersメソッドで、手書き認識エンジンのコレクションを取得します。
取得したコレクションの数だけ反復処理を行います。変数myRecNameの値が、手書き認識エンジンのコレクションのNameと一致する場合は、その手書き認識エンジンを、SetDefaultRecognizerメソッドで規定値として設定します。「Microsoft 日本語手書き認識エンジン」が規定値に設定されます。
RecognizeAsyncメソッドで一つ、または複数のInkStrokeオブジェクトの手書き文字認識を実行します。InkRecognitionTarget.Allで、ストロークコレクション内のすべてのストロークを認識エンジンに渡します。UpdateRecognitionResultsメソッドで、潜在的なテキストのコレクションが、手書きの認識からマッチするよう更新します。
認識された手書きの結果テキストのコレクション内を反復処理しながら、以下の処理を行います。
InkRecognitionResult.GetTextCandidatesメソッドで、手書き文字認識と一致する可能性のある候補として識別された、文字列のコレクションを取得して、変数myTextに格納します。認識された文字列を非表示となっているTextBoxに表示します。画面上では見えません。
非同期処理で行われますので、メソッドの先頭にAsyncを追加します。
非表示となっているTextBoxの値を引数に、文字列としての
String.Format("http://www.geocoding.jp/api/?v=1.1&q={0}", TextBox1.Text)
を作成して変数myUriに格納しておきます。GeocodingのWeb APIを使用しています。Geocodingについては、下記のサイトを参照してください。
→ Geocoding
HttpClientクラスの新しいインスタンスmyHttpClientオブジェクトを作成します。HttpClientクラスは、URI で識別されるリソースに HTTP 要求を送信し、そのリソースから HTTP 応答を受信するためのクラスです。
HttpClientクラスのGetStringAsyncメソッドで、指定したURIにGET送信し、非同期操作で応答本体を文字列として受け取り、変数myResponseに格納します。返された結果XMLをResultプロパティで受け取り、変数myContentに格納しておきます。XElement.Parseメソッドで、文字列として読み込まれたXML(myContent)を読み取ります。
MapPosition構造体のmyLatitudeに
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
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}", 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)
End Sub
[戻る]ボタンがクリックされた時の処理
Frameを非表示にします。[クリア]ボタンの使用を可能にします。Frameを背面に移動します。
Private Sub backButton_Click(sender As Object, e As RoutedEventArgs) Handles backButton.Click
myFrame.Visibility = Xaml.Visibility.Collapsed
clearButton.IsEnabled = True
myFrame.SetValue(Canvas.ZIndexProperty, 0)
End Sub
次に、ソリューションエクスプローラー内のBingMapsPage.xamlを展開して表示される、BingMapsPage.xaml.vbをダブルクリックしてリスト4のコードを記述します。
ロジックコードを記述する
リスト4 (BingMapsPage.xaml.vb)
Option Strict On
Bing Mapsに関するクラスの含まれるBing.Maps名前空間をインポートします。
Imports Bing.Maps
コア システムの機能とその UI についてのランタイム情報にアクセスするアプリケーションを提供するクラスの含まれる、Windows.UI名前空間をインポートします。描く円の色を指定する場合等に、この名前空間に含まれるクラスを使用します。
Imports Windows.UI
図形に関するクラスの含まれる、Windows.UI.Xaml.Shapes名前空間をインポートします。
Imports Windows.UI.Xaml.Shapes Public NotInheritable Class BingMapsPage Inherits Page
ページがアクティブになった時の処理
MainMageから送られた値(e.Parameter)をMapPosition構造体に変換し、myResultで参照します。
myLatitude変数に構造体のmyLatitudeの値(緯度)を格納します。myLongitude変数に構造体のmyLongitudeの値(経度)を格納します。myAddress変数に構造体のmyAddressの値(住所)を格納します。
MapのCenterプロパティにDouble型に変換したmyLatitudeとmyLongitudeの値を指定します。addressTextBoxに住所を表示します。地図のタイプをBirdseyeに指定しておきます。Birdseyeとは読んで字のごとく鳥の目線で見た地図のモードといったところでしょうか。
新しいEllipseのインスタンスmyEllipseオブジェクトを作成します。FillプロパティにCrimsonを指定し、Crimson色で塗りつぶします。枠線の太さを3に指定し、枠線の色をNavyに指定します。WidthとHeightは30とします。直径30pixelの円が描かれます。
新しいStackPanelのインスタンスmyStackpanelオブジェクトを作成します。Marginに5を指定して余白を設けます。背景色にNavyを指定します。初期状態ではmyStackPanelオブジェクトを非表示としておきます。
次に、TextBlockの新しいインスタンスmyTextBlockオブジェクトを作成します。文字色をRedに指定します。文字サイズは24、TextプロパティにはmyAddress変数の値を指定します。myStackPanelオブジェクトにmyTextBlockオブジェクトを追加します。
MapLayerクラスのSetPositionメソッドで、マップレイヤー内に要素の位置を設定します。この場合、myLatitudeとmyLongitudeの位置に円をセットします。MapLayerクラスは、地図上の要素の位置を保持しているマップレイヤーを表すクラスです。MapにAddメソッドでmyEllipseオブジェクトを追加します。
同様に、MapLayerクラスのSetPositionメソッドで、マップレイヤー内に要素の位置を設定します。この場合、myLatitudeとmyLongitudeの位置にStackPanelをセットします。MapにAddメソッドでmyStackPanelオブジェクトを追加します。
円がタップされた時はmyStackPanelオブジェクトを表示します。住所の書かれたTextBlockが表示されます。myStackPanelオブジェクトがタップされた時は、myStackPanelオブジェクトを非表示にします。住所の表示されたTextBlockも非表示になります。
Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
Dim myResult = DirectCast(e.Parameter, MapPosition)
Dim myLatitude = myResult.myLatitude
Dim myLongitude = myResult.myLogitude
Dim myAddress = myResult.myAddress
myMap.Center = New Location(CDbl(myLatitude), CDbl(myLongitude))
addressTextBox.Text = myAddress
myMap.MapType = MapType.Birdseye
Dim myEllipse As New Ellipse
With myEllipse
.Fill = New SolidColorBrush(Colors.Crimson)
.StrokeThickness = 3
.Stroke = New SolidColorBrush(Colors.Navy)
.Width = 30
.Height = 30
End With
Dim myStackPanel As New StackPanel
myStackPanel.Margin = New Thickness(5)
myStackPanel.Background = New SolidColorBrush(Colors.Navy)
myStackPanel.Visibility = Xaml.Visibility.Collapsed
Dim myTextBlock As New TextBlock
myTextBlock.Foreground = New SolidColorBrush(Colors.Red)
myTextBlock.FontSize = 24
myTextBlock.Text = myAddress
myStackPanel.Children.Add(myTextBlock)
MapLayer.SetPosition(myEllipse, New Location(CDbl(myLatitude), CDbl(myLongitude)))
myMap.Children.Add(myEllipse)
MapLayer.SetPosition(myStackPanel, New Location(CDbl(myLatitude), CDbl(myLongitude)))
myMap.Children.Add(myStackPanel)
AddHandler myEllipse.Tapped, Sub()
myStackPanel.Visibility = Xaml.Visibility.Visible
End Sub
AddHandler myStackPanel.Tapped, Sub()
myStackPanel.Visibility = Xaml.Visibility.Collapsed
End Sub
End Sub
End Class
今回はここまでです。ありがとうございました。
フリーハンドで住所を書いてBing Map上に表示するサンプルアプリ
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Bing Maps上に地震の震源地を表示するプログラムを作る
- APIを使って土地の公示価格を調べるプログラムを作る
- 場所と写真を記録するプログラムを作って思い出のシーンを保存しよう
- Bing Maps上の好きな場所をマークして情報を表示するプログラムを作る
- Yahoo!ローカルサーチAPIを使って地図上にランドマークを表示させるプログラムを作る
- 自分の現在位置を取得して表示するサンプルプログラム
- 写真と現在位置を入れた画像日記アプリを作る
- 現在位置近くの病院を素早く検索するサンプルプログラム
- 現在位置の近くにある宿を検索するサンプルプログラム
- キャラクターが声で天気予報を教えてくれるアプリを作る






