Shapely: parallel_offset and buffer don't close contours correctly

Created on 6 Feb 2018  ·  4Comments  ·  Source: Toblerity/Shapely

Expected behavior and actual behavior.

Sometimes, when using parallel_offset or buffer, the resulting contour is not closed correctly. The point where the contour is not closed correctly always seems to be the first/last point of the contour.

The following is an issue I initially posted on StackExchange.

Steps to reproduce the problem.

Here is a minimal working example that produces a contour which is not closed when using parallel_offset. When using buffer, a rounded edge is created (despite the mitred style).
Curiously, in my larger dataset there are other very similar contours which close successfully.

import matplotlib.pyplot as plt
from shapely.geometry.polygon import LinearRing

def plot_line(ax, ob, color):
    x, y = ob.xy
    ax.plot(x, y, color=color, alpha=0.7, linewidth=3, 
            solid_capstyle='round', zorder=2)

polygon = [[-29.675, -30.675],
           [-28.4094, -29.4094],
           [-28.325, -29.325],
           [-28.325, -29.764],
           [-28.325, -29.7933],
           [-28.4587, -29.8274],
           [-28.4676, -29.8297],
           [-28.5956, -29.8814],
           [-28.6041, -29.8848],
           [-28.724, -29.953],
           [-28.732, -29.9576],
           [-28.8417, -30.0413],
           [-28.849, -30.0469],
           [-28.9466, -30.1445],
           [-28.9531, -30.151],
           [-29.0368, -30.2607],
           [-29.0424, -30.268],
           [-29.1106, -30.3879],
           [-29.1152, -30.3959],
           [-29.1669, -30.5239],
           [-29.1703, -30.5324],
           [-29.2044, -30.6661],
           [-29.2067, -30.675],
           [-29.6457, -30.675],
           [-29.675, -30.675]]

poly_line = LinearRing(polygon)
poly_line_offset = poly_line.parallel_offset(0.05, side="left", resolution=16, 
                                             join_style=2, mitre_limit=1)
# Alternative:
# poly_line_offset = poly_line.buffer(0.05, resolution=16, join_style=2, mitre_limit=1).exterior

fig = plt.figure()
ax = fig.add_subplot(111)
plot_line(ax, poly_line, "blue")
plot_line(ax, poly_line_offset, "green")
plt.show()

Operating system

Windows 7, Python 3.6.2

Shapely Version and Provenance

Shapely 1.6.3 (installed from PyPI)

geos upstream bug

Most helpful comment

@doctor-ian this is an interesting application and in fact crashes my Python. I think there's a bug in the GEOS library here. Parallel offset isn't designed for closed rings, but ought to fail more gracefully. A negative buffer of a polygon, on the other hand, works:

untitled

All 4 comments

@doctor-ian this is an interesting application and in fact crashes my Python. I think there's a bug in the GEOS library here. Parallel offset isn't designed for closed rings, but ought to fail more gracefully. A negative buffer of a polygon, on the other hand, works:

untitled

@sgillies I already feared that the underlying problem is not in shapely. Regarding the buffer: It also fails when the value is exceeding a certain negative value, i.e. when self-intersections occur. Is this also a bug or intended?

A bug, I think.

In the C-API, GEOSOffsetCurve_r is documented to accept only LINESTRINGs. If we want to accept LinearRings too, then that support would need to be added on somehow.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chivasblue picture chivasblue  ·  3Comments

akadouri picture akadouri  ·  4Comments

sgillies picture sgillies  ·  5Comments

LostFan123 picture LostFan123  ·  3Comments

LostFan123 picture LostFan123  ·  5Comments