Как использовать файл автономных плиток Openstreetmap (osm) в ядре .net? - PullRequest
5 голосов
/ 04 апреля 2019

У меня есть веб-приложение, которое использует Leaflet для отображения карты небольшого региона.Проблема в том, что приложение должно работать в автономном режиме (в локальной сети), а листы карты загружаются из Openstreetmap.Я загрузил нужные мне плитки, но не нашел хорошей документации о том, как использовать загруженный файл (это файл размером 500 МБ с расширением .mbtiles).Вот подход по умолчанию, предложенный Leaflet:

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map); 

Как настроить сервер, используя dotnet core для использования моих автономных плиток и заданных параметров и получения изображений плиток? (Например, следующее):

L.tileLayer('https://example.com/DotnetCore/WepApi/GetTiles?{s}/{z}/{x}/{y}').addTo(map);

1 Ответ

4 голосов
/ 09 апреля 2019

Вот базовая реализация для чтения файла плиток и их обслуживания в WebApi.

Вам необходимо установить NuGet System.Data.SQLite.Core (или аналогичный) дляполучить доступ к базе данных.

Вспомогательный класс:

public class MbTilesReader
{
    private string _mbTilesFilename;

    public MbTilesReader(string mbTilesFilename)
    {
        _mbTilesFilename = mbTilesFilename;
    }

    public byte[] GetImageData(int x, int y, int zoom)
    {
        byte[] imageData = null;
        using (SQLiteConnection conn = new SQLiteConnection(string.Format("Data Source={0};Version=3;", _mbTilesFilename)))
        {
            conn.Open();
            using (SQLiteCommand cmd = new SQLiteCommand(conn))
            {
                cmd.CommandText = "SELECT * FROM tiles WHERE tile_column = @x and tile_row = @y and zoom_level = @z";
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.Parameters.Add(new SQLiteParameter("@x", x));
                cmd.Parameters.Add(new SQLiteParameter("@y", y));
                cmd.Parameters.Add(new SQLiteParameter("@z", zoom));
                SQLiteDataReader reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    imageData = reader["tile_data"] as byte[];
                }
            }
        }
        return imageData;
    }
}

Затем зарегистрируйте класс в качестве одиночного в вашем методе ConfigureServices и передайте путь к файлу:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton(new MbTilesReader("c:/temp/map.mbtiles"));
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Наконец, вы можете вернуть изображение в вашем действии WebApi следующим образом:

[Route("api/[controller]")]
[ApiController]
public class MapController : ControllerBase
{
    private MbTilesReader _tileReader;

    public MapController(MbTilesReader tileReader)
    {
        _tileReader = tileReader;

    }

    [HttpGet]
    public IActionResult Get(int x, int y, int z)
    {
        byte[] imageData = _tileReader.GetImageData(x, y, z);
        return File(imageData, "image/png");
    }
}

Возможные улучшения

  • Используйте кэш, чтобы не запрашивать все время дляте же изображения.
  • Сделать реализацию асинхронной (см. этот вопрос).

Правка - Форматы

В этом ответе предполагается, что ваши данные хранятся в формате PNG, файлы .mbtiles могут хранить данные в следующих форматах: pbf (для векторов), jpg, png и webapp.Чтобы узнать, какой формат использует ваша база данных, проверьте данные в метаданных таблицы базы данных SQLite .mbtiles.

Для получения дополнительной информации см. Следующую ссылку: https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md

...