Utilisation de tuiles de carte personnalisées avec l'API Google Map V2 pour Android.?

10

Je cherche un moyen d'utiliser des tuiles de carte personnalisées avec l'API Google Map V2 pour Android.

J'écris une application qui créera ses propres cartes en temps réel avec des données provenant d'un robot.

L'application doit montrer à l'opérateur cette carte. L'opérateur doit interagir avec cette carte, laisser des points de cheminement, etc.

Je souhaite utiliser le moteur GoogleMap pour faire de même que cette page:

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

Le problème est qu'il a utilisé l' API Javascript quand je veux utiliser l' API Android

Existe-t-il un moyen d'utiliser la carte de tuiles personnalisées sur Android avec le moteur Google Maps?

J'examine déjà comment utiliser ArcGIS mais, je préfère utiliser une API sans payer de licence.

MonkeyJLuffy
la source

Réponses:

8

Oui, vous pouvez utiliser des vignettes personnalisées avec l' API Android Maps v2 - vous pouvez voir un exemple pleinement fonctionnel dans notre application OpenTripPlanner pour Android sur Github . (Vous pouvez également télécharger l'application directement depuis Google Play )

Nous prenons en charge les fournisseurs de tuiles suivants:

  • LyrkOpenStreetMap
  • MapQuestOpenStreetMap
  • Mapnik
  • CycleMap
  • Google (normal, satellite, hybride, terrain)

Notre classe CustomUrlTileProvider peut être vue ici sur Github , et je l'ai également collée ci-dessous:

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

Et voici le code qui bascule entre les fournisseurs de tuiles de carte, en fonction des préférences de l'utilisateur:

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

Voici une capture d'écran des tuiles MapQuest OpenStreetMap: entrez la description de l'image ici

Pour plus d'informations sur la création de vos propres tuiles, consultez la documentation de Google pour TileOverlay ainsi que le wiki OpenStreetMap pour "Créer vos propres tuiles" .

Plus précisément, la documentation de Google indique:

Notez que le monde est projeté en utilisant la projection Mercator (voir Wikipedia) avec le côté gauche (ouest) de la carte correspondant à -180 degrés de longitude et le côté droit (est) de la carte correspondant à 180 degrés de longitude. Pour rendre la carte carrée, le côté supérieur (nord) de la carte correspond à 85,0511 degrés de latitude et le côté inférieur (sud) de la carte correspond à -85,0511 degrés de latitude. Les zones situées en dehors de cette plage de latitude ne sont pas rendues.

À chaque niveau de zoom, la carte est divisée en tuiles et seules les tuiles qui chevauchent l'écran sont téléchargées et rendues. Chaque tuile est carrée et la carte est divisée en tuiles comme suit:

  • Au niveau de zoom 0, une tuile représente le monde entier. Les coordonnées de cette tuile sont (x, y) = (0, 0).

  • Au niveau de zoom 1, le monde est divisé en 4 tuiles disposées dans une grille 2 x 2. ...

  • Au niveau de zoom N, le monde est divisé en 4 tuiles disposées dans une grille 2N x 2N.

Notez que le niveau de zoom minimum pris en charge par la caméra (qui peut dépendre de divers facteurs) est GoogleMap.getMinZoomLevel et le niveau de zoom maximum est GoogleMap.getMaxZoomLevel.

Les coordonnées des tuiles sont mesurées à partir du coin supérieur gauche (nord-ouest) de la carte. Au niveau de zoom N, les valeurs x des coordonnées de la mosaïque vont de 0 à 2N - 1 et augmentent d'ouest en est et les valeurs y vont de 0 à 2N - 1 et augmentent du nord au sud.

Les URL formatées utilisées dans OTP Android pour référencer chaque fournisseur de tuiles ressemblent à:

Ainsi, pour les fournisseurs ci-dessus, les images de tuiles sont des fichiers PNG disposés dans la structure de répertoires indiquée par la documentation de Google. Vous suivriez un format similaire pour créer vos propres tuiles de carte hébergées sur votre propre serveur. Notez que ces URL / images doivent être accessibles au public sur l'appareil mobile (c'est-à-dire qu'elles ne peuvent pas être protégées par mot de passe).

Sean Barbeau
la source
Merci pour votre temps. Est-il possible d'utiliser des images entièrement créées par mes soins dans un référentiel personnel? Quel est le format de cette tuile? Et l'arborescence?
MonkeyJLuffy
@MonkeyJLuffy Je viens d'ajouter quelques informations au bas de ma réponse pour cela. Veuillez me faire savoir si vous avez encore des questions après avoir lu ceci.
Sean Barbeau
1

La solution la plus complète que j'ai trouvée se trouve dans cette réponse StackOverflow :

Fondamentalement, vous devez implémenter votre propre TileProvider et l'utiliser comme un TileOverlay

Dans quelques applications, nous avons utilisé ce type de couche pour afficher les tuiles sur la carte, mais nous avons constaté que les tuiles prenaient beaucoup de place. Par conséquent, nous sommes passés à l'utilisation de mbtiles et de cette bibliothèque pour afficher les données des mbtiles sur la carte.

Devdatta Tengshe
la source