mapbox/vector-tile-cs

Error messages are not explanatory

Closed this issue · 8 comments

I was working with contour lines in terrain v1 dataset and it turns out that contour data is only available for higher zoom levels like z16. I tried with z14 for a long time and got "Exception: Layer has invalid version: contour" error message which I couldn't understand at all. I'm not sure if it's possible to understand what's wrong when that problem occurs but it would be nice to get those error messages to be a little more self explanatory.

cc @BergWerkGIS

@brnkhy Are you saying Layer has invalid version: contour happens because there is no layer contour in the VTs?
I don't think that's possible.
VectorTileReader.GetLayer("contour") should return null if the specified layer does not exist.

Could you share two links for the VTs you are trying to parse?
One for z14 and one for z16.


This library supports reading VTs made according to vector-tile-spec v2.x only.
The error means that the VTs you are reading are v1 tiles.
https://github.com/mapbox/vector-tile-spec

You could try to override the validation via the optional validate parameter, but I'm not positive that reading the data works - depends on the content of the tile and if it uses some v1 specific encoding:

var vtr = new VectorTileReader(data, false);
                                      ^^^

Nevertheless, going to add a more verbose message to the version error.

tl;dr @brnkhy would you mind switching to mapbox-terrain-v2 (https://www.mapbox.com/vector-tiles/mapbox-terrain/)?

Or is there any specific reason you are using mapbox-terrain-v1?


I tried these (terrain-v1 and terrain-v2) tiles

mapbox-terrain-v1:
https://a.tiles.mapbox.com/v4/mapbox.mapbox-terrain-v1/14/8902/5670.vector.pbf?access_token=<YOUR-TOKEN>
https://a.tiles.mapbox.com/v4/mapbox.mapbox-terrain-v1/16/35609/22682.vector.pbf?access_token=<YOUR-TOKEN>

mapbox-terrain-v2:
https://a.tiles.mapbox.com/v4/mapbox.mapbox-terrain-v2/14/8902/5670.vector.pbf?access_token=<YOUR-TOKEN>
https://a.tiles.mapbox.com/v4/mapbox.mapbox-terrain-v2/16/35609/22682.vector.pbf?access_token=<YOUR-TOKEN>

with the C# script below.
Tiles of terrain-v1@z14 seem to be encoded according to VT spec@v1 - that's why you are getting the error.

λ scriptcs contour.csx

---- v1_14-8902-5670.vector.pbf ----
layers: landcover, hillshade, contour
landcover:      version=1       features=7      keys=class
hillshade:      version=1       features=23     keys=class
contour:        version=1       features=47     keys=ele,index

---- v1_16-35609-22682.vector.pbf ----
layers: landcover, hillshade, contour
landcover:      version=2       features=4      keys=class
hillshade:      version=2       features=15     keys=class
contour:        version=2       features=44     keys=ele,index

---- v2_14-8902-5670.vector.pbf ----
layers: landcover, hillshade, contour
landcover:      version=2       features=21     keys=class
hillshade:      version=2       features=19     keys=class,level
contour:        version=2       features=28     keys=ele,index

---- v2_16-35609-22682.vector.pbf ----
layers: landcover, hillshade, contour
landcover:      version=2       features=4      keys=class
hillshade:      version=2       features=4      keys=class,level
contour:        version=2       features=28     keys=ele,index
#r "Mapbox.VectorTile.VectorTileReader.dll"

using Mapbox.VectorTile;
using System.Collections.Generic;
using System.IO;

private void logVt(string fileName, bool validate=true)
{
	Console.WriteLine(Environment.NewLine + $"---- {fileName} ----");
	VectorTileReader vtr = new VectorTileReader(File.ReadAllBytes(fileName), validate);
	Console.WriteLine("layers:\t" + string.Join(", ", new List<string>(vtr.LayerNames()).ToArray()));
	VectorTileLayer lyrContour = vtr.GetLayer("contour");
	if(null==lyrContour){
		Console.WriteLine("no layer 'contour");
		return;
	}
	foreach(var lyrName in vtr.LayerNames()){
		VectorTileLayer lyr = vtr.GetLayer(lyrName);
		Console.WriteLine($"{lyrName}:\tversion={lyr.Version}\tfeatures={lyr.FeatureCount()}\tkeys={string.Join(",",lyr.Keys.ToArray())}");
	}
}

logVt("v1_14-8902-5670.vector.pbf", false);
logVt("v1_16-35609-22682.vector.pbf", false);

logVt("v2_14-8902-5670.vector.pbf");
logVt("v2_16-35609-22682.vector.pbf");

More verbose error messages:

if(0 == layer.Version) {
throw new Exception($"Layer [{layer.Name}] has invalid version. Only version 2.x of 'Mapbox Vector Tile Specification' (https://github.com/mapbox/vector-tile-spec) is supported.");
}
if(2 != layer.Version) {
throw new Exception($"Layer [{layer.Name}] has invalid version: {layer.Version}. Only version 2.x of 'Mapbox Vector Tile Specification' (https://github.com/mapbox/vector-tile-spec) is supported.");
}

@brnkhy please close if those messages seems more appropriate to you and mapbox-terrain-v2 works for you.

@BergWerkGIS pinged me to review this. My thoughts are:

👍 on only supporting mapbox-terrain-v2 as mapbox-terrain-v1 was never re-rendered to be vector tile spec v2 compliant (/cc @MateoV to confirm my memory here)
👍 on better error messages around only supporting v2 tiles @BergWerkGIS

@BergWerkGIS sorry couldn't reply earlier, but the problem with v2 is that contour lines are defined as polygons in there and not lines. And those polygons have buffers outside the tile so we'll have to cut them properly to be able to use it, like v1 lines. We're cutting meshes on tile edges now so I'll check this again, might work better now.

@brnkhy I wasn't aware that the geometry type had changed (LineString -> Polygon).

Clipping is built in:

lyr.GetFeature(i, 0);
                  ^ distance (in internal tile coordinates resolution) to clip feature

but converting polygons to lines is not.

@BergWerkGIS ah even when clipped (I mean polygon) it'll have a lines at the tile edges right?
I wonder why they did changed it to polygon in the first place. Anyway this is a small issue, let's keep this ticket open and can get back to this later as it's really not that important/priority.

Done

if(0 == layer.Version) {
throw new Exception($"Layer [{layer.Name}] has invalid version. Only version 2.x of 'Mapbox Vector Tile Specification' (https://github.com/mapbox/vector-tile-spec) is supported.");
}
if(2 != layer.Version) {
throw new Exception($"Layer [{layer.Name}] has invalid version: {layer.Version}. Only version 2.x of 'Mapbox Vector Tile Specification' (https://github.com/mapbox/vector-tile-spec) is supported.");
}