Uso de mosaicos de mapas personalizados con Google Map API V2 para Android.

10

Estoy buscando una forma de utilizar mosaicos de mapas personalizados con la API de Google Map V2 para Android.

Estoy escribiendo una aplicación que creará sus propios mapas en tiempo real con datos que provienen de un robot.

La aplicación debe mostrarle al operador este mapa. El operador necesita interactuar con este mapa, dejando puntos de paso, etc.

Quiero usar el motor de GoogleMap para hacer lo mismo que esta página:

http://cdn.mikecouturier.com/blog.mikecouturier.com/tilesgenerator/index.html

El problema es que usó la API de Javascript cuando quiero usar la API de Android

¿Hay alguna forma de usar el mapa de mosaicos personalizados en Android con Google Maps Engine?

Ya estoy viendo cómo usar ArcGIS, pero prefiero usar una API sin pagar una licencia.

MonkeyJLuffy
fuente

Respuestas:

8

Sí, puede usar mosaicos personalizados con Android Maps API v2 ; puede ver un ejemplo completamente funcional en nuestra aplicación OpenTripPlanner para Android en Github . (También puede descargar la aplicación directamente desde Google Play )

Apoyamos a los siguientes proveedores de mosaicos:

  • LyrkOpenStreetMap
  • MapQuestOpenStreetMap
  • Mapnik
  • CycleMap
  • Google (normal, satélite, híbrido, terreno)

Nuestra clase CustomUrlTileProvider se puede ver aquí en Github , y también la he pegado a continuación:

public class CustomUrlTileProvider extends UrlTileProvider {

    private String baseUrl;

    public CustomUrlTileProvider(int width, int height, String url) {
        super(width, height);
        this.baseUrl = url;
    }

    @Override
    public URL getTileUrl(int x, int y, int zoom) {
        try {
            return new URL(baseUrl.replace("{z}", "" + zoom).replace("{x}", "" + x)
                    .replace("{y}", "" + y));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Y aquí está el código que cambia entre proveedores de mosaicos de mapas, según la preferencia del usuario:

/**
 * Changes the tiles used to display the map and sets max zoom level.
 *
 * @param overlayString tiles URL for custom tiles or description for
 *                      Google ones
 */
public void updateOverlay(String overlayString) {
    int tile_width = OTPApp.CUSTOM_MAP_TILE_SMALL_WIDTH;
    int tile_height = OTPApp.CUSTOM_MAP_TILE_SMALL_HEIGHT;

    if (overlayString == null) {
        overlayString = mPrefs.getString(OTPApp.PREFERENCE_KEY_MAP_TILE_SOURCE,
                mApplicationContext.getResources()
                        .getString(R.string.map_tiles_default_server));
    }
    if (mSelectedTileOverlay != null) {
        mSelectedTileOverlay.remove();
    }
    if (overlayString.startsWith(OTPApp.MAP_TILE_GOOGLE)) {
        int mapType = GoogleMap.MAP_TYPE_NORMAL;

        if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_HYBRID)) {
            mapType = GoogleMap.MAP_TYPE_HYBRID;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_NORMAL)) {
            mapType = GoogleMap.MAP_TYPE_NORMAL;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_TERRAIN)) {
            mapType = GoogleMap.MAP_TYPE_TERRAIN;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_SATELLITE)) {
            mapType = GoogleMap.MAP_TYPE_SATELLITE;
        }
        mMap.setMapType(mapType);
        mMaxZoomLevel = mMap.getMaxZoomLevel();
    } else {
        if (overlayString.equals(getResources().getString(R.string.tiles_mapnik))) {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_mapnik_max_zoom);
        } else if (overlayString.equals(getResources().getString(R.string.tiles_lyrk))) {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_lyrk_max_zoom);
            tile_width = OTPApp.CUSTOM_MAP_TILE_BIG_WIDTH;
            tile_height = OTPApp.CUSTOM_MAP_TILE_BIG_HEIGHT;
        } else {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_maquest_max_zoom);
        }

        mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
        CustomUrlTileProvider mTileProvider = new CustomUrlTileProvider(
                tile_width,
                tile_height, overlayString);
        mSelectedTileOverlay = mMap.addTileOverlay(
                new TileOverlayOptions().tileProvider(mTileProvider)
                        .zIndex(OTPApp.CUSTOM_MAP_TILE_Z_INDEX));

        if (mMap.getCameraPosition().zoom > mMaxZoomLevel) {
            mMap.moveCamera(CameraUpdateFactory.zoomTo(mMaxZoomLevel));
        }
    }
}

Aquí hay una captura de pantalla de los mosaicos de MapQuest OpenStreetMap: ingrese la descripción de la imagen aquí

Para obtener más información sobre cómo crear sus propios mosaicos, consulte la documentación de Google para TileOverlay , así como la wiki de OpenStreetMap para "Crear sus propios mosaicos" .

Específicamente, la documentación de Google dice:

Tenga en cuenta que el mundo se proyecta utilizando la proyección de Mercator (ver Wikipedia) con el lado izquierdo (oeste) del mapa correspondiente a -180 grados de longitud y el lado derecho (este) del mapa correspondiente a 180 grados de longitud. Para hacer que el mapa sea cuadrado, el lado superior (norte) del mapa corresponde a 85.0511 grados de latitud y el lado inferior (sur) del mapa corresponde a -85.0511 grados de latitud. Las áreas fuera de este rango de latitud no se representan.

En cada nivel de zoom, el mapa se divide en mosaicos y solo se descargan y representan los mosaicos que se superponen a la pantalla. Cada mosaico es cuadrado y el mapa se divide en mosaicos de la siguiente manera:

  • En el nivel de zoom 0, un mosaico representa el mundo entero. Las coordenadas de ese mosaico son (x, y) = (0, 0).

  • En el nivel de zoom 1, el mundo se divide en 4 mosaicos dispuestos en una cuadrícula de 2 x 2. ...

  • En el nivel de zoom N, el mundo se divide en fichas 4N dispuestas en una cuadrícula de 2N x 2N.

Tenga en cuenta que el nivel de zoom mínimo que admite la cámara (que puede depender de varios factores) es GoogleMap.getMinZoomLevel y el nivel de zoom máximo es GoogleMap.getMaxZoomLevel.

Las coordenadas de los mosaicos se miden desde la esquina superior izquierda (noroeste) del mapa. En el nivel de zoom N, los valores de x de las coordenadas de mosaico varían de 0 a 2N - 1 y aumentan de oeste a este y los valores de y varían de 0 a 2N - 1 y aumentan de norte a sur.

Las URL formateadas que se utilizan en OTP Android para hacer referencia a cada proveedor de mosaico se ven así:

Entonces, para los proveedores anteriores, las imágenes en mosaico son archivos PNG dispuestos en la estructura de directorios indicada por la documentación de Google. Seguiría un formato similar para crear sus propios mosaicos de mapas alojados en su propio servidor. Tenga en cuenta que estas URL / imágenes deben ser de acceso público para el dispositivo móvil (es decir, no pueden protegerse con contraseña).

Sean Barbeau
fuente
Gracias por tu tiempo. ¿Es posible usar imágenes totalmente creadas por mí en un repositorio personal? ¿Cuál es el formato de ese mosaico? ¿Y la arborescencia?
MonkeyJLuffy
@MonkeyJLuffy Acabo de agregar información al final de mi respuesta para esto. Avíseme si aún tiene preguntas después de leer esto.
Sean Barbeau
1

La solución más extensa que he encontrado está en esta respuesta de StackOverflow :

Básicamente, necesita implementar su propio TileProvider y usarlo como TileOverlay

En un par de aplicaciones, hemos utilizado este tipo de capa para mostrar mosaicos en el mapa, pero descubrimos que los mosaicos ocupaban mucho espacio. Por lo tanto, pasamos a usar mbtiles y esta biblioteca para mostrar los datos de mbtiles en el mapa.

Devdatta Tengshe
fuente