Categories &

Functions List

Function Reference: geom.offset

drafting: Q = geom.offset (P, D)

Offset a rectilinear polygon inward or outward.

Q = geom.offset (P, D) slides every edge of the polygon P a distance D along its own inward normal and returns the resulting outline Q, with one vertex per vertex of P.

A positive D offsets inward, shrinking the outline; a negative D offsets outward. D is in the units of P, so millimetres by package convention. D = 0 returns P unchanged.

The orientation of P, clockwise or counter-clockwise, is preserved in Q, and vertex k of Q corresponds to vertex k of P.

Rectilinear input only. P must satisfy geom.isrectilinear; anything else raises an error. This is a deliberate restriction rather than an oversight. Offsetting a general polygon is a genuinely hard problem — edges collapse, the outline self-intersects, and a correct implementation has to detect and resolve both — while the outlines this is wanted for are rectangular in the great majority of cases and L-shaped in most of the rest. The interface is general enough that support for arbitrary polygons can be added later without disturbing callers.

A general polygon is offset by geom.curveoffset instead, given its vertices and CLOSED set true. With one point per corner each normal is the angle bisector, which is the mitred offset exactly. Pass the vertices and not a dense sampling of the same outline: a corner resolved by sampling has a vanishing radius of curvature, so the undercut criterion rejects an offset the polygon itself absorbs without difficulty.

What this function adds over that route is the check below — an exact test that the outline can absorb the offset at all, which a criterion evaluated point by point cannot give.

An offset too large for the outline to absorb raises an error rather than returning a self-intersecting result. This is detected by checking that the orientation survives and that no edge has reversed direction, which is exact for rectilinear outlines.

See also: geom.isrectilinear, geom.largestrect, geom.signedarea

Source Code: geom.offset

Every edge slides along its own inward normal. A positive distance shrinks the outline, a negative one grows it, and the orientation and vertex order are preserved.

 P = [0, 0; 60, 0; 60, 20; 30, 20; 30, 45; 0, 45];
 D = draw.Drawing ().polyline (P, true);
 D.Colour = 'red';
 D = D.polyline (geom.offset (P, 5), true);
 D.Colour = 'blue';
 D = D.polyline (geom.offset (P, -5), true);
 plot (D);
 title ('an L-shaped outline offset 5 mm in (red) and out (blue)');
plotted figure

An offset too large for the outline to absorb raises rather than returning a self-intersecting result that looks plausible.

 try
   geom.offset ([0, 0; 40, 0; 40, 10; 0, 10], 8);
 catch err
   disp (err.message);
 end_try_catch
geom.offset: D is too large for P; the offset outline would be degenerate.