Offset Line Shapely#
Functionality#
Offset line using shapely library (GEOS-based). Unlike the native
Offset Line 2D Lite node, this node performs a “true” offset with
self-intersection removal via buffer, producing clean results on
complex topology: collapsing appendices, splitting into components,
holes, self-intersecting input.
Requires shapely installed in Blender’s Python:
Use developer mode of sverchok and in properties install shapely in bottom
If shapely is not installed, the node is not active
Inputs#
This node has the following inputs:
Verts - Vertices of objects. Expects an ordered vertices list. Only X and Y are used; Z is ignored (2D offset). Accepts a list of contours (one path per element).
Offset - Offset distance. For
Polygonend type: positive grows the area, negative shrinks it. ForClosedLineandOpen*types the sign flips the side of the “capsule”.Miter_limit - Ratio
miter_length / |offset|. Used only whenJoin Type = Miter. If the real miter spike is longer thanmiter_limit * |offset|, the corner is clipped (effectively to a bevel). Default2.0(same as Clipper). Clamped to1.0minimum.Quad_segs - Segments per quarter circle (90°), controls arc smoothness. If
> 0— used directly,Arc_tolis ignored. If<= 0— computed fromArc_tol. Default8(shapely default, coarse);16–32gives smooth arcs;> 64is visually indistinguishable from a perfect arc.Arc_tol - Absolute arc tolerance (in scene units). Used only when
Quad_segs <= 0. Converted toquad_segsvia the sagitta formula:theta = 2 * acos(1 - arc_tol / |offset|),quad_segs = ceil(pi / theta), clamped to[1, 512].
All parameters except Verts are optional: if a socket is not
connected, the value comes from the node’s property. If connected,
a list is supported (one value per contour; if shorter, [0] is
reused).
Options#
Join Type - controls how corners between segments are handled:
Miter - Sharp corners; the miter spike is limited by
Miter_limit. Shapelyjoin_style = 2(mitre).Round - Rounded corners; arcs are tessellated with
Quad_segssegments per quadrant. Shapelyjoin_style = 1(round).Bevel - Flat cut of the corner. Shapely
join_style = 3(bevel).Note
Bevelis not an equivalent of Clipper’sJT_SQUARE. Clipper’sJT_SQUAREproduces a 45° cut (“square” corner); Shapely’sbevelproduces a flat cut. There is no direct analogue ofJT_SQUAREin Shapely —Bevelis the closest visually.
End Type - controls the topology of the offset result:
Polygon - Offset of an area.
Polygon.buffer(d):d > 0grows outward,d < 0shrinks inward. Output: all rings (exterior + holes), each closed.ClosedLine - “Capsule” around a closed line:
LineString(ring).buffer(d, cap_style=round). Output: all rings of the capsule polygon, closed.OpenButt - “Thick” line with flat caps:
LineString(pts).buffer(d, cap_style=flat). Output: a closed capsule (exterior ring + possible holes).OpenSquare - Same, square caps (protruding by
d):cap_style=square.OpenRound - Same, round caps:
cap_style=round.Warning
Open*types produce a closed capsule, not a single one-sided offset line.LineString.bufferreturns a polygon (“thick” line); its boundary is two offset lines (left and right of the original) plus caps. This is not the same as Clipper’sET_OPENBUTT, which returns one line (offset in one direction). UseOffset Line 2D Litefor a one-sided offset, or add a half-edge filter (heuristic by normal, not always reliable).
Outputs#
This node has the following outputs:
Vers - Result vertices. Each vertex is
[x, y, 0.0](Z is always 0). The output is a list of lists: multiple rings/contours may be returned if shapely produced a multipolygon, a polygon with holes, or several components.Edgs - Result edges. For closed outputs — a cycle
[i, (i+1) % n]; for open outputs — a chain[i, i+1]. Also a list of lists, matching the structure ofVers.
Behaviour Notes#
Polygon with negative offset may produce a
MultiPolygonif the shape splits into parts. The node handles all polygons: every ring (exterior + holes) of every polygon becomes a separate contour in the output. This is correct for a “clean” offset.Polygon with negative offset may produce a polygon with holes if an inner “island” does not collapse. The hole is emitted as a separate closed ring (its winding may be opposite — take this into account in downstream processing).
Invalid input polygon: if
Polygon(ring)is not valid (self-intersecting, degenerate), the node callsbuffer(0)to repair it before applying the offset.quad_segs takes priority over
arc_tol. To control smoothness only viaarc_tol, setQuad_segs = 0.The node does not crash when shapely is missing: it draws an
ERRORindicator and returns empty outputs.