Skip to content

perpendicular_lines

cellseg_gsontools.lines.perpendicular_lines(lines, polygon=None)

Get perpendicular lines to the input lines starting from the line midpoints.

Parameters:

Name Type Description Default
lines GeoDataFrame

GeoDataFrame of the input lines.

required
polygon Polygon

Polygon to clip the perpendicular lines to.

None

Returns:

Type Description
GeoDataFrame

gpd.GeoDataFrame: GeoDataFrame of the perpendicular lines.

Source code in cellseg_gsontools/lines.py
def perpendicular_lines(
    lines: gpd.GeoDataFrame, polygon: shapely.Polygon = None
) -> gpd.GeoDataFrame:
    """Get perpendicular lines to the input lines starting from the line midpoints.

    Parameters:
        lines (gpd.GeoDataFrame):
            GeoDataFrame of the input lines.
        polygon (shapely.Polygon):
            Polygon to clip the perpendicular lines to.

    Returns:
        gpd.GeoDataFrame:
            GeoDataFrame of the perpendicular lines.
    """
    # create perpendicular lines to the medial lines
    if polygon is None:
        polygon = lines.unary_union.convex_hull

    seg_len = major_axis_len(polygon)
    func = partial(perpendicular_line, seg_length=seg_len)
    perp_lines = gdf_apply(lines, func, columns=["geometry"])

    # clip the perpendicular lines to the polygon
    perp_lines = gpd.GeoDataFrame(perp_lines, columns=["geometry"]).clip(polygon)

    # explode perpendicular lines & take only the ones that intersect w/ medial lines
    perp_lines = perp_lines.explode(index_parts=False).reset_index(drop=True)

    # drop the perpendicular lines that are too short or too long
    # since these are likely artefacts
    perp_lines["len"] = perp_lines.geometry.length
    low, high = perp_lines.len.quantile([0.05, 0.85])
    perp_lines = perp_lines.query(f"{low}<len<{high}")

    return perp_lines