Skip to content

medial_lines

Compute the medial lines of a polygon using voronoi diagram.

Parameters:

Name Type Description Default
poly Polygon

Polygon to compute the medial lines of.

required
num_points int

Number of resampled points in the input polygon.

100
delta float

Distance between resampled polygon points. Ignored if num_points is not None.

0.3

Returns:

Type Description
Union[MultiLineString, LineString]

shapely.geometry.MultiLineString or shapely.geometry.LineString: the medial line(s).

Examples:

>>> from histolytics.spatial_geom.medial_lines import medial_lines
>>> from histolytics.data import cervix_tissue
>>> import geopandas as gpd
>>>
>>> # Create a simple polygon
>>> cervix_tis = cervix_tissue()
>>> lesion = cervix_tis[cervix_tis["class_name"] == "cin"]
>>>
>>> # Compute medial lines for the largest lesion segmentation
>>> medials = medial_lines(lesion.geometry.iloc[2], num_points=240)
>>> medial_gdf = gpd.GeoDataFrame({"geometry": [medials]}, crs=lesion.crs)
>>> ax = cervix_tis.plot(column="class_name", figsize=(5, 5), aspect=1, alpha=0.5)
>>> medial_gdf.plot(ax=ax, color="red", lw=1, alpha=0.5)
>>> ax.set_axis_off()

out

Source code in src/histolytics/spatial_geom/medial_lines.py
def medial_lines(
    poly: Polygon, num_points: int = 100, delta: float = 0.3
) -> Union[MultiLineString, LineString]:
    """Compute the medial lines of a polygon using voronoi diagram.

    Parameters:
        poly (shapely.geometry.Polygon):
            Polygon to compute the medial lines of.
        num_points (int):
            Number of resampled points in the input polygon.
        delta (float):
            Distance between resampled polygon points. Ignored
            if `num_points` is not None.

    Returns:
        shapely.geometry.MultiLineString or shapely.geometry.LineString:
            the medial line(s).

    Examples:
        >>> from histolytics.spatial_geom.medial_lines import medial_lines
        >>> from histolytics.data import cervix_tissue
        >>> import geopandas as gpd
        >>>
        >>> # Create a simple polygon
        >>> cervix_tis = cervix_tissue()
        >>> lesion = cervix_tis[cervix_tis["class_name"] == "cin"]
        >>>
        >>> # Compute medial lines for the largest lesion segmentation
        >>> medials = medial_lines(lesion.geometry.iloc[2], num_points=240)
        >>> medial_gdf = gpd.GeoDataFrame({"geometry": [medials]}, crs=lesion.crs)
        >>> ax = cervix_tis.plot(column="class_name", figsize=(5, 5), aspect=1, alpha=0.5)
        >>> medial_gdf.plot(ax=ax, color="red", lw=1, alpha=0.5)
        >>> ax.set_axis_off()
    ![out](../../img/medial_lines.png)
    """
    coords = _equal_interval_points(poly.exterior, n=num_points, delta=delta)
    vor = Voronoi(coords)

    contains = vectorized.contains(poly, *vor.vertices.T)
    contains = np.append(contains, False)
    ridge = np.asanyarray(vor.ridge_vertices, dtype=np.int64)
    edges = ridge[contains[ridge].all(axis=1)]

    grouped_lines = _group_contiguous_vertices(vor.vertices[edges])
    medial = linemerge(grouped_lines)

    return medial