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.
$ 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 ] ] ] ] } }
] }
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 ] ] ] ] } };
---------------------------------------------------------------
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:
Decode one tile with tippecanoe-decode:
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.