Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Openstreetmap(osm) offline tiles file in .net core?

Tags:

I have web application that uses Leaflet to show map of a small region. The problem is that the application must work offline(on LAN) and map tiles are loaded from Openstreetmap. I downloaded the tiles that I needed but I haven't find a good documentation about how to use the downloaded file(which is a 500MB file with .mbtiles extension). Here is the default approach suggested by 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); 

How do I set up a server using dotnet core to use my offline tiles and given parameters and get tiles images?(like the following):

L.tileLayer('https://example.com/DotnetCore/WepApi/GetTiles?{s}/{z}/{x}/{y}').addTo(map);
like image 708
nAviD Avatar asked Apr 04 '19 16:04

nAviD


People also ask

Can I use OpenStreetMap tiles?

Can I use your map tiles? We are in principle happy for our map tiles to be used by external users for creative and unexpected uses - in contrast to most web mapping providers. However, the OpenStreetMap servers are run entirely on donated resources.

Is OpenStreetMap tiles free?

OpenMapTiles is an open-source project aiming to create world maps from open data. It consists of a set of tools allowing everyone to create their own vector map tiles from OpenStreetMap data for hosting, self-hosting, or offline use. It is available as free software on OpenMapTiles.org.


1 Answers

Here is a basic implementation to read the tiles file and serve them in your WebApi.

You need to install the NuGet System.Data.SQLite.Core (or similar) to access the database.

Helper class:

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

Then register the class as a singleton in your ConfigureServices method and pass the path to the file:

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

Finally, you can return the image in your WebApi action as follows:

[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");
    }
}

Possible improvements

  • Use a cache to avoid querying all the time for the same images.
  • Make the implementation async (see this question).

Edit - Formats

This answer assumes your data is stored in PNG format, .mbtiles files can store data in the following formats pbf (for vectors), jpg, png, and webapp. To know which format your database is using, check the data in the table metadata of the .mbtiles SQLite database.

See the following link for more info: https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md

like image 61
Isma Avatar answered Nov 15 '22 06:11

Isma