has_correct_winding
Geometric functions > has_correct_winding
syntax
- has_correct_winding(polygon_data_item)
description
has_correct_winding(polygon_data_item) results in a bool data item with the same domain unit as the polygon_data_item, True for each element whose ring order is certifiably correct.
An element is True when all of the following hold:
- every ring’s orientation agrees with its nesting — outer rings clockwise, holes counter-clockwise, at any nesting depth;
- no ring collapsed to fewer than three distinct points;
- the geometry is topologically valid: no self-intersecting ring, no hole outside its shell, no overlapping outer rings.
Anything else gives False, so has_correct_winding(g) == False never under-selects the features that need attention.
This is the test that area(g) < 0 used to stand in for. The area test only catches a feature whose rings are all flipped; a feature where only the lake is flipped has an area that is too large rather than negative, and passes it unnoticed. That is exactly the case has_correct_winding was added for.
An undefined or empty geometry has no rings and therefore no winding to get wrong: it answers True, so selecting on the negation does not drag in every null row.
applies to
- attribute polygon_data_item with a point value type and composition type polygon
conditions
The composition type of the polygon_data_item needs to be polygon.
since version
20.18
example
attribute<bool> winding_ok (district) := has_correct_winding(district/geometry);
unit<uint32> broken := select_with_org_rel(!winding_ok)
{
attribute<rdc> geometry (poly) := fix_winding_order(district/geometry[org_rel]);
}
| district/geometry | area(…, m2) | winding_ok |
|---|---|---|
| outer CW, lake CCW | 1003100 | True |
| outer CCW, lake CW | -1003100 | False |
| outer CW, lake CW (flipped) | 1077800 | False |
The third row is the one area < 0 misses.