NetTopologySuite / NetTopologySuite.IO.VectorTiles

A package that can be used to generate vector tiles using NTS.
Other
20 stars 13 forks source link

Weird breaks with large and small polygons across tiles #33

Open donnyv opened 3 weeks ago

donnyv commented 3 weeks ago

I was testing large polygons across multiple tiles and noticed these weird breaks. image

I found this fix but it looks like you guys made ToPolygon() method internal, so I can't use it. https://stackoverflow.com/a/78633268/1231

Is the tileBufferPercentage the same as MapboxTileWriter.DefaultMinPolygonalExtent? or am I going down the wrong path?

Looks like this zoomed in. image

Polygon should look like this. image

FObermaier commented 3 weeks ago

Could you provide the WKT of the polygon?

donnyv commented 3 weeks ago

Its from Postgis, as EPSG: 3857

MULTIPOLYGON(((-12711411.7775928 5033537.60700535,-11853004.6690575 5100033.93231443,-11605154.7292691 4852183.99252607,-11605154.7292691 4852183.99252607,-9809753.9459242 4948905.92024835,-7700006.89748184 4882409.59493928,-7706052.01796448 4779642.54673435,-12717456.8980754 4646649.89611621,-12711411.7775928 5033537.60700535)))

donnyv commented 2 weeks ago

Looks like if you zoom in past 20. You start seeing breaks also.

Zoom: 21 image

Zoom: 22 image

Here is the WKT for that.

wkt_geom    ogc_fid kfid
MultiPolygon (((-8265399.02747717034071684 5004340.60818658955395222, -8265374.9634824600070715 5004317.83408161997795105, -8265360.12063487991690636 5004285.30170634016394615, -8265355.22197114955633879 5004245.64277254976332188, -8265379.64601374045014381 5004265.73773442953824997, -8265429.85136584006249905 5004307.06933198031038046, -8265428.53704332001507282 5004308.68371067009866238, -8265427.14694999996572733 5004310.34843903034925461, -8265422.42116513010114431 5004315.92261928040534258, -8265417.56966396979987621 5004321.39530383981764317, -8265412.64267587009817362 5004326.81707161013036966, -8265407.61535602994263172 5004332.13754883967339993, -8265402.48744075000286102 5004337.35646899975836277, -8265399.02747717034071684 5004340.60818658955395222)))    9801    671efcb6474d61e394ccfe33
MultiPolygon (((-8265360.12063487991690636 5004285.30170634016394615, -8265301.38670296967029572 5004293.47586308978497982, -8265301.23746731039136648 5004292.81805668957531452, -8265300.64088738989084959 5004290.06034788023680449, -8265300.11980111990123987 5004287.30299057997763157, -8265299.62404049001634121 5004284.52035714965313673, -8265299.17865369003266096 5004281.73773725982755423, -8265298.75859173014760017 5004278.93010674044489861, -8265298.41402400005608797 5004276.12256233021616936, -8265295.24309423007071018 5004248.83234272990375757, -8265354.8036431698128581 5004242.17765498999506235, -8265355.22197114955633879 5004245.64277254976332188, -8265360.12063487991690636 5004285.30170634016394615)))  9813    671efcb6474d61e394ccfe3f
MultiPolygon (((-8265379.64601374045014381 5004265.73773442953824997, -8265355.22197114955633879 5004245.64277254976332188, -8265354.8036431698128581 5004242.17765498999506235, -8265352.02172139007598162 5004219.76844615954905748, -8265415.11501512955874205 5004201.87238970957696438, -8265415.7160243596881628 5004203.08772333990782499, -8265416.34243057016283274 5004204.25256325025111437, -8265416.64286295976489782 5004204.88557974994182587, -8265417.26884854026138783 5004206.15155238006263971, -8265417.89496648032218218 5004207.41752551961690187, -8265418.57139752991497517 5004208.65829365979880095, -8265419.27308086957782507 5004209.89926725998520851, -8265419.97483673039823771 5004211.11489135026931763, -8265420.70184529013931751 5004212.33058816008269787, -8265421.45404667034745216 5004213.52100768964737654, -8265422.2313681598752737 5004214.71163226012140512, -8265423.03401471022516489 5004215.87697990983724594, -8265423.83666144032031298 5004217.04232763033360243, -8265424.66463285032659769 5004218.18253111001104116, -8265425.51779710035771132 5004219.29745726007968187, -8265426.39608187042176723 5004220.41245569009333849, -8265427.29969170037657022 5004221.50217712018638849, -8265428.20330135989934206 5004222.59203131031244993, -8265429.13223608024418354 5004223.65660849958658218, -8265430.08636364992707968 5004224.69590828008949757, -8265431.04049105010926723 5004225.73534080013632774, -8265432.01988362986594439 5004226.72414624039083719, -8265433.0244566397741437 5004227.73837392963469028, -8265434.05442664958536625 5004228.70210761018097401, -8265435.08426466025412083 5004229.66584089025855064, -8265436.13955956045538187 5004230.6044301800429821, -8265437.19472283963114023 5004231.54288634005934, -8265438.30040307994931936 5004232.43105335999280214, -8265439.38083131983876228 5004233.31901504006236792, -8265440.51183682028204203 5004234.18190487008541822, -8265441.6427103104069829 5004235.04479425959289074, -8265442.2459596898406744 5004235.47641395032405853, -8265379.64601374045014381 5004265.73773442953824997))) 9825    671efcb6474d61e394ccfe4b
MultiPolygon (((-8265354.8036431698128581 5004242.17765498999506235, -8265295.24309423007071018 5004248.83234272990375757, -8265290.69543618988245726 5004209.83203996997326612, -8265350.0030909301713109 5004203.45472867041826248, -8265352.02172139007598162 5004219.76844615954905748, -8265354.8036431698128581 5004242.17765498999506235)))  9832    671efcb6474d61e394ccfe52

The 4 features should look like this. image

FObermaier commented 1 week ago

Sorry I can't reproduce your issue, neither with the current codebase nor with the released v1.1 package.

Quick and dirty code to create tiles off of the provided polygon

using NetTopologySuite.Geometries;
using NetTopologySuite.Features;
using NetTopologySuite.IO;
using NetTopologySuite.IO.VectorTiles;
using NetTopologySuite.IO.VectorTiles.Mapbox;
using NetTopologySuite.Operation.Union;
using System;

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Create tiles for zoom level 8");

const int zoom = 8;
var polygon = new WKTReader().Read("POLYGON ((-114.18855482548506 41.14354484447022, -106.47735256954401 41.591840938558008, -104.25087867874379 39.905256801217604, -104.25087867874379 39.905256801217604, -88.122519030754944 40.568524388081627, -69.170338838336733 40.113225684628624, -69.224643079575728 39.403549596204371, -114.2428590667237 38.47432122788581, -114.18855482548506 41.14354484447022))");

var att = new AttributesTable();
att.Add("id", 1);
var feature = new Feature(polygon, att);

var vtt = new VectorTileTree();
VectorTileTreeExtensions.Add(vtt, feature, zoom, "tst");

// Write vector tile tree
MapboxTileWriter.Write(vtt, Environment.CurrentDirectory,
    minLinealExtent: MapboxTileWriter.DefaultMinLinealExtent,
    minPolygonalExtent: MapboxTileWriter.DefaultMinPolygonalExtent);

/**
 ** Code from here is only required to get a unioned result polygon
 **
 */

// Compute the possible tile range
var envelope = polygon.EnvelopeInternal;
var lt = NetTopologySuite.IO.VectorTiles.Tiles.Tile.CreateAroundLocation(envelope.MaxY, envelope.MinX, zoom);
if (lt == null) throw new Exception();
var rb = NetTopologySuite.IO.VectorTiles.Tiles.Tile.CreateAroundLocation(envelope.MinY, envelope.MaxX, zoom);
if (rb == null) throw new Exception();

var tileRange = new NetTopologySuite.IO.VectorTiles.Tiles.TileRange(lt.X, lt.Y, rb.X, rb.Y, zoom);
var rdr = new MapboxTileReader(polygon.Factory);
var geoms = new List<Geometry>();

foreach (var t in tileRange)
{
    if (t == null)
        continue;

    string tilePath = $"{t.Zoom}/{t.X}/{t.Y}.mvt";
    if (!File.Exists(tilePath)) continue;

    using var fs = new FileStream(tilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
    var vt = rdr.Read(fs, t);
    if (!vt.IsEmpty)
    {
        geoms.Add(vt.Layers[0].Features[0].Geometry);
    }

    fs.Dispose();
}

var res = new UnaryUnionOp(geoms).Union();
Console.WriteLine(res.ToString());

Adding the result folder structure to a QGIS project leads to the correct result.

donnyv commented 1 week ago

I wonder if its a Maplibre issue then. I didn't know that QGIS could load the tile tree into project. I will take a look. Thanks!

FObermaier commented 1 week ago

@donnyv where did you take the packages from? ~I just noticed that these are outdated~.

The ones on NuGet and/or MyGet are up-to-date.

donnyv commented 1 week ago

I got the packages from NuGet, version 1.1.0

donnyv commented 4 days ago

Update I solved my problem. I went back to the original answer I found on StackOverflow and clipped the geometry. That was the issue. https://stackoverflow.com/a/78633268/1231

The Tile extension ToPolygon() used in the answer is not publicly available in the library. So I pulled it out and added it to mine, so I could use it. https://github.com/NetTopologySuite/NetTopologySuite.IO.VectorTiles/blob/develop/src/NetTopologySuite.IO.VectorTiles/Tiles/TileExtensions.cs

In the future you might want to add in the read me a note. That if broken polygon lines are happening from features that cross tiles, they need to be clipped. Right now it makes it look like there's something wrong with the library. But its just a feature issue.

I think the reason you couldn't replicate it. Is because you were using the tiling tree code that uses PolygonTiler.Tiles(). That actually clips the geometry. https://github.com/NetTopologySuite/NetTopologySuite.IO.VectorTiles/blob/5ac51b36b1017f1a27e6d3c161b48b839f5ee6bb/src/NetTopologySuite.IO.VectorTiles/Tilers/PolygonTiler.cs#L49

Maybe add a clipping option to VectorTile class?