fix_winding_order

Geometric functions > fix_winding_order

syntax

  • fix_winding_order(polygon_data_item)

description

fix_winding_order(polygon_data_item) gives each element of the polygon_data_item the ring order GeoDMS documents — outer rings clockwise, holes counter-clockwise — resulting in a data item with the same domain unit and values unit as the argument.

It differs from reverse_polygon in how it decides what a ring is. The ordinary geometry readers infer the role of a ring from its orientation: the first ring is the outer ring, and a ring turning the other way is a hole. fix_winding_order instead derives the roles from the nesting of the rings — which ring lies inside which — and only then applies the convention: a ring at even nesting depth is an outer ring, a ring at odd depth is a hole of the ring that contains it.

That is what makes it work on the cases a reversal cannot repair:

  • a feature where only some rings are flipped. Read by orientation, a flipped lake becomes a second outer ring and an island inside that lake becomes a hole of the wrong polygon. The area of such a feature is too large, never negative, so the usual area(g) < 0 test does not even flag it.
  • a feature where every ring is flipped — handled as well, and equivalently to reverse_polygon.
  • islands inside lakes, at any nesting depth.

The operator never moves a vertex; it only reorders rings and reverses their direction. The only points that disappear are repeated points and spikes, which every geometry reader in GeoDMS removes on input. Because the geometry library is used for the analysis only and the original points are written back, the result is exact for integer coordinates too.

self-intersecting rings

fix_winding_order does not repair a self-intersecting ring. For a bow-tie the signed area is not an orientation indicator at all — the two lobes cancel, and a symmetric bow-tie has an area of exactly zero — and repairing one means moving coordinates. Such features are passed through unchanged and reported with a warning. Use fix_polygon for those; it does the same ring reordering and then repairs what is left.

applies to

conditions

The composition type of the polygon_data_item needs to be polygon.

since version

20.18

example

attribute<rdc> geometry_fixed (poly, district) := fix_winding_order(district/geometry);

Selecting only the features that need it:

attribute<bool> is_ok  (district) := has_correct_winding(district/geometry);
attribute<rdc>  geometry (poly, district) :=
   is_ok ? district/geometry : fix_winding_order(district/geometry);

see also