Skip to content

Invalid GeoJSON Polygons passed to map step #76

@jamesbursa

Description

@jamesbursa

In some cases I'm seeing invalid GeoJSON Polygons passed to the map step. It looks like features that consist of multiple exterior polygons are being converted from vector tiles to a GeoJSON Polygon instead of a GeoJSON MultiPolygon.

Then, when these Polygons are used with turf.intersect(), it throws an "TopologyError: side location conflict" exception.

Here's a test case that shows the problem.

Input file: dc.json https://gist.github.com/jamesbursa/2026d7338b7a3d227732#file-dc-json

Convert to MBTiles using Tippecanoe:

$ tippecanoe -f -o dc.mbtiles -Z 15 -z 15 -b 0 -ps dc.json

Decode one tile with tippecanoe-decode:

$ tippecanoe-decode dc.mbtiles 15 9378 12535
{ "type": "FeatureCollection", "features": [
{ "type": "Feature", "properties": { "STFIPS": "11", "CTFIPS": "11001", "STATE": "District of Columbia", "COUNTY": "District of Columbia" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -76.965699, 38.897320 ], [ -76.968470, 38.893357 ], [ -76.968760, 38.892036 ], [ -76.968237, 38.891032 ], [ -76.970214, 38.891032 ], [ -76.970214, 38.899582 ], [ -76.965852, 38.899582 ], [ -76.965699, 38.897320 ] ] ], [ [ [ -76.965710, 38.891032 ], [ -76.966973, 38.891032 ], [ -76.966501, 38.892122 ], [ -76.966000, 38.894021 ], [ -76.965710, 38.891032 ] ] ], [ [ [ -76.962199, 38.897320 ], [ -76.962100, 38.896821 ], [ -76.963985, 38.891032 ], [ -76.965222, 38.891032 ], [ -76.965699, 38.897320 ], [ -76.964200, 38.899582 ], [ -76.962481, 38.899582 ], [ -76.962199, 38.897320 ] ] ], [ [ [ -76.959227, 38.891032 ], [ -76.962204, 38.891032 ], [ -76.961099, 38.896618 ], [ -76.961132, 38.896812 ], [ -76.961199, 38.897217 ], [ -76.961703, 38.898319 ], [ -76.961169, 38.899509 ], [ -76.961137, 38.899582 ], [ -76.959227, 38.899582 ], [ -76.959227, 38.891032 ] ] ] ] } }
] }

Note that the output is correctly a MultiPolygon (containing 4 Polygons). See https://gist.github.com/jamesbursa/2026d7338b7a3d227732#file-tile-json

Run through a test TileReduce:
https://gist.github.com/jamesbursa/2026d7338b7a3d227732#file-tilereduce_test-js
https://gist.github.com/jamesbursa/2026d7338b7a3d227732#file-tilereduce_test_map-js

This simply processes the one tile of interest (15 9378 12535), outputs the feature in the tile, and attempts a turf.intersect() which throws an exception. Note that the feature as passed to the map function is a Polygon, not a MultiPolygon as tippecanoe-decode produces for the same tile.

Converting the Polygon to a MultiPolygon manually allows the turf.intersect() to work.

$ ./tilereduce_test.js 
Starting up 8 workers... Job started.
Processing 1 tiles.
1 tiles processed in 0s.
map tile [9378,12535,15]
---------------------------------------------------------------
feature = { type: 'Feature',
  geometry: 
   { type: 'Polygon',
     coordinates: 
      [ [ [ -76.96570068597794, 38.89732062336043 ],
          [ -76.96847140789032, 38.89335845766496 ],
          [ -76.96876108646393, 38.89203699076319 ],
          [ -76.96823805570602, 38.89103282648847 ],
          [ -76.97021484375, 38.89103282648847 ],
          [ -76.97021484375, 38.89958342598271 ],
          [ -76.96585357189178, 38.89958342598271 ],
          [ -76.96570068597794, 38.89732062336043 ] ],
        [ [ -76.965711414814, 38.89103282648847 ],
          [ -76.96697473526001, 38.89103282648847 ],
          [ -76.96650266647339, 38.8921225841508 ],
          [ -76.9660010933876, 38.89402231327574 ],
          [ -76.965711414814, 38.89103282648847 ] ],
        [ [ -76.9622004032135, 38.89732062336043 ],
          [ -76.96210116147995, 38.89682171160487 ],
          [ -76.96398675441742, 38.89103282648847 ],
          [ -76.96522325277328, 38.89103282648847 ],
          [ -76.96570068597794, 38.89732062336043 ],
          [ -76.96420133113861, 38.89958342598271 ],
          [ -76.96248203516006, 38.89958342598271 ],
          [ -76.9622004032135, 38.89732062336043 ] ],
        [ [ -76.959228515625, 38.89103282648847 ],
          [ -76.96220576763153, 38.89103282648847 ],
          [ -76.9611006975174, 38.89661922340707 ],
          [ -76.96113288402557, 38.89681336158753 ],
          [ -76.96119993925095, 38.89721833629872 ],
          [ -76.96170419454575, 38.89832052381641 ],
          [ -76.96117043495178, 38.89951036613891 ],
          [ -76.9611382484436, 38.89958342598271 ],
          [ -76.959228515625, 38.89958342598271 ],
          [ -76.959228515625, 38.89103282648847 ] ] ] },
  properties: 
   { STFIPS: '11',
     CTFIPS: '11001',
     STATE: 'District of Columbia',
     COUNTY: 'District of Columbia' } };
square = { type: 'Feature',
  geometry: 
   { type: 'Polygon',
     coordinates: 
      [ [ [ -76.965, 38 ],
          [ -76, 38 ],
          [ -76, 38.895 ],
          [ -76.965, 38.895 ],
          [ -76.965, 38 ] ] ] },
  properties: {} };
*** turf.intersect exception: TopologyError: side location conflict [ (-76.96570068597794, 38.89732062336043) ]
---------------------------------------------------------------
converting to MultiPolygon
feature = { type: 'Feature',
  geometry: 
   { type: 'MultiPolygon',
     coordinates: 
      [ [ [ [ -76.96570068597794, 38.89732062336043 ],
            [ -76.96847140789032, 38.89335845766496 ],
            [ -76.96876108646393, 38.89203699076319 ],
            [ -76.96823805570602, 38.89103282648847 ],
            [ -76.97021484375, 38.89103282648847 ],
            [ -76.97021484375, 38.89958342598271 ],
            [ -76.96585357189178, 38.89958342598271 ],
            [ -76.96570068597794, 38.89732062336043 ] ] ],
        [ [ [ -76.965711414814, 38.89103282648847 ],
            [ -76.96697473526001, 38.89103282648847 ],
            [ -76.96650266647339, 38.8921225841508 ],
            [ -76.9660010933876, 38.89402231327574 ],
            [ -76.965711414814, 38.89103282648847 ] ] ],
        [ [ [ -76.9622004032135, 38.89732062336043 ],
            [ -76.96210116147995, 38.89682171160487 ],
            [ -76.96398675441742, 38.89103282648847 ],
            [ -76.96522325277328, 38.89103282648847 ],
            [ -76.96570068597794, 38.89732062336043 ],
            [ -76.96420133113861, 38.89958342598271 ],
            [ -76.96248203516006, 38.89958342598271 ],
            [ -76.9622004032135, 38.89732062336043 ] ] ],
        [ [ [ -76.959228515625, 38.89103282648847 ],
            [ -76.96220576763153, 38.89103282648847 ],
            [ -76.9611006975174, 38.89661922340707 ],
            [ -76.96113288402557, 38.89681336158753 ],
            [ -76.96119993925095, 38.89721833629872 ],
            [ -76.96170419454575, 38.89832052381641 ],
            [ -76.96117043495178, 38.89951036613891 ],
            [ -76.9611382484436, 38.89958342598271 ],
            [ -76.959228515625, 38.89958342598271 ],
            [ -76.959228515625, 38.89103282648847 ] ] ] ] },
  properties: 
   { STFIPS: '11',
     CTFIPS: '11001',
     STATE: 'District of Columbia',
     COUNTY: 'District of Columbia' } };
intersect = { type: 'Feature',
  properties: {},
  geometry: 
   { type: 'MultiPolygon',
     coordinates: 
      [ [ [ [ -76.96142100332834, 38.895 ],
            [ -76.959228515625, 38.895 ],
            [ -76.959228515625, 38.89103282648847 ],
            [ -76.96220576763153, 38.89103282648847 ],
            [ -76.96142100332834, 38.895 ] ] ],
        [ [ [ -76.965, 38.89103282648847 ],
            [ -76.965, 38.895 ],
            [ -76.96269454111474, 38.895 ],
            [ -76.96398675441742, 38.89103282648847 ],
            [ -76.965, 38.89103282648847 ] ] ] ] } };
---------------------------------------------------------------

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions