points2polygon - ObjectVision/GeoDMS GitHub Wiki

Constructs a point attribute with composition type polygon from a point table.

See points2sequence for the full description, arguments and examples.

Variants:

  • points2polygon
  • points2polygon_p
  • points2polygon_po
  • points2polygon_ps
  • points2polygon_pso

what points2polygon does not do

It assembles the point sequence exactly as configured and stops there. It is a re-arrangement, not a geometry construction: nothing about the result is checked or repaired. In particular it does not

  • close rings — the first point is not repeated at the end unless your point table repeats it;
  • fix the point order — a counter-clockwise exterior ring stays counter-clockwise, and every operator downstream will read it as a hole (see Point order in polygons);
  • remove duplicate points or spikes;
  • resolve self-intersections, or make the result a valid polygon in any other sense;
  • decide which ring is a shell and which is a hole, or check that holes lie inside their shell.

Whatever you feed in is what gets stored. Errors of this kind therefore do not surface here but somewhere downstream, often as a wrong area rather than as a message.

closing rings, and when it matters

A feature with one ring may be left open. Every polygon reader closes its own working copy, so points2polygon output with n corner points and no repeated start point is valid input.

Before GeoDMS 20.18.0 that was not true in a Debug build: the readers asserted that incoming rings were closed, and aborted on an open one, while a Release build of the same version computed the correct answer. If you hit that, see issue #1219.

A feature with more than one ring must close each ring. Rings inside one sequence are delimited by the repeat of the ring's own start point — that repeat is the only thing that marks where one ring ends and the next begins. Leave it out and the whole sequence is read as a single ring, silently. So a polygon with a hole, or a multi-polygon, needs its point table to repeat each ring's first point:

points in the table read as
a b c one open ring a b c
a b c a one closed ring
a b c a d e f d two rings
a b c d e f one ring of six points — not what you meant

Null values are not ring separators. They separate sub-geometries of arcs and multipoint compositions; inside a polygon ring a null is an error, and the message says so.

what you can do instead

Build the geometry with points2polygon, then repair or verify it explicitly:

goal use
test whether the point order is right has_correct_winding — a per-element bool; better than area(g) < 0, which misses a feature where only one lake is turned the wrong way
repair the point order fix_winding_order — derives shell/hole from ring nesting, so it also repairs a half-flipped multi-polygon
repair order and validity fix_polygonfix_winding_order plus GEOS MakeValid, which resolves self-intersections
clean and validate with one backend geos_polygon, bg_polygon, cgal_polygon, bp_polygon
// assemble, then repair, then use
attribute<dpoint> raw   (district, polygon) := points2polygon(pnt/xy, pnt/district_rel, pnt/ordinal);
attribute<dpoint> geom  (district, polygon) := fix_polygon(raw);

// or check first, and let the run fail if the source is not what you assumed
attribute<bool>   wound (district) := has_correct_winding(raw);
parameter<bool>   all_wound := all(wound), IntegrityCheck = "all_wound == True";

The check in that second form is worth the two lines: it turns a silently wrong area into a failed run, at the point where the source is read rather than three operators later.

see also

⚠️ **GitHub.com Fallback** ⚠️