地図へのタイル画像のオーバーレイ
重要
Bing Maps for Enterprise サービスの提供終了
Windows.Services.Maps 名前空間の UWP MapControlおよびマップ サービスは、Bing Maps に依存します。 Bing Maps for Enterprise は非推奨となり、廃止されます。その時点で、MapControl とサービスはデータを受信しなくなります。
詳細については、 Bing Maps デベロッパー センター および Bing Maps のドキュメントを参照してください。
Note
MapControl とマップ サービスには、MapServiceToken と呼ばれるマップ認証キーが必要です。 マップ認証キーを取得して設定する方法について詳しくは、「マップ認証キーの要求」をご覧ください。
タイル ソースを使って、地図上にサード パーティ製タイルまたはカスタム タイル画像をオーバーレイします。 タイル ソースを使って、気象データ、人口データ、地質データなどの特殊な情報をオーバーレイすることや、既定の地図を完全に置き換えることができます。
タイルイメージの概要
Bing Maps などのマップ サービスでは、マップを四角形のタイルに切り取り、すばやく取得して表示できます。 これらのタイルは 256 ピクセル x 256 ピクセルのサイズで、複数の詳細レベルで事前にレンダリングされます。 多くのサードパーティ サービスでは、タイルに切り取られたマップ ベースのデータも提供されます。 タイル ソースを使用してサードパーティ製のタイルを取得するか、独自のカスタム タイルを作成し、 MapControl に表示されるマップ上にオーバーレイします。
タイル ソースを使用する場合、個々のタイルを要求したり配置したりするコードを記述する必要はありません。 MapControlは必要に応じてタイルを要求します。 各要求では、個々のタイルの X 座標と Y 座標とズーム レベルを指定します。 UriFormatString プロパティのタイルを取得するために使用する URI またはファイル名の形式を指定するだけです。 つまり、ベース URI またはファイル名に置き換え可能なパラメーターを挿入して、X 座標と Y 座標を渡す場所と各タイルのズーム レベルを示します。
X 座標と Y 座標の置換可能なパラメーターとズーム レベルを示す、HttpMapTileDataSource の UriFormatString プロパティの例を次に示します。
http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}
(X 座標と Y 座標は、指定された詳細レベルでの世界地図内の個々のタイルの位置を表します。タイル番号システムは、マップの左上隅にある {0, 0} から始まります。たとえば、{1, 2} のタイルは、タイルのグリッドの 3 行目の 2 番目の列にあります)。
マッピング サービスで使用されるタイル システムの詳細については、「 Bing マップ タイル システム」を参照してください。
タイル ソースからタイルをオーバーレイする
MapTileDataSource を使用して、タイル ソースのタイル イメージをマップ上にオーバーレイします。
MapTileDataSource から継承する 3 つのタイル データ ソース クラスのいずれかをインスタンス化します。
ベース URI またはファイル名に置き換え可能なパラメーターを挿入してタイルを要求するために使用する UriFormatString を構成します。
次の例では、 HttpMapTileDataSource をインスタンス化します。 この例では、HttpMapTileDataSource のコンストラクターのUriFormatStringの値を指定します。
HttpMapTileDataSource dataSource = new HttpMapTileDataSource( "http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}");
MapTileSource をインスタンス化して構成します。 前の手順で構成したMapTileDataSourceを、MapTileSourceのDataSourceとして指定します。
次の例では、MapTileSource のコンストラクターで DataSource を指定します。
MapTileSource tileSource = new MapTileSource(dataSource);
タイルを表示する条件は、 MapTileSource のプロパティを使用して制限できます。
- Bounds プロパティの値を指定して、特定の地理的領域内でのみタイルを表示します。
- ZoomLevelRange プロパティの値を指定して、特定の詳細レベルでのみタイルを表示します。
必要に応じて、タイルの読み込みまたは表示に影響する MapTileSource の他のプロパティ ( Layer、 AllowOverstretch、 IsRetryEnabled、 IsTransparencyEnabled など) を構成。
MapTileSourceを MapControl の TileSources コレクションに追加します。
MapControl1.TileSources.Add(tileSource);
Web サービスからタイルをオーバーレイする
HttpMapTileDataSource を使用して、Web サービスから取得したタイルイメージをオーバーレイします。
HttpMapTileDataSource をインスタンス化します。
Web サービスが期待する URI の形式を、 UriFormatString プロパティの値として指定します。 この値を作成するには、ベース URI に置き換え可能なパラメーターを挿入します。 たとえば、次のコード サンプルでは、 UriFormatString の値は次のようになります。
http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}
Web サービスは、置換可能なパラメーター {x}、{y}、および {zoomlevel} を含む URI をサポートする必要があります。 ほとんどの Web サービス (Nokia、Bing、Google など) では、この形式の URI がサポートされています。 Web サービスで、 UriFormatString プロパティで使用できない追加の引数が必要な場合は、カスタム URI を作成する必要があります。 UriRequested イベントを処理して、カスタム URI を作成して返します。 詳細については、このトピックで後述する カスタム URI の作成 セクションを参照してください。
次に、 Tiled イメージの概要で前述した残りの手順に従います。
次の例では、架空の Web サービスのタイルを北米のマップにオーバーレイします。 UriFormatString の値は、HttpMapTileDataSource のコンストラクターで指定します。 この例では、タイルはオプションの Bounds プロパティで指定された地理的境界内にのみ表示されます。
private void AddHttpMapTileSource()
{
// Create the bounding box in which the tiles are displayed.
// This example represents North America.
BasicGeoposition northWestCorner =
new BasicGeoposition() { Latitude = 48.38544, Longitude = -124.667360 };
BasicGeoposition southEastCorner =
new BasicGeoposition() { Latitude = 25.26954, Longitude = -80.30182 };
GeoboundingBox boundingBox = new GeoboundingBox(northWestCorner, southEastCorner);
// Create an HTTP data source.
// This example retrieves tiles from a fictitious web service.
HttpMapTileDataSource dataSource = new HttpMapTileDataSource(
"http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}");
// Optionally, add custom HTTP headers if the web service requires them.
dataSource.AdditionalRequestHeaders.Add("header name", "header value");
// Create a tile source and add it to the Map control.
MapTileSource tileSource = new MapTileSource(dataSource);
tileSource.Bounds = boundingBox;
MapControl1.TileSources.Add(tileSource);
}
...
#include <winrt/Windows.Devices.Geolocation.h>
#include <winrt/Windows.UI.Xaml.Controls.Maps.h>
...
void MainPage::AddHttpMapTileSource()
{
Windows::Devices::Geolocation::BasicGeoposition northWest{ 48.38544, -124.667360 };
Windows::Devices::Geolocation::BasicGeoposition southEast{ 25.26954, -80.30182 };
Windows::Devices::Geolocation::GeoboundingBox boundingBox{ northWest, southEast };
Windows::UI::Xaml::Controls::Maps::HttpMapTileDataSource dataSource{
L"http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}" };
dataSource.AdditionalRequestHeaders().Insert(L"header name", L"header value");
Windows::UI::Xaml::Controls::Maps::MapTileSource tileSource{ dataSource };
tileSource.Bounds(boundingBox);
MapControl1().TileSources().Append(tileSource);
}
...
void MainPage::AddHttpMapTileSource()
{
BasicGeoposition northWest = { 48.38544, -124.667360 };
BasicGeoposition southEast = { 25.26954, -80.30182 };
GeoboundingBox^ boundingBox = ref new GeoboundingBox(northWest, southEast);
auto dataSource = ref new Windows::UI::Xaml::Controls::Maps::HttpMapTileDataSource(
"http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}");
dataSource->AdditionalRequestHeaders->Insert("header name", "header value");
auto tileSource = ref new Windows::UI::Xaml::Controls::Maps::MapTileSource(dataSource);
tileSource->Bounds = boundingBox;
this->MapControl1->TileSources->Append(tileSource);
}
ローカル ストレージからタイルをオーバーレイする
LocalMapTileDataSource を使用して、ローカル ストレージにファイルとして格納されたタイルイメージをオーバーレイします。 通常は、これらのファイルをパッケージ化してアプリと共に配布します。
LocalMapTileDataSource をインスタンス化します。
ファイル名の形式を UriFormatString プロパティの値として指定します。 この値を作成するには、ベース ファイル名に置き換え可能なパラメーターを挿入します。 たとえば、次のコード サンプルでは、 UriFormatString の値は次のようになります。
Tile_{zoomlevel}_{x}_{y}.png
ファイル名の形式に、 UriFormatString プロパティで使用できない追加の引数が必要な場合は、カスタム URI を作成する必要があります。 UriRequested イベントを処理して、カスタム URI を作成して返します。 詳細については、このトピックで後述する カスタム URI の作成 セクションを参照してください。
次に、 Tiled イメージの概要で前述した残りの手順に従います。
次のプロトコルと場所を使用して、ローカル ストレージからタイルを読み込むことができます。
Uri | 詳細情報 |
---|---|
ms-appx:/// | アプリのインストール フォルダーのルートをポイントします。 |
これは、 Package.InstalledLocation プロパティによって参照される場所です。 | |
ms-appdata:///local | アプリのローカル ストレージのルートをポイントします。 |
これは、 ApplicationData.LocalFolder プロパティによって参照される場所です。 | |
ms-appdata:///temp | アプリの一時フォルダーをポイントします。 |
これは、 ApplicationData.TemporaryFolder プロパティによって参照される場所です。 |
次の例では、 ms-appx:///
プロトコルを使用して、アプリのインストール フォルダーにファイルとして格納されているタイルを読み込みます。 UriFormatString の値は、LocalMapTileDataSource のコンストラクターで指定します。 この例では、マップのズーム レベルがオプションの ZoomLevelRange プロパティで指定された範囲内にある場合にのみタイルが表示されます。
void AddLocalMapTileSource()
{
// Specify the range of zoom levels
// at which the overlaid tiles are displayed.
MapZoomLevelRange range;
range.Min = 11;
range.Max = 20;
// Create a local data source.
LocalMapTileDataSource dataSource = new LocalMapTileDataSource(
"ms-appx:///TileSourceAssets/Tile_{zoomlevel}_{x}_{y}.png");
// Create a tile source and add it to the Map control.
MapTileSource tileSource = new MapTileSource(dataSource);
tileSource.ZoomLevelRange = range;
MapControl1.TileSources.Add(tileSource);
}
カスタム URI を指定する
HttpMapTileDataSource の UriFormatString プロパティまたは LocalMapTileDataSource の UriFormatString プロパティで使用できる置換可能なパラメーターが十分でない場合はカスタム Uri を作成する必要があります。 UriRequested イベントのカスタム ハンドラーを指定して、カスタム URI を作成して返します。 UriRequested イベントは、個々のタイルごとに発生します。
- UriRequested イベントのカスタム ハンドラーで、必要なカスタム引数を X、Y、および ZoomLevel MapTileUriRequestedEventArgs のプロパティと組み合わせてカスタム Uri を作成します。
- MapTileUriRequestedEventArgs の Request プロパティに含まれるMapTileUriRequestのUri プロパティのカスタム URI を返します。
次の例では、 UriRequested イベントのカスタム ハンドラーを作成してカスタム URI を指定する方法を示します。 また、カスタム URI を作成するために非同期的に何かを行う必要がある場合に遅延パターンを実装する方法も示します。
using Windows.UI.Xaml.Controls.Maps;
using System.Threading.Tasks;
...
var httpTileDataSource = new HttpMapTileDataSource();
// Attach a handler for the UriRequested event.
httpTileDataSource.UriRequested += HandleUriRequestAsync;
MapTileSource httpTileSource = new MapTileSource(httpTileDataSource);
MapControl1.TileSources.Add(httpTileSource);
...
// Handle the UriRequested event.
private async void HandleUriRequestAsync(HttpMapTileDataSource sender,
MapTileUriRequestedEventArgs args)
{
// Get a deferral to do something asynchronously.
// Omit this line if you don't have to do something asynchronously.
var deferral = args.Request.GetDeferral();
// Get the custom Uri.
var uri = await GetCustomUriAsync(args.X, args.Y, args.ZoomLevel);
// Specify the Uri in the Uri property of the MapTileUriRequest.
args.Request.Uri = uri;
// Notify the app that the custom Uri is ready.
// Omit this line also if you don't have to do something asynchronously.
deferral.Complete();
}
// Create the custom Uri.
private async Task<Uri> GetCustomUriAsync(int x, int y, int zoomLevel)
{
// Do something asynchronously to create and return the custom Uri. }
}
カスタム ソースからタイルをオーバーレイする
CustomMapTileDataSource を使用してカスタム タイルをオーバーレイします。 すぐにメモリ内にタイルをプログラムで作成するか、別のソースから既存のタイルを読み込む独自のコードを記述します。
カスタム タイルを作成または読み込むには、 BitmapRequested イベントのカスタム ハンドラーを指定します。 BitmapRequested イベントは、個々のタイルごとに発生します。
- BitmapRequested イベントのカスタム ハンドラーで、必要なカスタム引数を、MapTileBitmapRequestedEventArgs の X、Y、および ZoomLevel プロパティと組み合わせて、カスタム タイルを作成または取得します。
- MapTileBitmapRequestedEventArgs の Request プロパティに含まれる、MapTileBitmapRequest の PixelData プロパティのカスタム タイルを返します。 PixelData プロパティの型は IRandomAccessStreamReference です。
次の例では、 BitmapRequested イベントのカスタム ハンドラーを作成して、カスタム タイルを提供する方法を示します。 次の使用例は、部分的に不透明な同じ赤いタイルを作成します。 この例では、MapTileBitmapRequestedEventArgs の X、Y、および ZoomLevel プロパティを無視します。 これは実際の例ではありませんが、この例では、インメモリ カスタム タイルをその場で作成する方法を示しています。 この例では、カスタム タイルを作成するために非同期的に行う必要がある場合に遅延パターンを実装する方法も示します。
using Windows.UI.Xaml.Controls.Maps;
using Windows.Storage.Streams;
using System.Threading.Tasks;
...
CustomMapTileDataSource customDataSource = new CustomMapTileDataSource();
// Attach a handler for the BitmapRequested event.
customDataSource.BitmapRequested += customDataSource_BitmapRequestedAsync;
customTileSource = new MapTileSource(customDataSource);
MapControl1.TileSources.Add(customTileSource);
...
// Handle the BitmapRequested event.
private async void customDataSource_BitmapRequestedAsync(
CustomMapTileDataSource sender,
MapTileBitmapRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
args.Request.PixelData = await CreateBitmapAsStreamAsync();
deferral.Complete();
}
// Create the custom tiles.
// This example creates red tiles that are partially opaque.
private async Task<RandomAccessStreamReference> CreateBitmapAsStreamAsync()
{
int pixelHeight = 256;
int pixelWidth = 256;
int bpp = 4;
byte[] bytes = new byte[pixelHeight * pixelWidth * bpp];
for (int y = 0; y < pixelHeight; y++)
{
for (int x = 0; x < pixelWidth; x++)
{
int pixelIndex = y * pixelWidth + x;
int byteIndex = pixelIndex * bpp;
// Set the current pixel bytes.
bytes[byteIndex] = 0xff; // Red
bytes[byteIndex + 1] = 0x00; // Green
bytes[byteIndex + 2] = 0x00; // Blue
bytes[byteIndex + 3] = 0x80; // Alpha (0xff = fully opaque)
}
}
// Create RandomAccessStream from byte array.
InMemoryRandomAccessStream randomAccessStream =
new InMemoryRandomAccessStream();
IOutputStream outputStream = randomAccessStream.GetOutputStreamAt(0);
DataWriter writer = new DataWriter(outputStream);
writer.WriteBytes(bytes);
await writer.StoreAsync();
await writer.FlushAsync();
return RandomAccessStreamReference.CreateFromStream(randomAccessStream);
}
...
#include <winrt/Windows.Storage.Streams.h>
...
Windows::Foundation::IAsyncOperation<Windows::Storage::Streams::InMemoryRandomAccessStream> MainPage::CustomRandomAccessStream()
{
constexpr int pixelHeight{ 256 };
constexpr int pixelWidth{ 256 };
constexpr int bpp{ 4 };
std::array<uint8_t, pixelHeight * pixelWidth * bpp> bytes;
for (int y = 0; y < pixelHeight; y++)
{
for (int x = 0; x < pixelWidth; x++)
{
int pixelIndex{ y * pixelWidth + x };
int byteIndex{ pixelIndex * bpp };
// Set the current pixel bytes.
bytes[byteIndex] = (byte)(std::rand() % 256); // Red
bytes[byteIndex + 1] = (byte)(std::rand() % 256); // Green
bytes[byteIndex + 2] = (byte)(std::rand() % 256); // Blue
bytes[byteIndex + 3] = (byte)((std::rand() % 56) + 200); // Alpha (0xff = fully opaque)
}
}
// Create RandomAccessStream from byte array.
Windows::Storage::Streams::InMemoryRandomAccessStream randomAccessStream;
Windows::Storage::Streams::IOutputStream outputStream{ randomAccessStream.GetOutputStreamAt(0) };
Windows::Storage::Streams::DataWriter writer{ outputStream };
writer.WriteBytes(bytes);
co_await writer.StoreAsync();
co_await writer.FlushAsync();
co_return randomAccessStream;
}
...
InMemoryRandomAccessStream^ TileSources::CustomRandomAccessStream::get()
{
int pixelHeight = 256;
int pixelWidth = 256;
int bpp = 4;
Array<byte>^ bytes = ref new Array<byte>(pixelHeight * pixelWidth * bpp);
for (int y = 0; y < pixelHeight; y++)
{
for (int x = 0; x < pixelWidth; x++)
{
int pixelIndex = y * pixelWidth + x;
int byteIndex = pixelIndex * bpp;
// Set the current pixel bytes.
bytes[byteIndex] = (byte)(std::rand() % 256); // Red
bytes[byteIndex + 1] = (byte)(std::rand() % 256); // Green
bytes[byteIndex + 2] = (byte)(std::rand() % 256); // Blue
bytes[byteIndex + 3] = (byte)((std::rand() % 56) + 200); // Alpha (0xff = fully opaque)
}
}
// Create RandomAccessStream from byte array.
InMemoryRandomAccessStream^ randomAccessStream = ref new InMemoryRandomAccessStream();
IOutputStream^ outputStream = randomAccessStream->GetOutputStreamAt(0);
DataWriter^ writer = ref new DataWriter(outputStream);
writer->WriteBytes(bytes);
create_task(writer->StoreAsync()).then([writer](unsigned int)
{
create_task(writer->FlushAsync());
});
return randomAccessStream;
}
既定のマップを置き換える
既定のマップをサード パーティ製またはカスタム タイルに完全に置き換えるには:
- MapTileLayer.を指定するBackgroundReplacement MapTileSource の Layer プロパティの値。
- MapStyle.を指定するNone MapControl の Style プロパティの値です。