Compartir a través de


Superponer imágenes en mosaico en un mapa

Importante

Retirada del servicio Bing Maps for Enterprise

Los servicios MapControl y map de UWP del espacio de nombres Windows.Services.Maps se basan en Mapas de Bing. Bing Maps for Enterprise está en desuso y se retirará, momento en el que los servicios y MapControl ya no recibirán datos.

Para obtener más información, consulte la documentación del Centro para desarrolladores de Mapas de Bing y Mapas de Bing.

Nota:

MapControl y servicios de mapas requieren una clave de autenticación de mapas denominada MapServiceToken. Para obtener más información sobre cómo obtener y establecer una clave de autenticación de mapas, consulta Solicitar una clave de autenticación de mapas.

Superpón imágenes en mosaico personalizadas o de terceros en un mapa mediante orígenes de mosaico. Usa orígenes de mosaico para superponer información especializada como, por ejemplo, datos meteorológicos, datos de población o datos sísmicos, o bien para reemplazar el mapa predeterminado por completo.

Introducción a la imagen en mosaico

Los servicios de mapa como Mapas de Bing cortan mapas en mosaicos cuadrados para una recuperación y visualización rápidas. Estos iconos tienen un tamaño de 256 píxeles de 256 píxeles y se representan previamente en varios niveles de detalle. Muchos servicios de terceros también proporcionan datos basados en mapas que se cortan en iconos. Use orígenes de iconos para recuperar iconos de terceros o para crear sus propios iconos personalizados y superponerlos en el mapa mostrado en MapControl.

Cuando se usan orígenes de iconos, no es necesario escribir código para solicitar o colocar iconos individuales. MapControl solicita iconos tal como los necesita. Cada solicitud especifica las coordenadas X e Y y el nivel de zoom del icono individual. Simplemente especifique el formato del URI o el nombre de archivo que se va a usar para recuperar los iconos de la propiedad UriFormatString . Es decir, se insertan parámetros reemplazables en el URI base o el nombre de archivo para indicar dónde pasar las coordenadas X e Y y el nivel de zoom de cada icono.

Este es un ejemplo de la propiedad UriFormatString para un HttpMapTileDataSource que muestra los parámetros reemplazables para las coordenadas X e Y y el nivel de zoom.

http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}

(Las coordenadas X e Y representan la ubicación del icono individual dentro del mapa del mundo en el nivel de detalle especificado. El sistema de numeración de iconos comienza desde {0, 0} en la esquina superior izquierda del mapa. Por ejemplo, el icono de {1, 2} se encuentra en la segunda columna de la tercera fila de la cuadrícula de mosaicos).

Para obtener más información sobre el sistema de iconos usado por los servicios de asignación, consulte Sistema de iconos de Mapas de Bing.

Superponer iconos de un origen de mosaico

Superponer imágenes en mosaico de un origen de icono en un mapa mediante MapTileDataSource.

  1. Cree una instancia de una de las tres clases de origen de datos de icono que heredan de MapTileDataSource.

    Configure UriFormatString para que lo use para solicitar los iconos insertando parámetros reemplazables en el URI base o el nombre de archivo.

    En el ejemplo siguiente se crea una instancia de HttpMapTileDataSource. En este ejemplo se especifica el valor de UriFormatString en el constructor de HttpMapTileDataSource.

        HttpMapTileDataSource dataSource = new HttpMapTileDataSource(
          "http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}");
    
  2. Cree una instancia y configure un objeto MapTileSource. Especifique el objeto MapTileDataSource que configuró en el paso anterior como dataSource de MapTileSource.

    En el ejemplo siguiente se especifica dataSource en el constructor de MapTileSource.

        MapTileSource tileSource = new MapTileSource(dataSource);
    

    Puede restringir las condiciones en las que se muestran los iconos mediante las propiedades de MapTileSource.

    • Mostrar iconos solo dentro de un área geográfica específica proporcionando un valor para la propiedad Bounds.
    • Mostrar iconos solo en determinados niveles de detalle proporcionando un valor para la propiedad ZoomLevelRange.

    Opcionalmente, configure otras propiedades de MapTileSource que afecten a la carga o a la presentación de los iconos, como Layer, AllowOverstretch, IsRetryEnabled e IsTransparencyEnabled.

  3. Agregue mapTileSource a la colección TileSources de MapControl.

         MapControl1.TileSources.Add(tileSource);
    

Superponer iconos de un servicio web

Superponer imágenes en mosaico recuperadas de un servicio web mediante HttpMapTileDataSource.

  1. Cree una instancia de HttpMapTileDataSource.

  2. Especifique el formato del URI que el servicio web espera como valor de la propiedad UriFormatString. Para crear este valor, inserte parámetros reemplazables en el URI base. Por ejemplo, en el ejemplo de código siguiente, el valor de UriFormatString es:

    http://www.<web service name>.com/z={zoomlevel}&x={x}&y={y}
    

    El servicio web tiene que admitir un URI que contenga los parámetros reemplazables {x}, {y}y {zoomlevel}. La mayoría de los servicios web (por ejemplo, Nokia, Bing y Google) admiten URI en este formato. Si el servicio web requiere argumentos adicionales que no están disponibles con la propiedad UriFormatString , tendrá que crear un URI personalizado. Cree y devuelva un URI personalizado controlando el evento UriRequested. Para obtener más información, consulta la sección Proporcionar un URI personalizado más adelante en este tema.

  3. A continuación, siga los pasos restantes descritos anteriormente en la información general de la imagen en mosaico.

En el ejemplo siguiente se superponen iconos de un servicio web ficticio en un mapa de Norteamérica. El valor de UriFormatString se especifica en el constructor de HttpMapTileDataSource. En este ejemplo, los iconos solo se muestran dentro de los límites geográficos especificados por la propiedad Bounds opcional.

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);
}

Superponer iconos del almacenamiento local

Superponer imágenes en mosaico almacenadas como archivos en el almacenamiento local mediante LocalMapTileDataSource. Normalmente, empaquetas y distribuyes estos archivos con la aplicación.

  1. Cree una instancia de LocalMapTileDataSource.

  2. Especifique el formato de los nombres de archivo como valor de la propiedad UriFormatString . Para crear este valor, inserte parámetros reemplazables en el nombre de archivo base. Por ejemplo, en el ejemplo de código siguiente, el valor de UriFormatString es:

        Tile_{zoomlevel}_{x}_{y}.png
    

    Si el formato de los nombres de archivo requiere argumentos adicionales que no están disponibles con la propiedad UriFormatString , tendrá que crear un URI personalizado. Cree y devuelva un URI personalizado controlando el evento UriRequested. Para obtener más información, consulta la sección Proporcionar un URI personalizado más adelante en este tema.

  3. A continuación, siga los pasos restantes descritos anteriormente en la información general de la imagen en mosaico.

Puede usar los siguientes protocolos y ubicaciones para cargar iconos desde el almacenamiento local:

Identificador URI Más información
ms-appx:/// Apunta a la raíz de la carpeta de instalación de la aplicación.
Esta es la ubicación a la que hace referencia la propiedad Package.InstalledLocation .
ms-appdata:///local Apunta a la raíz del almacenamiento local de la aplicación.
Esta es la ubicación a la que hace referencia la propiedad ApplicationData.LocalFolder .
ms-appdata:///temp Apunta a la carpeta temporal de la aplicación.
Esta es la ubicación a la que hace referencia la propiedad ApplicationData.TemporaryFolder .

En el ejemplo siguiente se cargan iconos que se almacenan como archivos en la carpeta de instalación de la aplicación mediante el ms-appx:/// protocolo . El valor de UriFormatString se especifica en el constructor de LocalMapTileDataSource. En este ejemplo, los iconos solo se muestran cuando el nivel de zoom del mapa está dentro del intervalo especificado por la propiedad Opcional 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);
}

Proporcionar un URI personalizado

Si los parámetros reemplazables disponibles con la propiedad UriFormatString de HttpMapTileDataSource o la propiedad UriFormatString de LocalMapTileDataSource no son suficientes para recuperar los iconos, debe crear un URI personalizado. Cree y devuelva un URI personalizado proporcionando un controlador personalizado para el evento UriRequested . El evento UriRequested se genera para cada icono individual.

  1. En el controlador personalizado para el evento UriRequested, combine los argumentos personalizados necesarios con las propiedades X, Y y ZoomLevel del MapTileUriRequestedEventArgs para crear el URI personalizado.
  2. Devuelve el URI personalizado en la propiedad Uri de MapTileUriRequest, que se encuentra en la propiedad Request de MapTileUriRequestedEventArgs.

En el ejemplo siguiente se muestra cómo proporcionar un URI personalizado mediante la creación de un controlador personalizado para el evento UriRequested . También muestra cómo implementar el patrón de aplazamiento si tiene que hacer algo de forma asincrónica para crear el URI personalizado.

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.        }
        }

Superponer iconos de un origen personalizado

Superponer iconos personalizados mediante CustomMapTileDataSource. Cree iconos mediante programación en la memoria sobre la marcha o escriba su propio código para cargar iconos existentes desde otro origen.

Para crear o cargar iconos personalizados, proporcione un controlador personalizado para el evento BitmapRequested. El evento BitmapRequested se genera para cada icono individual.

  1. En el controlador personalizado para el evento BitmapRequested, combine los argumentos personalizados necesarios con las propiedades X, Y y ZoomLevel del mapTileBitmapRequestedEventArgs para crear o recuperar un icono personalizado.
  2. Devuelve el icono personalizado en la propiedad PixelData de MapTileBitmapRequest, que se encuentra en la propiedad Request de MapTileBitmapRequestedEventArgs. La propiedad PixelData es de tipo IRandomAccessStreamReference.

En el ejemplo siguiente se muestra cómo proporcionar iconos personalizados mediante la creación de un controlador personalizado para el evento BitmapRequested . En este ejemplo se crean iconos rojos idénticos que son parcialmente opacos. En el ejemplo se omiten las propiedades X, Y y ZoomLevel de MapTileBitmapRequestedEventArgs. Aunque no es un ejemplo real, el ejemplo muestra cómo puede crear iconos personalizados en memoria sobre la marcha. En el ejemplo también se muestra cómo implementar el patrón de aplazamiento si tiene que hacer algo de forma asincrónica para crear los iconos personalizados.

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;
}

Reemplazar el mapa predeterminado

Para reemplazar el mapa predeterminado por iconos personalizados o de terceros: