polygon-triangulation · git:20261026.79a684e · 2026-10-26 · sha256 bc0c82d6ff5f5710
polygon-triangulation git:20261026.79a684eA
Immutable. This exact content never changes and is served at /api/v1/blob/bc0c82d6ff5f5710.
--- name: polygon-triangulation description: How 33 map engines turn polygons into GPU triangles (earcut at bake or run time, stencil fill instead, ring and hole hygiene, clipping huge polygons, index layout, globe subdivision) and what they tried and reverted. Load it when a map-from-scratch renderer must fill polygons, before writing the triangulation step of bake.ts, when fills show spikes, missing or filled holes, flooded land, slivers or outlines along tile edges, or when choosing between baked triangles, stencil fill and shipping rings only. --- # Polygon triangulation: what to bake, what to check, what to skip A filled polygon reaches the GPU either as triangles or as a stencil trick. Triangles need a triangulator that is fast but fragile on real data (duplicate points, touching rings, wrong winding, thousands of holes, rings the size of a continent), and an index buffer whose size and layout cost bytes. Engines spent years on this: they swapped triangulators, capped holes, moved work between threads, shipped pre-built triangles and stopped shipping them. Most of their run-time machinery exists because a general engine cannot trust or pre-process its input. A renderer here can, because it triangulates once in `bake.ts` [1][2]. What still matters is what the engines learnt about input that breaks triangulation, about layout, and about when not to triangulate at all. Per-engine detail, with all numbers: [references/engines.md](references/engines.md). ## Where this repo stands - earcut is the only run-time dependency allowed, vendored at 3.2.4 in `vendor/earcut` [1][4]. Triangulation belongs in `bake.ts` [2]. - `tools/geo.ts` `triangulatePolygon(rings)` drops a repeated closing vertex and passes holes by index. It does not normalise winding, clip, drop holes or check its output [3]. - earcut reorients every ring itself (outer ring one way, holes the other) and so does not depend on input winding [4]. It also exports `deviation()`, the relative difference between polygon area and triangle area, and `refine()`, Lawson flips that remove slivers [4]. - 02 bakes 127,820 earcut triangles with delta-coded indices and shares the vertices with the border lines [5]. 07 skipped triangulation and fills land by per-ring fans with stencil INVERT (even-odd): 88 KB to 43 KB gzip [6]. ## Decision 1: triangles or stencil? | | earcut at bake | stencil-then-cover | | --- | --- | --- | | Shipped | vertices + indices | ring vertices only | | Per-feature colour, id picking | free (a colour or id per vertex) | needs an id buffer pass | | Overlapping features in one layer | fine | INVERT (even-odd) cancels the overlap | | GPU cost | one indexed draw | two passes, fill rate on large fans | - ortho-earth fills by fans into the stencil with non-zero winding (NOTEQUAL 0, never even-odd) after normalising orientation, so overlaps equal their union. For one colour it draws only arcs whose net reference is non-zero, so shared borders cancel: a 370k-edge parcel layer went from 20-37 ms to about 2 ms a frame. Per-feature colours take an additive id buffer and float blending; on half float the id limit is 2,047 [31]. - mapsforge VTM fills with stencil INVERT by default. Lake Zurich and a substation inside a fence were left unfilled because polygons of one layer overlapped. libtess2 meshes are "slightly slower to load ... but should be faster to render" [101]. Over nine years VTM switched tessellation on and off per theme, and in 2025 hard-wired it to the artificial land/sea polygons only, after fixing the overlapping regions in the data [102]. - Even-odd versus non-zero: Mapnik's even-odd fix for holes in GeoJSON caused line artifacts and was partly kept back; the lasting answer was to fix winding in the format [86]. Choose stencil when the layer is fill-only, one or few colours, features in it never overlap (or you dissolve them at bake, as 07 did) and bytes dominate the budget [6][31]. Choose earcut when features carry their own colour or id, may overlap, or are drawn many times per frame [5][101]. ## Decision 2: bake triangles, or rebuild them at load? The repo's rule is bake [2]. The one counter-measurement: MLT tiles with pre-built triangles were 21.9 to 35.8% larger, and decoding them was 14 to 145% slower than decoding outlines (v1 27 and 145%, v2 14 and 68%; v2 triangles-only 10 and 59%) [16]. MLT's encoder now prices each layer: transfer time per byte by network (3G 4 us/B to 5G 40 ns/B, offline 0) against client earcut time, with a slowdown of 2 for a mid-range phone [18]. Organic Maps stores triangle strips so phones never triangulate [93][96]. VTS users tessellating GeoJSON in the browser found it slow; the fix was to export the result once (55 MB JSON, 14 MB without whitespace) [73]. So: bake triangles, delta-code the indices (02 [5]), and record bytes. Only if a gzip budget is tight and the polygons are simple, measure earcut at load on the throttled phone profile against the index bytes, and write both into `performance_knowledge`. ## Decision 3: index layout - Indexed, not a triangle soup: ortho-earth fills went 4.96 to 3.08 MB with `drawElements` [33]. - Width from the vertex count: iTowns picks Uint8/16/32 per mesh but notes Uint8 is not a fast path on every GPU [70]. maplibre-rs moved to u32, doubling index memory, instead of splitting buffers under 65,536 vertices [13]. MapLibre caps globe subdivision at granularity 128 to stay inside 16-bit indices [7]. - One buffer per layer: indices counted from the layer's first vertex raised index entropy by under 0.01% and made MLT's code "a lot simpler" [20]. Per-feature bases help only if features are drawn or culled one by one. - Compressing the index stream: MLT v2 triangle trees store about 2 bits per triangle (0.3 B per index against 2 B); a tessellated dataset shrank 57.81 to 50.12 GB, decode is 7 ns per triangle, and the author thinks the buffer is probably no longer zero-copy to the GPU. It relies on earcut adding no interior vertices [17][19]. Delta coding plus gzip (02) is the cheap version here [5]. - Keep the rings if anything strokes or picks them. MLT's triangles-only layout cannot stroke outlines, and a decoder crashed on it [21]; Organic Maps dropped area outlines and had to rework the area centre [96]. 02 keeps ring lengths so borders reuse the fill vertices [5]. - One mesh beats many: walkers' switch from earcut to lyon was "way faster", but it also went from many shapes to one mesh, and the two causes were never separated [107]. ## Decision 4: input hygiene before earcut (checklist for bake.ts) 1. Closing vertex: decide whether rings repeat the first point and test it. mlt-core decoded rings with a closing point while the stored triangles assumed none; holes misaligned and the covered area was 134.5 instead of 91 [10][17]. `openRing` in `tools/geo.ts` handles it for earcut input [3]. 2. Ring roles explicit, not inferred from winding. MLT v2 takes roles from ring counts [17]; OpenLayers splits by winding only for MVT features [57]; Tangram infers the convention from the first ring of each source because Mapzen tiles were wound against MVT 2.1 [59]; GeoServer had to upgrade its encoder to follow MVT 2.1 winding [85]. 3. Normalise winding explicitly wherever it still matters (non-zero stencil, back-face culling, extruded walls, stroke offsets). Marble's 3D walls turned inside out once its clipper stopped normalising winding as a side effect [52]. d3-geo's spherical convention is the opposite of RFC 7946, and a wrongly wound ring renders as the whole planet except the polygon [67]. 4. Signed area: the plain sum over all edges, relative to a local origin. OpenLayers replaced it with a "faster" lowest-vertex test, patched it twice for duplicate points and reverted [56]. Mapnik's `is_clockwise` failed on thin rings at Web Mercator magnitudes until it subtracted the first vertex [81]. GRASS returned to a line integral as "more robust than surveyor's formula" [46], and a signed geodesic area routine silently skipped rings until it returned the absolute value [45]. 5. Remove near-duplicate points in projected units first. poly2tri crashed on them; QGIS simplifies, then skips the polygon [37]. 6. Validate after quantisation and after simplification. Tangram's TopoJSON water polygons (78-point outer, 21 holes) came out wrong only in earcut because quantisation made rings touch; the server raised the quantisation scale [60]. Organic Maps found outer rings that turn invalid at low zoom while their holes stay valid [95]. OsmAnd flooded St Petersburg by dropping closed coastline rings under 4 points [91]. 7. After clipping, keep only pieces of the input's dimension: drop the points and lines a polygon clip produces [84]. 8. Check the result. If earcut returns no indices, emit nothing: Tangram appended vertices first and drew artifacts [58]. Compare areas: iTowns tests meshes by area [71], and `deviation()` does it per polygon [4]. osgEarth's earcut needed a fix and an opt-in GLU fallback for bad input [76]. At bake, log the feature id and either repair, fall back or drop it, and count what was dropped. 9. Zero-area triangles: Organic Maps drops them with a robust orientation test scaled to the stored coordinate accuracy, though its author is unsure of the constant [99]. ## Decision 5: very large polygons - Thousands of holes: MapLibre keeps the 500 largest rings per polygon (first 100) with quickselect, because earcut slows with ring count [8]. Tangram copied the cap, but no code sets the ring `.area` its comparator reads, so its selection is arbitrary [63]. Here, drop holes below the smallest visible area at the bake's target zoom and count them. - Huge rings: cut into cells before triangulating. osgEarth crops polygons to a grid before tessellation [74]. Organic Maps tessellated whole continents with their lakes and reverted it two days later, keeping coast cells split by 4 and a 10,000-point limit [97]. Navit slices polygons that would sit above tile level 4 into squares [103]. - Clip with a rectangle clipper: GeoServer clips to an envelope, robust first, non-robust on exception [83]. MapServer's rectangle clip emits up to 3 points per input edge; 2 per edge overflowed [82]. Marble clips in 1e-7-degree integers [48] and replaced its own Weiler-Atherton with Clipper for robustness [49]. harp.gl moved clipping from 4 shader clip planes back to the decoder [65]. - Clip edges are not borders. QGIS drops edges on the chunk perimeter [40]; kothic-js skips segments between two points on the same tile edge [66]; mapsforge documents a tile-grid artifact for stroked areas [100]; Navit's sliced polygons render "checkered" when outlined [103]. Bake borders as lines from the unclipped rings. - Simplification does not cut triangles proportionally: Organic Maps notes a circle simplified from 50 to 10 points does not give 5 times fewer triangles [93]. Count triangles per zoom level. - Extruded buildings stay whole: Organic Maps clips areas by tile but not building triangles [98]. ## Decision 6: projections other than the baked flat one - Projected at bake (Equal Earth, local grid) and drawn with an affine camera: triangulate in projected coordinates; nothing below applies [2][5]. - Projected on the GPU (globe): subdivide earcut's output on a fixed square grid so neighbours match; MapLibre found this the fastest approach and warns of single-pixel seams [7]. globe.gl subdivides by an angular step and halved its default from 10 to 5 degrees after making generation faster [69]. Cesium triangulates small polygons in a tangent plane and spans of 180 degrees or more in a stereographic or cylindrical plane, split at the equator [26]. - Precision: tessellate in tile or local units. RustGIS strokes broke in map units [22]; QGIS roofs and walls lost precision until it subtracted an origin in double first [36]. ## If triangulation must happen at run time Only for user-supplied or editable geometry. - In the thread that already parses the data: deck.gl rejected a second worker because the data would cross threads twice [28][29]. - Only the layers the style draws [14]; estimate vertices before tessellating (1.5M tiny polygons became 30-50M vertices) [23]. - Flat arrays, no per-vertex objects or coordinate-keyed maps: MapLibre's array remap made its bench about 15% faster [9]; cartopy's single coordinate extraction was 50-100x faster [108]. If you hash quantised coordinates, mix the bits: 161 s to 13 s [34]. - Not WASM per polygon: the call frequency and small payload cancel the gain [30]. - Decode MVT commands yourself; SVG path semantics differ [15]. ## Tried and reverted | Engine | Tried | Outcome | | --- | --- | --- | | OpenLayers | own robust ear clipper, 40x slower than earcut at first [53] | new WebGL renderer uses earcut in a worker [53] | | OpenLayers | fast lowest-vertex winding test [56] | back to the signed-area sum [56] | | Organic Maps | triangulating whole continents [97] | reverted in two days, coast cells [97] | | harp.gl | tile clipping in the fragment shader [65] | CPU clipping in the decoder [65] | | mapsforge VTM | tessellation per theme, on and off [102] | only land/sea, overlaps fixed in data [102] | | Mapnik | Clipper, boost.geometry, own clipper [80] | simple AGG clipper for drawing [80] | | osgEarth | own ear clipper, then earcut [75][76] | earcut with GLU fallback [76] | | OsmAnd | dropping off-screen polygon vertices [92] | full geometry for areas [92] | | MLT | compact triangle trees [19] | author: "As networks get faster, we might need to revert" [19] | ## Sources Paths are relative to the repository root; `ref-repos/<owner>__<repo>/` is the local clone. 1. README.md 2. skills/map-from-scratch/SKILL.md; skills/map-from-scratch/references/patterns.md 3. tools/geo.ts 4. vendor/earcut/earcut.js; vendor/earcut/package.json 5. examples/02-world-population-mobile/spec.yaml; examples/02-world-population-mobile/REQUEST.md 6. examples/07-world-cities-hover/spec.yaml 7. ref-repos/maplibre__maplibre-gl-js/developer-guides/globe.md 8. https://github.com/maplibre/maplibre-gl-js/commit/3d39142e4; ref-repos/maplibre__maplibre-gl-js/src/data/bucket/fill_bucket.ts 9. https://github.com/maplibre/maplibre-gl-js/commit/761f0f3d6 10. https://github.com/maplibre/maplibre-native/pull/4428 11. https://github.com/maplibre/maplibre-native/commit/fb37f5e54; https://github.com/maplibre/maplibre-native/commit/8552d6312 12. https://github.com/maplibre/maplibre-rs/blob/main/maplibre/src/lib.rs; ref-repos/maplibre__maplibre-rs/docs/src/development-documents/figures/data-model.drawio.svg 13. https://github.com/maplibre/maplibre-rs/commit/1b4eada 14. https://github.com/maplibre/maplibre-rs/commit/635df81; https://github.com/maplibre/maplibre-rs/commit/b30beb8; https://github.com/maplibre/maplibre-rs/commit/37a2953 15. https://github.com/maplibre/maplibre-rs/commit/e6f3b18 16. https://github.com/maplibre/maplibre-tile-spec/blob/main/docs/benchmarks.md; ref-repos/yuiseki__maplibre-tile-spec/docs/benchmarks.md; https://github.com/maplibre/maplibre-tile-spec/blob/main/rust/mlt-core/CHANGELOG.md; ref-repos/yuiseki__maplibre-tile-spec/rust/mlt-core/CHANGELOG.md 17. https://github.com/maplibre/maplibre-tile-spec/blob/main/docs/specification/v2.md; ref-repos/yuiseki__maplibre-tile-spec/docs/specification/v2.md 18. https://github.com/yuiseki/maplibre-tile-spec/commit/a7eac51d; https://github.com/yuiseki/maplibre-tile-spec/commit/85684b59 19. https://github.com/yuiseki/maplibre-tile-spec/commit/8c8b4d64; https://github.com/yuiseki/maplibre-tile-spec/commit/1cdc94a6 20. https://github.com/yuiseki/maplibre-tile-spec/commit/211c4124 21. https://github.com/yuiseki/maplibre-tile-spec/commit/364a9852; https://github.com/yuiseki/maplibre-tile-spec/commit/2deacaa4 22. https://github.com/opengeos/RustGIS/commit/d724d89; https://github.com/opengeos/RustGIS/commit/9f318db 23. https://github.com/opengeos/RustGIS/commit/57036b6 24. ref-repos/CesiumGS__cesium/CHANGES.md; https://github.com/CesiumGS/cesium/issues/2788; https://github.com/CesiumGS/cesium/pull/10593 25. https://github.com/CesiumGS/cesium/commit/a2b4e3498; https://github.com/CesiumGS/cesium/commit/e55aa7ea1; https://github.com/CesiumGS/cesium/commit/483644a97 26. https://github.com/CesiumGS/cesium/commit/3033b0c1e543fba30fdc8e32395d34d81e34d7b8; https://github.com/CesiumGS/cesium/commit/b6c35bd710e1e6c7e14561f758832eb5f15a8b5e 27. https://github.com/visgl/deck.gl/commit/9c40fa60; https://github.com/visgl/deck.gl/commit/91534412 28. https://github.com/visgl/deck.gl/commit/bacb7c24; https://github.com/visgl/deck.gl/commit/0275d745; https://github.com/visgl/deck.gl/commit/8746716d; ref-repos/visgl__deck.gl/dev-docs/RFCs/proposals/loader-worker-triangulation.md 29. https://github.com/visgl/deck.gl/commit/2c31fb13; https://github.com/visgl/deck.gl/commit/7643eea0 30. https://github.com/kenjiyoshidahome2026-bit/ortho-earth/blob/main/packages/ortho-core/perf%20survey.md; ref-repos/kenjiyoshidahome2026-bit__ortho-earth/packages/ortho-core/perf survey.md; ref-repos/kenjiyoshidahome2026-bit__ortho-earth/packages/ortho-core/perf plan.md 31. https://github.com/kenjiyoshidahome2026-bit/ortho-earth/blob/main/packages/ortho-core/gint%20draw%20spec.md; ref-repos/kenjiyoshidahome2026-bit__ortho-earth/packages/ortho-core/gint draw spec.md; ref-repos/kenjiyoshidahome2026-bit__ortho-earth/packages/ortho-core/webgpu port.md 32. https://github.com/kenjiyoshidahome2026-bit/ortho-earth/commit/82c17eb6 33. https://github.com/kenjiyoshidahome2026-bit/ortho-earth/commit/c8febdff 34. https://github.com/kenjiyoshidahome2026-bit/ortho-earth/commit/f125c3c2 35. https://github.com/qgis/QGIS/pull/58583; https://gdal.org/en/latest/development/rfc/rfc64_triangle_polyhedralsurface_tin.html 36. https://github.com/qgis/QGIS/commit/042bf97336; https://github.com/qgis/QGIS/commit/5b74bdfe21; https://github.com/qgis/QGIS/commit/59fa541bc0 37. https://github.com/qgis/QGIS/commit/7bce7ea9ca; https://github.com/qgis/QGIS/commit/35b37a228f; https://github.com/qgis/QGIS/commit/b773d617b1 38. https://github.com/qgis/QGIS/commit/9b07075fae; https://github.com/qgis/QGIS/commit/800c54fc91; https://github.com/qgis/QGIS/commit/6bc298456b 39. https://github.com/qgis/QGIS/commit/577e1e962d; https://github.com/qgis/QGIS/commit/04ca01a795; https://github.com/qgis/QGIS/commit/8adc498421; https://github.com/qgis/QGIS/commit/efcc9c5240 40. https://github.com/qgis/QGIS/commit/13d03b559a 41. https://github.com/qgis/QGIS/commit/a0d9093889; https://github.com/qgis/QGIS/commit/be4ccb5c66 42. https://github.com/qgis/QGIS/commit/127fabd093; https://github.com/qgis/QGIS/commit/434e7028dc; https://github.com/qgis/QGIS/commit/40df5696b5 43. ref-repos/OSGeo__grass/lib/vector/vectorlib_topology.dox; ref-repos/OSGeo__grass/lib/vector/vectorlib_ogr.dox; ref-repos/OSGeo__grass/doc/vector/TODO 44. ref-repos/OSGeo__grass/lib/symbol/README 45. https://github.com/OSGeo/grass/pull/1283 46. https://github.com/OSGeo/grass/commit/d780df670 47. https://github.com/OSGeo/grass/commit/c5755a9354e6c9e0355688b0b45259aa41dfb70d; https://github.com/OSGeo/grass/commit/6246b5a0a683d2ba6262eccf1952f691d778ec9d 48. ref-repos/KDE__marble/tools/vectorosm-tilecreator/VectorClipper.h; https://invent.kde.org/education/marble/-/blob/master/tools/vectorosm-tilecreator/VectorClipper.h 49. https://github.com/KDE/marble/commit/89a0e9010; https://github.com/KDE/marble/commit/342aa8041; https://github.com/KDE/marble/commit/1e879be7b 50. https://github.com/KDE/marble/commit/75fe1f3d2; https://github.com/KDE/marble/commit/73c4289d2 51. https://github.com/KDE/marble/commit/bfd575312 52. https://github.com/KDE/marble/commit/d3c923f75; https://github.com/KDE/marble/commit/48c412ef1 53. https://github.com/openlayers/openlayers/pull/5462#issuecomment-246985147; https://github.com/openlayers/openlayers/pull/13461 54. https://github.com/openlayers/openlayers/pull/5462 55. https://github.com/openlayers/openlayers/commit/87a10200e; https://github.com/openlayers/openlayers/commit/a0089b512; https://github.com/openlayers/openlayers/commit/dc27f768d 56. https://github.com/openlayers/openlayers/commit/c490745ff; https://github.com/openlayers/openlayers/commit/f2b790adf; https://github.com/openlayers/openlayers/commit/c1a547a9a 57. https://github.com/openlayers/openlayers/commit/1361a7907; https://github.com/openlayers/openlayers/commit/4c58b9788 58. https://github.com/tangrams/tangram/pull/651 59. https://github.com/tangrams/tangram/pull/241 60. https://github.com/tangrams/tangram/issues/456 61. https://github.com/tangrams/tangram/commit/f6e3537e; https://github.com/tangrams/tangram/commit/5e7686d4 62. https://github.com/tangrams/tangram/commit/ee3c3706; https://github.com/tangrams/tangram/commit/44b34bcd 63. https://github.com/tangrams/tangram/commit/d0b887d09a3645aad91a18bd3bd0362d74627da3; ref-repos/tangrams__tangram/src/builders/polygons.js 64. https://github.com/tangrams/tangram-es/commit/eea679cc; https://github.com/tangrams/tangram-es/commit/63019355; https://github.com/tangrams/tangram-es/issues/1639 65. https://github.com/heremaps/harp.gl/commit/9fcdb8a0; https://github.com/heremaps/harp.gl/commit/73d457a1; https://github.com/heremaps/harp.gl/commit/6665f189; https://github.com/heremaps/harp.gl/commit/93197f27 66. https://github.com/kothic/kothic-js/commit/b5de689; ref-repos/kothic__kothic-js/src/renderer/path.js 67. https://github.com/d3/d3-geo/issues/138; https://github.com/d3/d3-geo/issues/140; https://github.com/d3/d3-geo/blob/18eb2fb/README.md 68. https://github.com/d3/d3-geo/commit/ed81279 69. https://github.com/vasturiano/globe.gl/commit/2d6197f; https://github.com/vasturiano/globe.gl/commit/36c6686; https://github.com/vasturiano/globe.gl/commit/4d47b41; ref-repos/vasturiano__globe.gl/README.md 70. https://github.com/iTowns/itowns/commit/378c092; https://github.com/iTowns/itowns/commit/06c7181 71. https://github.com/iTowns/itowns/pull/691 72. https://github.com/iTowns/itowns/pull/195 73. https://github.com/melowntech/vts-browser-js/issues/179; https://github.com/melowntech/vts-browser-js/commit/a557f84; ref-repos/melowntech__vts-browser-js/src/core/map/geodata-import/vts-geodata.js 74. https://github.com/pelicanmapping/osgearth/commit/0a6b0a5be4df33d91dce0b1d0669b037d8b2e42e; https://github.com/pelicanmapping/osgearth/commit/0e1e4bca4775e28307b7db26e0b9db751c5b7d9e 75. https://github.com/pelicanmapping/osgearth/commit/bc7678ab590ce1d4f7800f0d23475861866767e8; https://github.com/pelicanmapping/osgearth/commit/1882da8c16d60945bd93af56ae5fb13b0a712d07 76. https://github.com/pelicanmapping/osgearth/commit/46b784681; https://github.com/pelicanmapping/osgearth/commit/ec9bad79b; https://github.com/pelicanmapping/osgearth/commit/e762c2744 77. https://github.com/pelicanmapping/osgearth/commit/10c588a0b; https://github.com/gwaldron/osgearth/issues/1440 78. https://github.com/pelicanmapping/osgearth/commit/a285cd919 79. https://github.com/mapnik/mapnik/blob/master/CHANGELOG.md; https://github.com/mapnik/mapnik/issues/2739 80. https://github.com/mapnik/mapnik/commit/4bdc5cdc1; https://github.com/mapnik/mapnik/commit/a8d49b811; https://github.com/mapnik/mapnik/commit/cf784f5e2; https://github.com/mapnik/mapnik/commit/775fcb537; https://github.com/mapnik/mapnik/commit/a138b8717 81. https://github.com/mapnik/mapnik/commit/34d96f3ef; https://github.com/mapnik/mapnik/commit/ce291a553; https://github.com/mapnik/mapnik/commit/66160e975 82. https://github.com/MapServer/MapServer/commit/40624a2b 83. https://github.com/geoserver/geoserver/commit/f4eeb55439 84. https://github.com/geoserver/geoserver/commit/712e52963f 85. https://github.com/geoserver/geoserver/commit/f363bb4987 86. https://github.com/tilemill-project/tilemill/issues/2110 87. https://github.com/osmandapp/OsmAnd-core/pull/1138; https://github.com/osmandapp/OsmAnd-core/pull/1137 88. https://github.com/osmandapp/OsmAnd-core/pull/280; https://github.com/osmandapp/OsmAnd-core/pull/365; https://github.com/osmandapp/OsmAnd-core/pull/1094 89. https://github.com/osmandapp/OsmAnd-core/commit/2d924177 90. https://github.com/osmandapp/OsmAnd-core/commit/41c5a7cf2e396b33dd2fa6d61471f2d3f9d222b4 91. https://github.com/osmandapp/OsmAnd-core/commit/e0099eabaefbe3864cc0e5d37afad91af3dc19b5 92. https://github.com/osmandapp/OsmAnd-core/commit/0753b344; https://github.com/osmandapp/OsmAnd-core/commit/61fff9af; https://github.com/osmandapp/OsmAnd-core/commit/1501163d; https://github.com/osmandapp/OsmAnd-core/commit/375a2025 93. ref-repos/organicmaps__organicmaps/generator/feature_sorter.cpp; ref-repos/organicmaps__organicmaps/libs/indexer/feature.hpp; https://github.com/organicmaps/organicmaps/blob/master/generator/feature_sorter.cpp 94. https://github.com/organicmaps/organicmaps/pull/13253 95. https://github.com/organicmaps/organicmaps/pull/6537 96. https://github.com/organicmaps/organicmaps/commit/bfcb154531; https://github.com/organicmaps/organicmaps/commit/50cafffc72; https://github.com/organicmaps/organicmaps/commit/9d5595ca7e; https://github.com/organicmaps/organicmaps/commit/5b533632a6; https://github.com/organicmaps/organicmaps/commit/3f869a3c19; https://github.com/organicmaps/organicmaps/commit/776c5b3fa7; https://github.com/organicmaps/organicmaps/commit/1a03b05f71 97. https://github.com/organicmaps/organicmaps/commit/bf52883265; https://github.com/organicmaps/organicmaps/commit/3ba0b12968; https://github.com/organicmaps/organicmaps/commit/820a59c8f0; https://github.com/organicmaps/organicmaps/commit/d6106655de; https://github.com/organicmaps/organicmaps/commit/02be5af144 98. https://github.com/organicmaps/organicmaps/commit/cf0b75e26a; https://github.com/organicmaps/organicmaps/commit/40e5f2ecfa; https://github.com/organicmaps/organicmaps/commit/23cba423c3; https://github.com/organicmaps/organicmaps/commit/01835487d0; https://github.com/organicmaps/organicmaps/commit/750c7bf1ab 99. https://github.com/organicmaps/organicmaps/commit/af2fb3ff9768c6109887f4d82d0201e7628543c1; https://github.com/organicmaps/organicmaps/commit/e2051d71c2a71d8bb7077769bca3cb0cdb886903 100. ref-repos/mapsforge__mapsforge/docs/Getting-Started-Map-Writer.md 101. https://github.com/mapsforge/vtm/issues/224; ref-repos/mapsforge__vtm/vtm/src/org/oscim/renderer/bucket/PolygonBucket.java; ref-repos/mapsforge__vtm/vtm/src/org/oscim/renderer/bucket/MeshBucket.java 102. https://github.com/mapsforge/vtm/commit/892ea925802e1805d309ca33e710c56388031324; https://github.com/mapsforge/vtm/pull/1202; https://github.com/mapsforge/vtm/pull/1207; https://github.com/mapsforge/vtm/pull/903; https://github.com/mapsforge/vtm/issues/224 103. https://github.com/navit-gps/navit/pull/906; https://github.com/navit-gps/navit/commit/b99187ee 104. https://github.com/navit-gps/navit/commit/1d364ed6 105. https://github.com/navit-gps/navit/commit/d95d2c11; https://github.com/navit-gps/navit/commit/8bf234d5; https://github.com/navit-gps/navit/commit/47f9ecef; https://github.com/navit-gps/navit/commit/df2c55b4 106. https://github.com/galileo-map/galileo/issues/41 107. https://github.com/podusowski/walkers/pull/418 108. https://github.com/SciTools/cartopy/pull/2693; ref-repos/SciTools__cartopy/lib/cartopy/mpl/path.py