Atlaslog / Field Notes / Styling & rendering
Field note · Styling & rendering
Hole ring winds the wrong way and the lake gets filled
Quick answer
A polygon with a 240-vertex outer boundary and an inner lake ring renders with the lake painted in the same color. Both rings wind clockwise, so nonzero fill never cancels the hole and the satellite basemap disappears underneath.
Symptom
- The lake area is filled with the same translucent blue and hides the satellite basemap
- The shoelace signed area is `1.2e-3` for the outer ring and `3.4e-5` for the inner ring, so both are positive
- QGIS geometry validity checks pass and the area computation is correct, so the geometry itself is fine
Checklist
- Compute the signed area of each ring with the shoelace formula; outer and inner must have opposite signs
- Run a QGIS validity check for `Ring Self-intersection` or `Hole lies outside shell`
- Temporarily switch the fill rule to `evenodd` and see whether the hole appears
- Compare the winding against RFC 7946: outer counter-clockwise, inner clockwise
- Check whether the data provider rewound rings during export
Fix
Rewind rings before rendering, outer counter-clockwise (positive area) and inner clockwise (negative), by reversing any ring whose sign does not match; as a fallback set `fill-rule: evenodd` on the SVG path via `layer._path.setAttribute('fill-rule', 'evenodd')`.
Code
function signedArea(ring) {
let s = 0;
for (let i = 0, n = ring.length; i < n - 1; i++) {
s += ring[i][0] * ring[i + 1][1] - ring[i + 1][0] * ring[i][1];
}
return s / 2;
}
signedArea(poly[0]); // 外环 1.2e-3 正
signedArea(poly[1]); // 内环 3.4e-5 正 -> 同号,洞失效function rewindPolygon(rings) {
const out = rings.map((ring, i) => {
const positive = signedArea(ring) > 0;
const wantPositive = i === 0; // 外环为正,内环为负
return positive === wantPositive ? ring : ring.slice().reverse();
});
return out;
}
fc.features.forEach(f => {
if (f.geometry.type !== 'Polygon') return;
f.geometry.coordinates = rewindPolygon(f.geometry.coordinates);
});
Watch out
- Assuming QGIS-valid geometry renders correctly, since validity is topological and does not guarantee winding
- Reversing only the outer ring, which makes both rings agree in direction and fills the hole again
English edition written for Atlaslog from the original Chinese field note. Code is unchanged and runs as-is.
Atlaslog (2026). Hole ring winds the wrong way and the lake gets filled. https://www.jingweizhi.com/en/cookbook/polygon-hole-winding.html (accessed 2026-11-03).