question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bug in `VectorTileFeature.toGeoJSON()` causes polygon overlap

See original GitHub issue

Overview

After a lot of consternation in a couple issues (1 2) in the Deck.gl library, I believe I’ve come up with a simple, reproducible example that the problem is caused by VectorTileFeature.toGeoJSON in this library.

Downstream problem

When hosting Mapbox Vector tiles representing polygons, there are dark regions where the tiles meet, which I believe are caused by incorrect overlapping regions from .toGeoJSON.

image

Reproducible example

  1. Create a simple bounding box that crosses over a tile boundary.

image

bbox.geojson:

{
    "type": "Feature",
    "geometry": {
        "type": "Polygon",
        "coordinates": [
            [
                [
                    -119.286701,
                    37.68731
                ],
                [
                    -119.286701,
                    37.821895
                ],
                [
                    -119.71789,
                    37.821895
                ],
                [
                    -119.71789,
                    37.68731
                ],
                [
                    -119.286701,
                    37.68731
                ]
            ]
        ]
    },
    "properties": {}
}
  1. Use tippecanoe to split it into tiles.

    tippecanoe -Z8 -z8 -e tiles bbox.geojson
    
  2. Upload the four outputted tiles to S3. (My JS isn’t perfect yet and I couldn’t get the example working with local files).

    aws s3 cp tiles s3://tiles.nst.guide/mvt-testing/ --recursive --content-type application/x-protobuf --content-encoding 'gzip'
    
  3. Use vector-tile-js to create 4 GeoJSON files from the vector tiles.

npm install @mapbox/vector-tile pbf node-fetch
var VectorTile = require('@mapbox/vector-tile').VectorTile
var Protobuf = require('pbf');
var fs = require('fs')
var fetch = require('node-fetch');

var xyz_array = [
  [42, 98, 8],
  [43, 98, 8],
  [42, 99, 8],
  [43, 99, 8],
]

for (var i = 0; i < xyz_array.length; i++) {
  let [x, y, z] = xyz_array[i]
  let mapSource = `https://tiles.nst.guide/mvt-testing/${z}/${x}/${y}.pbf`;
  fetch(mapSource).then(
    response => response.arrayBuffer()
  ).then(buffer => {
    let tile = new VectorTile(new Protobuf(buffer));
    let vectorTileLayer = tile.layers['bbox']
    let vectorTileFeature = vectorTileLayer.feature(0);
    let geoJSONFeature = vectorTileFeature.toGeoJSON(x, y, z);
    fs.writeFile(`tmp_${z}_${x}_${y}.geojson`, JSON.stringify(geoJSONFeature), () => console.log('written'))
  })
}
  1. Merge the GeoJSON files together
npm install @mapbox/geojson-merge
geojson-merge tmp_8_42_98.geojson tmp_8_42_99.geojson tmp_8_43_98.geojson tmp_8_43_99.geojson > combined.geojson
  1. Inspect the merged GeoJSON and see the overlap.

image

combined.geojson:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -119.5037841796875,
              37.821988845756366
            ],
            [
              -119.5037841796875,
              37.696860987441895
            ],
            [
              -119.718017578125,
              37.696860987441895
            ],
            [
              -119.718017578125,
              37.821988845756366
            ],
            [
              -119.5037841796875,
              37.821988845756366
            ]
          ]
        ]
      },
      "properties": {}
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -119.5037841796875,
              37.74031329210264
            ],
            [
              -119.5037841796875,
              37.68735239874452
            ],
            [
              -119.718017578125,
              37.68735239874452
            ],
            [
              -119.718017578125,
              37.74031329210264
            ],
            [
              -119.5037841796875,
              37.74031329210264
            ]
          ]
        ]
      },
      "properties": {}
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -119.28680419921875,
              37.821988845756366
            ],
            [
              -119.28680419921875,
              37.696860987441895
            ],
            [
              -119.5587158203125,
              37.696860987441895
            ],
            [
              -119.5587158203125,
              37.821988845756366
            ],
            [
              -119.28680419921875,
              37.821988845756366
            ]
          ]
        ]
      },
      "properties": {}
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -119.28680419921875,
              37.74031329210264
            ],
            [
              -119.28680419921875,
              37.68735239874452
            ],
            [
              -119.5587158203125,
              37.68735239874452
            ],
            [
              -119.5587158203125,
              37.74031329210264
            ],
            [
              -119.28680419921875,
              37.74031329210264
            ]
          ]
        ]
      },
      "properties": {}
    }
  ]
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
e-n-fcommented, Nov 26, 2019

Since you mentioned you were using Tippecanoe to create the tiles, I should have mentioned that you want tippecanoe -b 0 to create tiles with no buffer.

0reactions
kylebarroncommented, Nov 26, 2019

Thanks for your response!

Read more comments on GitHub >

github_iconTop Results From Across the Web

geojson - Rendering overlapping polygons without holes in ...
A valid simple feature MultiPolygon cannot have overlapping parts. That does not prevent Leaflet from dealing with them. I do not know if...
Read more >
Vector tiles standards | Tilesets - Mapbox docs
Simplification can cause invalid polygons according to the OGC standards by oversimplifying polygon rings to the point where their edges overlap. See below...
Read more >
Bug report #8002: Voronoi Polygons tool makes overlapped ...
2) Build Voronoi Polygons using appropriate tool; 3) Change transparency of layer to 50%; In result you can see that some of adjacent...
Read more >
Leaflet overlapping polygons merge before applying opacity
I have a leaflet map to which I add hundreds of polygons. It happens sometimes that there are numerous polygons overlapping at the...
Read more >
What's New in PhotoMesh 7.7.2 - Skyline
In this article: New Features in 7.7.2 Bug Fixes and Stability Improvements ... Resolved bug causing PhotoMesh to crash during water polygon ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found