Obtenção de Tiles MVT de WebSites para Lat/Lon e DXF
- Adauto Costa

- 30 de jun.
- 4 min de leitura
De forma bem objetiva, a ideia é capturar, direto de um site com webmapping, os limites de um polígono de interesse para um estudo e convertê-los em DXF. Em outras palavras, queremos converter Tiles MVT para DXF em Latitude e Longitude.

Tiles MVT: Captura via Network
Pressione F12 no navegador e, na aba Network das DevTools, devemos localizar as requisições para os arquivos .mvt, normalmente estruturados no formato de tiles:
.../tiles/z/x/y.mvtEsses arquivos são compactos e leves, contendo vetores (pontos, linhas e polígonos) codificados em um grid local.
Você precisará primeiro gravar o log, clicando no botão exibido na figura abaixo.


No centro você verá esse botão de Reload page. Clique nele para atualizar a página.

Mantenha o filtro Fetch/XHR ativado e repare que surgirá uma lista de requisições de tiles. Cada vez que você aplicar um zoom no mapa, essa lista será incrementada.

Quando alcançar o nível de zoom desejado, os últimos itens da lista serão os arquivos MVT correspondentes. Queremos o polígono em rosa. Clique no arquivo MVT mais recente.

Observe que a URL requisitada terá esse padrão:
.../tiles/z/x/y.mvt
Na imagem acima, vemos que z = 13, x = 3299 e y = 4284. Ao clicar duas vezes no arquivo, ele será baixado. Para facilitar o uso, renomeie-o para:
z_x_y.mvtConversão para JSON
O arquivo MVT é um formato binário compacto, usado para armazenar dados vetoriais em tiles. Para poder visualizar ou trabalhar com suas informações de forma legível, você pode convertê-lo para JSON utilizando um script em Python. Essa conversão permite acessar as geometrias e atributos contidos no tile de maneira estruturada e fácil de manipular.
Use o script abaixo:
import mapbox_vector_tile
import json
# ====== CONFIGURAÇÃO ======
input_mvt_file = "13_3299_4284.mvt"
output_json_file = "13_3299_4284_decoded.json"
# ====== LER E DECODIFICAR ======
with open(input_mvt_file, 'rb') as f:
tile_data = f.read()
decoded = mapbox_vector_tile.decode(tile_data)
# ====== SALVAR EM JSON ======
with open(output_json_file, 'w', encoding='utf-8') as out:
json.dump(decoded, out, ensure_ascii=False, indent=2)
print(f"Arquivo salvo como {output_json_file}")No nosso caso, o arquivo JSON obtido foi:
{
"default": {
"extent": 4096,
"version": 2,
"features": [
{
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
4316,
4352
],
[
4334,
4333
],
[
4352,
4323
],
[
4352,
-256
],
[
-256,
-256
],
[
-256,
4352
],
[
4316,
4352
]
]
]
},
"properties": {
"id": "770dd4dc-9ad5-44b3-b921-87f18e1b6177",
"grouping": "cities",
"name": "Cabo de Santo Agostinho"
},
"id": 0,
"type": "Feature"
}
],
"type": "FeatureCollection"
}
}Observe de cara que não é o arquivo que queremos, uma vez que possui poucos vértices e suas propriedades não atendem ao que procuramos. Vamos examinar com mais cuidado a lista de requisições.
A estrutura das pastas costuma seguir uma lógica importante para organizar os dados nos mapas online, então o polígono que buscamos deve estar em um diretório específico. No nosso caso, queremos uma unidade de conservação. Ao verificar melhor os últimos itens da lista, identificamos um arquivo cuja URL indica que ele corresponde ao dado desejado.
.../uc/tiles/13/3300/4283.mvt
Após a conversão, perceba agora que este é o arquivo que estávamos procurando.
...
"properties": {
"name": "APA Estuarina dos Rios Jaboatão e Pirapama",
"sphere": "Estadual",
"category": "Área de proteção ambiental",
"id": "0074cbee-5555-4507-b1e6-e8358b3367e7",
"law": "Lei nº 9931/86"
},
"id": 0,
"type": "Feature"
}
],
"type": "FeatureCollection"
}
}Finalmente: Tiles MVT para DXF
Antes de prosseguir, entenda o Sistema de Tiles Web Mercator.
Execute este script para converter o arquivo JSON em DXF. Verifique atentamente os valores das variáveis de entrada, especialmente tile_z, tile_x e tile_y.
import ezdxf
import json
import math
# ====== CONFIGURAÇÃO ======
input_json_file = "13_3300_4283_decoded.json"
output_dxf_file = "13_3300_4283_decoded_latlon_export.dxf"
tile_z = 13
tile_x = 3300
# Escolha aqui o Y do servidor
tile_y_xyz = 4283
tile_y = tile_y_xyz
extent = 4096
# ====== FUNÇÃO ======
def mvt_to_latlon(px, py, z, x_tile, y_tile, extent):
# Flip local dentro do tile
py_flipped = extent - py
n = 2.0 ** z
x_norm = (x_tile + (px / extent)) / n
y_norm = (y_tile + (py_flipped / extent)) / n
lon = x_norm * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * y_norm)))
lat = math.degrees(lat_rad)
return lon, lat
# ====== LEITURA ======
with open(input_json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
if 'features' in data:
features = data['features']
elif 'default' in data and 'features' in data['default']:
features = data['default']['features']
else:
raise KeyError("Não encontrei campo 'features' no JSON!")
# ====== CRIA DXF ======
doc = ezdxf.new('R2000')
msp = doc.modelspace()
layer_counter = 1
for feature in features:
geom_type = feature['geometry']['type']
coords = feature['geometry']['coordinates']
if geom_type == 'Polygon':
polygons = [coords]
elif geom_type == 'MultiPolygon':
polygons = coords
else:
continue
for poly in polygons:
for ring in poly:
converted_ring = [
mvt_to_latlon(pt[0], pt[1], tile_z, tile_x, tile_y, extent)
for pt in ring
]
layer_name = f"OUTER_SHAPE_{layer_counter}"
if layer_name not in doc.layers:
doc.layers.add(name=layer_name)
msp.add_lwpolyline(converted_ring, close=True, dxfattribs={'layer': layer_name})
layer_counter += 1
doc.saveas(output_dxf_file)
print(f"DXF gerado com sucesso: {output_dxf_file}")Vale lembrar que o resultado pode ser apenas parcial. Por isso, será necessário localizar as outras partes que forem do seu interesse.

Assim, finalizamos mais um conteúdo! Compartilhe com seus amigos!







































Comentários