Usando blocos de mapa personalizados com a API do Google Map V2 para Android.?

10

Estou procurando uma maneira de usar blocos de mapas personalizados com a API do Google Map V2 para Android.

Estou escrevendo um aplicativo que criará seus próprios mapas em tempo real com dados provenientes de um robô.

O aplicativo precisa mostrar ao operador este mapa. O operador precisa interagir com este mapa, deixando pontos de passagem, etc.

Quero usar o mecanismo do GoogleMap para fazer o mesmo que nesta página:

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

O problema é que ele usou a API Javascript quando eu quero usar a API Android

Existe alguma maneira de usar o mapa de blocos personalizados no Android com o Google Maps Engine?

Eu já estou vendo como usar o ArcGIS, mas prefiro usar uma API sem pagar por uma licença.

MonkeyJLuffy
fonte

Respostas:

8

Sim, você pode usar blocos personalizados com a API do Android Maps v2 - você pode ver um exemplo completo no nosso aplicativo OpenTripPlanner para Android no Github . (Você também pode baixar o aplicativo diretamente do Google Play )

Apoiamos os seguintes fornecedores de bloco:

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

Nossa classe CustomUrlTileProvider pode ser vista aqui no Github , e eu também a colei abaixo:

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

E aqui está o código que alterna entre os provedores de bloco de mapa, com base na preferência do usuário:

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

Aqui está uma captura de tela dos blocos do MapQuest OpenStreetMap: insira a descrição da imagem aqui

Para obter mais informações sobre como criar seus próprios blocos, consulte a documentação do Google para TileOverlay , bem como o wiki do OpenStreetMap para "Criando seus próprios blocos" .

Especificamente, a documentação do Google diz:

Observe que o mundo é projetado usando a projeção Mercator (consulte a Wikipedia) com o lado esquerdo (oeste) do mapa correspondente a -180 graus de longitude e o lado direito (leste) do mapa correspondente a 180 graus de longitude. Para tornar o mapa quadrado, o lado superior (norte) do mapa corresponde a 85,0511 graus de latitude e o lado inferior (sul) do mapa corresponde a -85,0511 graus de latitude. Áreas fora desse intervalo de latitude não são renderizadas.

Em cada nível de zoom, o mapa é dividido em blocos e apenas os blocos que se sobrepõem à tela são baixados e renderizados. Cada bloco é quadrado e o mapa é dividido em blocos da seguinte maneira:

  • No nível de zoom 0, um bloco representa o mundo inteiro. As coordenadas desse bloco são (x, y) = (0, 0).

  • No nível 1 de zoom, o mundo é dividido em 4 blocos dispostos em uma grade 2 x 2. ...

  • No nível de zoom N, o mundo é dividido em blocos 4N dispostos em uma grade 2N x 2N.

Observe que o nível mínimo de zoom suportado pela câmera (que pode depender de vários fatores) é GoogleMap.getMinZoomLevel e o nível máximo de zoom é GoogleMap.getMaxZoomLevel.

As coordenadas dos blocos são medidas no canto superior esquerdo (noroeste) do mapa. No nível de zoom N, os valores x das coordenadas do bloco variam de 0 a 2N - 1 e aumentam de oeste para leste e os valores y variam de 0 a 2N - 1 e aumentam de norte a sul.

Os URLs formatados usados ​​no OTP Android para referenciar cada provedor de bloco são semelhantes a:

Portanto, para os provedores acima, as imagens de bloco são arquivos PNG organizados na estrutura de diretórios indicada pela documentação do Google. Você seguiria um formato semelhante para criar seus próprios blocos de mapa hospedados em seu próprio servidor. Observe que esses URLs / imagens devem estar acessíveis ao público para o dispositivo móvel (ou seja, não podem ser protegidos por senha).

Sean Barbeau
fonte
Obrigado pelo seu tempo. É possível usar imagens totalmente criadas por mim em um repositório pessoal? Qual é o formato desse bloco? E a arborescência?
precisa saber é o seguinte
@MonkeyJLuffy Acabei de adicionar algumas informações na parte inferior da minha resposta para isso. Entre em contato se você ainda tiver dúvidas depois de ler isso.
9788 Sean Bareau
0

A solução mais extensa que encontrei está nesta resposta do StackOverflow :

Basicamente, você precisa implementar seu próprio TileProvider e usá-lo como um TileOverlay

Em algumas aplicações, usamos esse tipo de camada para mostrar blocos no mapa, mas descobrimos que os blocos ocupavam muito espaço. Por isso, passamos a usar mbtiles e esta biblioteca para exibir os dados de mbtiles no mapa.

Devdatta Tengshe
fonte