Geopandas Python – Buffer with No Overlap

buffergeopandaspython

I have a GeoDataFrame of a (tiny) street network and want to buffer with no overlap.
Thus far I have:

#- get the stuff
rd = gpd.read_file('./data/roads-cput_proj.geojson')
rd.set_crs(epsg=32734, inplace=True, allow_override=True)
rd['lanes'] = rd['tags'].apply(lambda x: x.get('lanes'))
rd['lanes'] = pd.to_numeric(rd['lanes'])
#- clean
rd = rd[rd['geometry'].type != 'Polygon']
rd = rd[rd.geometry.length > 10]
rd.dropna(subset=['lanes'], inplace=True)
rd_buffer = rd.copy()

#- buffer_func
def buffer(row):
    #return row.geometry.buffer(row.lanes * 1.5)
    return row.geometry.buffer(round(float(row['lanes']) * 1.5, 2), 
                               cap_style=2, join_style=2)

#-- loop through and trim each geometry based on how it overlaps
for i, row in rd_buffer.iterrows():
    #-- the entire street network without this one segment at i
    rd_copy = rd.copy()
    #-- delete one street
    rd_copy.drop(i, axis=0, inplace=True)
    rd_copy['geometry'] = rd_copy.apply(buffer, axis=1)
    #-- union
    union = rd_copy.explode().dissolve()

    #-- now the single steet at i that needs to be trimmed
    g = row.geometry.buffer(round(float(row['lanes']) * 1.8, 2), 
                               cap_style=2)
    g = gpd.GeoDataFrame(index=[0], crs=jparams['crs'], geometry=[g])
    #-- difference: g minus union
    g = gpd.overlay(g, union, how='difference')
    #- I want the result to be a polygon so overwrite the geometry at that index
    rd_buffer.at[i, 'geometry'] = g.geometry[0]
    #break

If I uncomment the break I get (zoomed):

enter image description here

—where the buffered green polygon represents one street segment trimed back from the its perpendicular connection; it would overlap with when that road is buffered.

Without the break; I get:

enter image description here

Overlaps remain (nothing is trimmed).
Where has the loop gone wrong?
the data is here ~ 79KB.

Best Answer

Use unary_union (Shapely unary_union)

Buffer with intersections

enter image description here

union = rd_buffer.unary_union

Four polygons without intersection

enter image description here

But you lose the original attributes.