def _bearings_distribution(
    G: nx.MultiGraph | nx.MultiDiGraph,
    num_bins: int,
    min_length: float,
    weight: str | None,
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
    """
    Compute distribution of bearings across evenly spaced bins.

    Prevents bin-edge effects around common values like 0 degrees and 90
    degrees by initially creating twice as many bins as desired, then merging
    them in pairs. For example, if `num_bins=36` is provided, then each bin
    will represent 10 degrees around the compass, with the first bin
    representing 355 degrees to 5 degrees.

    Parameters
    ----------
    G
        Unprojected graph with `bearing` attributes on each edge.
    num_bins
        Number of bins for the bearing histogram.
    min_length
        Ignore edges with `length` attributes less than `min_length`. Useful
        to ignore the noise of many very short edges.
    weight
        If None, apply equal weight for each bearing. Otherwise, weight edges'
        bearings by this (non-null) edge attribute. For example, if "length"
        is provided, each edge's bearing observation will be weighted by its
        "length" attribute value.

    Returns
    -------
    bin_counts, bin_centers
        Counts of bearings per bin and the bins' centers in degrees. Both
        arrays are of length `num_bins`.
    """
    # Split bins in half to prevent bin-edge effects around common values.
    # Bins will be merged in pairs after the histogram is computed. The last
    # bin edge is the same as the first (i.e., 0 degrees = 360 degrees).
    num_split_bins = num_bins * 2
    split_bin_edges = np.linspace(0, 360, num_split_bins + 1)

    bearings, weights = _extract_edge_bearings(G, min_length, weight)
    split_bin_counts, split_bin_edges = np.histogram(
        bearings,
        bins=split_bin_edges,
        weights=weights,
    )

    # Move last bin to front, so eg 0.01 degrees and 359.99 degrees will be
    # binned together. Then combine counts from pairs of split bins.
    split_bin_counts = np.roll(split_bin_counts, 1)
    bin_counts = split_bin_counts[::2] + split_bin_counts[1::2]

    # Every other edge of the split bins is the center of a merged bin.
    bin_centers = split_bin_edges[range(0, num_split_bins - 1, 2)]
    return bin_counts, bin_centers

    Compute distribution of bearings across evenly spaced bins.

    Prevents bin-edge effects around common values like 0 degrees and 90
    degrees by initially creating twice as many bins as desired, then merging
    them in pairs. For example, if `num_bins=36` is provided, then each bin
    will represent 10 degrees around the compass, with the first bin
    representing 355 degrees to 5 degrees.

    Parameters
    ----------
    G
        Unprojected graph with `bearing` attributes on each edge.
    num_bins
        Number of bins for the bearing histogram.
    min_length
        Ignore edges with `length` attributes less than `min_length`. Useful
        to ignore the noise of many very short edges.
    weight
        If None, apply equal weight for each bearing. Otherwise, weight edges'
        bearings by this (non-null) edge attribute. For example, if "length"
        is provided, each edge's bearing observation will be weighted by its
        "length" attribute value.

    Returns
    -------
    bin_counts, bin_centers
        Counts of bearings per bin and the bins' centers in degrees. Both
        arrays are of length `num_bins`.
    
osmnx/bearing.py