我正在编写一个 Qt 应用程序,该应用程序应该在其视图之一中显示特定地理区域的地理地图,我需要能够在其上绘制各种其他图形元素。
要求所有地图图块必须预先下载以供离线使用,因为在使用应用程序期间不会有互联网连接。
经过漫长的搜索,我可以链接到我的 Qt 项目来支持我的需求(离线图块加载、在 Qt 框架中渲染和绘制地图、非 QML 仅 C++ 集成)的合适库之后,我认为 libOsmScout 会完成工作。
但是,我设法从 OpenMapTiles 下载我所在区域的 .mbtiles 文件,只是为了意识到 libOsmScout 本身无法使用 .mbtiles。 该库只能与 .osm.pbf 文件一起使用(“导入”后间接使用)。 (http://libosmscout.sourceforge.net/tutorials/importing/)
我在网上进行了广泛的搜索,但所有结果都指向相反方向的转换过程,即转换为 .mbtiles。
所以我的问题是:是否可以将 .mbtiles 文件转换为 .osm.pbf 格式,以便我可以将 import 到 libOsmScout 兼容的内部文件集? 如果可以的话,流程是怎样的?
任何帮助或指导将不胜感激。 谢谢。
过去,我使用过 mb-utils 方法。然而,跨平台和使用多个版本的 Python 工作,它变得非常耗时。我建议使用 ogr2ogr (如 Aman Bagrecha 发布的)。这是一个脚本,它将转换目录中的每个 .mbtiles 文件。 (注意:它会删除 .mbtile 文件,因此如果您不需要,请进行修改)。
import os
import sqlite3
def get_zoom_levels(filename):
# Connect to the SQLite database file
conn = sqlite3.connect(filename)
cursor = conn.cursor()
# Fetch minzoom and maxzoom from metadata
cursor.execute("SELECT value FROM metadata WHERE name='minzoom';")
minzoom = cursor.fetchone()[0]
cursor.execute("SELECT value FROM metadata WHERE name='maxzoom';")
maxzoom = cursor.fetchone()[0]
# Close the connection
conn.close()
return minzoom, maxzoom
new_line = "\r\n"
print("Requires Python 3! Use python3 from the command line if needed.")
srcDir = os.getcwd()
mbtilesFileCount = 0
# Counting mbtiles files
for file in os.listdir(srcDir):
if file.endswith(".mbtiles"):
mbtilesFileCount += 1
print(f"{mbtilesFileCount} mbtiles file(s) found{new_line}")
# Processing each mbtiles file
for file in os.listdir(srcDir):
if file.endswith(".mbtiles"):
newDirName = os.path.basename(file).split('.')[0]
# Check if the directory already exists
if os.path.exists(newDirName):
print(f"Error: Directory '{newDirName}' already exists. Skipping command.")
continue # Skip to the next iteration of the loop
# This gets the actual zoom levels needed to correctly output the sub-directories
minzoom, maxzoom = get_zoom_levels(file)
command = f'ogr2ogr -f MVT {newDirName} {file} -dsco MINZOOM={minzoom} -dsco MAXZOOM={maxzoom}'
print(f'Running {command}')
result = os.system(command)
# If command was successful, delete the file
if result == 0:
print(f"Deleting {file} after successful processing.")
os.remove(file)
else:
print(f"Failed to process {file}. File not deleted.")