export function isValidLabelOverflowing()

in src/label/dataLabelRectPositioner.ts [151:201]


export function isValidLabelOverflowing(labelRect: IRect, labelPoint: LabelDataPoint, hasMultipleDataSeries: boolean): boolean {
    const parentRect = (<LabelParentRect>labelPoint.parentShape).rect;

    if (!shapes.Rect.isIntersecting(labelRect, parentRect)) {
        return false; // label isn't overflowing from within parent
    }

    const intersection = shapes.Rect.intersect(labelRect, parentRect);
    const precision = LabelOverflowingConsts.equalityPrecision;
    const isLabelContainedVertically =
        double.equalWithPrecision(intersection.top, labelRect.top, precision) &&
        double.equalWithPrecision(intersection.height, labelRect.height, precision);
    const isLabelContainedHorizontally =
        double.equalWithPrecision(intersection.left, labelRect.left, precision) &&
        double.equalWithPrecision(intersection.width, labelRect.width, precision);

    const isParentOrientVertically = [
        NewRectOrientation.VerticalBottomBased,
        NewRectOrientation.VerticalTopBased
    ].some((orientation) => orientation === (<LabelParentRect>labelPoint.parentShape).orientation);


    if (!isLabelContainedHorizontally && !isLabelContainedVertically ||
        (hasMultipleDataSeries &&
            (isParentOrientVertically && !isLabelContainedVertically ||
                !isParentOrientVertically && !isLabelContainedHorizontally)
        )) {
        // Our overflowing definition require that at least one label's rectangle dimension (width / height) to be contained in parent rectangle.
        // Furthermore, if we have multiple data series the contained dimention should be respective with the parent's orientation.
        // To avoid data labels collisions from one series to another which appears inside the same bar.
        return false;
    } else if (isLabelContainedHorizontally && isLabelContainedVertically) {
        return true; // null-overflowing, label is fully contained.
    }

    // Our overflowing definition require that the label and parent "will touch each other enough", this is defined by the ratio of their intersection
    // (touching) against each of them, we look at the maximal intersection ratio which means that at least one of them is 'touched' enought by the other.
    const labelAndParentIntersectEnough = maximalIntersectionRatio(labelRect, parentRect) >= LabelOverflowingConsts.minIntersectionRatio;

    // Our overflowing definition require that the overflowing dimensions will not be too big in comparison to the same dimension of parent.
    // this is done to avoid situationion where the parent is barely visible or that label text is very long.
    let labelOverflowIsValid = false;
    const parentToLabelOverflowRatioThreshold = LabelOverflowingConsts.parentToLabelOverflowRatioThreshold;
    if (isLabelContainedVertically) {
        labelOverflowIsValid = parentRect.width === 0 || (parentRect.width / labelRect.width) > parentToLabelOverflowRatioThreshold;
    } else if (isLabelContainedHorizontally) {
        labelOverflowIsValid = parentRect.height === 0 || (parentRect.height / labelRect.height) > parentToLabelOverflowRatioThreshold;
    }

    return labelAndParentIntersectEnough && labelOverflowIsValid;
}