静止画地図表示範囲の緯度経度を計算する(BingMapsScaleコンポーネントの改善)


※当初のタイトルは「BingMapsScaleコンポーネントの改善」でしたが、本稿の内容はコンポーネントに関しては特定の地図サービスに依存しない計算なので「静止画地図表示範囲の緯度経度を計算する」に変更しました。後半の確認ではBingMapsを使います。

はじめに

次回はマルチポイントのタップに対応したコンポーネントの紹介、と書いていましたが、
以前の記事「PowerAppsでBingMapsを活用する時のお決まり計算をコンポーネントに」で作ったコンポーネント(ここではBingMapsScaleコンポーネントと呼びます)を使っていて、気になる点が出てきました。

  1. コンポーネント内のコントロールと同じコントロール名をアプリ内で使えない。
  2. コンポーネントを使う時、同時に地図の表示範囲を計算することが多い(データを絞り込むため)。
  3. コンポーネントのアウトプットを使うタイミングによっては、初期値が渡されてしまう。

次の記事で使う前に、このうちの1と2を改善しておこうと思います(3を無くす方法は思いついていない)。
前回からの差分しか書いていないので、最初から作るには以下の記事を参照してください。

まずは出来上がりから

前回の記事からの変更点です。

  • コンポーネント名を「cmpBingMapsScale」に変更しました。
  • 先述の1.の課題であるコントロール名の衝突を防ぐために、すべてのコントロールの後ろに「_cmpBMS」を付けました。
  • 地図の表示範囲を出すために、カスタムプロパティの入力項目として Longitude、MapXPixels、MapYPixels(青い部分)、出力項目として MapLatitudeFrom、MapLatitudeTo、MapLongitudeFrom、MapLongitudeTo(赤い部分)を追加しました。

入力項目の設定

以下の3つのカスタムプロパティを設定します。

表示名 名前 プロパティの型 データ型 コメント
Longitude Longitude 入力 数値 地図中央の経度。初期値は任意ですが仮に135とします
MapXPixels MapXPixels 入力 数値 地図の横幅をピクセルで設定します。初期値は仮に400とします
MapYPixels MapYPixels 入力 数値 地図の高さをピクセルで設定します。初期値は仮に300とします

地図範囲の計算

地図範囲を示す緯度経度を計算するために、以下4つのラベルコントロールを追加し、それぞれのTextプロパティに式を設定します。
計算にあたっては、中央(0,0)に1ピクセル使われるため、地図のピクセル数が偶数の場合、マイナス部分のピクセル数を1減らすことにします。
例えば横幅400ピクセルだと、(-199 ~ 200)が範囲となります。

ラベルコントロールの名前 プロパティ名 設定値  コメント
MapLatitudeFrom_cmpBMS Text cmpBingMapsScale.Latitude-LatitudePer1000Pixels_cmpBMS*(RoundUp(MapYPixels_cmpBMS/2,0)-1)/1000 地図の表示範囲の最小の緯度。地図の中心から、高さの半分に相当する度数を引きます。
MapLatitudeTo_cmpBMS Text cmpBingMapsScale.Latitude+LatitudePer1000Pixels_cmpBMS*RoundDown(MapYPixels_cmpBMS/2,0)/1000 地図の表示範囲の最大の緯度。地図の中心から、高さの半分に相当する度数を足します。
MapLongitudeFrom_cmpBMS Text cmpBingMapsScale.Longitude-LongitudePer1000Pixels_cmpBMS*(RoundUp(MapXPixels_cmpBMS/2,0)-1)/1000 地図の表示範囲の最小の経度。地図の中心から、横幅の半分に相当する度数を引きます。
MapLongitudeTo_cmpBMS Text cmpBingMapsScale.Longitude+LongitudePer1000Pixels_cmpBMS*RoundDown(MapXPixels_cmpBMS/2,0)/1000 地図の表示範囲の最大の経度。地図の中心から、横幅の半分に相当する度数を足します。

出力項目の設定

以下の4つのカスタムプロパティを設定します。

表示名 名前 プロパティの型 データ型 コメント
MapLatitudeFrom MapLatitudeFrom 出力 数値 地図の表示範囲の最小の緯度
MapLatitudeTo MapLatitudeTo 出力 数値 地図の表示範囲の最大の緯度
MapLongitudeFrom MapLongitudeFrom 出力 数値 地図の表示範囲の最小の経度
MapLongitudeTo MapLongitudeTo 出力 数値 地図の表示範囲の最大の経度

それぞれのカスタムプロパティに、先程の計算結果を割り当てます。

確認してみよう

確認のために、イメージコントロールを2つ準備し、1つには地図の中心となる緯度経度、もうひとつには地図の緯度経度範囲を指定して、内容を較べてみることにしましょう。表示位置は前記事と同じ東京駅近くの{35.68111701,139.76362492}にします。
それぞれのイメージコントロールのImageプロパティは、以下のような記述になると思います。

Image1.Image
"https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/35.68111701,139.76362492/17?mapSize=600,350&Key=YourAPIKey"
Image2.Image
"https://dev.virtualearth.net/REST/v1/Imagery/Map/Road?zoomLevel=17&mapArea=" & cmpBingMapsScale_1.MapLatitudeFrom & "," & cmpBingMapsScale_1.MapLongitudeFrom & "," & cmpBingMapsScale_1.MapLatitudeTo & "," & cmpBingMapsScale_1.MapLongitudeTo & "&mapSize=600,350&Key=YourAPIKey"


どうやら同じ範囲になっているようです。
(この部分、表示範囲を指定しているのだからZoomLevelが必要ないと思うのですが、外すと表示範囲が一回り大きくなります。4隅の緯度経度を確認する限りzoomLevelを付けた時の表示のほうが正しいので、付けたままにしています)

この範囲を使うことで、元のデータから地図に表示される範囲内にあるレコードを抽出することが出来るようになりました。

最後に

今回はちょっと寄り道して、コンポーネント改善の記事でした。
次回はいよいよタップに対応していきます。