tilemaker icon indicating copy to clipboard operation
tilemaker copied to clipboard

tilemaker generates degenerate polygons not present in source

Open breunigs opened this issue 1 month ago • 3 comments

Given this way in version 1 as input: https://www.openstreetmap.org/way/1422845261/history (a thin, L-shaped, valid polygon)

as source files for convenience:

and this very minimal configuration:

config.json

{
	"layers": {
		"building": {
			"minzoom": 14,
			"maxzoom": 14
		}
	},
	"settings": {
		"minzoom": 14,
		"maxzoom": 14,
		"basezoom": 14,
		"include_ids": true,
		"name": "debug",
		"version": "3.0",
		"description": "",
		"compress": "gzip"
	}
}

process.lua

function way_function()
  Layer("building", true)
end

and generating tiles from it:

./tilemaker \
  --input bug.osm.pbf \
  --output bug.mbtiles \
  --config ./config.json \
  --process ./process.lua \
  --bbox 10.0534129,53.6191617,10.0544429,53.619693 # same as from bug.osm

sqlite3 \
  bug.mbtiles \
  'select quote(tile_data) from tiles where zoom_level=14 and tile_column=8649 and tile_row=11094' \
  | cut -d\' -f2 \
  | xxd -r -p > bug.mvt

vt2geojson -z 14 -y 5289 -x 8649 bug.mvt

yields a degenerate polygon:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              10.053927898406982,
              53.61927620546507
            ],
            [
              10.053858160972595,
              53.61927620546507
            ],
            [
              10.053799152374268,
              53.61927620546507
            ],
            [
              10.053927898406982,
              53.61927620546507
            ]
          ]
        ]
      },
      "properties": {},
      "id": 1422845261
    }
  ]
}

The spec technically allows degenerate polygons, but discourages them:

A linear ring SHOULD NOT have an area calculated by the surveyor's formula equal to zero, as this would signify a ring with anomalous geometric points.

It also includes wording like

An exterior ring is DEFINED as a linear ring having a positive area as calculated by applying the surveyor's formula to the vertices of the polygon in tile coordinates.

where it depends on your definition of zero if this is valid or not.

Practically speaking this causes issues in reading libraries like java-vector-tile which skip such polygons and return an empty GeometryCollection instead.

It's unexpected to me that tilemaker:

  • modifies the polygon at all. I expected it to be kept 1:1 with the configuration given.
  • includes degenerated polygons. If this is the result of a simplification algorithm, excluding the polygon seem sensible as it can't be rendered sensibly anyway.

breunigs avatar Nov 30 '25 12:11 breunigs

  • modifies the polygon at all. I expected it to be kept 1:1 with the configuration given.

Modifying geometries is core to what tilemaker does. OSM geometries need to be reprojected to web mercator then placed on the tile grid.

yields a degenerate polygon:

Can you check what the geometry is on the tile's coordinate grid? I think vt2geojson will give these to you if you don't specify an z,x,y

pnorman avatar Dec 01 '25 01:12 pnorman

Can you check what the geometry is on the tile's coordinate grid? I think vt2geojson will give these to you if you don't specify an z,x,y

It doesn't out of the box. I added some debug output, does this answer your question?

VectorTileFeature {
  properties: {},
  extent: 4096,
  type: 3,
  _pbf: {
    buf: <Buffer 1a 26 78 02 0a 08 62 75 69 6c 64 69 6e 67 28 80 20 12 15 18 03 08 cd ca bb a6 05 22 0b 09 98 24 ca 3c 12 19 00 15 00 0f>,
    pos: 40,
    length: 40
  },
  _geometry: 28,
  _keys: [],
  _values: [],
  _id: 1422845261
}
// loadGeometry() output
[
  { x: 2316, y: 3877 },
  { x: 2303, y: 3877 },
  { x: 2292, y: 3877 },
  { x: 2316, y: 3877 }
]

breunigs avatar Dec 02 '25 18:12 breunigs

The height and width of the narrow parts are 17cm and 29cm (mercator). The grid size for that vector tile is 60cm. So, the correct response is to drop the feature.

pnorman avatar Dec 02 '25 19:12 pnorman