AliFlux / VectorTileRenderer

A comprehensive Vector Map Tile Renderer for .Net/C#
MIT License
183 stars 51 forks source link

At some zoom levels some tiles are not rendered #27

Open kezara opened 2 years ago

kezara commented 2 years ago

Hello, I have issues with rendering of mbtiles, as you can see from attached screenshots. At some zoom level some tiles are not rendered. I've used tiles made with TileMaker from extract downloaded from Geofabrik. I'm not sure what zoom level is on the first image, but zoom on second is higher than zoom on the first, and zoom on third image is higher than zoom on second. zoom 1 zoom 2 zoom 3

kezara commented 2 years ago

In addition to first comment, second image is at zoom 13, and third at zoom 14.

Also, I've noted that when I'm using MapsUI instead of missing tiles I can see tiles from previous zoom levels, which are blurry and have lot of pixelation, and this is not the only location where it is visible (or not visible)

AliFlux commented 2 years ago

@kezara please check if the tiles generated from TileMaker are complete. It's possible that some tiles are missing in the mbtiles.

Furthermore, you can also put breakpoints to observe exceptions and null values. It may help you debug your tileset

kezara commented 2 years ago

@AliFlux thanks for reply. In method public async static Task<BitmapSource> Render(Style style, ICanvas canvas, int x, int y, double zoom, double sizeX = 512, double sizeY = 512, double scale = 1, List<string> whiteListLayers = null)inif (layer.Source.Type == "vector") I've sent to output all tiles that are null, and number of tiles that can't be loaded is about the same as number of the missing tiles on the screen. So, I'd say that those tiles are missing from mbtiles file, am I right?

kezara commented 2 years ago

@AliFlux After systemed helped me to confirm that issue is not in the mbtiles file, I debugged the VectorTileRenderer for two tiles that are missing (and I guess that same issue is with other missing tiles) and found the following:

Tiles that have been debugged are

  1. 4547, 5255, zoom 13 (osm tiles 4547, 2936)
  2. 4546, 5254, zoom 13 (osm tiles 4546, 2937)

For both tiles exception is thrown in method PbfTileSource.baseTileToVector(object baseTile) on the transportation layer on the line vectorFeature.Attributes = feat.GetProperties();

For the first tile exception has been thrown when i == 11, and for second when i == 20, in both cases feature is LineString.

This is the exception that is thrown on feat.GetProperties() line:

  • $exception {"An item with the same key has already been added. Key: class"} System.ArgumentException
  • Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal} HResult -2147024809 int HelpLink null string
  • InnerException null System.Exception Message "An item with the same key has already been added. Key: class" string ParamName null string SerializationRemoteStackTraceString null string SerializationStackTraceString Evaluation of method System.Exception.getSerializationStackTraceString requires calling method System.Reflection.MethodInfo.CreateDelegate, which cannot be called in this context. string SerializationWatsonBuckets null object Source "System.Private.CoreLib" string StackTrace " at System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException[T](T key) in //src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs:line 187\r\n at System.Collections.Generic.Dictionary2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) in /_/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs:line 608\r\n at System.Collections.Generic.Dictionary2.Add(TKey key, TValue value) in /_/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs:line 195\r\n at Mapbox.VectorTile.VectorTileFeature.GetProperties()\r\n at VectorTileRenderer.Sources.PbfTileSource.d__15.MoveNext() in E:\Users\Borko\Source\Repos\GMap.Net_Demo\VectorTileRenderer\Sources\PbfTileSource.cs:line 115" string
  • TargetSite {Void ThrowAddingDuplicateWithKeyArgumentExceptionT} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo} _HResult -2147024809 int _data null System.Collections.IDictionary _dynamicMethods null object[] _exceptionMethod null System.Reflection.MethodBase _helpURL null string
  • _innerException null System.Exception _ipForWatsonBuckets 0x00007ffc939824d5 System.UIntPtr _message "An item with the same key has already been added. Key: class" string _paramName null string _remoteStackTraceString null string _source null string
  • _stackTrace {byte[192]} byte[] _stackTraceString null string _watsonBuckets null byte[] _xcode -532462766 int _xptrs 0x0000000000000000 System.IntPtr
  • Static members

and on the return from PbfTileSource.baseTileToVector(object baseTile) exception looks like:

  • System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException returned Id = 486, Status = Faulted, Method = "{null}", Result = "{Not yet computed}" System.Threading.Tasks.Task AsyncState null object CancellationPending false bool CreationOptions None System.Threading.Tasks.TaskCreationOptions
  • Exception Count = 1 System.Exception {System.AggregateException}
  • Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal} HResult -2146233088 int HelpLink null string
  • InnerException {"An item with the same key has already been added. Key: class"} System.Exception {System.ArgumentException} InnerExceptionCount 1 int
  • InnerExceptions Count = 1 System.Collections.ObjectModel.ReadOnlyCollection Message "One or more errors occurred. (An item with the same key has already been added. Key: class)" string SerializationRemoteStackTraceString null string SerializationStackTraceString null string SerializationWatsonBuckets null object Source null string StackTrace null string TargetSite null System.Reflection.MethodBase _HResult -2146233088 int
  • _data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal} _dynamicMethods null object[] _exceptionMethod null System.Reflection.MethodBase _helpURL null string
  • _innerException {"An item with the same key has already been added. Key: class"} System.Exception {System.ArgumentException} _ipForWatsonBuckets 0x0000000000000000 System.UIntPtr _message "One or more errors occurred." string _remoteStackTraceString null string _source null string _stackTrace null byte[] _stackTraceString null string _watsonBuckets null byte[] _xcode -532462766 int _xptrs 0x0000000000000000 System.IntPtr
  • m_innerExceptions Count = 1 System.Collections.ObjectModel.ReadOnlyCollection
  • Static members
    Id 486 int Result null VectorTileRenderer.VectorTile Status Faulted System.Threading.Tasks.TaskStatus
  • Raw View

and below is the screenshot of the feature where it breaks and sends null tile for 4547, 5255, zoom 13

Feat where it breaks

Could you please see what's the issue here and how to fix it. Many thanks.

AliFlux commented 2 years ago

Can you please share the tileset? It may be easier to debug it that way

kezara commented 2 years ago

Please see this answer, I think it will make this issue more clearer and will cost you less time than debugging. According to the answer, issue is not in your code, issue is with MapBox method Mapbox.VectorTile.VectorTileFeature,GetProperties() as it returns Dictionary<string,object>() which can't accept duplicate keys...In the meantime systemed has changed his code so now TileMaker doesn't create duplicate tags...

In your project, I've replaced Mapbox Nuget dependencies with projects from Mapbox and changed GetProperties() to return List<KeyValuePair<string, object>>() and I've changed your code accordingly. I'm not tested this extensively, and I'm not sure if it can impact to something else (as I could see it should not have any impact), but with this change mbtiles with duplicate tags are shown correctly, at least this mbtiles file.

Here are mbtiles