(gdf, tolerance, target=None, barrier=None, extension=0)
return df
Extends lines from gdf to itself or target within a set tolerance

    Extends unjoined ends of LineString segments to join with other segments or
    target. If ``target`` is passed, extend lines to target. Otherwise extend
    lines to itself.

    If ``barrier`` is passed, each extended line is checked for intersection
    with ``barrier``. If they intersect, extended line is not returned. This
    can be useful if you don't want to extend street network segments through
    buildings.

    Parameters
    ----------
    gdf : GeoDataFrame
        GeoDataFrame containing LineString geometry
    tolerance : float
        tolerance in snapping (by how much could be each segment
        extended).
    target : GeoDataFrame, GeoSeries
        target geometry to which ``gdf`` gets extended. Has to be
        (Multi)LineString geometry.
    barrier : GeoDataFrame, GeoSeries
        extended line is not used if it intersects barrier
    extension : float
        by how much to extend line beyond the snapped geometry. Useful
        when creating enclosures to avoid floating point imprecision.

    Returns
    -------
    GeoDataFrame
        GeoDataFrame of with extended geometry

    See also
    --------
    momepy.close_gaps
    momepy.remove_false_nodes
Extends lines from gdf to itself or target within a set tolerance
Extends lines from gdf to itself or target within a set tolerance
def extend_lines(gdf, tolerance, target=None, barrier=None, extension=0):
    """Extends lines from gdf to itself or target within a set tolerance

    Extends unjoined ends of LineString segments to join with other segments or
    target. If ``target`` is passed, extend lines to target. Otherwise extend
    lines to itself.

    If ``barrier`` is passed, each extended line is checked for intersection
    with ``barrier``. If they intersect, extended line is not returned. This
    can be useful if you don't want to extend street network segments through
    buildings.

    Parameters
    ----------
    gdf : GeoDataFrame
        GeoDataFrame containing LineString geometry
    tolerance : float
        tolerance in snapping (by how much could be each segment
        extended).
    target : GeoDataFrame, GeoSeries
        target geometry to which ``gdf`` gets extended. Has to be
        (Multi)LineString geometry.
    barrier : GeoDataFrame, GeoSeries
        extended line is not used if it intersects barrier
    extension : float
        by how much to extend line beyond the snapped geometry. Useful
        when creating enclosures to avoid floating point imprecision.

    Returns
    -------
    GeoDataFrame
        GeoDataFrame of with extended geometry

    See also
    --------
    momepy.close_gaps
    momepy.remove_false_nodes

    """
    # explode to avoid MultiLineStrings
    # reset index due to the bug in GeoPandas explode
    if GPD_10:
        df = gdf.reset_index(drop=True).explode(ignore_index=True)
    else:
        df = gdf.reset_index(drop=True).explode().reset_index(drop=True)

    if target is None:
        target = df
        itself = True
    else:
        itself = False

    # get underlying pygeos geometry
    geom = df.geometry.values.data

    # extract array of coordinates and number per geometry
    coords = pygeos.get_coordinates(geom)
    indices = pygeos.get_num_coordinates(geom)

    # generate a list of start and end coordinates and create point geometries
    edges = [0]
    i = 0
    for ind in indices:
        ix = i + ind
        edges.append(ix - 1)
        edges.append(ix)
        i = ix
    edges = edges[:-1]
    points = pygeos.points(np.unique(coords[edges], axis=0))

    # query LineString geometry to identify points intersecting 2 geometries
    tree = pygeos.STRtree(geom)
    inp, res = tree.query_bulk(points, predicate="intersects")
    unique, counts = np.unique(inp, return_counts=True)
    ends = np.unique(res[np.isin(inp, unique[counts == 1])])

    new_geoms = []
    # iterate over cul-de-sac-like segments and attempt to snap them to street network
    for line in ends:

        l_coords = pygeos.get_coordinates(geom[line])

        start = pygeos.points(l_coords[0])
        end = pygeos.points(l_coords[-1])

        first = list(tree.query(start, predicate="intersects"))
        second = list(tree.query(end, predicate="intersects"))
        first.remove(line)
        second.remove(line)

        t = target if not itself else target.drop(line)

        if first and not second:
            snapped = _extend_line(l_coords, t, tolerance)
            if (
                barrier is not None
                and barrier.sindex.query(
                    pygeos.linestrings(snapped), predicate="intersects"
                ).size
                > 0
            ):
                new_geoms.append(geom[line])
            else:
                if extension == 0:
                    new_geoms.append(pygeos.linestrings(snapped))
                else:
                    new_geoms.append(
                        pygeos.linestrings(
                            _extend_line(snapped, t, extension, snap=False)
                        )
                    )
        elif not first and second:
            snapped = _extend_line(np.flip(l_coords, axis=0), t, tolerance)
            if (
                barrier is not None
                and barrier.sindex.query(
                    pygeos.linestrings(snapped), predicate="intersects"
                ).size
                > 0
            ):
                new_geoms.append(geom[line])
            else:
                if extension == 0:
                    new_geoms.append(pygeos.linestrings(snapped))
                else:
                    new_geoms.append(
                        pygeos.linestrings(
                            _extend_line(snapped, t, extension, snap=False)
                        )
                    )
        elif not first and not second:
            one_side = _extend_line(l_coords, t, tolerance)
            one_side_e = _extend_line(one_side, t, extension, snap=False)
            snapped = _extend_line(np.flip(one_side_e, axis=0), t, tolerance)
            if (
                barrier is not None
                and barrier.sindex.query(
                    pygeos.linestrings(snapped), predicate="intersects"
                ).size
                > 0
            ):
                new_geoms.append(geom[line])
            else:
                if extension == 0:
                    new_geoms.append(pygeos.linestrings(snapped))
                else:
                    new_geoms.append(
                        pygeos.linestrings(
                            _extend_line(snapped, t, extension, snap=False)
                        )
                    )

    df.iloc[ends, df.columns.get_loc(df.geometry.name)] = new_geoms
    return df
def extend_lines ( gdf , tolerance , target = None , barrier = None , extension = 0 ) : # explode to avoid MultiLineStrings # reset index due to the bug in GeoPandas explode if GPD_10 : df = gdf . reset_index ( drop = True ) . explode ( ignore_index = True ) else : df = gdf . reset_index ( drop = True ) . explode ( ) . reset_index ( drop = True ) if target is None : target = df itself = True else : itself = False # get underlying pygeos geometry geom = df . geometry . values . data # extract array of coordinates and number per geometry coords = pygeos . get_coordinates ( geom ) indices = pygeos . get_num_coordinates ( geom ) # generate a list of start and end coordinates and create point geometries edges = [ 0 ] i = 0 for ind in indices : ix = i + ind edges . append ( ix - 1 ) edges . append ( ix ) i = ix edges = edges [ : - 1 ] points = pygeos . points ( np . unique ( coords [ edges ] , axis = 0 ) ) # query LineString geometry to identify points intersecting 2 geometries tree = pygeos . STRtree ( geom ) inp , res = tree . query_bulk ( points , predicate = "intersects" ) unique , counts = np . unique ( inp , return_counts = True ) ends = np . unique ( res [ np . isin ( inp , unique [ counts == 1 ] ) ] ) new_geoms = [ ] # iterate over cul-de-sac-like segments and attempt to snap them to street network for line in ends : l_coords = pygeos . get_coordinates ( geom [ line ] ) start = pygeos . points ( l_coords [ 0 ] ) end = pygeos . points ( l_coords [ - 1 ] ) first = list ( tree . query ( start , predicate = "intersects" ) ) second = list ( tree . query ( end , predicate = "intersects" ) ) first . remove ( line ) second . remove ( line ) t = target if not itself else target . drop ( line ) if first and not second : snapped = _extend_line ( l_coords , t , tolerance ) if ( barrier is not None and barrier . sindex . query ( pygeos . linestrings ( snapped ) , predicate = "intersects" ) . size > 0 ) : new_geoms . append ( geom [ line ] ) else : if extension == 0 : new_geoms . append ( pygeos . linestrings ( snapped ) ) else : new_geoms . append ( pygeos . linestrings ( _extend_line ( snapped , t , extension , snap = False ) ) ) elif not first and second : snapped = _extend_line ( np . flip ( l_coords , axis = 0 ) , t , tolerance ) if ( barrier is not None and barrier . sindex . query ( pygeos . linestrings ( snapped ) , predicate = "intersects" ) . size > 0 ) : new_geoms . append ( geom [ line ] ) else : if extension == 0 : new_geoms . append ( pygeos . linestrings ( snapped ) ) else : new_geoms . append ( pygeos . linestrings ( _extend_line ( snapped , t , extension , snap = False ) ) ) elif not first and not second : one_side = _extend_line ( l_coords , t , tolerance ) one_side_e = _extend_line ( one_side , t , extension , snap = False ) snapped = _extend_line ( np . flip ( one_side_e , axis = 0 ) , t , tolerance ) if ( barrier is not None and barrier . sindex . query ( pygeos . linestrings ( snapped ) , predicate = "intersects" ) . size > 0 ) : new_geoms . append ( geom [ line ] ) else : if extension == 0 : new_geoms . append ( pygeos . linestrings ( snapped ) ) else : new_geoms . append ( pygeos . linestrings ( _extend_line ( snapped , t , extension , snap = False ) ) ) df . iloc [ ends , df . columns . get_loc ( df . geometry . name ) ] = new_geoms return df