Mapsui / Mapsui

Mapsui is a .NET Map component for: MAUI, WPF, Avalonia, Uno, Blazor, WinUI, Xamarin and Eto
https://mapsui.com
MIT License
1.21k stars 316 forks source link

Vector MBTiles #2268

Open DiabloRusso opened 7 years ago

DiabloRusso commented 7 years ago

Hi, pauldendulk! Can I use mapsui to display vector tiles from *.mbtiles, such as here? Thanx!

pauldendulk commented 7 years ago

It's complicated. I think the answer is, 'yes, but it will take some work from your side', but I haven't tested that yet.

Some pieces of the puzzle:

There will still be limitations of this approach though. For what purpose do you need it?

The alternative is to turn vector tiles into Mapsui geometries. Which will have the highest quality.

DiabloRusso commented 7 years ago

Hi, Paul den Dulk! Thanx for help! You wrote:

For what purpose do you need it? I am a beginner in mapping. I review the ability to display maps with vector tile (no raster) offline (WPF C# for desktop). Map must be in English and Russian (if available) languages. In addition, user data will be displayed on the map.

The alternative is to turn vector tiles into Mapsui geometries. Which will have the highest quality. I looked sample OsmSharp https://github.com/OsmSharp/core/tree/develop/samples/Sample.GeometryStream, convert NetTopologySuite.Geometry to Mapsui.Geometry and display, like this:

        _source = new PBFOsmStreamSource(fileStream);
        var filtered = from osmGeo in progress
                       where osmGeo.Type == OsmSharp.OsmGeoType.Node ||
                             (osmGeo.Type == OsmSharp.OsmGeoType.Way &&

osmGeo.Tags != null && osmGeo.Tags.Any(t => t.Key == "boundary")) select osmGeo; var features = filtered.ToFeatureSource();

        // filter out only linestrings.
        var lineStrings = (from feature in features
                           where feature.Geometry is

NetTopologySuite.Geometries.LineString select feature).ToArray(); var map = new Map(); var layer = new MemoryLayer() { DataSource = new MemoryProvider(lineStrings.Select(s => new Feature { Geometry = new LineString(s.Geometry.Coordinates.Select(c => new Point(c.X, c.Y)).ToList()) })) }; map.Layers.Add(layer); MapControl.Map = map;

This is very slow(((

Thanx, DBBrowser functionality is strong! But in osm2vectortiles.mbtiles file https://osm2vectortiles-downloads.os.zhdk.cloud.switch.ch/v2.0/planet_2016-06-20_7088ce06a738dcb3104c769adc11ac2c_z0-z5.mbtiles tile data is not image.

Best regards, DiabloRusso!

2016-11-29 23:08 GMT+03:00 Paul den Dulk notifications@github.com:

ah yes, when I user Axis.TMS by hacking the samples code I get a proper map, and it zooms to the right extent at load: [image: image] https://cloud.githubusercontent.com/assets/963462/20726962/f7b55f8c-b677-11e6-8a5c-8c78c1a32766.png

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/pauldendulk/Mapsui/issues/108#issuecomment-263683760, or mute the thread https://github.com/notifications/unsubscribe-auth/AWpACiuklczJJlE6HPjYXNZlTYMCPg2sks5rDIZLgaJpZM4K8gGr .

xivk commented 7 years ago

Usually you won't include raw OSM files but some preprocessed version of it. Try converting to GeoJSON and reading that using Mapsui.

Once you can do that you can build a mbtiles db with geojson data and then show that on the map per tile.

Next step can be to decode protobuf tiles.

DiabloRusso commented 7 years ago

Hi, Ben! Right now I'm considering an mapbox-vector-tile-cs. Thanx!

pauldendulk commented 7 years ago

@DiabloRusso That projects is what is used in the VectorTileRenderer that I pointed to: https://github.com/OsmSharp/VectorTileToBitmapRenderer You could also improve VectorTileToBitmapRenderer. It should allow to specify the style. With some improvements I could turn it into a separate nuget package which could be used from Mapsui.

DiabloRusso commented 7 years ago

@pauldendulk This is an excellent tip for me! To read osm2vectortiles-file I modified GetTile function in class MbTilesTileSource like in HttpVectorTileSource and invert the Y-axis! I would like to inherit MyMbTilesTileSource from MbTilesTileSource, but it does not have a virtual method GetTile like HttpTileSource. I solved problem by copying sources from BruTile.MbTiles (Cache, Provider and Source) and modify them. I do not know where to get ready styles for rendering vector tiles, I'll be grateful if you could tell me? Many thanks for help!

pauldendulk commented 7 years ago

I should change MbTilesTileSource so that it can be constructed with inverted Y-axis.

I have not looked into vector style tiling yet. I think @https://github.com/bertt knows more about it.

Feroks commented 7 years ago

@DiabloRusso Can you post a modified GetFile function code or upload the whole project? For some reason, i can not get it working using locally stored .mbfiles from http://osm2vectortiles.org.

DiabloRusso commented 7 years ago

@Feroks this my project.

bertt commented 7 years ago

it would be nice to have a renderer that works with Mapbox style json (for example https://github.com/lukasmartinelli/osm-liberty/blob/gh-pages/style.json) and vector tile data.

charlenni commented 7 years ago

@DiabloRusso Sorry, but the link doesn't work for me. Is it possible to get your code from an other location?

DiabloRusso commented 7 years ago

@charlenni, sent on email

Phantamos commented 7 years ago

@DiabloRusso , I did a little bit of move stuff from the VectorTileToBitmapRenderer to a edited version of MbTilesTileSource to see if I could get it to work. Came up with this.

  public override byte[] GetTile(TileInfo tileInfo)
        {
            var index = tileInfo.Index;

            if (IsTileIndexValid(index))
            {
                byte[] result;
                var cn = new SQLiteConnectionWithLock(_connectionString, SQLiteOpenFlags.ReadOnly);
                using (cn.Lock())
                {
                    const string sql =
                        "SELECT tile_data FROM \"tiles\" WHERE zoom_level=? AND tile_row=? AND tile_column=?;";
                    result = cn.ExecuteScalar<byte[]>(sql, int.Parse(index.Level), index.Row, index.Col);

                    if(result == null)
                    {
                        return null;
                    }
                    else
                    {
                        var zippedData = new MemoryStream(result);
                        var unzippedData = new GZipStream(zippedData, CompressionMode.Decompress);
                        var layerInfos = VectorTileParser.Parse(unzippedData);
                        var bytes = base.GetTile(tileInfo);
                        var tileWidth = Schema.GetTileWidth(tileInfo.Index.Level);
                        var tileHeight = Schema.GetTileHeight(tileInfo.Index.Level);
                        UseGdi = true;
                        var geoJSONRenderer = GetGeoJsonRenderer(tileInfo, tileWidth, tileHeight);     
                        return geoJSONRenderer.Render(layerInfos.Select(i => i.ToGeoJSON(index.Col, index.Row, int.Parse(index.Level))));
                    }

                }
            }
            return null;
        }

Which works at the first level of the world map. But gives some weird colors. firstlevel

Any level beyond that either is blank, or displays as 2 lines of images secondlevel

Don't know if this helps.

AliFlux commented 6 years ago

There's a server available that takes in vector tiles in mbtiles format, and outputs raster images on a REST end-point.

https://github.com/klokantech/tileserver-gl based on https://github.com/mapbox/mapbox-gl-native/tree/master/platform/node

I've tried it, core renderer is based in OpenGL C++, and requires Linux. Is there a way to port this to C#?

pauldendulk commented 6 years ago

The vector tile renderer in the vectortile branch can work like this. I would actually prefer vectors because they don't get blocky when inflated but to improve performance I added the rasterizer.

To improve vector tiles I would need to improve skia performance. Cache the skia native geomety, perhaps also cache the skia native skpaint. Use the hardware acceleration. There are many options to improve performance. But no time to actually work on it :(

I could create a issue describing what should be done.

AliFlux commented 6 years ago

I couldn't find any existing suitable vector tile rendering library for Windows. So I ended up writing one by myself. It has extensive support for mapbox vector tiles and mapbox style specification (+openmaptiles). The included demos are for Mapsui, Gmap.Net, and static tile rendering.

strip

Please check it out and let me know what you think of it.

AliFlux commented 6 years ago

https://github.com/AliFlux/VectorTileRenderer